com.badlogic.gdx.utils.BufferUtils Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.utils;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
/** Class with static helper methods to increase the speed of array/direct buffer and direct buffer/direct buffer transfers
*
* @author mzechner */
public class BufferUtils {
static Array unsafeBuffers = new Array();
static int allocatedUnsafe = 0;
/** Copies numFloats floats from src starting at offset to dst. Dst is assumed to be a direct {@link Buffer}. The method will
* crash if that is not the case. The position and limit of the buffer are ignored, the copy is placed at position 0 in the
* buffer. After the copying process the position of the buffer is set to 0 and its limit is set to numFloats * 4 if it is a
* ByteBuffer and numFloats if it is a FloatBuffer. In case the Buffer is neither a ByteBuffer nor a FloatBuffer the limit is
* not set. This is an expert method, use at your own risk.
*
* @param src the source array
* @param dst the destination buffer, has to be a direct Buffer
* @param numFloats the number of floats to copy
* @param offset the offset in src to start copying from */
public static void copy (float[] src, Buffer dst, int numFloats, int offset) {
copyJni(src, dst, numFloats, offset);
dst.position(0);
if (dst instanceof ByteBuffer)
dst.limit(numFloats << 2);
else if (dst instanceof FloatBuffer) dst.limit(numFloats);
}
/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
* {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
* will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
* performed.
*
* @param src the source array.
* @param srcOffset the offset into the source array.
* @param dst the destination Buffer, its position is used as an offset.
* @param numElements the number of elements to copy. */
public static void copy (byte[] src, int srcOffset, Buffer dst, int numElements) {
copyJni(src, srcOffset, dst, positionInBytes(dst), numElements);
dst.limit(dst.position() + bytesToElements(dst, numElements));
}
/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
* {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
* will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
* performed.
*
* @param src the source array.
* @param srcOffset the offset into the source array.
* @param dst the destination Buffer, its position is used as an offset.
* @param numElements the number of elements to copy. */
public static void copy (short[] src, int srcOffset, Buffer dst, int numElements) {
copyJni(src, srcOffset << 1, dst, positionInBytes(dst), numElements << 1);
dst.limit(dst.position() + bytesToElements(dst, numElements << 1));
}
/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
* {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
* will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
* performed.
*
* @param src the source array.
* @param srcOffset the offset into the source array.
* @param dst the destination Buffer, its position is used as an offset.
* @param numElements the number of elements to copy. */
public static void copy (char[] src, int srcOffset, Buffer dst, int numElements) {
copyJni(src, srcOffset << 1, dst, positionInBytes(dst), numElements << 1);
dst.limit(dst.position() + bytesToElements(dst, numElements << 1));
}
/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
* {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
* will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
* performed.
*
* @param src the source array.
* @param srcOffset the offset into the source array.
* @param dst the destination Buffer, its position is used as an offset.
* @param numElements the number of elements to copy. */
public static void copy (int[] src, int srcOffset, Buffer dst, int numElements) {
copyJni(src, srcOffset << 2, dst, positionInBytes(dst), numElements << 2);
dst.limit(dst.position() + bytesToElements(dst, numElements << 2));
}
/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
* {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
* will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
* performed.
*
* @param src the source array.
* @param srcOffset the offset into the source array.
* @param dst the destination Buffer, its position is used as an offset.
* @param numElements the number of elements to copy. */
public static void copy (long[] src, int srcOffset, Buffer dst, int numElements) {
copyJni(src, srcOffset << 3, dst, positionInBytes(dst), numElements << 3);
dst.limit(dst.position() + bytesToElements(dst, numElements << 3));
}
/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
* {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
* will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
* performed.
*
* @param src the source array.
* @param srcOffset the offset into the source array.
* @param dst the destination Buffer, its position is used as an offset.
* @param numElements the number of elements to copy. */
public static void copy (float[] src, int srcOffset, Buffer dst, int numElements) {
copyJni(src, srcOffset << 2, dst, positionInBytes(dst), numElements << 2);
dst.limit(dst.position() + bytesToElements(dst, numElements << 2));
}
/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
* {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
* will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
* performed.
*
* @param src the source array.
* @param srcOffset the offset into the source array.
* @param dst the destination Buffer, its position is used as an offset.
* @param numElements the number of elements to copy. */
public static void copy (double[] src, int srcOffset, Buffer dst, int numElements) {
copyJni(src, srcOffset << 3, dst, positionInBytes(dst), numElements << 3);
dst.limit(dst.position() + bytesToElements(dst, numElements << 3));
}
/** Copies the contents of src to dst, starting from the current position of src, copying numElements elements (using the data
* type of src, no matter the datatype of dst). The dst {@link Buffer#position()} is used as the writing offset. The position
* of both Buffers will stay the same. The limit of the src Buffer will stay the same. The limit of the dst Buffer will be set
* to dst.position() + numElements, where numElements are translated to the number of elements appropriate for the dst Buffer
* data type. The Buffers must be direct Buffers with native byte order. No error checking is performed.
*
* @param src the source Buffer.
* @param dst the destination Buffer.
* @param numElements the number of elements to copy. */
public static void copy (Buffer src, Buffer dst, int numElements) {
int numBytes = elementsToBytes(src, numElements);
copyJni(src, positionInBytes(src), dst, positionInBytes(dst), numBytes);
dst.limit(dst.position() + bytesToElements(dst, numBytes));
}
private static int positionInBytes (Buffer dst) {
if (dst instanceof ByteBuffer)
return dst.position();
else if (dst instanceof ShortBuffer)
return dst.position() << 1;
else if (dst instanceof CharBuffer)
return dst.position() << 1;
else if (dst instanceof IntBuffer)
return dst.position() << 2;
else if (dst instanceof LongBuffer)
return dst.position() << 3;
else if (dst instanceof FloatBuffer)
return dst.position() << 2;
else if (dst instanceof DoubleBuffer)
return dst.position() << 3;
else
throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
}
private static int bytesToElements (Buffer dst, int bytes) {
if (dst instanceof ByteBuffer)
return bytes;
else if (dst instanceof ShortBuffer)
return bytes >>> 1;
else if (dst instanceof CharBuffer)
return bytes >>> 1;
else if (dst instanceof IntBuffer)
return bytes >>> 2;
else if (dst instanceof LongBuffer)
return bytes >>> 3;
else if (dst instanceof FloatBuffer)
return bytes >>> 2;
else if (dst instanceof DoubleBuffer)
return bytes >>> 3;
else
throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
}
private static int elementsToBytes (Buffer dst, int elements) {
if (dst instanceof ByteBuffer)
return elements;
else if (dst instanceof ShortBuffer)
return elements << 1;
else if (dst instanceof CharBuffer)
return elements << 1;
else if (dst instanceof IntBuffer)
return elements << 2;
else if (dst instanceof LongBuffer)
return elements << 3;
else if (dst instanceof FloatBuffer)
return elements << 2;
else if (dst instanceof DoubleBuffer)
return elements << 3;
else
throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
}
public static FloatBuffer newFloatBuffer (int numFloats) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numFloats * 4);
buffer.order(ByteOrder.nativeOrder());
return buffer.asFloatBuffer();
}
public static DoubleBuffer newDoubleBuffer (int numDoubles) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numDoubles * 8);
buffer.order(ByteOrder.nativeOrder());
return buffer.asDoubleBuffer();
}
public static ByteBuffer newByteBuffer (int numBytes) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numBytes);
buffer.order(ByteOrder.nativeOrder());
return buffer;
}
public static ShortBuffer newShortBuffer (int numShorts) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numShorts * 2);
buffer.order(ByteOrder.nativeOrder());
return buffer.asShortBuffer();
}
public static CharBuffer newCharBuffer (int numChars) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numChars * 2);
buffer.order(ByteOrder.nativeOrder());
return buffer.asCharBuffer();
}
public static IntBuffer newIntBuffer (int numInts) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numInts * 4);
buffer.order(ByteOrder.nativeOrder());
return buffer.asIntBuffer();
}
public static LongBuffer newLongBuffer (int numLongs) {
ByteBuffer buffer = ByteBuffer.allocateDirect(numLongs * 8);
buffer.order(ByteOrder.nativeOrder());
return buffer.asLongBuffer();
}
/*JNI
#include
#include
#include
*/
public static void disposeUnsafeByteBuffer(ByteBuffer buffer) {
int size = 0;
synchronized(unsafeBuffers) {
if(!unsafeBuffers.removeValue(buffer, true))
throw new IllegalArgumentException("buffer not allocated with newUnsafeByteBuffer or already disposed");
}
allocatedUnsafe -= size;
freeMemory(buffer);
}
/** Allocates a new direct ByteBuffer from native heap memory using the native byte order. Needs to be disposed with
* {@link #freeMemory(ByteBuffer)}.
* @param numBytes */
public static ByteBuffer newUnsafeByteBuffer (int numBytes) {
ByteBuffer buffer = newDisposableByteBuffer(numBytes);
buffer.order(ByteOrder.nativeOrder());
allocatedUnsafe += numBytes;
synchronized(unsafeBuffers) {
unsafeBuffers.add(buffer);
}
return buffer;
}
/**
* @return the number of bytes allocated with {@link #newUnsafeByteBuffer(int)}
*/
public static int getAllocatedBytesUnsafe() {
return allocatedUnsafe;
}
/** Frees the memory allocated for the ByteBuffer. DO NOT USE THIS ON BYTEBUFFERS ALLOCATEd VIA METHODS IN THIS CLASS OR
* ByteBuffer.allocateDirect()! IT WILL EXPLODE! */
private static native void freeMemory (ByteBuffer buffer); /*
free(buffer);
*/
private static native ByteBuffer newDisposableByteBuffer (int numBytes); /*
char* ptr = (char*)malloc(numBytes);
return env->NewDirectByteBuffer(ptr, numBytes);
*/
/** Writes the specified number of zeros to the buffer. This is generally faster than reallocating a new buffer. */
public static native void clear (ByteBuffer buffer, int numBytes); /*
memset(buffer, 0, numBytes);
*/
private native static void copyJni (float[] src, Buffer dst, int numFloats, int offset); /*
memcpy(dst, src + offset, numFloats << 2 );
*/
private native static void copyJni (byte[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
memcpy(dst + dstOffset, src + srcOffset, numBytes);
*/
private native static void copyJni (char[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
memcpy(dst + dstOffset, src + srcOffset, numBytes);
*/
private native static void copyJni (short[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
memcpy(dst + dstOffset, src + srcOffset, numBytes);
*/
private native static void copyJni (int[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
memcpy(dst + dstOffset, src + srcOffset, numBytes);
*/
private native static void copyJni (long[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
memcpy(dst + dstOffset, src + srcOffset, numBytes);
*/
private native static void copyJni (float[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
memcpy(dst + dstOffset, src + srcOffset, numBytes);
*/
private native static void copyJni (double[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
memcpy(dst + dstOffset, src + srcOffset, numBytes);
*/
private native static void copyJni (Buffer src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
memcpy(dst + dstOffset, src + srcOffset, numBytes);
*/
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy