OSDN Git Service

[RenderScript] Allow copyTo(short[]) etc for Float16 Allocations
[android-x86/frameworks-base.git] / rs / java / android / renderscript / Allocation.java
1 /*
2  * Copyright (C) 2008-2012 The Android Open Source Project
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 android.renderscript;
18
19 import java.nio.ByteBuffer;
20 import java.util.HashMap;
21
22 import android.content.res.Resources;
23 import android.graphics.Bitmap;
24 import android.graphics.BitmapFactory;
25 import android.graphics.Canvas;
26 import android.os.Trace;
27 import android.util.Log;
28 import android.view.Surface;
29
30 /**
31  * <p> This class provides the primary method through which data is passed to
32  * and from RenderScript kernels.  An Allocation provides the backing store for
33  * a given {@link android.renderscript.Type}.  </p>
34  *
35  * <p>An Allocation also contains a set of usage flags that denote how the
36  * Allocation could be used. For example, an Allocation may have usage flags
37  * specifying that it can be used from a script as well as input to a {@link
38  * android.renderscript.Sampler}. A developer must synchronize across these
39  * different usages using {@link android.renderscript.Allocation#syncAll} in
40  * order to ensure that different users of the Allocation have a consistent view
41  * of memory. For example, in the case where an Allocation is used as the output
42  * of one kernel and as Sampler input in a later kernel, a developer must call
43  * {@link #syncAll syncAll(Allocation.USAGE_SCRIPT)} prior to launching the
44  * second kernel to ensure correctness.
45  *
46  * <p>An Allocation can be populated with the {@link #copyFrom} routines. For
47  * more complex Element types, the {@link #copyFromUnchecked} methods can be
48  * used to copy from byte arrays or similar constructs.</p>
49  *
50  * <div class="special reference">
51  * <h3>Developer Guides</h3>
52  * <p>For more information about creating an application that uses RenderScript, read the
53  * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
54  * </div>
55  **/
56
57 public class Allocation extends BaseObj {
58     private static final int MAX_NUMBER_IO_INPUT_ALLOC = 16;
59
60     Type mType;
61     Bitmap mBitmap;
62     int mUsage;
63     Allocation mAdaptedAllocation;
64     int mSize;
65     MipmapControl mMipmapControl;
66
67     long mTimeStamp = -1;
68     boolean mReadAllowed = true;
69     boolean mWriteAllowed = true;
70     boolean mAutoPadding = false;
71     int mSelectedX;
72     int mSelectedY;
73     int mSelectedZ;
74     int mSelectedLOD;
75     int mSelectedArray[];
76     Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
77
78     int mCurrentDimX;
79     int mCurrentDimY;
80     int mCurrentDimZ;
81     int mCurrentCount;
82     static HashMap<Long, Allocation> mAllocationMap =
83             new HashMap<Long, Allocation>();
84     OnBufferAvailableListener mBufferNotifier;
85
86     private Surface mGetSurfaceSurface = null;
87     private ByteBuffer mByteBuffer = null;
88     private long mByteBufferStride = -1;
89
90     private Element.DataType validateObjectIsPrimitiveArray(Object d, boolean checkType) {
91         final Class c = d.getClass();
92         if (!c.isArray()) {
93             throw new RSIllegalArgumentException("Object passed is not an array of primitives.");
94         }
95         final Class cmp = c.getComponentType();
96         if (!cmp.isPrimitive()) {
97             throw new RSIllegalArgumentException("Object passed is not an Array of primitives.");
98         }
99
100         if (cmp == Long.TYPE) {
101             if (checkType) {
102                 validateIsInt64();
103                 return mType.mElement.mType;
104             }
105             return Element.DataType.SIGNED_64;
106         }
107
108         if (cmp == Integer.TYPE) {
109             if (checkType) {
110                 validateIsInt32();
111                 return mType.mElement.mType;
112             }
113             return Element.DataType.SIGNED_32;
114         }
115
116         if (cmp == Short.TYPE) {
117             if (checkType) {
118                 validateIsInt16OrFloat16();
119                 return mType.mElement.mType;
120             }
121             return Element.DataType.SIGNED_16;
122         }
123
124         if (cmp == Byte.TYPE) {
125             if (checkType) {
126                 validateIsInt8();
127                 return mType.mElement.mType;
128             }
129             return Element.DataType.SIGNED_8;
130         }
131
132         if (cmp == Float.TYPE) {
133             if (checkType) {
134                 validateIsFloat32();
135             }
136             return Element.DataType.FLOAT_32;
137         }
138
139         if (cmp == Double.TYPE) {
140             if (checkType) {
141                 validateIsFloat64();
142             }
143             return Element.DataType.FLOAT_64;
144         }
145         return null;
146     }
147
148
149     /**
150      * The usage of the Allocation.  These signal to RenderScript where to place
151      * the Allocation in memory.
152      *
153      */
154
155     /**
156      * The Allocation will be bound to and accessed by scripts.
157      */
158     public static final int USAGE_SCRIPT = 0x0001;
159
160     /**
161      * The Allocation will be used as a texture source by one or more graphics
162      * programs.
163      *
164      */
165     public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
166
167     /**
168      * The Allocation will be used as a graphics mesh.
169      *
170      * This was deprecated in API level 16.
171      *
172      */
173     public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
174
175
176     /**
177      * The Allocation will be used as the source of shader constants by one or
178      * more programs.
179      *
180      * This was deprecated in API level 16.
181      *
182      */
183     public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
184
185     /**
186      * The Allocation will be used as a target for offscreen rendering
187      *
188      * This was deprecated in API level 16.
189      *
190      */
191     public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
192
193     /**
194      * The Allocation will be used as a {@link android.view.Surface}
195      * consumer.  This usage will cause the Allocation to be created
196      * as read-only.
197      *
198      */
199     public static final int USAGE_IO_INPUT = 0x0020;
200
201     /**
202      * The Allocation will be used as a {@link android.view.Surface}
203      * producer.  The dimensions and format of the {@link
204      * android.view.Surface} will be forced to those of the
205      * Allocation.
206      *
207      */
208     public static final int USAGE_IO_OUTPUT = 0x0040;
209
210     /**
211      * The Allocation's backing store will be inherited from another object
212      * (usually a {@link android.graphics.Bitmap}); copying to or from the
213      * original source Bitmap will cause a synchronization rather than a full
214      * copy.  {@link #syncAll} may also be used to synchronize the Allocation
215      * and the source Bitmap.
216      *
217      * <p>This is set by default for allocations created with {@link
218      * #createFromBitmap} in API version 18 and higher.</p>
219      *
220      */
221     public static final int USAGE_SHARED = 0x0080;
222
223     /**
224      * Controls mipmap behavior when using the bitmap creation and update
225      * functions.
226      */
227     public enum MipmapControl {
228         /**
229          * No mipmaps will be generated and the type generated from the incoming
230          * bitmap will not contain additional LODs.
231          */
232         MIPMAP_NONE(0),
233
234         /**
235          * A full mipmap chain will be created in script memory.  The Type of
236          * the Allocation will contain a full mipmap chain.  On upload, the full
237          * chain will be transferred.
238          */
239         MIPMAP_FULL(1),
240
241         /**
242          * The Type of the Allocation will be the same as MIPMAP_NONE.  It will
243          * not contain mipmaps.  On upload, the allocation data will contain a
244          * full mipmap chain generated from the top level in script memory.
245          */
246         MIPMAP_ON_SYNC_TO_TEXTURE(2);
247
248         int mID;
249         MipmapControl(int id) {
250             mID = id;
251         }
252     }
253
254
255     private long getIDSafe() {
256         if (mAdaptedAllocation != null) {
257             return mAdaptedAllocation.getID(mRS);
258         }
259         return getID(mRS);
260     }
261
262
263    /**
264      * Get the {@link android.renderscript.Element} of the {@link
265      * android.renderscript.Type} of the Allocation.
266      *
267      * @return Element
268      *
269      */
270     public Element getElement() {
271         return mType.getElement();
272     }
273
274     /**
275      * Get the usage flags of the Allocation.
276      *
277      * @return usage this Allocation's set of the USAGE_* flags OR'd together
278      *
279      */
280     public int getUsage() {
281         return mUsage;
282     }
283
284     /**
285      * @hide
286      * Get the Mipmap control flag of the Allocation.
287      *
288      * @return the Mipmap control flag of the Allocation
289      *
290      */
291     public MipmapControl getMipmap() {
292         return mMipmapControl;
293     }
294
295     /**
296      * Enable/Disable AutoPadding for Vec3 elements.
297      * By default: Diabled.
298      *
299      * @param useAutoPadding True: enable AutoPadding; False: disable AutoPadding
300      *
301      */
302     public void setAutoPadding(boolean useAutoPadding) {
303         mAutoPadding = useAutoPadding;
304     }
305
306     /**
307      * Get the size of the Allocation in bytes.
308      *
309      * @return size of the Allocation in bytes.
310      *
311      */
312     public int getBytesSize() {
313         if (mType.mDimYuv != 0) {
314             return (int)Math.ceil(mType.getCount() * mType.getElement().getBytesSize() * 1.5);
315         }
316         return mType.getCount() * mType.getElement().getBytesSize();
317     }
318
319     private void updateCacheInfo(Type t) {
320         mCurrentDimX = t.getX();
321         mCurrentDimY = t.getY();
322         mCurrentDimZ = t.getZ();
323         mCurrentCount = mCurrentDimX;
324         if (mCurrentDimY > 1) {
325             mCurrentCount *= mCurrentDimY;
326         }
327         if (mCurrentDimZ > 1) {
328             mCurrentCount *= mCurrentDimZ;
329         }
330     }
331
332     private void setBitmap(Bitmap b) {
333         mBitmap = b;
334     }
335
336     Allocation(long id, RenderScript rs, Type t, int usage) {
337         super(id, rs);
338         if ((usage & ~(USAGE_SCRIPT |
339                        USAGE_GRAPHICS_TEXTURE |
340                        USAGE_GRAPHICS_VERTEX |
341                        USAGE_GRAPHICS_CONSTANTS |
342                        USAGE_GRAPHICS_RENDER_TARGET |
343                        USAGE_IO_INPUT |
344                        USAGE_IO_OUTPUT |
345                        USAGE_SHARED)) != 0) {
346             throw new RSIllegalArgumentException("Unknown usage specified.");
347         }
348
349         if ((usage & USAGE_IO_INPUT) != 0) {
350             mWriteAllowed = false;
351
352             if ((usage & ~(USAGE_IO_INPUT |
353                            USAGE_GRAPHICS_TEXTURE |
354                            USAGE_SCRIPT)) != 0) {
355                 throw new RSIllegalArgumentException("Invalid usage combination.");
356             }
357         }
358
359         mType = t;
360         mUsage = usage;
361
362         if (t != null) {
363             // TODO: A3D doesn't have Type info during creation, so we can't
364             // calculate the size ahead of time. We can possibly add a method
365             // to update the size in the future if it seems reasonable.
366             mSize = mType.getCount() * mType.getElement().getBytesSize();
367             updateCacheInfo(t);
368         }
369         try {
370             RenderScript.registerNativeAllocation.invoke(RenderScript.sRuntime, mSize);
371         } catch (Exception e) {
372             Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e);
373             throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e);
374         }
375     }
376
377     Allocation(long id, RenderScript rs, Type t, int usage, MipmapControl mips) {
378         this(id, rs, t, usage);
379         mMipmapControl = mips;
380     }
381
382     protected void finalize() throws Throwable {
383         RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
384         super.finalize();
385     }
386
387     private void validateIsInt64() {
388         if ((mType.mElement.mType == Element.DataType.SIGNED_64) ||
389             (mType.mElement.mType == Element.DataType.UNSIGNED_64)) {
390             return;
391         }
392         throw new RSIllegalArgumentException(
393             "64 bit integer source does not match allocation type " + mType.mElement.mType);
394     }
395
396     private void validateIsInt32() {
397         if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
398             (mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
399             return;
400         }
401         throw new RSIllegalArgumentException(
402             "32 bit integer source does not match allocation type " + mType.mElement.mType);
403     }
404
405     private void validateIsInt16OrFloat16() {
406         if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
407             (mType.mElement.mType == Element.DataType.UNSIGNED_16) ||
408             (mType.mElement.mType == Element.DataType.FLOAT_16)) {
409             return;
410         }
411         throw new RSIllegalArgumentException(
412             "16 bit integer source does not match allocation type " + mType.mElement.mType);
413     }
414
415     private void validateIsInt8() {
416         if ((mType.mElement.mType == Element.DataType.SIGNED_8) ||
417             (mType.mElement.mType == Element.DataType.UNSIGNED_8)) {
418             return;
419         }
420         throw new RSIllegalArgumentException(
421             "8 bit integer source does not match allocation type " + mType.mElement.mType);
422     }
423
424     private void validateIsFloat32() {
425         if (mType.mElement.mType == Element.DataType.FLOAT_32) {
426             return;
427         }
428         throw new RSIllegalArgumentException(
429             "32 bit float source does not match allocation type " + mType.mElement.mType);
430     }
431
432     private void validateIsFloat64() {
433         if (mType.mElement.mType == Element.DataType.FLOAT_64) {
434             return;
435         }
436         throw new RSIllegalArgumentException(
437             "64 bit float source does not match allocation type " + mType.mElement.mType);
438     }
439
440     private void validateIsObject() {
441         if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) ||
442             (mType.mElement.mType == Element.DataType.RS_TYPE) ||
443             (mType.mElement.mType == Element.DataType.RS_ALLOCATION) ||
444             (mType.mElement.mType == Element.DataType.RS_SAMPLER) ||
445             (mType.mElement.mType == Element.DataType.RS_SCRIPT) ||
446             (mType.mElement.mType == Element.DataType.RS_MESH) ||
447             (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) ||
448             (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) ||
449             (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) ||
450             (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) {
451             return;
452         }
453         throw new RSIllegalArgumentException(
454             "Object source does not match allocation type " + mType.mElement.mType);
455     }
456
457     @Override
458     void updateFromNative() {
459         super.updateFromNative();
460         long typeID = mRS.nAllocationGetType(getID(mRS));
461         if(typeID != 0) {
462             mType = new Type(typeID, mRS);
463             mType.updateFromNative();
464             updateCacheInfo(mType);
465         }
466     }
467
468     /**
469      * Get the {@link android.renderscript.Type} of the Allocation.
470      *
471      * @return Type
472      *
473      */
474     public Type getType() {
475         return mType;
476     }
477
478     /**
479      * Propagate changes from one usage of the Allocation to the
480      * other usages of the Allocation.
481      *
482      */
483     public void syncAll(int srcLocation) {
484         try {
485             Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll");
486             switch (srcLocation) {
487                 case USAGE_GRAPHICS_TEXTURE:
488                 case USAGE_SCRIPT:
489                     if ((mUsage & USAGE_SHARED) != 0) {
490                         copyFrom(mBitmap);
491                     }
492                     break;
493                 case USAGE_GRAPHICS_CONSTANTS:
494                 case USAGE_GRAPHICS_VERTEX:
495                     break;
496                 case USAGE_SHARED:
497                     if ((mUsage & USAGE_SHARED) != 0) {
498                         copyTo(mBitmap);
499                     }
500                     break;
501                 default:
502                     throw new RSIllegalArgumentException("Source must be exactly one usage type.");
503             }
504             mRS.validate();
505             mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
506         } finally {
507             Trace.traceEnd(RenderScript.TRACE_TAG);
508         }
509     }
510
511     /**
512      * Send a buffer to the output stream.  The contents of the Allocation will
513      * be undefined after this operation. This operation is only valid if {@link
514      * #USAGE_IO_OUTPUT} is set on the Allocation.
515      *
516      *
517      */
518     public void ioSend() {
519         try {
520             Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend");
521             if ((mUsage & USAGE_IO_OUTPUT) == 0) {
522                 throw new RSIllegalArgumentException(
523                     "Can only send buffer if IO_OUTPUT usage specified.");
524             }
525             mRS.validate();
526             mRS.nAllocationIoSend(getID(mRS));
527         } finally {
528             Trace.traceEnd(RenderScript.TRACE_TAG);
529         }
530     }
531
532     /**
533      * Receive the latest input into the Allocation. This operation
534      * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation.
535      *
536      */
537     public void ioReceive() {
538         try {
539             Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive");
540             if ((mUsage & USAGE_IO_INPUT) == 0) {
541                 throw new RSIllegalArgumentException(
542                     "Can only receive if IO_INPUT usage specified.");
543             }
544             mRS.validate();
545             mTimeStamp = mRS.nAllocationIoReceive(getID(mRS));
546         } finally {
547             Trace.traceEnd(RenderScript.TRACE_TAG);
548         }
549     }
550
551     /**
552      * Copy an array of RS objects to the Allocation.
553      *
554      * @param d Source array.
555      */
556     public void copyFrom(BaseObj[] d) {
557         try {
558             Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
559             mRS.validate();
560             validateIsObject();
561             if (d.length != mCurrentCount) {
562                 throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
563                                                       mCurrentCount + ", array length = " + d.length);
564             }
565
566             if (RenderScript.sPointerSize == 8) {
567                 long i[] = new long[d.length * 4];
568                 for (int ct=0; ct < d.length; ct++) {
569                     i[ct * 4] = d[ct].getID(mRS);
570                 }
571                 copy1DRangeFromUnchecked(0, mCurrentCount, i);
572             } else {
573                 int i[] = new int[d.length];
574                 for (int ct=0; ct < d.length; ct++) {
575                     i[ct] = (int) d[ct].getID(mRS);
576                 }
577                 copy1DRangeFromUnchecked(0, mCurrentCount, i);
578             }
579         } finally {
580             Trace.traceEnd(RenderScript.TRACE_TAG);
581         }
582     }
583
584     private void validateBitmapFormat(Bitmap b) {
585         Bitmap.Config bc = b.getConfig();
586         if (bc == null) {
587             throw new RSIllegalArgumentException("Bitmap has an unsupported format for this operation");
588         }
589         switch (bc) {
590         case ALPHA_8:
591             if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
592                 throw new RSIllegalArgumentException("Allocation kind is " +
593                                                      mType.getElement().mKind + ", type " +
594                                                      mType.getElement().mType +
595                                                      " of " + mType.getElement().getBytesSize() +
596                                                      " bytes, passed bitmap was " + bc);
597             }
598             break;
599         case ARGB_8888:
600             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
601                 (mType.getElement().getBytesSize() != 4)) {
602                 throw new RSIllegalArgumentException("Allocation kind is " +
603                                                      mType.getElement().mKind + ", type " +
604                                                      mType.getElement().mType +
605                                                      " of " + mType.getElement().getBytesSize() +
606                                                      " bytes, passed bitmap was " + bc);
607             }
608             break;
609         case RGB_565:
610             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
611                 (mType.getElement().getBytesSize() != 2)) {
612                 throw new RSIllegalArgumentException("Allocation kind is " +
613                                                      mType.getElement().mKind + ", type " +
614                                                      mType.getElement().mType +
615                                                      " of " + mType.getElement().getBytesSize() +
616                                                      " bytes, passed bitmap was " + bc);
617             }
618             break;
619         case ARGB_4444:
620             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
621                 (mType.getElement().getBytesSize() != 2)) {
622                 throw new RSIllegalArgumentException("Allocation kind is " +
623                                                      mType.getElement().mKind + ", type " +
624                                                      mType.getElement().mType +
625                                                      " of " + mType.getElement().getBytesSize() +
626                                                      " bytes, passed bitmap was " + bc);
627             }
628             break;
629
630         }
631     }
632
633     private void validateBitmapSize(Bitmap b) {
634         if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) {
635             throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
636         }
637     }
638
639     private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
640         try {
641             Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
642             mRS.validate();
643             if (mCurrentDimZ > 0) {
644                 copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
645             } else if (mCurrentDimY > 0) {
646                 copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
647             } else {
648                 copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
649             }
650         } finally {
651             Trace.traceEnd(RenderScript.TRACE_TAG);
652         }
653     }
654
655     /**
656      * Copy into this Allocation from an array. This method does not guarantee
657      * that the Allocation is compatible with the input buffer; it copies memory
658      * without reinterpretation.
659      *
660      * @param array The source data array
661      */
662     public void copyFromUnchecked(Object array) {
663         try {
664             Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
665             copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
666                               java.lang.reflect.Array.getLength(array));
667         } finally {
668             Trace.traceEnd(RenderScript.TRACE_TAG);
669         }
670     }
671
672     /**
673      * Copy into this Allocation from an array. This method does not guarantee
674      * that the Allocation is compatible with the input buffer; it copies memory
675      * without reinterpretation.
676      *
677      * @param d the source data array
678      */
679     public void copyFromUnchecked(int[] d) {
680         copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
681     }
682
683     /**
684      * Copy into this Allocation from an array. This method does not guarantee
685      * that the Allocation is compatible with the input buffer; it copies memory
686      * without reinterpretation.
687      *
688      * @param d the source data array
689      */
690     public void copyFromUnchecked(short[] d) {
691         copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
692     }
693
694     /**
695      * Copy into this Allocation from an array. This method does not guarantee
696      * that the Allocation is compatible with the input buffer; it copies memory
697      * without reinterpretation.
698      *
699      * @param d the source data array
700      */
701     public void copyFromUnchecked(byte[] d) {
702         copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
703     }
704
705     /**
706      * Copy into this Allocation from an array. This method does not guarantee
707      * that the Allocation is compatible with the input buffer; it copies memory
708      * without reinterpretation.
709      *
710      * @param d the source data array
711      */
712     public void copyFromUnchecked(float[] d) {
713         copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
714     }
715
716
717     /**
718      * Copy into this Allocation from an array.  This variant is type checked
719      * and will generate exceptions if the Allocation's {@link
720      * android.renderscript.Element} does not match the array's
721      * primitive type.
722      *
723      * @param array The source data array
724      */
725     public void copyFrom(Object array) {
726         try {
727             Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
728             copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
729                               java.lang.reflect.Array.getLength(array));
730         } finally {
731             Trace.traceEnd(RenderScript.TRACE_TAG);
732         }
733     }
734
735     /**
736      * Copy into this Allocation from an array.  This variant is type checked
737      * and will generate exceptions if the Allocation's {@link
738      * android.renderscript.Element} is not a 32 bit integer type.
739      *
740      * @param d the source data array
741      */
742     public void copyFrom(int[] d) {
743         validateIsInt32();
744         copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
745     }
746
747     /**
748      * Copy into this Allocation from an array.  This variant is type checked
749      * and will generate exceptions if the Allocation's {@link
750      * android.renderscript.Element} is not a 16 bit integer type.
751      *
752      * @param d the source data array
753      */
754     public void copyFrom(short[] d) {
755         validateIsInt16OrFloat16();
756         copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
757     }
758
759     /**
760      * Copy into this Allocation from an array.  This variant is type checked
761      * and will generate exceptions if the Allocation's {@link
762      * android.renderscript.Element} is not an 8 bit integer type.
763      *
764      * @param d the source data array
765      */
766     public void copyFrom(byte[] d) {
767         validateIsInt8();
768         copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
769     }
770
771     /**
772      * Copy into this Allocation from an array.  This variant is type checked
773      * and will generate exceptions if the Allocation's {@link
774      * android.renderscript.Element} is not a 32 bit float type.
775      *
776      * @param d the source data array
777      */
778     public void copyFrom(float[] d) {
779         validateIsFloat32();
780         copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
781     }
782
783     /**
784      * Copy into an Allocation from a {@link android.graphics.Bitmap}.  The
785      * height, width, and format of the bitmap must match the existing
786      * allocation.
787      *
788      * <p>If the {@link android.graphics.Bitmap} is the same as the {@link
789      * android.graphics.Bitmap} used to create the Allocation with {@link
790      * #createFromBitmap} and {@link #USAGE_SHARED} is set on the Allocation,
791      * this will synchronize the Allocation with the latest data from the {@link
792      * android.graphics.Bitmap}, potentially avoiding the actual copy.</p>
793      *
794      * @param b the source bitmap
795      */
796     public void copyFrom(Bitmap b) {
797         try {
798             Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
799             mRS.validate();
800             if (b.getConfig() == null) {
801                 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
802                 Canvas c = new Canvas(newBitmap);
803                 c.drawBitmap(b, 0, 0, null);
804                 copyFrom(newBitmap);
805                 return;
806             }
807             validateBitmapSize(b);
808             validateBitmapFormat(b);
809             mRS.nAllocationCopyFromBitmap(getID(mRS), b);
810         } finally {
811             Trace.traceEnd(RenderScript.TRACE_TAG);
812         }
813     }
814
815     /**
816      * Copy an Allocation from an Allocation.  The types of both allocations
817      * must be identical.
818      *
819      * @param a the source allocation
820      */
821     public void copyFrom(Allocation a) {
822         try {
823             Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
824             mRS.validate();
825             if (!mType.equals(a.getType())) {
826                 throw new RSIllegalArgumentException("Types of allocations must match.");
827             }
828             copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
829         } finally {
830             Trace.traceEnd(RenderScript.TRACE_TAG);
831         }
832     }
833
834     /**
835      * This is only intended to be used by auto-generated code reflected from
836      * the RenderScript script files and should not be used by developers.
837      *
838      * @param xoff
839      * @param fp
840      */
841     public void setFromFieldPacker(int xoff, FieldPacker fp) {
842         mRS.validate();
843         int eSize = mType.mElement.getBytesSize();
844         final byte[] data = fp.getData();
845         int data_length = fp.getPos();
846
847         int count = data_length / eSize;
848         if ((eSize * count) != data_length) {
849             throw new RSIllegalArgumentException("Field packer length " + data_length +
850                                                " not divisible by element size " + eSize + ".");
851         }
852         copy1DRangeFromUnchecked(xoff, count, data);
853     }
854
855
856     /**
857      * This is only intended to be used by auto-generated code reflected from
858      * the RenderScript script files and should not be used by developers.
859      *
860      * @param xoff
861      * @param component_number
862      * @param fp
863      */
864     public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
865         setFromFieldPacker(xoff, 0, 0, component_number, fp);
866     }
867
868     /**
869      * This is only intended to be used by auto-generated code reflected from
870      * the RenderScript script files and should not be used by developers.
871      *
872      * @param xoff
873      * @param yoff
874      * @param zoff
875      * @param component_number
876      * @param fp
877      */
878     public void setFromFieldPacker(int xoff, int yoff, int zoff, int component_number, FieldPacker fp) {
879         mRS.validate();
880         if (component_number >= mType.mElement.mElements.length) {
881             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
882         }
883         if(xoff < 0) {
884             throw new RSIllegalArgumentException("Offset x must be >= 0.");
885         }
886         if(yoff < 0) {
887             throw new RSIllegalArgumentException("Offset y must be >= 0.");
888         }
889         if(zoff < 0) {
890             throw new RSIllegalArgumentException("Offset z must be >= 0.");
891         }
892
893         final byte[] data = fp.getData();
894         int data_length = fp.getPos();
895         int eSize = mType.mElement.mElements[component_number].getBytesSize();
896         eSize *= mType.mElement.mArraySizes[component_number];
897
898         if (data_length != eSize) {
899             throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
900                                                " does not match component size " + eSize + ".");
901         }
902
903         mRS.nAllocationElementData(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
904                                    component_number, data, data_length);
905     }
906
907     private void data1DChecks(int off, int count, int len, int dataSize, boolean usePadding) {
908         mRS.validate();
909         if(off < 0) {
910             throw new RSIllegalArgumentException("Offset must be >= 0.");
911         }
912         if(count < 1) {
913             throw new RSIllegalArgumentException("Count must be >= 1.");
914         }
915         if((off + count) > mCurrentCount) {
916             throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
917                                                ", got " + count + " at offset " + off + ".");
918         }
919         if(usePadding) {
920             if(len < dataSize / 4 * 3) {
921                 throw new RSIllegalArgumentException("Array too small for allocation type.");
922             }
923         } else {
924             if(len < dataSize) {
925                 throw new RSIllegalArgumentException("Array too small for allocation type.");
926             }
927         }
928     }
929
930     /**
931      * Generate a mipmap chain. This is only valid if the Type of the Allocation
932      * includes mipmaps.
933      *
934      * <p>This function will generate a complete set of mipmaps from the top
935      * level LOD and place them into the script memory space.</p>
936      *
937      * <p>If the Allocation is also using other memory spaces, a call to {@link
938      * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p>
939      */
940     public void generateMipmaps() {
941         mRS.nAllocationGenerateMipmaps(getID(mRS));
942     }
943
944     private void copy1DRangeFromUnchecked(int off, int count, Object array,
945                                           Element.DataType dt, int arrayLen) {
946         try {
947             Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
948             final int dataSize = mType.mElement.getBytesSize() * count;
949             // AutoPadding for Vec3 Element
950             boolean usePadding = false;
951             if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
952                 usePadding = true;
953             }
954             data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
955             mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
956                                   mType.mElement.mType.mSize, usePadding);
957         } finally {
958             Trace.traceEnd(RenderScript.TRACE_TAG);
959         }
960     }
961
962     /**
963      * Copy an array into part of this Allocation.  This method does not
964      * guarantee that the Allocation is compatible with the input buffer.
965      *
966      * @param off The offset of the first element to be copied.
967      * @param count The number of elements to be copied.
968      * @param array The source data array
969      */
970     public void copy1DRangeFromUnchecked(int off, int count, Object array) {
971         copy1DRangeFromUnchecked(off, count, array,
972                                  validateObjectIsPrimitiveArray(array, false),
973                                  java.lang.reflect.Array.getLength(array));
974     }
975
976     /**
977      * Copy an array into part of this Allocation.  This method does not
978      * guarantee that the Allocation is compatible with the input buffer.
979      *
980      * @param off The offset of the first element to be copied.
981      * @param count The number of elements to be copied.
982      * @param d the source data array
983      */
984     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
985         copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
986     }
987
988     /**
989      * Copy an array into part of this Allocation.  This method does not
990      * guarantee that the Allocation is compatible with the input buffer.
991      *
992      * @param off The offset of the first element to be copied.
993      * @param count The number of elements to be copied.
994      * @param d the source data array
995      */
996     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
997         copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
998     }
999
1000     /**
1001      * Copy an array into part of this Allocation.  This method does not
1002      * guarantee that the Allocation is compatible with the input buffer.
1003      *
1004      * @param off The offset of the first element to be copied.
1005      * @param count The number of elements to be copied.
1006      * @param d the source data array
1007      */
1008     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
1009         copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
1010     }
1011
1012     /**
1013      * Copy an array into part of this Allocation.  This method does not
1014      * guarantee that the Allocation is compatible with the input buffer.
1015      *
1016      * @param off The offset of the first element to be copied.
1017      * @param count The number of elements to be copied.
1018      * @param d the source data array
1019      */
1020     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
1021         copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
1022     }
1023
1024
1025     /**
1026      * Copy an array into part of this Allocation.  This variant is type checked
1027      * and will generate exceptions if the Allocation type does not
1028      * match the component type of the array passed in.
1029      *
1030      * @param off The offset of the first element to be copied.
1031      * @param count The number of elements to be copied.
1032      * @param array The source data array.
1033      */
1034     public void copy1DRangeFrom(int off, int count, Object array) {
1035         copy1DRangeFromUnchecked(off, count, array,
1036                                  validateObjectIsPrimitiveArray(array, true),
1037                                  java.lang.reflect.Array.getLength(array));
1038     }
1039
1040     /**
1041      * Copy an array into part of this Allocation.  This variant is type checked
1042      * and will generate exceptions if the Allocation type is not a 32 bit
1043      * integer type.
1044      *
1045      * @param off The offset of the first element to be copied.
1046      * @param count The number of elements to be copied.
1047      * @param d the source data array
1048      */
1049     public void copy1DRangeFrom(int off, int count, int[] d) {
1050         validateIsInt32();
1051         copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
1052     }
1053
1054     /**
1055      * Copy an array into part of this Allocation.  This variant is type checked
1056      * and will generate exceptions if the Allocation type is not a 16 bit
1057      * integer type.
1058      *
1059      * @param off The offset of the first element to be copied.
1060      * @param count The number of elements to be copied.
1061      * @param d the source data array
1062      */
1063     public void copy1DRangeFrom(int off, int count, short[] d) {
1064         validateIsInt16OrFloat16();
1065         copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
1066     }
1067
1068     /**
1069      * Copy an array into part of this Allocation.  This variant is type checked
1070      * and will generate exceptions if the Allocation type is not an 8 bit
1071      * integer type.
1072      *
1073      * @param off The offset of the first element to be copied.
1074      * @param count The number of elements to be copied.
1075      * @param d the source data array
1076      */
1077     public void copy1DRangeFrom(int off, int count, byte[] d) {
1078         validateIsInt8();
1079         copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
1080     }
1081
1082     /**
1083      * Copy an array into part of this Allocation.  This variant is type checked
1084      * and will generate exceptions if the Allocation type is not a 32 bit float
1085      * type.
1086      *
1087      * @param off The offset of the first element to be copied.
1088      * @param count The number of elements to be copied.
1089      * @param d the source data array.
1090      */
1091     public void copy1DRangeFrom(int off, int count, float[] d) {
1092         validateIsFloat32();
1093         copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
1094     }
1095
1096      /**
1097      * Copy part of an Allocation into this Allocation.
1098      *
1099      * @param off The offset of the first element to be copied.
1100      * @param count The number of elements to be copied.
1101      * @param data the source data allocation.
1102      * @param dataOff off The offset of the first element in data to
1103      *          be copied.
1104      */
1105     public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
1106         Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
1107         mRS.nAllocationData2D(getIDSafe(), off, 0,
1108                               mSelectedLOD, mSelectedFace.mID,
1109                               count, 1, data.getID(mRS), dataOff, 0,
1110                               data.mSelectedLOD, data.mSelectedFace.mID);
1111         Trace.traceEnd(RenderScript.TRACE_TAG);
1112     }
1113
1114     private void validate2DRange(int xoff, int yoff, int w, int h) {
1115         if (mAdaptedAllocation != null) {
1116
1117         } else {
1118
1119             if (xoff < 0 || yoff < 0) {
1120                 throw new RSIllegalArgumentException("Offset cannot be negative.");
1121             }
1122             if (h < 0 || w < 0) {
1123                 throw new RSIllegalArgumentException("Height or width cannot be negative.");
1124             }
1125             if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
1126                 throw new RSIllegalArgumentException("Updated region larger than allocation.");
1127             }
1128         }
1129     }
1130
1131     void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array,
1132                                   Element.DataType dt, int arrayLen) {
1133         try {
1134             Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
1135             mRS.validate();
1136             validate2DRange(xoff, yoff, w, h);
1137             final int dataSize = mType.mElement.getBytesSize() * w * h;
1138             // AutoPadding for Vec3 Element
1139             boolean usePadding = false;
1140             int sizeBytes = arrayLen * dt.mSize;
1141             if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1142                 if (dataSize / 4 * 3 > sizeBytes) {
1143                     throw new RSIllegalArgumentException("Array too small for allocation type.");
1144                 }
1145                 usePadding = true;
1146                 sizeBytes = dataSize;
1147             } else {
1148                 if (dataSize > sizeBytes) {
1149                     throw new RSIllegalArgumentException("Array too small for allocation type.");
1150                 }
1151             }
1152             mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
1153                                   array, sizeBytes, dt,
1154                                   mType.mElement.mType.mSize, usePadding);
1155         } finally {
1156             Trace.traceEnd(RenderScript.TRACE_TAG);
1157         }
1158     }
1159
1160     /**
1161      * Copy from an array into a rectangular region in this Allocation.  The
1162      * array is assumed to be tightly packed.
1163      *
1164      * @param xoff X offset of the region to update in this Allocation
1165      * @param yoff Y offset of the region to update in this Allocation
1166      * @param w Width of the region to update
1167      * @param h Height of the region to update
1168      * @param array Data to be placed into the Allocation
1169      */
1170     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) {
1171         try {
1172             Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1173             copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
1174                                      validateObjectIsPrimitiveArray(array, true),
1175                                      java.lang.reflect.Array.getLength(array));
1176         } finally {
1177             Trace.traceEnd(RenderScript.TRACE_TAG);
1178         }
1179     }
1180
1181     /**
1182      * Copy from an array into a rectangular region in this Allocation.  The
1183      * array is assumed to be tightly packed.
1184      *
1185      * @param xoff X offset of the region to update in this Allocation
1186      * @param yoff Y offset of the region to update in this Allocation
1187      * @param w Width of the region to update
1188      * @param h Height of the region to update
1189      * @param data to be placed into the Allocation
1190      */
1191     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
1192         validateIsInt8();
1193         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1194                                  Element.DataType.SIGNED_8, data.length);
1195     }
1196
1197     /**
1198      * Copy from an array into a rectangular region in this Allocation.  The
1199      * array is assumed to be tightly packed.
1200      *
1201      * @param xoff X offset of the region to update in this Allocation
1202      * @param yoff Y offset of the region to update in this Allocation
1203      * @param w Width of the region to update
1204      * @param h Height of the region to update
1205      * @param data to be placed into the Allocation
1206      */
1207     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
1208         validateIsInt16OrFloat16();
1209         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1210                                  Element.DataType.SIGNED_16, data.length);
1211     }
1212
1213     /**
1214      * Copy from an array into a rectangular region in this Allocation.  The
1215      * array is assumed to be tightly packed.
1216      *
1217      * @param xoff X offset of the region to update in this Allocation
1218      * @param yoff Y offset of the region to update in this Allocation
1219      * @param w Width of the region to update
1220      * @param h Height of the region to update
1221      * @param data to be placed into the Allocation
1222      */
1223     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
1224         validateIsInt32();
1225         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1226                                  Element.DataType.SIGNED_32, data.length);
1227     }
1228
1229     /**
1230      * Copy from an array into a rectangular region in this Allocation.  The
1231      * array is assumed to be tightly packed.
1232      *
1233      * @param xoff X offset of the region to update in this Allocation
1234      * @param yoff Y offset of the region to update in this Allocation
1235      * @param w Width of the region to update
1236      * @param h Height of the region to update
1237      * @param data to be placed into the Allocation
1238      */
1239     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
1240         validateIsFloat32();
1241         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1242                                  Element.DataType.FLOAT_32, data.length);
1243     }
1244
1245     /**
1246      * Copy a rectangular region from an Allocation into a rectangular region in
1247      * this Allocation.
1248      *
1249      * @param xoff X offset of the region in this Allocation
1250      * @param yoff Y offset of the region in this Allocation
1251      * @param w Width of the region to update.
1252      * @param h Height of the region to update.
1253      * @param data source Allocation.
1254      * @param dataXoff X offset in source Allocation
1255      * @param dataYoff Y offset in source Allocation
1256      */
1257     public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
1258                                 Allocation data, int dataXoff, int dataYoff) {
1259         try {
1260             Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1261             mRS.validate();
1262             validate2DRange(xoff, yoff, w, h);
1263             mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
1264                                   mSelectedLOD, mSelectedFace.mID,
1265                                   w, h, data.getID(mRS), dataXoff, dataYoff,
1266                                   data.mSelectedLOD, data.mSelectedFace.mID);
1267         } finally {
1268             Trace.traceEnd(RenderScript.TRACE_TAG);
1269         }
1270     }
1271
1272     /**
1273      * Copy a {@link android.graphics.Bitmap} into an Allocation.  The height
1274      * and width of the update will use the height and width of the {@link
1275      * android.graphics.Bitmap}.
1276      *
1277      * @param xoff X offset of the region to update in this Allocation
1278      * @param yoff Y offset of the region to update in this Allocation
1279      * @param data the Bitmap to be copied
1280      */
1281     public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
1282         try {
1283             Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1284             mRS.validate();
1285             if (data.getConfig() == null) {
1286                 Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888);
1287                 Canvas c = new Canvas(newBitmap);
1288                 c.drawBitmap(data, 0, 0, null);
1289                 copy2DRangeFrom(xoff, yoff, newBitmap);
1290                 return;
1291             }
1292             validateBitmapFormat(data);
1293             validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
1294             mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
1295         } finally {
1296             Trace.traceEnd(RenderScript.TRACE_TAG);
1297         }
1298     }
1299
1300     private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) {
1301         if (mAdaptedAllocation != null) {
1302
1303         } else {
1304
1305             if (xoff < 0 || yoff < 0 || zoff < 0) {
1306                 throw new RSIllegalArgumentException("Offset cannot be negative.");
1307             }
1308             if (h < 0 || w < 0 || d < 0) {
1309                 throw new RSIllegalArgumentException("Height or width cannot be negative.");
1310             }
1311             if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
1312                 throw new RSIllegalArgumentException("Updated region larger than allocation.");
1313             }
1314         }
1315     }
1316
1317     /**
1318      * Copy a rectangular region from the array into the allocation.
1319      * The array is assumed to be tightly packed.
1320      *
1321      * The data type of the array is not required to be the same as
1322      * the element data type.
1323      */
1324     private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
1325                                           Object array, Element.DataType dt, int arrayLen) {
1326         try {
1327             Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
1328             mRS.validate();
1329             validate3DRange(xoff, yoff, zoff, w, h, d);
1330             final int dataSize = mType.mElement.getBytesSize() * w * h * d;
1331             // AutoPadding for Vec3 Element
1332             boolean usePadding = false;
1333             int sizeBytes = arrayLen * dt.mSize;
1334             if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1335                 if (dataSize / 4 * 3 > sizeBytes) {
1336                     throw new RSIllegalArgumentException("Array too small for allocation type.");
1337                 }
1338                 usePadding = true;
1339                 sizeBytes = dataSize;
1340             } else {
1341                 if (dataSize > sizeBytes) {
1342                     throw new RSIllegalArgumentException("Array too small for allocation type.");
1343                 }
1344             }
1345             mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
1346                                   array, sizeBytes, dt,
1347                                   mType.mElement.mType.mSize, usePadding);
1348         } finally {
1349             Trace.traceEnd(RenderScript.TRACE_TAG);
1350         }
1351     }
1352
1353     /**
1354      * Copy a rectangular region from the array into the allocation.
1355      * The array is assumed to be tightly packed.
1356      *
1357      * @param xoff X offset of the region to update in this Allocation
1358      * @param yoff Y offset of the region to update in this Allocation
1359      * @param zoff Z offset of the region to update in this Allocation
1360      * @param w Width of the region to update
1361      * @param h Height of the region to update
1362      * @param d Depth of the region to update
1363      * @param array to be placed into the allocation
1364      */
1365     public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
1366         try {
1367             Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
1368             copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
1369                                      validateObjectIsPrimitiveArray(array, true),
1370                                      java.lang.reflect.Array.getLength(array));
1371         } finally {
1372             Trace.traceEnd(RenderScript.TRACE_TAG);
1373         }
1374     }
1375
1376     /**
1377      * Copy a rectangular region into the allocation from another
1378      * allocation.
1379      *
1380      * @param xoff X offset of the region to update in this Allocation
1381      * @param yoff Y offset of the region to update in this Allocation
1382      * @param zoff Z offset of the region to update in this Allocation
1383      * @param w Width of the region to update.
1384      * @param h Height of the region to update.
1385      * @param d Depth of the region to update.
1386      * @param data source allocation.
1387      * @param dataXoff X offset of the region in the source Allocation
1388      * @param dataYoff Y offset of the region in the source Allocation
1389      * @param dataZoff Z offset of the region in the source Allocation
1390      */
1391     public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d,
1392                                 Allocation data, int dataXoff, int dataYoff, int dataZoff) {
1393         mRS.validate();
1394         validate3DRange(xoff, yoff, zoff, w, h, d);
1395         mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
1396                               w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff,
1397                               data.mSelectedLOD);
1398     }
1399
1400
1401     /**
1402      * Copy from the Allocation into a {@link android.graphics.Bitmap}.  The
1403      * bitmap must match the dimensions of the Allocation.
1404      *
1405      * @param b The bitmap to be set from the Allocation.
1406      */
1407     public void copyTo(Bitmap b) {
1408         try {
1409             Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
1410             mRS.validate();
1411             validateBitmapFormat(b);
1412             validateBitmapSize(b);
1413             mRS.nAllocationCopyToBitmap(getID(mRS), b);
1414         } finally {
1415             Trace.traceEnd(RenderScript.TRACE_TAG);
1416         }
1417     }
1418
1419     private void copyTo(Object array, Element.DataType dt, int arrayLen) {
1420         try {
1421             Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
1422             mRS.validate();
1423             boolean usePadding = false;
1424             if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1425                 usePadding = true;
1426             }
1427             if (usePadding) {
1428                 if (dt.mSize * arrayLen < mSize / 4 * 3) {
1429                     throw new RSIllegalArgumentException(
1430                         "Size of output array cannot be smaller than size of allocation.");
1431                 }
1432             } else {
1433                 if (dt.mSize * arrayLen < mSize) {
1434                     throw new RSIllegalArgumentException(
1435                         "Size of output array cannot be smaller than size of allocation.");
1436                 }
1437             }
1438             mRS.nAllocationRead(getID(mRS), array, dt, mType.mElement.mType.mSize, usePadding);
1439         } finally {
1440             Trace.traceEnd(RenderScript.TRACE_TAG);
1441         }
1442     }
1443
1444     /**
1445      * Copy from the Allocation into an array.  The array must be at
1446      * least as large as the Allocation.  The
1447      * {@link android.renderscript.Element} must match the component
1448      * type of the array passed in.
1449      *
1450      * @param array The array to be set from the Allocation.
1451      */
1452     public void copyTo(Object array) {
1453         copyTo(array, validateObjectIsPrimitiveArray(array, true),
1454                java.lang.reflect.Array.getLength(array));
1455     }
1456
1457     /**
1458      * Copy from the Allocation into a byte array.  The array must be at least
1459      * as large as the Allocation.  The allocation must be of an 8 bit integer
1460      * {@link android.renderscript.Element} type.
1461      *
1462      * @param d The array to be set from the Allocation.
1463      */
1464     public void copyTo(byte[] d) {
1465         validateIsInt8();
1466         copyTo(d, Element.DataType.SIGNED_8, d.length);
1467     }
1468
1469     /**
1470      * Copy from the Allocation into a short array.  The array must be at least
1471      * as large as the Allocation.  The allocation must be of an 16 bit integer
1472      * {@link android.renderscript.Element} type.
1473      *
1474      * @param d The array to be set from the Allocation.
1475      */
1476     public void copyTo(short[] d) {
1477         validateIsInt16OrFloat16();
1478         copyTo(d, Element.DataType.SIGNED_16, d.length);
1479     }
1480
1481     /**
1482      * Copy from the Allocation into a int array.  The array must be at least as
1483      * large as the Allocation.  The allocation must be of an 32 bit integer
1484      * {@link android.renderscript.Element} type.
1485      *
1486      * @param d The array to be set from the Allocation.
1487      */
1488     public void copyTo(int[] d) {
1489         validateIsInt32();
1490         copyTo(d, Element.DataType.SIGNED_32, d.length);
1491     }
1492
1493     /**
1494      * Copy from the Allocation into a float array.  The array must be at least
1495      * as large as the Allocation.  The allocation must be of an 32 bit float
1496      * {@link android.renderscript.Element} type.
1497      *
1498      * @param d The array to be set from the Allocation.
1499      */
1500     public void copyTo(float[] d) {
1501         validateIsFloat32();
1502         copyTo(d, Element.DataType.FLOAT_32, d.length);
1503     }
1504
1505     /**
1506      * @hide
1507      *
1508      * This is only intended to be used by auto-generated code reflected from
1509      * the RenderScript script files and should not be used by developers.
1510      *
1511      * @param xoff
1512      * @param yoff
1513      * @param zoff
1514      * @param component_number
1515      * @param fp
1516      */
1517     public void copyToFieldPacker(int xoff, int yoff, int zoff, int component_number, FieldPacker fp) {
1518         mRS.validate();
1519         if (component_number >= mType.mElement.mElements.length) {
1520             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
1521         }
1522         if(xoff < 0) {
1523             throw new RSIllegalArgumentException("Offset x must be >= 0.");
1524         }
1525         if(yoff < 0) {
1526             throw new RSIllegalArgumentException("Offset y must be >= 0.");
1527         }
1528         if(zoff < 0) {
1529             throw new RSIllegalArgumentException("Offset z must be >= 0.");
1530         }
1531
1532         final byte[] data = fp.getData();
1533         int data_length = data.length;
1534         int eSize = mType.mElement.mElements[component_number].getBytesSize();
1535         eSize *= mType.mElement.mArraySizes[component_number];
1536
1537         if (data_length != eSize) {
1538             throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
1539                                                " does not match component size " + eSize + ".");
1540         }
1541
1542         mRS.nAllocationElementRead(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
1543                                    component_number, data, data_length);
1544     }
1545     /**
1546      * Resize a 1D allocation.  The contents of the allocation are preserved.
1547      * If new elements are allocated objects are created with null contents and
1548      * the new region is otherwise undefined.
1549      *
1550      * <p>If the new region is smaller the references of any objects outside the
1551      * new region will be released.</p>
1552      *
1553      * <p>A new type will be created with the new dimension.</p>
1554      *
1555      * @param dimX The new size of the allocation.
1556      *
1557      * @deprecated RenderScript objects should be immutable once created.  The
1558      * replacement is to create a new allocation and copy the contents. This
1559      * function will throw an exception if API 21 or higher is used.
1560      */
1561     public synchronized void resize(int dimX) {
1562         if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 21) {
1563             throw new RSRuntimeException("Resize is not allowed in API 21+.");
1564         }
1565         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
1566             throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
1567         }
1568         mRS.nAllocationResize1D(getID(mRS), dimX);
1569         mRS.finish();  // Necessary because resize is fifoed and update is async.
1570
1571         long typeID = mRS.nAllocationGetType(getID(mRS));
1572         mType = new Type(typeID, mRS);
1573         mType.updateFromNative();
1574         updateCacheInfo(mType);
1575     }
1576
1577     private void copy1DRangeToUnchecked(int off, int count, Object array,
1578                                         Element.DataType dt, int arrayLen) {
1579         try {
1580             Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeToUnchecked");
1581             final int dataSize = mType.mElement.getBytesSize() * count;
1582             // AutoPadding for Vec3 Element
1583             boolean usePadding = false;
1584             if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1585                 usePadding = true;
1586             }
1587             data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
1588             mRS.nAllocationRead1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
1589                                   mType.mElement.mType.mSize, usePadding);
1590         } finally {
1591             Trace.traceEnd(RenderScript.TRACE_TAG);
1592         }
1593     }
1594
1595     /**
1596      * Copy part of this Allocation into an array.  This method does not
1597      * guarantee that the Allocation is compatible with the input buffer.
1598      *
1599      * @param off The offset of the first element to be copied.
1600      * @param count The number of elements to be copied.
1601      * @param array The dest data array
1602      */
1603     public void copy1DRangeToUnchecked(int off, int count, Object array) {
1604         copy1DRangeToUnchecked(off, count, array,
1605                                validateObjectIsPrimitiveArray(array, false),
1606                                java.lang.reflect.Array.getLength(array));
1607     }
1608
1609     /**
1610      * Copy part of this Allocation into an array.  This method does not
1611      * guarantee that the Allocation is compatible with the input buffer.
1612      *
1613      * @param off The offset of the first element to be copied.
1614      * @param count The number of elements to be copied.
1615      * @param d the source data array
1616      */
1617     public void copy1DRangeToUnchecked(int off, int count, int[] d) {
1618         copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
1619     }
1620
1621     /**
1622      * Copy part of this Allocation into an array.  This method does not
1623      * guarantee that the Allocation is compatible with the input buffer.
1624      *
1625      * @param off The offset of the first element to be copied.
1626      * @param count The number of elements to be copied.
1627      * @param d the source data array
1628      */
1629     public void copy1DRangeToUnchecked(int off, int count, short[] d) {
1630         copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
1631     }
1632
1633     /**
1634      * Copy part of this Allocation into an array.  This method does not
1635      * guarantee that the Allocation is compatible with the input buffer.
1636      *
1637      * @param off The offset of the first element to be copied.
1638      * @param count The number of elements to be copied.
1639      * @param d the source data array
1640      */
1641     public void copy1DRangeToUnchecked(int off, int count, byte[] d) {
1642         copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
1643     }
1644
1645     /**
1646      * Copy part of this Allocation into an array.  This method does not
1647      * guarantee that the Allocation is compatible with the input buffer.
1648      *
1649      * @param off The offset of the first element to be copied.
1650      * @param count The number of elements to be copied.
1651      * @param d the source data array
1652      */
1653     public void copy1DRangeToUnchecked(int off, int count, float[] d) {
1654         copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
1655     }
1656
1657
1658     /**
1659      * Copy part of this Allocation into an array.  This method does not
1660      * and will generate exceptions if the Allocation type does not
1661      * match the component type of the array passed in.
1662      *
1663      * @param off The offset of the first element to be copied.
1664      * @param count The number of elements to be copied.
1665      * @param array The source data array.
1666      */
1667     public void copy1DRangeTo(int off, int count, Object array) {
1668         copy1DRangeToUnchecked(off, count, array,
1669                                validateObjectIsPrimitiveArray(array, true),
1670                                java.lang.reflect.Array.getLength(array));
1671     }
1672
1673     /**
1674      * Copy part of this Allocation into an array.  This method does not
1675      * and will generate exceptions if the Allocation type is not a 32 bit
1676      * integer type.
1677      *
1678      * @param off The offset of the first element to be copied.
1679      * @param count The number of elements to be copied.
1680      * @param d the source data array
1681      */
1682     public void copy1DRangeTo(int off, int count, int[] d) {
1683         validateIsInt32();
1684         copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
1685     }
1686
1687     /**
1688      * Copy part of this Allocation into an array.  This method does not
1689      * and will generate exceptions if the Allocation type is not a 16 bit
1690      * integer type.
1691      *
1692      * @param off The offset of the first element to be copied.
1693      * @param count The number of elements to be copied.
1694      * @param d the source data array
1695      */
1696     public void copy1DRangeTo(int off, int count, short[] d) {
1697         validateIsInt16OrFloat16();
1698         copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
1699     }
1700
1701     /**
1702      * Copy part of this Allocation into an array.  This method does not
1703      * and will generate exceptions if the Allocation type is not an 8 bit
1704      * integer type.
1705      *
1706      * @param off The offset of the first element to be copied.
1707      * @param count The number of elements to be copied.
1708      * @param d the source data array
1709      */
1710     public void copy1DRangeTo(int off, int count, byte[] d) {
1711         validateIsInt8();
1712         copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
1713     }
1714
1715     /**
1716      * Copy part of this Allocation into an array.  This method does not
1717      * and will generate exceptions if the Allocation type is not a 32 bit float
1718      * type.
1719      *
1720      * @param off The offset of the first element to be copied.
1721      * @param count The number of elements to be copied.
1722      * @param d the source data array.
1723      */
1724     public void copy1DRangeTo(int off, int count, float[] d) {
1725         validateIsFloat32();
1726         copy1DRangeToUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
1727     }
1728
1729
1730     void copy2DRangeToUnchecked(int xoff, int yoff, int w, int h, Object array,
1731                                 Element.DataType dt, int arrayLen) {
1732         try {
1733             Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeToUnchecked");
1734             mRS.validate();
1735             validate2DRange(xoff, yoff, w, h);
1736             final int dataSize = mType.mElement.getBytesSize() * w * h;
1737             // AutoPadding for Vec3 Element
1738             boolean usePadding = false;
1739             int sizeBytes = arrayLen * dt.mSize;
1740             if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1741                 if (dataSize / 4 * 3 > sizeBytes) {
1742                     throw new RSIllegalArgumentException("Array too small for allocation type.");
1743                 }
1744                 usePadding = true;
1745                 sizeBytes = dataSize;
1746             } else {
1747                 if (dataSize > sizeBytes) {
1748                     throw new RSIllegalArgumentException("Array too small for allocation type.");
1749                 }
1750             }
1751             mRS.nAllocationRead2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
1752                                   array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
1753         } finally {
1754             Trace.traceEnd(RenderScript.TRACE_TAG);
1755         }
1756     }
1757
1758     /**
1759      * Copy from a rectangular region in this Allocation into an array.
1760      *
1761      * @param xoff X offset of the region to copy in this Allocation
1762      * @param yoff Y offset of the region to copy in this Allocation
1763      * @param w Width of the region to copy
1764      * @param h Height of the region to copy
1765      * @param array Dest Array to be copied into
1766      */
1767     public void copy2DRangeTo(int xoff, int yoff, int w, int h, Object array) {
1768         copy2DRangeToUnchecked(xoff, yoff, w, h, array,
1769                                validateObjectIsPrimitiveArray(array, true),
1770                                java.lang.reflect.Array.getLength(array));
1771     }
1772
1773     /**
1774      * Copy from a rectangular region in this Allocation into an array.
1775      *
1776      * @param xoff X offset of the region to copy in this Allocation
1777      * @param yoff Y offset of the region to copy in this Allocation
1778      * @param w Width of the region to copy
1779      * @param h Height of the region to copy
1780      * @param data Dest Array to be copied into
1781      */
1782     public void copy2DRangeTo(int xoff, int yoff, int w, int h, byte[] data) {
1783         validateIsInt8();
1784         copy2DRangeToUnchecked(xoff, yoff, w, h, data,
1785                                Element.DataType.SIGNED_8, data.length);
1786     }
1787
1788     /**
1789      * Copy from a rectangular region in this Allocation into an array.
1790      *
1791      * @param xoff X offset of the region to copy in this Allocation
1792      * @param yoff Y offset of the region to copy in this Allocation
1793      * @param w Width of the region to copy
1794      * @param h Height of the region to copy
1795      * @param data Dest Array to be copied into
1796      */
1797     public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) {
1798         validateIsInt16OrFloat16();
1799         copy2DRangeToUnchecked(xoff, yoff, w, h, data,
1800                                Element.DataType.SIGNED_16, data.length);
1801     }
1802
1803     /**
1804      * Copy from a rectangular region in this Allocation into an array.
1805      *
1806      * @param xoff X offset of the region to copy in this Allocation
1807      * @param yoff Y offset of the region to copy in this Allocation
1808      * @param w Width of the region to copy
1809      * @param h Height of the region to copy
1810      * @param data Dest Array to be copied into
1811      */
1812     public void copy2DRangeTo(int xoff, int yoff, int w, int h, int[] data) {
1813         validateIsInt32();
1814         copy2DRangeToUnchecked(xoff, yoff, w, h, data,
1815                                Element.DataType.SIGNED_32, data.length);
1816     }
1817
1818     /**
1819      * Copy from a rectangular region in this Allocation into an array.
1820      *
1821      * @param xoff X offset of the region to copy in this Allocation
1822      * @param yoff Y offset of the region to copy in this Allocation
1823      * @param w Width of the region to copy
1824      * @param h Height of the region to copy
1825      * @param data Dest Array to be copied into
1826      */
1827     public void copy2DRangeTo(int xoff, int yoff, int w, int h, float[] data) {
1828         validateIsFloat32();
1829         copy2DRangeToUnchecked(xoff, yoff, w, h, data,
1830                                Element.DataType.FLOAT_32, data.length);
1831     }
1832
1833
1834     /**
1835      * Copy from a rectangular region in this Allocation into an array.
1836      * The array is assumed to be tightly packed.
1837      *
1838      * The data type of the array is not required to be the same as
1839      * the element data type.
1840      */
1841     private void copy3DRangeToUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
1842                                         Object array, Element.DataType dt, int arrayLen) {
1843         try {
1844             Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeToUnchecked");
1845             mRS.validate();
1846             validate3DRange(xoff, yoff, zoff, w, h, d);
1847             final int dataSize = mType.mElement.getBytesSize() * w * h * d;
1848             // AutoPadding for Vec3 Element
1849             boolean usePadding = false;
1850             int sizeBytes = arrayLen * dt.mSize;
1851             if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1852                 if (dataSize / 4 * 3 > sizeBytes) {
1853                     throw new RSIllegalArgumentException("Array too small for allocation type.");
1854                 }
1855                 usePadding = true;
1856                 sizeBytes = dataSize;
1857             } else {
1858                 if (dataSize > sizeBytes) {
1859                     throw new RSIllegalArgumentException("Array too small for allocation type.");
1860                 }
1861             }
1862             mRS.nAllocationRead3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
1863                                   array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
1864         } finally {
1865             Trace.traceEnd(RenderScript.TRACE_TAG);
1866         }
1867     }
1868
1869     /*
1870      * Copy from a rectangular region in this Allocation into an array.
1871      *
1872      * @param xoff X offset of the region to copy in this Allocation
1873      * @param yoff Y offset of the region to copy in this Allocation
1874      * @param zoff Z offset of the region to copy in this Allocation
1875      * @param w Width of the region to copy
1876      * @param h Height of the region to copy
1877      * @param d Depth of the region to copy
1878      * @param array Dest Array to be copied into
1879      */
1880     public void copy3DRangeTo(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
1881         copy3DRangeToUnchecked(xoff, yoff, zoff, w, h, d, array,
1882                                  validateObjectIsPrimitiveArray(array, true),
1883                                  java.lang.reflect.Array.getLength(array));
1884     }
1885
1886     // creation
1887
1888     static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
1889     static {
1890         mBitmapOptions.inScaled = false;
1891     }
1892
1893     /**
1894      * Creates a new Allocation with the given {@link
1895      * android.renderscript.Type}, mipmap flag, and usage flags.
1896      *
1897      * @param type RenderScript type describing data layout
1898      * @param mips specifies desired mipmap behaviour for the
1899      *             allocation
1900      * @param usage bit field specifying how the Allocation is
1901      *              utilized
1902      */
1903     static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
1904         try {
1905             Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped");
1906             rs.validate();
1907             if (type.getID(rs) == 0) {
1908                 throw new RSInvalidStateException("Bad Type");
1909             }
1910             long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
1911             if (id == 0) {
1912                 throw new RSRuntimeException("Allocation creation failed.");
1913             }
1914             return new Allocation(id, rs, type, usage, mips);
1915         } finally {
1916             Trace.traceEnd(RenderScript.TRACE_TAG);
1917         }
1918     }
1919
1920     /**
1921      * Creates an Allocation with the size specified by the type and no mipmaps
1922      * generated by default
1923      *
1924      * @param rs Context to which the allocation will belong.
1925      * @param type renderscript type describing data layout
1926      * @param usage bit field specifying how the allocation is
1927      *              utilized
1928      *
1929      * @return allocation
1930      */
1931     static public Allocation createTyped(RenderScript rs, Type type, int usage) {
1932         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
1933     }
1934
1935     /**
1936      * Creates an Allocation for use by scripts with a given {@link
1937      * android.renderscript.Type} and no mipmaps
1938      *
1939      * @param rs Context to which the Allocation will belong.
1940      * @param type RenderScript Type describing data layout
1941      *
1942      * @return allocation
1943      */
1944     static public Allocation createTyped(RenderScript rs, Type type) {
1945         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
1946     }
1947
1948     /**
1949      * Creates an Allocation with a specified number of given elements
1950      *
1951      * @param rs Context to which the Allocation will belong.
1952      * @param e Element to use in the Allocation
1953      * @param count the number of Elements in the Allocation
1954      * @param usage bit field specifying how the Allocation is
1955      *              utilized
1956      *
1957      * @return allocation
1958      */
1959     static public Allocation createSized(RenderScript rs, Element e,
1960                                          int count, int usage) {
1961         try {
1962             Trace.traceBegin(RenderScript.TRACE_TAG, "createSized");
1963             rs.validate();
1964             Type.Builder b = new Type.Builder(rs, e);
1965             b.setX(count);
1966             Type t = b.create();
1967
1968             long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
1969             if (id == 0) {
1970                 throw new RSRuntimeException("Allocation creation failed.");
1971             }
1972             return new Allocation(id, rs, t, usage, MipmapControl.MIPMAP_NONE);
1973         } finally {
1974             Trace.traceEnd(RenderScript.TRACE_TAG);
1975         }
1976     }
1977
1978     /**
1979      * Creates an Allocation with a specified number of given elements
1980      *
1981      * @param rs Context to which the Allocation will belong.
1982      * @param e Element to use in the Allocation
1983      * @param count the number of Elements in the Allocation
1984      *
1985      * @return allocation
1986      */
1987     static public Allocation createSized(RenderScript rs, Element e, int count) {
1988         return createSized(rs, e, count, USAGE_SCRIPT);
1989     }
1990
1991     static Element elementFromBitmap(RenderScript rs, Bitmap b) {
1992         final Bitmap.Config bc = b.getConfig();
1993         if (bc == Bitmap.Config.ALPHA_8) {
1994             return Element.A_8(rs);
1995         }
1996         if (bc == Bitmap.Config.ARGB_4444) {
1997             return Element.RGBA_4444(rs);
1998         }
1999         if (bc == Bitmap.Config.ARGB_8888) {
2000             return Element.RGBA_8888(rs);
2001         }
2002         if (bc == Bitmap.Config.RGB_565) {
2003             return Element.RGB_565(rs);
2004         }
2005         throw new RSInvalidStateException("Bad bitmap type: " + bc);
2006     }
2007
2008     static Type typeFromBitmap(RenderScript rs, Bitmap b,
2009                                        MipmapControl mip) {
2010         Element e = elementFromBitmap(rs, b);
2011         Type.Builder tb = new Type.Builder(rs, e);
2012         tb.setX(b.getWidth());
2013         tb.setY(b.getHeight());
2014         tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
2015         return tb.create();
2016     }
2017
2018     /**
2019      * Creates an Allocation from a {@link android.graphics.Bitmap}.
2020      *
2021      * @param rs Context to which the allocation will belong.
2022      * @param b Bitmap source for the allocation data
2023      * @param mips specifies desired mipmap behaviour for the
2024      *             allocation
2025      * @param usage bit field specifying how the allocation is
2026      *              utilized
2027      *
2028      * @return Allocation containing bitmap data
2029      *
2030      */
2031     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
2032                                               MipmapControl mips,
2033                                               int usage) {
2034         try {
2035             Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap");
2036             rs.validate();
2037
2038             // WAR undocumented color formats
2039             if (b.getConfig() == null) {
2040                 if ((usage & USAGE_SHARED) != 0) {
2041                     throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config.");
2042                 }
2043                 Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
2044                 Canvas c = new Canvas(newBitmap);
2045                 c.drawBitmap(b, 0, 0, null);
2046                 return createFromBitmap(rs, newBitmap, mips, usage);
2047             }
2048
2049             Type t = typeFromBitmap(rs, b, mips);
2050
2051             // enable optimized bitmap path only with no mipmap and script-only usage
2052             if (mips == MipmapControl.MIPMAP_NONE &&
2053                  t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
2054                  usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) {
2055                 long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
2056                 if (id == 0) {
2057                     throw new RSRuntimeException("Load failed.");
2058                 }
2059
2060                 // keep a reference to the Bitmap around to prevent GC
2061                 Allocation alloc = new Allocation(id, rs, t, usage, mips);
2062                 alloc.setBitmap(b);
2063                 return alloc;
2064             }
2065
2066
2067             long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
2068             if (id == 0) {
2069                 throw new RSRuntimeException("Load failed.");
2070             }
2071             return new Allocation(id, rs, t, usage, mips);
2072         } finally {
2073             Trace.traceEnd(RenderScript.TRACE_TAG);
2074         }
2075     }
2076
2077     /**
2078      * Gets or creates a ByteBuffer that contains the raw data of the current Allocation.
2079      * If the Allocation is created with USAGE_IO_INPUT, the returned ByteBuffer
2080      * would contain the up-to-date data as READ ONLY.
2081      * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
2082      * the Allocation has certain alignment. The size of each row including padding,
2083      * called stride, can be queried using the {@link #getStride()} method.
2084      *
2085      * Note: Operating on the ByteBuffer of a destroyed Allocation will triger errors.
2086      *
2087      * @return ByteBuffer The ByteBuffer associated with raw data pointer of the Allocation.
2088      */
2089     public ByteBuffer getByteBuffer() {
2090         // Create a new ByteBuffer if it is not initialized or using IO_INPUT.
2091         if (mType.hasFaces()) {
2092             throw new RSInvalidStateException("Cubemap is not supported for getByteBuffer().");
2093         }
2094         if (mType.getYuv() == android.graphics.ImageFormat.NV21 ||
2095             mType.getYuv() == android.graphics.ImageFormat.YV12 ||
2096             mType.getYuv() == android.graphics.ImageFormat.YUV_420_888 ) {
2097             throw new RSInvalidStateException("YUV format is not supported for getByteBuffer().");
2098         }
2099         if (mByteBuffer == null || (mUsage & USAGE_IO_INPUT) != 0) {
2100             int xBytesSize = mType.getX() * mType.getElement().getBytesSize();
2101             long[] stride = new long[1];
2102             mByteBuffer = mRS.nAllocationGetByteBuffer(getID(mRS), stride, xBytesSize, mType.getY(), mType.getZ());
2103             mByteBufferStride = stride[0];
2104         }
2105         if ((mUsage & USAGE_IO_INPUT) != 0) {
2106             return mByteBuffer.asReadOnlyBuffer();
2107         }
2108         return mByteBuffer;
2109     }
2110
2111     /**
2112      * Creates a new Allocation Array with the given {@link
2113      * android.renderscript.Type}, and usage flags.
2114      * Note: If the input allocation is of usage: USAGE_IO_INPUT,
2115      * the created Allocation will be sharing the same BufferQueue.
2116      *
2117      * @param rs RenderScript context
2118      * @param t RenderScript type describing data layout
2119      * @param usage bit field specifying how the Allocation is
2120      *              utilized
2121      * @param numAlloc Number of Allocations in the array.
2122      * @return Allocation[]
2123      */
2124     public static Allocation[] createAllocations(RenderScript rs, Type t, int usage, int numAlloc) {
2125         try {
2126             Trace.traceBegin(RenderScript.TRACE_TAG, "createAllocations");
2127             rs.validate();
2128             if (t.getID(rs) == 0) {
2129                 throw new RSInvalidStateException("Bad Type");
2130             }
2131
2132             Allocation[] mAllocationArray = new Allocation[numAlloc];
2133             mAllocationArray[0] = createTyped(rs, t, usage);
2134             if ((usage & USAGE_IO_INPUT) != 0) {
2135                 if (numAlloc > MAX_NUMBER_IO_INPUT_ALLOC) {
2136                     throw new RSIllegalArgumentException("Exceeds the max number of Allocations allowed: " +
2137                                                          MAX_NUMBER_IO_INPUT_ALLOC);
2138                 }
2139                 mAllocationArray[0].setupBufferQueue(numAlloc);;
2140             }
2141
2142             for (int i=1; i<numAlloc; i++) {
2143                 mAllocationArray[i] = createFromAllcation(rs, mAllocationArray[0]);
2144             }
2145             return mAllocationArray;
2146         } finally {
2147             Trace.traceEnd(RenderScript.TRACE_TAG);
2148         }
2149     }
2150
2151     /**
2152      * Creates a new Allocation with the given {@link
2153      * android.renderscript.Allocation}. The same data layout of
2154      * the input Allocation will be applied.
2155      * If the input allocation is of usage: USAGE_IO_INPUT, the created
2156      * Allocation will be sharing the same BufferQueue.
2157      *
2158      * @param rs Context to which the allocation will belong.
2159      * @param alloc RenderScript Allocation describing data layout.
2160      * @return Allocation sharing the same data structure.
2161      */
2162     static Allocation createFromAllcation(RenderScript rs, Allocation alloc) {
2163         try {
2164             Trace.traceBegin(RenderScript.TRACE_TAG, "createFromAllcation");
2165             rs.validate();
2166             if (alloc.getID(rs) == 0) {
2167                 throw new RSInvalidStateException("Bad input Allocation");
2168             }
2169
2170             Type type = alloc.getType();
2171             int usage = alloc.getUsage();
2172             MipmapControl mips = alloc.getMipmap();
2173             long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
2174             if (id == 0) {
2175                 throw new RSRuntimeException("Allocation creation failed.");
2176             }
2177             Allocation outAlloc = new Allocation(id, rs, type, usage, mips);
2178             if ((usage & USAGE_IO_INPUT) != 0) {
2179                 outAlloc.shareBufferQueue(alloc);
2180             }
2181             return outAlloc;
2182         } finally {
2183             Trace.traceEnd(RenderScript.TRACE_TAG);
2184         }
2185     }
2186
2187     /**
2188      * Initialize BufferQueue with specified max number of buffers.
2189      */
2190     void setupBufferQueue(int numAlloc) {
2191         mRS.validate();
2192         if ((mUsage & USAGE_IO_INPUT) == 0) {
2193             throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
2194         }
2195         mRS.nAllocationSetupBufferQueue(getID(mRS), numAlloc);
2196     }
2197
2198     /**
2199      * Share the BufferQueue with another {@link #USAGE_IO_INPUT} Allocation.
2200      *
2201      * @param alloc Allocation to associate with allocation
2202      */
2203     void shareBufferQueue(Allocation alloc) {
2204         mRS.validate();
2205         if ((mUsage & USAGE_IO_INPUT) == 0) {
2206             throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
2207         }
2208         mGetSurfaceSurface = alloc.getSurface();
2209         mRS.nAllocationShareBufferQueue(getID(mRS), alloc.getID(mRS));
2210     }
2211
2212     /**
2213      * Gets the stride of the Allocation.
2214      * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
2215      * the Allocation has certain alignment. The size of each row including such
2216      * padding is called stride.
2217      *
2218      * @return the stride. For 1D Allocation, the stride will be the number of
2219      *         bytes of this Allocation. For 2D and 3D Allocations, the stride
2220      *         will be the stride in X dimension measuring in bytes.
2221      */
2222     public long getStride() {
2223         if (mByteBufferStride == -1) {
2224             getByteBuffer();
2225         }
2226         return mByteBufferStride;
2227     }
2228
2229     /**
2230      * Get the timestamp for the most recent buffer held by this Allocation.
2231      * The timestamp is guaranteed to be unique and monotonically increasing.
2232      * Default value: -1. The timestamp will be updated after each {@link
2233      * #ioReceive ioReceive()} call.
2234      *
2235      * It can be used to identify the images by comparing the unique timestamps
2236      * when used with {@link android.hardware.camera2} APIs.
2237      * Example steps:
2238      *   1. Save {@link android.hardware.camera2.TotalCaptureResult} when the
2239      *      capture is completed.
2240      *   2. Get the timestamp after {@link #ioReceive ioReceive()} call.
2241      *   3. Comparing totalCaptureResult.get(CaptureResult.SENSOR_TIMESTAMP) with
2242      *      alloc.getTimeStamp().
2243      * @return long Timestamp associated with the buffer held by the Allocation.
2244      */
2245     public long getTimeStamp() {
2246         return mTimeStamp;
2247     }
2248
2249     /**
2250      * Returns the handle to a raw buffer that is being managed by the screen
2251      * compositor. This operation is only valid for Allocations with {@link
2252      * #USAGE_IO_INPUT}.
2253      *
2254      * @return Surface object associated with allocation
2255      *
2256      */
2257     public Surface getSurface() {
2258         if ((mUsage & USAGE_IO_INPUT) == 0) {
2259             throw new RSInvalidStateException("Allocation is not a surface texture.");
2260         }
2261
2262         if (mGetSurfaceSurface == null) {
2263             mGetSurfaceSurface = mRS.nAllocationGetSurface(getID(mRS));
2264         }
2265
2266         return mGetSurfaceSurface;
2267     }
2268
2269     /**
2270      * Associate a {@link android.view.Surface} with this Allocation. This
2271      * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}.
2272      *
2273      * @param sur Surface to associate with allocation
2274      */
2275     public void setSurface(Surface sur) {
2276         mRS.validate();
2277         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
2278             throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
2279         }
2280
2281         mRS.nAllocationSetSurface(getID(mRS), sur);
2282     }
2283
2284     /**
2285      * Creates an Allocation from a {@link android.graphics.Bitmap}.
2286      *
2287      * <p>With target API version 18 or greater, this Allocation will be created
2288      * with {@link #USAGE_SHARED}, {@link #USAGE_SCRIPT}, and {@link
2289      * #USAGE_GRAPHICS_TEXTURE}. With target API version 17 or lower, this
2290      * Allocation will be created with {@link #USAGE_GRAPHICS_TEXTURE}.</p>
2291      *
2292      * @param rs Context to which the allocation will belong.
2293      * @param b bitmap source for the allocation data
2294      *
2295      * @return Allocation containing bitmap data
2296      *
2297      */
2298     static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
2299         if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
2300             return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
2301                                     USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
2302         }
2303         return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
2304                                 USAGE_GRAPHICS_TEXTURE);
2305     }
2306
2307     /**
2308      * Creates a cubemap Allocation from a {@link android.graphics.Bitmap}
2309      * containing the horizontal list of cube faces. Each face must be a square,
2310      * have the same size as all other faces, and have a width that is a power
2311      * of 2.
2312      *
2313      * @param rs Context to which the allocation will belong.
2314      * @param b Bitmap with cubemap faces layed out in the following
2315      *          format: right, left, top, bottom, front, back
2316      * @param mips specifies desired mipmap behaviour for the cubemap
2317      * @param usage bit field specifying how the cubemap is utilized
2318      *
2319      * @return allocation containing cubemap data
2320      *
2321      */
2322     static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
2323                                                      MipmapControl mips,
2324                                                      int usage) {
2325         rs.validate();
2326
2327         int height = b.getHeight();
2328         int width = b.getWidth();
2329
2330         if (width % 6 != 0) {
2331             throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
2332         }
2333         if (width / 6 != height) {
2334             throw new RSIllegalArgumentException("Only square cube map faces supported");
2335         }
2336         boolean isPow2 = (height & (height - 1)) == 0;
2337         if (!isPow2) {
2338             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
2339         }
2340
2341         Element e = elementFromBitmap(rs, b);
2342         Type.Builder tb = new Type.Builder(rs, e);
2343         tb.setX(height);
2344         tb.setY(height);
2345         tb.setFaces(true);
2346         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
2347         Type t = tb.create();
2348
2349         long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
2350         if(id == 0) {
2351             throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
2352         }
2353         return new Allocation(id, rs, t, usage, mips);
2354     }
2355
2356     /**
2357      * Creates a non-mipmapped cubemap Allocation for use as a graphics texture
2358      * from a {@link android.graphics.Bitmap} containing the horizontal list of
2359      * cube faces. Each face must be a square, have the same size as all other
2360      * faces, and have a width that is a power of 2.
2361      *
2362      * @param rs Context to which the allocation will belong.
2363      * @param b bitmap with cubemap faces layed out in the following
2364      *          format: right, left, top, bottom, front, back
2365      *
2366      * @return allocation containing cubemap data
2367      *
2368      */
2369     static public Allocation createCubemapFromBitmap(RenderScript rs,
2370                                                      Bitmap b) {
2371         return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
2372                                        USAGE_GRAPHICS_TEXTURE);
2373     }
2374
2375     /**
2376      * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap}
2377      * objects containing the cube faces. Each face must be a square, have the
2378      * same size as all other faces, and have a width that is a power of 2.
2379      *
2380      * @param rs Context to which the allocation will belong.
2381      * @param xpos cubemap face in the positive x direction
2382      * @param xneg cubemap face in the negative x direction
2383      * @param ypos cubemap face in the positive y direction
2384      * @param yneg cubemap face in the negative y direction
2385      * @param zpos cubemap face in the positive z direction
2386      * @param zneg cubemap face in the negative z direction
2387      * @param mips specifies desired mipmap behaviour for the cubemap
2388      * @param usage bit field specifying how the cubemap is utilized
2389      *
2390      * @return allocation containing cubemap data
2391      *
2392      */
2393     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
2394                                                         Bitmap xpos,
2395                                                         Bitmap xneg,
2396                                                         Bitmap ypos,
2397                                                         Bitmap yneg,
2398                                                         Bitmap zpos,
2399                                                         Bitmap zneg,
2400                                                         MipmapControl mips,
2401                                                         int usage) {
2402         int height = xpos.getHeight();
2403         if (xpos.getWidth() != height ||
2404             xneg.getWidth() != height || xneg.getHeight() != height ||
2405             ypos.getWidth() != height || ypos.getHeight() != height ||
2406             yneg.getWidth() != height || yneg.getHeight() != height ||
2407             zpos.getWidth() != height || zpos.getHeight() != height ||
2408             zneg.getWidth() != height || zneg.getHeight() != height) {
2409             throw new RSIllegalArgumentException("Only square cube map faces supported");
2410         }
2411         boolean isPow2 = (height & (height - 1)) == 0;
2412         if (!isPow2) {
2413             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
2414         }
2415
2416         Element e = elementFromBitmap(rs, xpos);
2417         Type.Builder tb = new Type.Builder(rs, e);
2418         tb.setX(height);
2419         tb.setY(height);
2420         tb.setFaces(true);
2421         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
2422         Type t = tb.create();
2423         Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
2424
2425         AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
2426         adapter.setFace(Type.CubemapFace.POSITIVE_X);
2427         adapter.copyFrom(xpos);
2428         adapter.setFace(Type.CubemapFace.NEGATIVE_X);
2429         adapter.copyFrom(xneg);
2430         adapter.setFace(Type.CubemapFace.POSITIVE_Y);
2431         adapter.copyFrom(ypos);
2432         adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
2433         adapter.copyFrom(yneg);
2434         adapter.setFace(Type.CubemapFace.POSITIVE_Z);
2435         adapter.copyFrom(zpos);
2436         adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
2437         adapter.copyFrom(zneg);
2438
2439         return cubemap;
2440     }
2441
2442     /**
2443      * Creates a non-mipmapped cubemap Allocation for use as a sampler input
2444      * from 6 {@link android.graphics.Bitmap} objects containing the cube
2445      * faces. Each face must be a square, have the same size as all other faces,
2446      * and have a width that is a power of 2.
2447      *
2448      * @param rs Context to which the allocation will belong.
2449      * @param xpos cubemap face in the positive x direction
2450      * @param xneg cubemap face in the negative x direction
2451      * @param ypos cubemap face in the positive y direction
2452      * @param yneg cubemap face in the negative y direction
2453      * @param zpos cubemap face in the positive z direction
2454      * @param zneg cubemap face in the negative z direction
2455      *
2456      * @return allocation containing cubemap data
2457      *
2458      */
2459     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
2460                                                         Bitmap xpos,
2461                                                         Bitmap xneg,
2462                                                         Bitmap ypos,
2463                                                         Bitmap yneg,
2464                                                         Bitmap zpos,
2465                                                         Bitmap zneg) {
2466         return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
2467                                           zpos, zneg, MipmapControl.MIPMAP_NONE,
2468                                           USAGE_GRAPHICS_TEXTURE);
2469     }
2470
2471     /**
2472      * Creates an Allocation from the Bitmap referenced
2473      * by resource ID.
2474      *
2475      * @param rs Context to which the allocation will belong.
2476      * @param res application resources
2477      * @param id resource id to load the data from
2478      * @param mips specifies desired mipmap behaviour for the
2479      *             allocation
2480      * @param usage bit field specifying how the allocation is
2481      *              utilized
2482      *
2483      * @return Allocation containing resource data
2484      *
2485      */
2486     static public Allocation createFromBitmapResource(RenderScript rs,
2487                                                       Resources res,
2488                                                       int id,
2489                                                       MipmapControl mips,
2490                                                       int usage) {
2491
2492         rs.validate();
2493         if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) {
2494             throw new RSIllegalArgumentException("Unsupported usage specified.");
2495         }
2496         Bitmap b = BitmapFactory.decodeResource(res, id);
2497         Allocation alloc = createFromBitmap(rs, b, mips, usage);
2498         b.recycle();
2499         return alloc;
2500     }
2501
2502     /**
2503      * Creates a non-mipmapped Allocation to use as a graphics texture from the
2504      * {@link android.graphics.Bitmap} referenced by resource ID.
2505      *
2506      * <p>With target API version 18 or greater, this allocation will be created
2507      * with {@link #USAGE_SCRIPT} and {@link #USAGE_GRAPHICS_TEXTURE}. With
2508      * target API version 17 or lower, this allocation will be created with
2509      * {@link #USAGE_GRAPHICS_TEXTURE}.</p>
2510      *
2511      * @param rs Context to which the allocation will belong.
2512      * @param res application resources
2513      * @param id resource id to load the data from
2514      *
2515      * @return Allocation containing resource data
2516      *
2517      */
2518     static public Allocation createFromBitmapResource(RenderScript rs,
2519                                                       Resources res,
2520                                                       int id) {
2521         if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
2522             return createFromBitmapResource(rs, res, id,
2523                                             MipmapControl.MIPMAP_NONE,
2524                                             USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
2525         }
2526         return createFromBitmapResource(rs, res, id,
2527                                         MipmapControl.MIPMAP_NONE,
2528                                         USAGE_GRAPHICS_TEXTURE);
2529     }
2530
2531     /**
2532      * Creates an Allocation containing string data encoded in UTF-8 format.
2533      *
2534      * @param rs Context to which the allocation will belong.
2535      * @param str string to create the allocation from
2536      * @param usage bit field specifying how the allocaiton is
2537      *              utilized
2538      *
2539      */
2540     static public Allocation createFromString(RenderScript rs,
2541                                               String str,
2542                                               int usage) {
2543         rs.validate();
2544         byte[] allocArray = null;
2545         try {
2546             allocArray = str.getBytes("UTF-8");
2547             Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
2548             alloc.copyFrom(allocArray);
2549             return alloc;
2550         }
2551         catch (Exception e) {
2552             throw new RSRuntimeException("Could not convert string to utf-8.");
2553         }
2554     }
2555
2556     /**
2557      * Interface to handle notification when new buffers are available via
2558      * {@link #USAGE_IO_INPUT}. An application will receive one notification
2559      * when a buffer is available. Additional buffers will not trigger new
2560      * notifications until a buffer is processed.
2561      */
2562     public interface OnBufferAvailableListener {
2563         public void onBufferAvailable(Allocation a);
2564     }
2565
2566     /**
2567      * Set a notification handler for {@link #USAGE_IO_INPUT}.
2568      *
2569      * @param callback instance of the OnBufferAvailableListener
2570      *                 class to be called when buffer arrive.
2571      */
2572     public void setOnBufferAvailableListener(OnBufferAvailableListener callback) {
2573         synchronized(mAllocationMap) {
2574             mAllocationMap.put(new Long(getID(mRS)), this);
2575             mBufferNotifier = callback;
2576         }
2577     }
2578
2579     static void sendBufferNotification(long id) {
2580         synchronized(mAllocationMap) {
2581             Allocation a = mAllocationMap.get(new Long(id));
2582
2583             if ((a != null) && (a.mBufferNotifier != null)) {
2584                 a.mBufferNotifier.onBufferAvailable(a);
2585             }
2586         }
2587     }
2588
2589     /**
2590      * For USAGE_IO_OUTPUT, destroy() implies setSurface(null).
2591      *
2592      */
2593     @Override
2594     public void destroy() {
2595         if((mUsage & USAGE_IO_OUTPUT) != 0) {
2596             setSurface(null);
2597         }
2598         super.destroy();
2599     }
2600 }