Path: blob/master/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java
41159 views
/*1* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d.pipe;2627import jdk.internal.misc.Unsafe;282930/**31* The RenderBuffer class is a simplified, high-performance, Unsafe wrapper32* used for buffering rendering operations in a single-threaded rendering33* environment. It's functionality is similar to the ByteBuffer and related34* NIO classes. However, the methods in this class perform little to no35* alignment or bounds checks for performance reasons. Therefore, it is36* the caller's responsibility to ensure that all put() calls are properly37* aligned and within bounds:38* - int and float values must be aligned on 4-byte boundaries39* - long and double values must be aligned on 8-byte boundaries40*41* This class only includes the bare minimum of methods to support42* single-threaded rendering. For example, there is no put(double[]) method43* because we currently have no need for such a method in the STR classes.44*/45public class RenderBuffer {4647/**48* These constants represent the size of various data types (in bytes).49*/50protected static final long SIZEOF_BYTE = 1L;51protected static final long SIZEOF_SHORT = 2L;52protected static final long SIZEOF_INT = 4L;53protected static final long SIZEOF_FLOAT = 4L;54protected static final long SIZEOF_LONG = 8L;55protected static final long SIZEOF_DOUBLE = 8L;5657/**58* Represents the number of elements at which we have empirically59* determined that the average cost of a JNI call exceeds the expense60* of an element by element copy. In other words, if the number of61* elements in an array to be copied exceeds this value, then we should62* use the copyFromArray() method to complete the bulk put operation.63* (This value can be adjusted if the cost of JNI downcalls is reduced64* in a future release.)65*/66private static final int COPY_FROM_ARRAY_THRESHOLD = 6;6768protected final Unsafe unsafe;69protected final long baseAddress;70protected final long endAddress;71protected long curAddress;72protected final int capacity;7374protected RenderBuffer(int numBytes) {75unsafe = Unsafe.getUnsafe();76curAddress = baseAddress = unsafe.allocateMemory(numBytes);77endAddress = baseAddress + numBytes;78capacity = numBytes;79}8081/**82* Allocates a fresh buffer using the machine endianness.83*/84public static RenderBuffer allocate(int numBytes) {85return new RenderBuffer(numBytes);86}8788/**89* Returns the base address of the underlying memory buffer.90*/91public final long getAddress() {92return baseAddress;93}9495/**96* The behavior (and names) of the following methods are nearly97* identical to their counterparts in the various NIO Buffer classes.98*/99100public final int capacity() {101return capacity;102}103104public final int remaining() {105return (int)(endAddress - curAddress);106}107108public final int position() {109return (int)(curAddress - baseAddress);110}111112public final void position(long numBytes) {113curAddress = baseAddress + numBytes;114}115116public final void clear() {117curAddress = baseAddress;118}119120public final RenderBuffer skip(long numBytes) {121curAddress += numBytes;122return this;123}124125/**126* putByte() methods...127*/128129public final RenderBuffer putByte(byte x) {130unsafe.putByte(curAddress, x);131curAddress += SIZEOF_BYTE;132return this;133}134135public RenderBuffer put(byte[] x) {136return put(x, 0, x.length);137}138139public RenderBuffer put(byte[] x, int offset, int length) {140if (length > COPY_FROM_ARRAY_THRESHOLD) {141long offsetInBytes = offset * SIZEOF_BYTE + Unsafe.ARRAY_BYTE_BASE_OFFSET;142long lengthInBytes = length * SIZEOF_BYTE;143unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);144position(position() + lengthInBytes);145} else {146int end = offset + length;147for (int i = offset; i < end; i++) {148putByte(x[i]);149}150}151return this;152}153154/**155* putShort() methods...156*/157158public final RenderBuffer putShort(short x) {159// assert (position() % SIZEOF_SHORT == 0);160unsafe.putShort(curAddress, x);161curAddress += SIZEOF_SHORT;162return this;163}164165public RenderBuffer put(short[] x) {166return put(x, 0, x.length);167}168169public RenderBuffer put(short[] x, int offset, int length) {170// assert (position() % SIZEOF_SHORT == 0);171if (length > COPY_FROM_ARRAY_THRESHOLD) {172long offsetInBytes = offset * SIZEOF_SHORT + Unsafe.ARRAY_SHORT_BASE_OFFSET;173long lengthInBytes = length * SIZEOF_SHORT;174unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);175position(position() + lengthInBytes);176} else {177int end = offset + length;178for (int i = offset; i < end; i++) {179putShort(x[i]);180}181}182return this;183}184185/**186* putInt() methods...187*/188189public final RenderBuffer putInt(int pos, int x) {190// assert (baseAddress + pos % SIZEOF_INT == 0);191unsafe.putInt(baseAddress + pos, x);192return this;193}194195public final RenderBuffer putInt(int x) {196// assert (position() % SIZEOF_INT == 0);197unsafe.putInt(curAddress, x);198curAddress += SIZEOF_INT;199return this;200}201202public RenderBuffer put(int[] x) {203return put(x, 0, x.length);204}205206public RenderBuffer put(int[] x, int offset, int length) {207// assert (position() % SIZEOF_INT == 0);208if (length > COPY_FROM_ARRAY_THRESHOLD) {209long offsetInBytes = offset * SIZEOF_INT + Unsafe.ARRAY_INT_BASE_OFFSET;210long lengthInBytes = length * SIZEOF_INT;211unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);212position(position() + lengthInBytes);213} else {214int end = offset + length;215for (int i = offset; i < end; i++) {216putInt(x[i]);217}218}219return this;220}221222/**223* putFloat() methods...224*/225226public final RenderBuffer putFloat(float x) {227// assert (position() % SIZEOF_FLOAT == 0);228unsafe.putFloat(curAddress, x);229curAddress += SIZEOF_FLOAT;230return this;231}232233public RenderBuffer put(float[] x) {234return put(x, 0, x.length);235}236237public RenderBuffer put(float[] x, int offset, int length) {238// assert (position() % SIZEOF_FLOAT == 0);239if (length > COPY_FROM_ARRAY_THRESHOLD) {240long offsetInBytes = offset * SIZEOF_FLOAT + Unsafe.ARRAY_FLOAT_BASE_OFFSET;241long lengthInBytes = length * SIZEOF_FLOAT;242unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);243position(position() + lengthInBytes);244} else {245int end = offset + length;246for (int i = offset; i < end; i++) {247putFloat(x[i]);248}249}250return this;251}252253/**254* putLong() methods...255*/256257public final RenderBuffer putLong(long x) {258// assert (position() % SIZEOF_LONG == 0);259unsafe.putLong(curAddress, x);260curAddress += SIZEOF_LONG;261return this;262}263264public RenderBuffer put(long[] x) {265return put(x, 0, x.length);266}267268public RenderBuffer put(long[] x, int offset, int length) {269// assert (position() % SIZEOF_LONG == 0);270if (length > COPY_FROM_ARRAY_THRESHOLD) {271long offsetInBytes = offset * SIZEOF_LONG + Unsafe.ARRAY_LONG_BASE_OFFSET;272long lengthInBytes = length * SIZEOF_LONG;273unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes);274position(position() + lengthInBytes);275} else {276int end = offset + length;277for (int i = offset; i < end; i++) {278putLong(x[i]);279}280}281return this;282}283284/**285* putDouble() method(s)...286*/287288public final RenderBuffer putDouble(double x) {289// assert (position() % SIZEOF_DOUBLE == 0);290unsafe.putDouble(curAddress, x);291curAddress += SIZEOF_DOUBLE;292return this;293}294}295296297