• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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