PageRenderTime 415ms CodeModel.GetById 27ms RepoModel.GetById 2ms app.codeStats 0ms

/gdx/src/com/badlogic/gdx/utils/BufferUtils.java

https://bitbucket.org/cng1985/libgdx
Java | 284 lines | 127 code | 23 blank | 134 comment | 45 complexity | dc0dd332cc141f899f1a340a0e97aa7f MD5 | raw file
  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. package com.badlogic.gdx.utils;
  17. import java.nio.Buffer;
  18. import java.nio.ByteBuffer;
  19. import java.nio.ByteOrder;
  20. import java.nio.CharBuffer;
  21. import java.nio.DoubleBuffer;
  22. import java.nio.FloatBuffer;
  23. import java.nio.IntBuffer;
  24. import java.nio.LongBuffer;
  25. import java.nio.ShortBuffer;
  26. /**
  27. * Class with static helper methods to increase the speed of array/direct buffer and direct buffer/direct buffer transfers
  28. *
  29. * @author mzechner
  30. *
  31. */
  32. public class BufferUtils {
  33. /**
  34. * Frees the memory allocated for the ByteBuffer. DO NOT USE THIS ON BYTEBUFFERS ALLOCATEd
  35. * VIA METHODS IN THIS CLASS OR ByteBuffer.allocateDirect()! IT WILL EXPLODE!
  36. */
  37. public static native void freeMemory(ByteBuffer buffer) /*-{ }-*/;
  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
  49. */
  50. public static void copy (float[] src, Buffer dst, int numFloats, int offset) {
  51. copyJni(src, dst, numFloats, offset);
  52. dst.position(0);
  53. if (dst instanceof ByteBuffer)
  54. dst.limit(numFloats << 2);
  55. else if (dst instanceof FloatBuffer) dst.limit(numFloats);
  56. }
  57. /**
  58. * Copies the contents of src to dst, starting from src[srcOffset], copying numElements
  59. * elements. The {@link Buffer} instance's {@link Buffer#position()} is used to define
  60. * the offset into the Buffer itself. The position will stay the same, the limit will be
  61. * set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order.
  62. * No error checking is performed</b>.
  63. *
  64. * @param src the source array.
  65. * @param srcOffset the offset into the source array.
  66. * @param dst the destination Buffer, its position is used as an offset.
  67. * @param numElements the number of elements to copy.
  68. */
  69. public static void copy (byte[] src, int srcOffset, Buffer dst, int numElements) {
  70. copyJni(src, srcOffset, dst, positionInBytes(dst), numElements);
  71. dst.limit(dst.position() + bytesToElements(dst, numElements));
  72. }
  73. /**
  74. * Copies the contents of src to dst, starting from src[srcOffset], copying numElements
  75. * elements. The {@link Buffer} instance's {@link Buffer#position()} is used to define
  76. * the offset into the Buffer itself. The position will stay the same, the limit will be
  77. * set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order.
  78. * No error checking is performed</b>.
  79. *
  80. * @param src the source array.
  81. * @param srcOffset the offset into the source array.
  82. * @param dst the destination Buffer, its position is used as an offset.
  83. * @param numElements the number of elements to copy.
  84. */
  85. public static void copy (short[] src, int srcOffset, Buffer dst, int numElements) {
  86. copyJni(src, srcOffset << 1, dst, positionInBytes(dst), numElements << 1);
  87. dst.limit(dst.position() + bytesToElements(dst, numElements << 1));
  88. }
  89. /**
  90. * Copies the contents of src to dst, starting from src[srcOffset], copying numElements
  91. * elements. The {@link Buffer} instance's {@link Buffer#position()} is used to define
  92. * the offset into the Buffer itself. The position will stay the same, the limit will be
  93. * set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order.
  94. * No error checking is performed</b>.
  95. *
  96. * @param src the source array.
  97. * @param srcOffset the offset into the source array.
  98. * @param dst the destination Buffer, its position is used as an offset.
  99. * @param numElements the number of elements to copy.
  100. */
  101. public static void copy (char[] src, int srcOffset, Buffer dst, int numElements) {
  102. copyJni(src, srcOffset << 1, dst, positionInBytes(dst), numElements << 1);
  103. dst.limit(dst.position() + bytesToElements(dst, numElements << 1));
  104. }
  105. /**
  106. * Copies the contents of src to dst, starting from src[srcOffset], copying numElements
  107. * elements. The {@link Buffer} instance's {@link Buffer#position()} is used to define
  108. * the offset into the Buffer itself. The position will stay the same, the limit will be
  109. * set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order.
  110. * No error checking is performed</b>.
  111. *
  112. * @param src the source array.
  113. * @param srcOffset the offset into the source array.
  114. * @param dst the destination Buffer, its position is used as an offset.
  115. * @param numElements the number of elements to copy.
  116. */
  117. public static void copy (int[] src, int srcOffset, Buffer dst, int numElements) {
  118. copyJni(src, srcOffset << 2, dst, positionInBytes(dst), numElements << 2);
  119. dst.limit(dst.position() + bytesToElements(dst, numElements << 2));
  120. }
  121. /**
  122. * Copies the contents of src to dst, starting from src[srcOffset], copying numElements
  123. * elements. The {@link Buffer} instance's {@link Buffer#position()} is used to define
  124. * the offset into the Buffer itself. The position will stay the same, the limit will be
  125. * set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order.
  126. * No error checking is performed</b>.
  127. *
  128. * @param src the source array.
  129. * @param srcOffset the offset into the source array.
  130. * @param dst the destination Buffer, its position is used as an offset.
  131. * @param numElements the number of elements to copy.
  132. */
  133. public static void copy (long[] src, int srcOffset, Buffer dst, int numElements) {
  134. copyJni(src, srcOffset << 3, dst, positionInBytes(dst), numElements << 3);
  135. dst.limit(dst.position() + bytesToElements(dst, numElements << 3));
  136. }
  137. /**
  138. * Copies the contents of src to dst, starting from src[srcOffset], copying numElements
  139. * elements. The {@link Buffer} instance's {@link Buffer#position()} is used to define
  140. * the offset into the Buffer itself. The position will stay the same, the limit will be
  141. * set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order.
  142. * No error checking is performed</b>.
  143. *
  144. * @param src the source array.
  145. * @param srcOffset the offset into the source array.
  146. * @param dst the destination Buffer, its position is used as an offset.
  147. * @param numElements the number of elements to copy.
  148. */
  149. public static void copy (float[] src, int srcOffset, Buffer dst, int numElements) {
  150. copyJni(src, srcOffset << 2, dst, positionInBytes(dst), numElements << 2);
  151. dst.limit(dst.position() + bytesToElements(dst, numElements << 2));
  152. }
  153. /**
  154. * Copies the contents of src to dst, starting from src[srcOffset], copying numElements
  155. * elements. The {@link Buffer} instance's {@link Buffer#position()} is used to define
  156. * the offset into the Buffer itself. The position will stay the same, the limit will be
  157. * set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order.
  158. * No error checking is performed</b>.
  159. *
  160. * @param src the source array.
  161. * @param srcOffset the offset into the source array.
  162. * @param dst the destination Buffer, its position is used as an offset.
  163. * @param numElements the number of elements to copy.
  164. */
  165. public static void copy (double[] src, int srcOffset, Buffer dst, int numElements) {
  166. copyJni(src, srcOffset << 3, dst, positionInBytes(dst), numElements << 3);
  167. dst.limit(dst.position() + bytesToElements(dst, numElements << 3));
  168. }
  169. /**
  170. * Copies the contents of src to dst, starting from the current position of src, copying
  171. * numElements elements (using the data type of src, no matter the datatype of dst). The
  172. * dst {@link Buffer#position()} is used as the writing offset. The position of both Buffers
  173. * will stay the same. The limit of the src Buffer will stay the same. The limit of the dst Buffer
  174. * will be set to dst.position() + numElements, where numElements are translated to the number of
  175. * elements appropriate for the dst Buffer data type. <b>The Buffers must be direct Buffers with native byte order.
  176. * No error checking is performed</b>.
  177. *
  178. * @param src the source Buffer.
  179. * @param dst the destination Buffer.
  180. * @param numElements the number of elements to copy.
  181. */
  182. public static void copy(Buffer src, Buffer dst, int numElements) {
  183. int numBytes = elementsToBytes(src, numElements);
  184. copyJni(src, positionInBytes(src), dst, positionInBytes(dst), numBytes);
  185. dst.limit(dst.position() + bytesToElements(dst, numBytes));
  186. }
  187. private static int positionInBytes(Buffer dst) {
  188. if(dst instanceof ByteBuffer) return dst.position();
  189. else if(dst instanceof ShortBuffer) return dst.position() << 1;
  190. else if(dst instanceof CharBuffer) return dst.position() << 1;
  191. else if(dst instanceof IntBuffer) return dst.position() << 2;
  192. else if(dst instanceof LongBuffer) return dst.position() << 3;
  193. else if(dst instanceof FloatBuffer) return dst.position() << 2;
  194. else if(dst instanceof DoubleBuffer) return dst.position() << 3;
  195. else throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
  196. }
  197. private static int bytesToElements(Buffer dst, int bytes) {
  198. if(dst instanceof ByteBuffer) return bytes;
  199. else if(dst instanceof ShortBuffer) return bytes >>> 1;
  200. else if(dst instanceof CharBuffer) return bytes >>> 1;
  201. else if(dst instanceof IntBuffer) return bytes >>> 2;
  202. else if(dst instanceof LongBuffer) return bytes >>> 3;
  203. else if(dst instanceof FloatBuffer) return bytes >>> 2;
  204. else if(dst instanceof DoubleBuffer) return bytes >>> 3;
  205. else throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
  206. }
  207. private static int elementsToBytes(Buffer dst, int elements) {
  208. if(dst instanceof ByteBuffer) return elements;
  209. else if(dst instanceof ShortBuffer) return elements << 1;
  210. else if(dst instanceof CharBuffer) return elements << 1;
  211. else if(dst instanceof IntBuffer) return elements << 2;
  212. else if(dst instanceof LongBuffer) return elements << 3;
  213. else if(dst instanceof FloatBuffer) return elements << 2;
  214. else if(dst instanceof DoubleBuffer) return elements << 3;
  215. else throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
  216. }
  217. private native static void copyJni (float[] src, Buffer dst, int numFloats, int offset) /*-{ }-*/;
  218. private native static void copyJni (byte[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes) /*-{ }-*/;
  219. private native static void copyJni (char[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes) /*-{ }-*/;
  220. private native static void copyJni (short[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes) /*-{ }-*/;
  221. private native static void copyJni (int[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes) /*-{ }-*/;
  222. private native static void copyJni (long[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes) /*-{ }-*/;
  223. private native static void copyJni (float[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes) /*-{ }-*/;
  224. private native static void copyJni (double[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes) /*-{ }-*/;
  225. private native static void copyJni (Buffer src, int srcOffset, Buffer dst, int dstOffset, int numBytes) /*-{ }-*/;
  226. public static FloatBuffer newFloatBuffer (int numFloats) {
  227. ByteBuffer buffer = ByteBuffer.allocateDirect(numFloats * 4);
  228. buffer.order(ByteOrder.nativeOrder());
  229. return buffer.asFloatBuffer();
  230. }
  231. public static DoubleBuffer newDoubleBuffer (int numDoubles) {
  232. ByteBuffer buffer = ByteBuffer.allocateDirect(numDoubles * 8);
  233. buffer.order(ByteOrder.nativeOrder());
  234. return buffer.asDoubleBuffer();
  235. }
  236. public static ByteBuffer newByteBuffer (int numBytes) {
  237. ByteBuffer buffer = ByteBuffer.allocateDirect(numBytes);
  238. buffer.order(ByteOrder.nativeOrder());
  239. return buffer;
  240. }
  241. public static ShortBuffer newShortBuffer (int numShorts) {
  242. ByteBuffer buffer = ByteBuffer.allocateDirect(numShorts * 2);
  243. buffer.order(ByteOrder.nativeOrder());
  244. return buffer.asShortBuffer();
  245. }
  246. public static CharBuffer newCharBuffer(int numChars) {
  247. ByteBuffer buffer = ByteBuffer.allocateDirect(numChars * 2);
  248. buffer.order(ByteOrder.nativeOrder());
  249. return buffer.asCharBuffer();
  250. }
  251. public static IntBuffer newIntBuffer (int numInts) {
  252. ByteBuffer buffer = ByteBuffer.allocateDirect(numInts * 4);
  253. buffer.order(ByteOrder.nativeOrder());
  254. return buffer.asIntBuffer();
  255. }
  256. public static LongBuffer newLongBuffer (int numLongs) {
  257. ByteBuffer buffer = ByteBuffer.allocateDirect(numLongs * 8);
  258. buffer.order(ByteOrder.nativeOrder());
  259. return buffer.asLongBuffer();
  260. }
  261. }