1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.utils; 18 19 import java.nio.Buffer; 20 import java.nio.ByteBuffer; 21 import java.nio.ByteOrder; 22 import java.nio.CharBuffer; 23 import java.nio.DoubleBuffer; 24 import java.nio.FloatBuffer; 25 import java.nio.IntBuffer; 26 import java.nio.LongBuffer; 27 import java.nio.ShortBuffer; 28 29 import com.badlogic.gdx.math.Matrix3; 30 import com.badlogic.gdx.math.Matrix4; 31 32 /** Class with static helper methods to increase the speed of array/direct buffer and direct buffer/direct buffer transfers 33 * 34 * @author mzechner, xoppa */ 35 public final class BufferUtils { 36 static Array<ByteBuffer> unsafeBuffers = new Array<ByteBuffer>(); 37 static int allocatedUnsafe = 0; 38 39 /** Copies numFloats floats from src starting at offset to dst. Dst is assumed to be a direct {@link Buffer}. The method will 40 * 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 41 * 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 42 * ByteBuffer and numFloats if it is a FloatBuffer. In case the Buffer is neither a ByteBuffer nor a FloatBuffer the limit is 43 * not set. This is an expert method, use at your own risk. 44 * 45 * @param src the source array 46 * @param dst the destination buffer, has to be a direct Buffer 47 * @param numFloats the number of floats to copy 48 * @param offset the offset in src to start copying from */ copy(float[] src, Buffer dst, int numFloats, int offset)49 public static void copy (float[] src, Buffer dst, int numFloats, int offset) { 50 if (dst instanceof ByteBuffer) 51 dst.limit(numFloats << 2); 52 else if (dst instanceof FloatBuffer) dst.limit(numFloats); 53 54 copyJni(src, dst, numFloats, offset); 55 dst.position(0); 56 } 57 58 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 59 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit 60 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is 61 * performed</b>. 62 * 63 * @param src the source array. 64 * @param srcOffset the offset into the source array. 65 * @param dst the destination Buffer, its position is used as an offset. 66 * @param numElements the number of elements to copy. */ copy(byte[] src, int srcOffset, Buffer dst, int numElements)67 public static void copy (byte[] src, int srcOffset, Buffer dst, int numElements) { 68 dst.limit(dst.position() + bytesToElements(dst, numElements)); 69 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements); 70 } 71 72 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 73 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit 74 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is 75 * performed</b>. 76 * 77 * @param src the source array. 78 * @param srcOffset the offset into the source array. 79 * @param dst the destination Buffer, its position is used as an offset. 80 * @param numElements the number of elements to copy. */ copy(short[] src, int srcOffset, Buffer dst, int numElements)81 public static void copy (short[] src, int srcOffset, Buffer dst, int numElements) { 82 dst.limit(dst.position() + bytesToElements(dst, numElements << 1)); 83 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1); 84 } 85 86 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 87 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same. 88 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>. 89 * 90 * @param src the source array. 91 * @param srcOffset the offset into the source array. 92 * @param numElements the number of elements to copy. 93 * @param dst the destination Buffer, its position is used as an offset. */ copy(char[] src, int srcOffset, int numElements, Buffer dst)94 public static void copy (char[] src, int srcOffset, int numElements, Buffer dst) { 95 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1); 96 } 97 98 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 99 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same. 100 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>. 101 * 102 * @param src the source array. 103 * @param srcOffset the offset into the source array. 104 * @param numElements the number of elements to copy. 105 * @param dst the destination Buffer, its position is used as an offset. */ copy(int[] src, int srcOffset, int numElements, Buffer dst)106 public static void copy (int[] src, int srcOffset, int numElements, Buffer dst) { 107 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2); 108 } 109 110 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 111 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same. 112 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>. 113 * 114 * @param src the source array. 115 * @param srcOffset the offset into the source array. 116 * @param numElements the number of elements to copy. 117 * @param dst the destination Buffer, its position is used as an offset. */ copy(long[] src, int srcOffset, int numElements, Buffer dst)118 public static void copy (long[] src, int srcOffset, int numElements, Buffer dst) { 119 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3); 120 } 121 122 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 123 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same. 124 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>. 125 * 126 * @param src the source array. 127 * @param srcOffset the offset into the source array. 128 * @param numElements the number of elements to copy. 129 * @param dst the destination Buffer, its position is used as an offset. */ copy(float[] src, int srcOffset, int numElements, Buffer dst)130 public static void copy (float[] src, int srcOffset, int numElements, Buffer dst) { 131 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2); 132 } 133 134 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 135 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same. 136 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>. 137 * 138 * @param src the source array. 139 * @param srcOffset the offset into the source array. 140 * @param numElements the number of elements to copy. 141 * @param dst the destination Buffer, its position is used as an offset. */ copy(double[] src, int srcOffset, int numElements, Buffer dst)142 public static void copy (double[] src, int srcOffset, int numElements, Buffer dst) { 143 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3); 144 } 145 146 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 147 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit 148 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is 149 * performed</b>. 150 * 151 * @param src the source array. 152 * @param srcOffset the offset into the source array. 153 * @param dst the destination Buffer, its position is used as an offset. 154 * @param numElements the number of elements to copy. */ copy(char[] src, int srcOffset, Buffer dst, int numElements)155 public static void copy (char[] src, int srcOffset, Buffer dst, int numElements) { 156 dst.limit(dst.position() + bytesToElements(dst, numElements << 1)); 157 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1); 158 } 159 160 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 161 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit 162 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is 163 * performed</b>. 164 * 165 * @param src the source array. 166 * @param srcOffset the offset into the source array. 167 * @param dst the destination Buffer, its position is used as an offset. 168 * @param numElements the number of elements to copy. */ copy(int[] src, int srcOffset, Buffer dst, int numElements)169 public static void copy (int[] src, int srcOffset, Buffer dst, int numElements) { 170 dst.limit(dst.position() + bytesToElements(dst, numElements << 2)); 171 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2); 172 } 173 174 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 175 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit 176 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is 177 * performed</b>. 178 * 179 * @param src the source array. 180 * @param srcOffset the offset into the source array. 181 * @param dst the destination Buffer, its position is used as an offset. 182 * @param numElements the number of elements to copy. */ copy(long[] src, int srcOffset, Buffer dst, int numElements)183 public static void copy (long[] src, int srcOffset, Buffer dst, int numElements) { 184 dst.limit(dst.position() + bytesToElements(dst, numElements << 3)); 185 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3); 186 } 187 188 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 189 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit 190 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is 191 * performed</b>. 192 * 193 * @param src the source array. 194 * @param srcOffset the offset into the source array. 195 * @param dst the destination Buffer, its position is used as an offset. 196 * @param numElements the number of elements to copy. */ copy(float[] src, int srcOffset, Buffer dst, int numElements)197 public static void copy (float[] src, int srcOffset, Buffer dst, int numElements) { 198 dst.limit(dst.position() + bytesToElements(dst, numElements << 2)); 199 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2); 200 } 201 202 /** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's 203 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit 204 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is 205 * performed</b>. 206 * 207 * @param src the source array. 208 * @param srcOffset the offset into the source array. 209 * @param dst the destination Buffer, its position is used as an offset. 210 * @param numElements the number of elements to copy. */ copy(double[] src, int srcOffset, Buffer dst, int numElements)211 public static void copy (double[] src, int srcOffset, Buffer dst, int numElements) { 212 dst.limit(dst.position() + bytesToElements(dst, numElements << 3)); 213 copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3); 214 } 215 216 /** Copies the contents of src to dst, starting from the current position of src, copying numElements elements (using the data 217 * type of src, no matter the datatype of dst). The dst {@link Buffer#position()} is used as the writing offset. The position 218 * 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 219 * to dst.position() + numElements, where numElements are translated to the number of elements appropriate for the dst Buffer 220 * data type. <b>The Buffers must be direct Buffers with native byte order. No error checking is performed</b>. 221 * 222 * @param src the source Buffer. 223 * @param dst the destination Buffer. 224 * @param numElements the number of elements to copy. */ copy(Buffer src, Buffer dst, int numElements)225 public static void copy (Buffer src, Buffer dst, int numElements) { 226 int numBytes = elementsToBytes(src, numElements); 227 dst.limit(dst.position() + bytesToElements(dst, numBytes)); 228 copyJni(src, positionInBytes(src), dst, positionInBytes(dst), numBytes); 229 } 230 231 /** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the 232 * offset. 233 * @param data The buffer to transform. 234 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw) 235 * @param strideInBytes The offset between the first and the second vector to transform 236 * @param count The number of vectors to transform 237 * @param matrix The matrix to multiply the vector with */ transform(Buffer data, int dimensions, int strideInBytes, int count, Matrix4 matrix)238 public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix4 matrix) { 239 transform(data, dimensions, strideInBytes, count, matrix, 0); 240 } 241 242 /** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the 243 * offset. 244 * @param data The buffer to transform. 245 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw) 246 * @param strideInBytes The offset between the first and the second vector to transform 247 * @param count The number of vectors to transform 248 * @param matrix The matrix to multiply the vector with */ transform(float[] data, int dimensions, int strideInBytes, int count, Matrix4 matrix)249 public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix4 matrix) { 250 transform(data, dimensions, strideInBytes, count, matrix, 0); 251 } 252 253 /** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the 254 * {@link Buffer#position()} and used as the offset. 255 * @param data The buffer to transform. 256 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw) 257 * @param strideInBytes The offset between the first and the second vector to transform 258 * @param count The number of vectors to transform 259 * @param matrix The matrix to multiply the vector with 260 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */ transform(Buffer data, int dimensions, int strideInBytes, int count, Matrix4 matrix, int offset)261 public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix4 matrix, int offset) { 262 switch (dimensions) { 263 case 4: 264 transformV4M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset); 265 break; 266 case 3: 267 transformV3M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset); 268 break; 269 case 2: 270 transformV2M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset); 271 break; 272 default: 273 throw new IllegalArgumentException(); 274 } 275 } 276 277 /** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the 278 * {@link Buffer#position()} and used as the offset. 279 * @param data The buffer to transform. 280 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw) 281 * @param strideInBytes The offset between the first and the second vector to transform 282 * @param count The number of vectors to transform 283 * @param matrix The matrix to multiply the vector with 284 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */ transform(float[] data, int dimensions, int strideInBytes, int count, Matrix4 matrix, int offset)285 public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix4 matrix, int offset) { 286 switch (dimensions) { 287 case 4: 288 transformV4M4Jni(data, strideInBytes, count, matrix.val, offset); 289 break; 290 case 3: 291 transformV3M4Jni(data, strideInBytes, count, matrix.val, offset); 292 break; 293 case 2: 294 transformV2M4Jni(data, strideInBytes, count, matrix.val, offset); 295 break; 296 default: 297 throw new IllegalArgumentException(); 298 } 299 } 300 301 /** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the 302 * offset. 303 * @param data The buffer to transform. 304 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz) 305 * @param strideInBytes The offset between the first and the second vector to transform 306 * @param count The number of vectors to transform 307 * @param matrix The matrix to multiply the vector with */ transform(Buffer data, int dimensions, int strideInBytes, int count, Matrix3 matrix)308 public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix3 matrix) { 309 transform(data, dimensions, strideInBytes, count, matrix, 0); 310 } 311 312 /** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the 313 * offset. 314 * @param data The buffer to transform. 315 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz) 316 * @param strideInBytes The offset between the first and the second vector to transform 317 * @param count The number of vectors to transform 318 * @param matrix The matrix to multiply the vector with */ transform(float[] data, int dimensions, int strideInBytes, int count, Matrix3 matrix)319 public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix3 matrix) { 320 transform(data, dimensions, strideInBytes, count, matrix, 0); 321 } 322 323 /** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the 324 * {@link Buffer#position()} and used as the offset. 325 * @param data The buffer to transform. 326 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz) 327 * @param strideInBytes The offset between the first and the second vector to transform 328 * @param count The number of vectors to transform 329 * @param matrix The matrix to multiply the vector with, 330 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */ transform(Buffer data, int dimensions, int strideInBytes, int count, Matrix3 matrix, int offset)331 public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix3 matrix, int offset) { 332 switch (dimensions) { 333 case 3: 334 transformV3M3Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset); 335 break; 336 case 2: 337 transformV2M3Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset); 338 break; 339 default: 340 throw new IllegalArgumentException(); 341 } 342 } 343 344 /** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the 345 * {@link Buffer#position()} and used as the offset. 346 * @param data The buffer to transform. 347 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz) 348 * @param strideInBytes The offset between the first and the second vector to transform 349 * @param count The number of vectors to transform 350 * @param matrix The matrix to multiply the vector with, 351 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */ transform(float[] data, int dimensions, int strideInBytes, int count, Matrix3 matrix, int offset)352 public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix3 matrix, int offset) { 353 switch (dimensions) { 354 case 3: 355 transformV3M3Jni(data, strideInBytes, count, matrix.val, offset); 356 break; 357 case 2: 358 transformV2M3Jni(data, strideInBytes, count, matrix.val, offset); 359 break; 360 default: 361 throw new IllegalArgumentException(); 362 } 363 } 364 findFloats(Buffer vertex, int strideInBytes, Buffer vertices, int numVertices)365 public static long findFloats (Buffer vertex, int strideInBytes, Buffer vertices, int numVertices) { 366 return find(vertex, positionInBytes(vertex), strideInBytes, vertices, positionInBytes(vertices), numVertices); 367 } 368 findFloats(float[] vertex, int strideInBytes, Buffer vertices, int numVertices)369 public static long findFloats (float[] vertex, int strideInBytes, Buffer vertices, int numVertices) { 370 return find(vertex, 0, strideInBytes, vertices, positionInBytes(vertices), numVertices); 371 } 372 findFloats(Buffer vertex, int strideInBytes, float[] vertices, int numVertices)373 public static long findFloats (Buffer vertex, int strideInBytes, float[] vertices, int numVertices) { 374 return find(vertex, positionInBytes(vertex), strideInBytes, vertices, 0, numVertices); 375 } 376 findFloats(float[] vertex, int strideInBytes, float[] vertices, int numVertices)377 public static long findFloats (float[] vertex, int strideInBytes, float[] vertices, int numVertices) { 378 return find(vertex, 0, strideInBytes, vertices, 0, numVertices); 379 } 380 findFloats(Buffer vertex, int strideInBytes, Buffer vertices, int numVertices, float epsilon)381 public static long findFloats (Buffer vertex, int strideInBytes, Buffer vertices, int numVertices, float epsilon) { 382 return find(vertex, positionInBytes(vertex), strideInBytes, vertices, positionInBytes(vertices), numVertices, epsilon); 383 } 384 findFloats(float[] vertex, int strideInBytes, Buffer vertices, int numVertices, float epsilon)385 public static long findFloats (float[] vertex, int strideInBytes, Buffer vertices, int numVertices, float epsilon) { 386 return find(vertex, 0, strideInBytes, vertices, positionInBytes(vertices), numVertices, epsilon); 387 } 388 findFloats(Buffer vertex, int strideInBytes, float[] vertices, int numVertices, float epsilon)389 public static long findFloats (Buffer vertex, int strideInBytes, float[] vertices, int numVertices, float epsilon) { 390 return find(vertex, positionInBytes(vertex), strideInBytes, vertices, 0, numVertices, epsilon); 391 } 392 findFloats(float[] vertex, int strideInBytes, float[] vertices, int numVertices, float epsilon)393 public static long findFloats (float[] vertex, int strideInBytes, float[] vertices, int numVertices, float epsilon) { 394 return find(vertex, 0, strideInBytes, vertices, 0, numVertices, epsilon); 395 } 396 positionInBytes(Buffer dst)397 private static int positionInBytes (Buffer dst) { 398 if (dst instanceof ByteBuffer) 399 return dst.position(); 400 else if (dst instanceof ShortBuffer) 401 return dst.position() << 1; 402 else if (dst instanceof CharBuffer) 403 return dst.position() << 1; 404 else if (dst instanceof IntBuffer) 405 return dst.position() << 2; 406 else if (dst instanceof LongBuffer) 407 return dst.position() << 3; 408 else if (dst instanceof FloatBuffer) 409 return dst.position() << 2; 410 else if (dst instanceof DoubleBuffer) 411 return dst.position() << 3; 412 else 413 throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance"); 414 } 415 bytesToElements(Buffer dst, int bytes)416 private static int bytesToElements (Buffer dst, int bytes) { 417 if (dst instanceof ByteBuffer) 418 return bytes; 419 else if (dst instanceof ShortBuffer) 420 return bytes >>> 1; 421 else if (dst instanceof CharBuffer) 422 return bytes >>> 1; 423 else if (dst instanceof IntBuffer) 424 return bytes >>> 2; 425 else if (dst instanceof LongBuffer) 426 return bytes >>> 3; 427 else if (dst instanceof FloatBuffer) 428 return bytes >>> 2; 429 else if (dst instanceof DoubleBuffer) 430 return bytes >>> 3; 431 else 432 throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance"); 433 } 434 elementsToBytes(Buffer dst, int elements)435 private static int elementsToBytes (Buffer dst, int elements) { 436 if (dst instanceof ByteBuffer) 437 return elements; 438 else if (dst instanceof ShortBuffer) 439 return elements << 1; 440 else if (dst instanceof CharBuffer) 441 return elements << 1; 442 else if (dst instanceof IntBuffer) 443 return elements << 2; 444 else if (dst instanceof LongBuffer) 445 return elements << 3; 446 else if (dst instanceof FloatBuffer) 447 return elements << 2; 448 else if (dst instanceof DoubleBuffer) 449 return elements << 3; 450 else 451 throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance"); 452 } 453 newFloatBuffer(int numFloats)454 public static FloatBuffer newFloatBuffer (int numFloats) { 455 ByteBuffer buffer = ByteBuffer.allocateDirect(numFloats * 4); 456 buffer.order(ByteOrder.nativeOrder()); 457 return buffer.asFloatBuffer(); 458 } 459 newDoubleBuffer(int numDoubles)460 public static DoubleBuffer newDoubleBuffer (int numDoubles) { 461 ByteBuffer buffer = ByteBuffer.allocateDirect(numDoubles * 8); 462 buffer.order(ByteOrder.nativeOrder()); 463 return buffer.asDoubleBuffer(); 464 } 465 newByteBuffer(int numBytes)466 public static ByteBuffer newByteBuffer (int numBytes) { 467 ByteBuffer buffer = ByteBuffer.allocateDirect(numBytes); 468 buffer.order(ByteOrder.nativeOrder()); 469 return buffer; 470 } 471 newShortBuffer(int numShorts)472 public static ShortBuffer newShortBuffer (int numShorts) { 473 ByteBuffer buffer = ByteBuffer.allocateDirect(numShorts * 2); 474 buffer.order(ByteOrder.nativeOrder()); 475 return buffer.asShortBuffer(); 476 } 477 newCharBuffer(int numChars)478 public static CharBuffer newCharBuffer (int numChars) { 479 ByteBuffer buffer = ByteBuffer.allocateDirect(numChars * 2); 480 buffer.order(ByteOrder.nativeOrder()); 481 return buffer.asCharBuffer(); 482 } 483 newIntBuffer(int numInts)484 public static IntBuffer newIntBuffer (int numInts) { 485 ByteBuffer buffer = ByteBuffer.allocateDirect(numInts * 4); 486 buffer.order(ByteOrder.nativeOrder()); 487 return buffer.asIntBuffer(); 488 } 489 newLongBuffer(int numLongs)490 public static LongBuffer newLongBuffer (int numLongs) { 491 ByteBuffer buffer = ByteBuffer.allocateDirect(numLongs * 8); 492 buffer.order(ByteOrder.nativeOrder()); 493 return buffer.asLongBuffer(); 494 } 495 496 // @off 497 /*JNI 498 #include <stdio.h> 499 #include <stdlib.h> 500 #include <string.h> 501 */ 502 disposeUnsafeByteBuffer(ByteBuffer buffer)503 public static void disposeUnsafeByteBuffer(ByteBuffer buffer) { 504 int size = buffer.capacity(); 505 synchronized(unsafeBuffers) { 506 if(!unsafeBuffers.removeValue(buffer, true)) 507 throw new IllegalArgumentException("buffer not allocated with newUnsafeByteBuffer or already disposed"); 508 } 509 allocatedUnsafe -= size; 510 freeMemory(buffer); 511 } 512 513 /** Allocates a new direct ByteBuffer from native heap memory using the native byte order. Needs to be disposed with 514 * {@link #freeMemory(ByteBuffer)}. 515 * @param numBytes */ newUnsafeByteBuffer(int numBytes)516 public static ByteBuffer newUnsafeByteBuffer (int numBytes) { 517 ByteBuffer buffer = newDisposableByteBuffer(numBytes); 518 buffer.order(ByteOrder.nativeOrder()); 519 allocatedUnsafe += numBytes; 520 synchronized(unsafeBuffers) { 521 unsafeBuffers.add(buffer); 522 } 523 return buffer; 524 } 525 526 /** 527 * Returns the address of the Buffer, it assumes it is an unsafe buffer. 528 * @param buffer The Buffer to ask the address for. 529 * @return the address of the Buffer. 530 */ getUnsafeBufferAddress(Buffer buffer)531 public static long getUnsafeBufferAddress(Buffer buffer) { 532 return getBufferAddress(buffer) + buffer.position(); 533 } 534 535 /** 536 * Registers the given ByteBuffer as an unsafe ByteBuffer. The ByteBuffer must have been 537 * allocated in native code, pointing to a memory region allocated via malloc. Needs to 538 * be disposed with {@link #freeMemory(ByteBuffer)}. 539 * @param buffer the {@link ByteBuffer} to register 540 * @return the ByteBuffer passed to the method 541 */ newUnsafeByteBuffer(ByteBuffer buffer)542 public static ByteBuffer newUnsafeByteBuffer(ByteBuffer buffer) { 543 allocatedUnsafe += buffer.capacity(); 544 synchronized(unsafeBuffers) { 545 unsafeBuffers.add(buffer); 546 } 547 return buffer; 548 } 549 550 /** 551 * @return the number of bytes allocated with {@link #newUnsafeByteBuffer(int)} 552 */ getAllocatedBytesUnsafe()553 public static int getAllocatedBytesUnsafe() { 554 return allocatedUnsafe; 555 } 556 557 /** Frees the memory allocated for the ByteBuffer. DO NOT USE THIS ON BYTEBUFFERS ALLOCATEd VIA METHODS IN THIS CLASS OR 558 * ByteBuffer.allocateDirect()! IT WILL EXPLODE! */ freeMemory(ByteBuffer buffer)559 private static native void freeMemory (ByteBuffer buffer); /* 560 free(buffer); 561 */ 562 newDisposableByteBuffer(int numBytes)563 private static native ByteBuffer newDisposableByteBuffer (int numBytes); /* 564 return env->NewDirectByteBuffer((char*)malloc(numBytes), numBytes); 565 */ 566 getBufferAddress(Buffer buffer)567 private static native long getBufferAddress (Buffer buffer); /* 568 return (jlong) buffer; 569 */ 570 571 /** Writes the specified number of zeros to the buffer. This is generally faster than reallocating a new buffer. */ clear(ByteBuffer buffer, int numBytes)572 public static native void clear (ByteBuffer buffer, int numBytes); /* 573 memset(buffer, 0, numBytes); 574 */ 575 copyJni(float[] src, Buffer dst, int numFloats, int offset)576 private native static void copyJni (float[] src, Buffer dst, int numFloats, int offset); /* 577 memcpy(dst, src + offset, numFloats << 2 ); 578 */ 579 copyJni(byte[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes)580 private native static void copyJni (byte[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /* 581 memcpy(dst + dstOffset, src + srcOffset, numBytes); 582 */ 583 copyJni(char[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes)584 private native static void copyJni (char[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /* 585 memcpy(dst + dstOffset, src + srcOffset, numBytes); 586 */ 587 copyJni(short[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes)588 private native static void copyJni (short[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /* 589 memcpy(dst + dstOffset, src + srcOffset, numBytes); 590 */ 591 copyJni(int[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes)592 private native static void copyJni (int[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /* 593 memcpy(dst + dstOffset, src + srcOffset, numBytes); 594 */ 595 copyJni(long[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes)596 private native static void copyJni (long[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /* 597 memcpy(dst + dstOffset, src + srcOffset, numBytes); 598 */ 599 copyJni(float[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes)600 private native static void copyJni (float[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /* 601 memcpy(dst + dstOffset, src + srcOffset, numBytes); 602 */ 603 copyJni(double[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes)604 private native static void copyJni (double[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /* 605 memcpy(dst + dstOffset, src + srcOffset, numBytes); 606 */ 607 copyJni(Buffer src, int srcOffset, Buffer dst, int dstOffset, int numBytes)608 private native static void copyJni (Buffer src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /* 609 memcpy(dst + dstOffset, src + srcOffset, numBytes); 610 */ 611 612 /*JNI 613 template<size_t n1, size_t n2> void transform(float * const &src, float * const &m, float * const &dst) {} 614 615 template<> inline void transform<4, 4>(float * const &src, float * const &m, float * const &dst) { 616 const float x = src[0], y = src[1], z = src[2], w = src[3]; 617 dst[0] = x * m[ 0] + y * m[ 4] + z * m[ 8] + w * m[12]; 618 dst[1] = x * m[ 1] + y * m[ 5] + z * m[ 9] + w * m[13]; 619 dst[2] = x * m[ 2] + y * m[ 6] + z * m[10] + w * m[14]; 620 dst[3] = x * m[ 3] + y * m[ 7] + z * m[11] + w * m[15]; 621 } 622 623 template<> inline void transform<3, 4>(float * const &src, float * const &m, float * const &dst) { 624 const float x = src[0], y = src[1], z = src[2]; 625 dst[0] = x * m[ 0] + y * m[ 4] + z * m[ 8] + m[12]; 626 dst[1] = x * m[ 1] + y * m[ 5] + z * m[ 9] + m[13]; 627 dst[2] = x * m[ 2] + y * m[ 6] + z * m[10] + m[14]; 628 } 629 630 template<> inline void transform<2, 4>(float * const &src, float * const &m, float * const &dst) { 631 const float x = src[0], y = src[1]; 632 dst[0] = x * m[ 0] + y * m[ 4] + m[12]; 633 dst[1] = x * m[ 1] + y * m[ 5] + m[13]; 634 } 635 636 template<> inline void transform<3, 3>(float * const &src, float * const &m, float * const &dst) { 637 const float x = src[0], y = src[1], z = src[2]; 638 dst[0] = x * m[0] + y * m[3] + z * m[6]; 639 dst[1] = x * m[1] + y * m[4] + z * m[7]; 640 dst[2] = x * m[2] + y * m[5] + z * m[8]; 641 } 642 643 template<> inline void transform<2, 3>(float * const &src, float * const &m, float * const &dst) { 644 const float x = src[0], y = src[1]; 645 dst[0] = x * m[0] + y * m[3] + m[6]; 646 dst[1] = x * m[1] + y * m[4] + m[7]; 647 } 648 649 template<size_t n1, size_t n2> void transform(float * const &v, int const &stride, int const &count, float * const &m, int offset) { 650 for (int i = 0; i < count; i++) { 651 transform<n1, n2>(&v[offset], m, &v[offset]); 652 offset += stride; 653 } 654 } 655 656 template<size_t n1, size_t n2> void transform(float * const &v, int const &stride, unsigned short * const &indices, int const &count, float * const &m, int offset) { 657 for (int i = 0; i < count; i++) { 658 transform<n1, n2>(&v[offset], m, &v[offset]); 659 offset += stride; 660 } 661 } 662 663 inline bool compare(float * const &lhs, float * const & rhs, const unsigned int &size, const float &epsilon) { 664 for (unsigned int i = 0; i < size; i++) 665 if ((*(unsigned int*)&lhs[i] != *(unsigned int*)&rhs[i]) && ((lhs[i] > rhs[i] ? lhs[i] - rhs[i] : rhs[i] - lhs[i]) > epsilon)) 666 return false; 667 return true; 668 } 669 670 long find(float * const &vertex, const unsigned int &size, float * const &vertices, const unsigned int &count, const float &epsilon) { 671 for (unsigned int i = 0; i < count; i++) 672 if (compare(&vertices[i*size], vertex, size, epsilon)) 673 return (long)i; 674 return -1; 675 } 676 677 inline bool compare(float * const &lhs, float * const & rhs, const unsigned int &size) { 678 for (unsigned int i = 0; i < size; i++) 679 if ((*(unsigned int*)&lhs[i] != *(unsigned int*)&rhs[i]) && lhs[i] != rhs[i]) 680 return false; 681 return true; 682 } 683 684 long find(float * const &vertex, const unsigned int &size, float * const &vertices, const unsigned int &count) { 685 for (unsigned int i = 0; i < count; i++) 686 if (compare(&vertices[i*size], vertex, size)) 687 return (long)i; 688 return -1; 689 } 690 691 inline unsigned int calcHash(float * const &vertex, const unsigned int &size) { 692 unsigned int result = 0; 693 for (unsigned int i = 0; i < size; ++i) 694 result += ((*((unsigned int *)&vertex[i])) & 0xffffff80) >> (i & 0x7); 695 return result & 0x7fffffff; 696 } 697 698 long find(float * const &vertex, const unsigned int &size, float * const &vertices, unsigned int * const &hashes, const unsigned int &count) { 699 const unsigned int hash = calcHash(vertex, size); 700 for (unsigned int i = 0; i < count; i++) 701 if (hashes[i] == hash && compare(&vertices[i*size], vertex, size)) 702 return (long)i; 703 return -1; 704 } 705 */ 706 transformV4M4Jni(Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes)707 private native static void transformV4M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 708 transform<4, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 709 */ 710 transformV4M4Jni(float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes)711 private native static void transformV4M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 712 transform<4, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 713 */ 714 transformV3M4Jni(Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes)715 private native static void transformV3M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 716 transform<3, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 717 */ 718 transformV3M4Jni(float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes)719 private native static void transformV3M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 720 transform<3, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 721 */ 722 transformV2M4Jni(Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes)723 private native static void transformV2M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 724 transform<2, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 725 */ 726 transformV2M4Jni(float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes)727 private native static void transformV2M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 728 transform<2, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 729 */ 730 transformV3M3Jni(Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes)731 private native static void transformV3M3Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 732 transform<3, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 733 */ 734 transformV3M3Jni(float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes)735 private native static void transformV3M3Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 736 transform<3, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 737 */ 738 transformV2M3Jni(Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes)739 private native static void transformV2M3Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 740 transform<2, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 741 */ 742 transformV2M3Jni(float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes)743 private native static void transformV2M3Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /* 744 transform<2, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4); 745 */ 746 find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices)747 private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices); /* 748 return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices); 749 */ 750 find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices)751 private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices); /* 752 return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices); 753 */ 754 find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices)755 private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices); /* 756 return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices); 757 */ 758 find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices)759 private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices); /* 760 return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices); 761 */ 762 find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices, float epsilon)763 private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /* 764 return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon); 765 */ 766 find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices, float epsilon)767 private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /* 768 return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon); 769 */ 770 find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices, float epsilon)771 private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /* 772 return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon); 773 */ 774 find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices, float epsilon)775 private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /* 776 return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon); 777 */ 778 } 779