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.util.HashMap;
20 import android.content.res.Resources;
21 import android.graphics.Bitmap;
22 import android.graphics.BitmapFactory;
23 import android.view.Surface;
24 import android.util.Log;
25 import android.graphics.Canvas;
26 import android.os.Trace;
27 
28 /**
29  * <p> This class provides the primary method through which data is passed to
30  * and from RenderScript kernels.  An Allocation provides the backing store for
31  * a given {@link android.renderscript.Type}.  </p>
32  *
33  * <p>An Allocation also contains a set of usage flags that denote how the
34  * Allocation could be used. For example, an Allocation may have usage flags
35  * specifying that it can be used from a script as well as input to a {@link
36  * android.renderscript.Sampler}. A developer must synchronize across these
37  * different usages using {@link android.renderscript.Allocation#syncAll} in
38  * order to ensure that different users of the Allocation have a consistent view
39  * of memory. For example, in the case where an Allocation is used as the output
40  * of one kernel and as Sampler input in a later kernel, a developer must call
41  * {@link #syncAll syncAll(Allocation.USAGE_SCRIPT)} prior to launching the
42  * second kernel to ensure correctness.
43  *
44  * <p>An Allocation can be populated with the {@link #copyFrom} routines. For
45  * more complex Element types, the {@link #copyFromUnchecked} methods can be
46  * used to copy from byte arrays or similar constructs.</p>
47  *
48  * <div class="special reference">
49  * <h3>Developer Guides</h3>
50  * <p>For more information about creating an application that uses RenderScript, read the
51  * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
52  * </div>
53  **/
54 public class Allocation extends BaseObj {
55     Type mType;
56     Bitmap mBitmap;
57     int mUsage;
58     Allocation mAdaptedAllocation;
59     int mSize;
60 
61     boolean mConstrainedLOD;
62     boolean mConstrainedFace;
63     boolean mConstrainedY;
64     boolean mConstrainedZ;
65     boolean mReadAllowed = true;
66     boolean mWriteAllowed = true;
67     int mSelectedY;
68     int mSelectedZ;
69     int mSelectedLOD;
70     Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
71 
72     int mCurrentDimX;
73     int mCurrentDimY;
74     int mCurrentDimZ;
75     int mCurrentCount;
76     static HashMap<Long, Allocation> mAllocationMap =
77             new HashMap<Long, Allocation>();
78     OnBufferAvailableListener mBufferNotifier;
79 
validateObjectIsPrimitiveArray(Object d, boolean checkType)80     private Element.DataType validateObjectIsPrimitiveArray(Object d, boolean checkType) {
81         final Class c = d.getClass();
82         if (!c.isArray()) {
83             throw new RSIllegalArgumentException("Object passed is not an array of primitives.");
84         }
85         final Class cmp = c.getComponentType();
86         if (!cmp.isPrimitive()) {
87             throw new RSIllegalArgumentException("Object passed is not an Array of primitives.");
88         }
89 
90         if (cmp == Long.TYPE) {
91             if (checkType) {
92                 validateIsInt64();
93                 return mType.mElement.mType;
94             }
95             return Element.DataType.SIGNED_64;
96         }
97 
98         if (cmp == Integer.TYPE) {
99             if (checkType) {
100                 validateIsInt32();
101                 return mType.mElement.mType;
102             }
103             return Element.DataType.SIGNED_32;
104         }
105 
106         if (cmp == Short.TYPE) {
107             if (checkType) {
108                 validateIsInt16();
109                 return mType.mElement.mType;
110             }
111             return Element.DataType.SIGNED_16;
112         }
113 
114         if (cmp == Byte.TYPE) {
115             if (checkType) {
116                 validateIsInt8();
117                 return mType.mElement.mType;
118             }
119             return Element.DataType.SIGNED_8;
120         }
121 
122         if (cmp == Float.TYPE) {
123             if (checkType) {
124                 validateIsFloat32();
125             }
126             return Element.DataType.FLOAT_32;
127         }
128 
129         if (cmp == Double.TYPE) {
130             if (checkType) {
131                 validateIsFloat64();
132             }
133             return Element.DataType.FLOAT_64;
134         }
135         return null;
136     }
137 
138 
139     /**
140      * The usage of the Allocation.  These signal to RenderScript where to place
141      * the Allocation in memory.
142      *
143      */
144 
145     /**
146      * The Allocation will be bound to and accessed by scripts.
147      */
148     public static final int USAGE_SCRIPT = 0x0001;
149 
150     /**
151      * The Allocation will be used as a texture source by one or more graphics
152      * programs.
153      *
154      */
155     public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
156 
157     /**
158      * The Allocation will be used as a graphics mesh.
159      *
160      * This was deprecated in API level 16.
161      *
162      */
163     public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
164 
165 
166     /**
167      * The Allocation will be used as the source of shader constants by one or
168      * more programs.
169      *
170      * This was deprecated in API level 16.
171      *
172      */
173     public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
174 
175     /**
176      * The Allocation will be used as a target for offscreen rendering
177      *
178      * This was deprecated in API level 16.
179      *
180      */
181     public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
182 
183     /**
184      * The Allocation will be used as a {@link android.view.Surface}
185      * consumer.  This usage will cause the Allocation to be created
186      * as read-only.
187      *
188      */
189     public static final int USAGE_IO_INPUT = 0x0020;
190 
191     /**
192      * The Allocation will be used as a {@link android.view.Surface}
193      * producer.  The dimensions and format of the {@link
194      * android.view.Surface} will be forced to those of the
195      * Allocation.
196      *
197      */
198     public static final int USAGE_IO_OUTPUT = 0x0040;
199 
200     /**
201      * The Allocation's backing store will be inherited from another object
202      * (usually a {@link android.graphics.Bitmap}); copying to or from the
203      * original source Bitmap will cause a synchronization rather than a full
204      * copy.  {@link #syncAll} may also be used to synchronize the Allocation
205      * and the source Bitmap.
206      *
207      * <p>This is set by default for allocations created with {@link
208      * #createFromBitmap} in API version 18 and higher.</p>
209      *
210      */
211     public static final int USAGE_SHARED = 0x0080;
212 
213     /**
214      * Controls mipmap behavior when using the bitmap creation and update
215      * functions.
216      */
217     public enum MipmapControl {
218         /**
219          * No mipmaps will be generated and the type generated from the incoming
220          * bitmap will not contain additional LODs.
221          */
222         MIPMAP_NONE(0),
223 
224         /**
225          * A full mipmap chain will be created in script memory.  The Type of
226          * the Allocation will contain a full mipmap chain.  On upload, the full
227          * chain will be transferred.
228          */
229         MIPMAP_FULL(1),
230 
231         /**
232          * The Type of the Allocation will be the same as MIPMAP_NONE.  It will
233          * not contain mipmaps.  On upload, the allocation data will contain a
234          * full mipmap chain generated from the top level in script memory.
235          */
236         MIPMAP_ON_SYNC_TO_TEXTURE(2);
237 
238         int mID;
MipmapControl(int id)239         MipmapControl(int id) {
240             mID = id;
241         }
242     }
243 
244 
getIDSafe()245     private long getIDSafe() {
246         if (mAdaptedAllocation != null) {
247             return mAdaptedAllocation.getID(mRS);
248         }
249         return getID(mRS);
250     }
251 
252 
253    /**
254      * Get the {@link android.renderscript.Element} of the {@link
255      * android.renderscript.Type} of the Allocation.
256      *
257      * @return Element
258      *
259      */
getElement()260     public Element getElement() {
261         return mType.getElement();
262     }
263 
264     /**
265      * Get the usage flags of the Allocation.
266      *
267      * @return usage this Allocation's set of the USAGE_* flags OR'd together
268      *
269      */
getUsage()270     public int getUsage() {
271         return mUsage;
272     }
273 
274     /**
275      * Get the size of the Allocation in bytes.
276      *
277      * @return size of the Allocation in bytes.
278      *
279      */
getBytesSize()280     public int getBytesSize() {
281         if (mType.mDimYuv != 0) {
282             return (int)Math.ceil(mType.getCount() * mType.getElement().getBytesSize() * 1.5);
283         }
284         return mType.getCount() * mType.getElement().getBytesSize();
285     }
286 
updateCacheInfo(Type t)287     private void updateCacheInfo(Type t) {
288         mCurrentDimX = t.getX();
289         mCurrentDimY = t.getY();
290         mCurrentDimZ = t.getZ();
291         mCurrentCount = mCurrentDimX;
292         if (mCurrentDimY > 1) {
293             mCurrentCount *= mCurrentDimY;
294         }
295         if (mCurrentDimZ > 1) {
296             mCurrentCount *= mCurrentDimZ;
297         }
298     }
299 
setBitmap(Bitmap b)300     private void setBitmap(Bitmap b) {
301         mBitmap = b;
302     }
303 
Allocation(long id, RenderScript rs, Type t, int usage)304     Allocation(long id, RenderScript rs, Type t, int usage) {
305         super(id, rs);
306         if ((usage & ~(USAGE_SCRIPT |
307                        USAGE_GRAPHICS_TEXTURE |
308                        USAGE_GRAPHICS_VERTEX |
309                        USAGE_GRAPHICS_CONSTANTS |
310                        USAGE_GRAPHICS_RENDER_TARGET |
311                        USAGE_IO_INPUT |
312                        USAGE_IO_OUTPUT |
313                        USAGE_SHARED)) != 0) {
314             throw new RSIllegalArgumentException("Unknown usage specified.");
315         }
316 
317         if ((usage & USAGE_IO_INPUT) != 0) {
318             mWriteAllowed = false;
319 
320             if ((usage & ~(USAGE_IO_INPUT |
321                            USAGE_GRAPHICS_TEXTURE |
322                            USAGE_SCRIPT)) != 0) {
323                 throw new RSIllegalArgumentException("Invalid usage combination.");
324             }
325         }
326 
327         mType = t;
328         mUsage = usage;
329 
330         if (t != null) {
331             // TODO: A3D doesn't have Type info during creation, so we can't
332             // calculate the size ahead of time. We can possibly add a method
333             // to update the size in the future if it seems reasonable.
334             mSize = mType.getCount() * mType.getElement().getBytesSize();
335             updateCacheInfo(t);
336         }
337         try {
338             RenderScript.registerNativeAllocation.invoke(RenderScript.sRuntime, mSize);
339         } catch (Exception e) {
340             Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e);
341             throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e);
342         }
343     }
344 
finalize()345     protected void finalize() throws Throwable {
346         RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
347         super.finalize();
348     }
349 
validateIsInt64()350     private void validateIsInt64() {
351         if ((mType.mElement.mType == Element.DataType.SIGNED_64) ||
352             (mType.mElement.mType == Element.DataType.UNSIGNED_64)) {
353             return;
354         }
355         throw new RSIllegalArgumentException(
356             "64 bit integer source does not match allocation type " + mType.mElement.mType);
357     }
358 
validateIsInt32()359     private void validateIsInt32() {
360         if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
361             (mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
362             return;
363         }
364         throw new RSIllegalArgumentException(
365             "32 bit integer source does not match allocation type " + mType.mElement.mType);
366     }
367 
validateIsInt16()368     private void validateIsInt16() {
369         if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
370             (mType.mElement.mType == Element.DataType.UNSIGNED_16)) {
371             return;
372         }
373         throw new RSIllegalArgumentException(
374             "16 bit integer source does not match allocation type " + mType.mElement.mType);
375     }
376 
validateIsInt8()377     private void validateIsInt8() {
378         if ((mType.mElement.mType == Element.DataType.SIGNED_8) ||
379             (mType.mElement.mType == Element.DataType.UNSIGNED_8)) {
380             return;
381         }
382         throw new RSIllegalArgumentException(
383             "8 bit integer source does not match allocation type " + mType.mElement.mType);
384     }
385 
validateIsFloat32()386     private void validateIsFloat32() {
387         if (mType.mElement.mType == Element.DataType.FLOAT_32) {
388             return;
389         }
390         throw new RSIllegalArgumentException(
391             "32 bit float source does not match allocation type " + mType.mElement.mType);
392     }
393 
validateIsFloat64()394     private void validateIsFloat64() {
395         if (mType.mElement.mType == Element.DataType.FLOAT_64) {
396             return;
397         }
398         throw new RSIllegalArgumentException(
399             "64 bit float source does not match allocation type " + mType.mElement.mType);
400     }
401 
validateIsObject()402     private void validateIsObject() {
403         if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) ||
404             (mType.mElement.mType == Element.DataType.RS_TYPE) ||
405             (mType.mElement.mType == Element.DataType.RS_ALLOCATION) ||
406             (mType.mElement.mType == Element.DataType.RS_SAMPLER) ||
407             (mType.mElement.mType == Element.DataType.RS_SCRIPT) ||
408             (mType.mElement.mType == Element.DataType.RS_MESH) ||
409             (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) ||
410             (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) ||
411             (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) ||
412             (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) {
413             return;
414         }
415         throw new RSIllegalArgumentException(
416             "Object source does not match allocation type " + mType.mElement.mType);
417     }
418 
419     @Override
updateFromNative()420     void updateFromNative() {
421         super.updateFromNative();
422         long typeID = mRS.nAllocationGetType(getID(mRS));
423         if(typeID != 0) {
424             mType = new Type(typeID, mRS);
425             mType.updateFromNative();
426             updateCacheInfo(mType);
427         }
428     }
429 
430     /**
431      * Get the {@link android.renderscript.Type} of the Allocation.
432      *
433      * @return Type
434      *
435      */
getType()436     public Type getType() {
437         return mType;
438     }
439 
440     /**
441      * Propagate changes from one usage of the Allocation to the
442      * other usages of the Allocation.
443      *
444      */
syncAll(int srcLocation)445     public void syncAll(int srcLocation) {
446         Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll");
447         switch (srcLocation) {
448         case USAGE_GRAPHICS_TEXTURE:
449         case USAGE_SCRIPT:
450             if ((mUsage & USAGE_SHARED) != 0) {
451                 copyFrom(mBitmap);
452             }
453             break;
454         case USAGE_GRAPHICS_CONSTANTS:
455         case USAGE_GRAPHICS_VERTEX:
456             break;
457         case USAGE_SHARED:
458             if ((mUsage & USAGE_SHARED) != 0) {
459                 copyTo(mBitmap);
460             }
461             break;
462         default:
463             throw new RSIllegalArgumentException("Source must be exactly one usage type.");
464         }
465         mRS.validate();
466         mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
467         Trace.traceEnd(RenderScript.TRACE_TAG);
468     }
469 
470     /**
471      * Send a buffer to the output stream.  The contents of the Allocation will
472      * be undefined after this operation. This operation is only valid if {@link
473      * #USAGE_IO_OUTPUT} is set on the Allocation.
474      *
475      *
476      */
ioSend()477     public void ioSend() {
478         Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend");
479         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
480             throw new RSIllegalArgumentException(
481                 "Can only send buffer if IO_OUTPUT usage specified.");
482         }
483         mRS.validate();
484         mRS.nAllocationIoSend(getID(mRS));
485         Trace.traceEnd(RenderScript.TRACE_TAG);
486     }
487 
488     /**
489      * Receive the latest input into the Allocation. This operation
490      * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation.
491      *
492      */
ioReceive()493     public void ioReceive() {
494         Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive");
495         if ((mUsage & USAGE_IO_INPUT) == 0) {
496             throw new RSIllegalArgumentException(
497                 "Can only receive if IO_INPUT usage specified.");
498         }
499         mRS.validate();
500         mRS.nAllocationIoReceive(getID(mRS));
501         Trace.traceEnd(RenderScript.TRACE_TAG);
502     }
503 
504     /**
505      * Copy an array of RS objects to the Allocation.
506      *
507      * @param d Source array.
508      */
copyFrom(BaseObj[] d)509     public void copyFrom(BaseObj[] d) {
510         Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
511         mRS.validate();
512         validateIsObject();
513         if (d.length != mCurrentCount) {
514             throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
515                                                  mCurrentCount + ", array length = " + d.length);
516         }
517 
518         if (RenderScript.sPointerSize == 8) {
519             long i[] = new long[d.length * 4];
520             for (int ct=0; ct < d.length; ct++) {
521                 i[ct * 4] = d[ct].getID(mRS);
522             }
523             copy1DRangeFromUnchecked(0, mCurrentCount, i);
524         } else {
525             int i[] = new int[d.length];
526             for (int ct=0; ct < d.length; ct++) {
527                 i[ct] = (int)d[ct].getID(mRS);
528             }
529             copy1DRangeFromUnchecked(0, mCurrentCount, i);
530         }
531         Trace.traceEnd(RenderScript.TRACE_TAG);
532     }
533 
validateBitmapFormat(Bitmap b)534     private void validateBitmapFormat(Bitmap b) {
535         Bitmap.Config bc = b.getConfig();
536         if (bc == null) {
537             throw new RSIllegalArgumentException("Bitmap has an unsupported format for this operation");
538         }
539         switch (bc) {
540         case ALPHA_8:
541             if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
542                 throw new RSIllegalArgumentException("Allocation kind is " +
543                                                      mType.getElement().mKind + ", type " +
544                                                      mType.getElement().mType +
545                                                      " of " + mType.getElement().getBytesSize() +
546                                                      " bytes, passed bitmap was " + bc);
547             }
548             break;
549         case ARGB_8888:
550             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
551                 (mType.getElement().getBytesSize() != 4)) {
552                 throw new RSIllegalArgumentException("Allocation kind is " +
553                                                      mType.getElement().mKind + ", type " +
554                                                      mType.getElement().mType +
555                                                      " of " + mType.getElement().getBytesSize() +
556                                                      " bytes, passed bitmap was " + bc);
557             }
558             break;
559         case RGB_565:
560             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
561                 (mType.getElement().getBytesSize() != 2)) {
562                 throw new RSIllegalArgumentException("Allocation kind is " +
563                                                      mType.getElement().mKind + ", type " +
564                                                      mType.getElement().mType +
565                                                      " of " + mType.getElement().getBytesSize() +
566                                                      " bytes, passed bitmap was " + bc);
567             }
568             break;
569         case ARGB_4444:
570             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
571                 (mType.getElement().getBytesSize() != 2)) {
572                 throw new RSIllegalArgumentException("Allocation kind is " +
573                                                      mType.getElement().mKind + ", type " +
574                                                      mType.getElement().mType +
575                                                      " of " + mType.getElement().getBytesSize() +
576                                                      " bytes, passed bitmap was " + bc);
577             }
578             break;
579 
580         }
581     }
582 
validateBitmapSize(Bitmap b)583     private void validateBitmapSize(Bitmap b) {
584         if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) {
585             throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
586         }
587     }
588 
copyFromUnchecked(Object array, Element.DataType dt, int arrayLen)589     private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
590         Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
591         mRS.validate();
592         if (mCurrentDimZ > 0) {
593             copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
594         } else if (mCurrentDimY > 0) {
595             copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
596         } else {
597             copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
598         }
599         Trace.traceEnd(RenderScript.TRACE_TAG);
600     }
601 
602     /**
603      * Copy into this Allocation from an array. This method does not guarantee
604      * that the Allocation is compatible with the input buffer; it copies memory
605      * without reinterpretation.
606      *
607      * @param array The source data array
608      */
copyFromUnchecked(Object array)609     public void copyFromUnchecked(Object array) {
610         Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
611         copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
612                           java.lang.reflect.Array.getLength(array));
613         Trace.traceEnd(RenderScript.TRACE_TAG);
614     }
615 
616     /**
617      * Copy into this Allocation from an array. This method does not guarantee
618      * that the Allocation is compatible with the input buffer; it copies memory
619      * without reinterpretation.
620      *
621      * @param d the source data array
622      */
copyFromUnchecked(int[] d)623     public void copyFromUnchecked(int[] d) {
624         copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
625     }
626 
627     /**
628      * Copy into this Allocation from an array. This method does not guarantee
629      * that the Allocation is compatible with the input buffer; it copies memory
630      * without reinterpretation.
631      *
632      * @param d the source data array
633      */
copyFromUnchecked(short[] d)634     public void copyFromUnchecked(short[] d) {
635         copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
636     }
637 
638     /**
639      * Copy into this Allocation from an array. This method does not guarantee
640      * that the Allocation is compatible with the input buffer; it copies memory
641      * without reinterpretation.
642      *
643      * @param d the source data array
644      */
copyFromUnchecked(byte[] d)645     public void copyFromUnchecked(byte[] d) {
646         copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
647     }
648 
649     /**
650      * Copy into this Allocation from an array. This method does not guarantee
651      * that the Allocation is compatible with the input buffer; it copies memory
652      * without reinterpretation.
653      *
654      * @param d the source data array
655      */
copyFromUnchecked(float[] d)656     public void copyFromUnchecked(float[] d) {
657         copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
658     }
659 
660 
661     /**
662      * Copy into this Allocation from an array.  This variant is type checked
663      * and will generate exceptions if the Allocation's {@link
664      * android.renderscript.Element} does not match the array's
665      * primitive type.
666      *
667      * @param array The source data array
668      */
copyFrom(Object array)669     public void copyFrom(Object array) {
670         Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
671         copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
672                           java.lang.reflect.Array.getLength(array));
673         Trace.traceEnd(RenderScript.TRACE_TAG);
674     }
675 
676     /**
677      * Copy into this Allocation from an array.  This variant is type checked
678      * and will generate exceptions if the Allocation's {@link
679      * android.renderscript.Element} is not a 32 bit integer type.
680      *
681      * @param d the source data array
682      */
copyFrom(int[] d)683     public void copyFrom(int[] d) {
684         validateIsInt32();
685         copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
686     }
687 
688     /**
689      * Copy into this Allocation from an array.  This variant is type checked
690      * and will generate exceptions if the Allocation's {@link
691      * android.renderscript.Element} is not a 16 bit integer type.
692      *
693      * @param d the source data array
694      */
copyFrom(short[] d)695     public void copyFrom(short[] d) {
696         validateIsInt16();
697         copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
698     }
699 
700     /**
701      * Copy into this Allocation from an array.  This variant is type checked
702      * and will generate exceptions if the Allocation's {@link
703      * android.renderscript.Element} is not an 8 bit integer type.
704      *
705      * @param d the source data array
706      */
copyFrom(byte[] d)707     public void copyFrom(byte[] d) {
708         validateIsInt8();
709         copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
710     }
711 
712     /**
713      * Copy into this Allocation from an array.  This variant is type checked
714      * and will generate exceptions if the Allocation's {@link
715      * android.renderscript.Element} is not a 32 bit float type.
716      *
717      * @param d the source data array
718      */
copyFrom(float[] d)719     public void copyFrom(float[] d) {
720         validateIsFloat32();
721         copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
722     }
723 
724     /**
725      * Copy into an Allocation from a {@link android.graphics.Bitmap}.  The
726      * height, width, and format of the bitmap must match the existing
727      * allocation.
728      *
729      * <p>If the {@link android.graphics.Bitmap} is the same as the {@link
730      * android.graphics.Bitmap} used to create the Allocation with {@link
731      * #createFromBitmap} and {@link #USAGE_SHARED} is set on the Allocation,
732      * this will synchronize the Allocation with the latest data from the {@link
733      * android.graphics.Bitmap}, potentially avoiding the actual copy.</p>
734      *
735      * @param b the source bitmap
736      */
copyFrom(Bitmap b)737     public void copyFrom(Bitmap b) {
738         Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
739         mRS.validate();
740         if (b.getConfig() == null) {
741             Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
742             Canvas c = new Canvas(newBitmap);
743             c.drawBitmap(b, 0, 0, null);
744             copyFrom(newBitmap);
745             return;
746         }
747         validateBitmapSize(b);
748         validateBitmapFormat(b);
749         mRS.nAllocationCopyFromBitmap(getID(mRS), b);
750         Trace.traceEnd(RenderScript.TRACE_TAG);
751     }
752 
753     /**
754      * Copy an Allocation from an Allocation.  The types of both allocations
755      * must be identical.
756      *
757      * @param a the source allocation
758      */
copyFrom(Allocation a)759     public void copyFrom(Allocation a) {
760         Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
761         mRS.validate();
762         if (!mType.equals(a.getType())) {
763             throw new RSIllegalArgumentException("Types of allocations must match.");
764         }
765         copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
766         Trace.traceEnd(RenderScript.TRACE_TAG);
767     }
768 
769     /**
770      * This is only intended to be used by auto-generated code reflected from
771      * the RenderScript script files and should not be used by developers.
772      *
773      * @param xoff
774      * @param fp
775      */
setFromFieldPacker(int xoff, FieldPacker fp)776     public void setFromFieldPacker(int xoff, FieldPacker fp) {
777         mRS.validate();
778         int eSize = mType.mElement.getBytesSize();
779         final byte[] data = fp.getData();
780         int data_length = fp.getPos();
781 
782         int count = data_length / eSize;
783         if ((eSize * count) != data_length) {
784             throw new RSIllegalArgumentException("Field packer length " + data_length +
785                                                " not divisible by element size " + eSize + ".");
786         }
787         copy1DRangeFromUnchecked(xoff, count, data);
788     }
789 
790     /**
791      * This is only intended to be used by auto-generated code reflected from
792      * the RenderScript script files.
793      *
794      * @param xoff
795      * @param component_number
796      * @param fp
797      */
setFromFieldPacker(int xoff, int component_number, FieldPacker fp)798     public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
799         mRS.validate();
800         if (component_number >= mType.mElement.mElements.length) {
801             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
802         }
803         if(xoff < 0) {
804             throw new RSIllegalArgumentException("Offset must be >= 0.");
805         }
806 
807         final byte[] data = fp.getData();
808         int data_length = fp.getPos();
809         int eSize = mType.mElement.mElements[component_number].getBytesSize();
810         eSize *= mType.mElement.mArraySizes[component_number];
811 
812         if (data_length != eSize) {
813             throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
814                                                " does not match component size " + eSize + ".");
815         }
816 
817         mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
818                                      component_number, data, data_length);
819     }
820 
data1DChecks(int off, int count, int len, int dataSize)821     private void data1DChecks(int off, int count, int len, int dataSize) {
822         mRS.validate();
823         if(off < 0) {
824             throw new RSIllegalArgumentException("Offset must be >= 0.");
825         }
826         if(count < 1) {
827             throw new RSIllegalArgumentException("Count must be >= 1.");
828         }
829         if((off + count) > mCurrentCount) {
830             throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
831                                                ", got " + count + " at offset " + off + ".");
832         }
833         if(len < dataSize) {
834             throw new RSIllegalArgumentException("Array too small for allocation type.");
835         }
836     }
837 
838     /**
839      * Generate a mipmap chain. This is only valid if the Type of the Allocation
840      * includes mipmaps.
841      *
842      * <p>This function will generate a complete set of mipmaps from the top
843      * level LOD and place them into the script memory space.</p>
844      *
845      * <p>If the Allocation is also using other memory spaces, a call to {@link
846      * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p>
847      */
generateMipmaps()848     public void generateMipmaps() {
849         mRS.nAllocationGenerateMipmaps(getID(mRS));
850     }
851 
copy1DRangeFromUnchecked(int off, int count, Object array, Element.DataType dt, int arrayLen)852     private void copy1DRangeFromUnchecked(int off, int count, Object array,
853                                           Element.DataType dt, int arrayLen) {
854         Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
855         final int dataSize = mType.mElement.getBytesSize() * count;
856         data1DChecks(off, count, arrayLen * dt.mSize, dataSize);
857         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt);
858         Trace.traceEnd(RenderScript.TRACE_TAG);
859     }
860 
861     /**
862      * Copy an array into part of this Allocation.  This method does not
863      * guarantee that the Allocation is compatible with the input buffer.
864      *
865      * @param off The offset of the first element to be copied.
866      * @param count The number of elements to be copied.
867      * @param array The source data array
868      */
copy1DRangeFromUnchecked(int off, int count, Object array)869     public void copy1DRangeFromUnchecked(int off, int count, Object array) {
870         copy1DRangeFromUnchecked(off, count, array,
871                                  validateObjectIsPrimitiveArray(array, false),
872                                  java.lang.reflect.Array.getLength(array));
873     }
874 
875     /**
876      * Copy an array into part of this Allocation.  This method does not
877      * guarantee that the Allocation is compatible with the input buffer.
878      *
879      * @param off The offset of the first element to be copied.
880      * @param count The number of elements to be copied.
881      * @param d the source data array
882      */
copy1DRangeFromUnchecked(int off, int count, int[] d)883     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
884         copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
885     }
886 
887     /**
888      * Copy an array into part of this Allocation.  This method does not
889      * guarantee that the Allocation is compatible with the input buffer.
890      *
891      * @param off The offset of the first element to be copied.
892      * @param count The number of elements to be copied.
893      * @param d the source data array
894      */
copy1DRangeFromUnchecked(int off, int count, short[] d)895     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
896         copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
897     }
898 
899     /**
900      * Copy an array into part of this Allocation.  This method does not
901      * guarantee that the Allocation is compatible with the input buffer.
902      *
903      * @param off The offset of the first element to be copied.
904      * @param count The number of elements to be copied.
905      * @param d the source data array
906      */
copy1DRangeFromUnchecked(int off, int count, byte[] d)907     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
908         copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
909     }
910 
911     /**
912      * Copy an array into part of this Allocation.  This method does not
913      * guarantee that the Allocation is compatible with the input buffer.
914      *
915      * @param off The offset of the first element to be copied.
916      * @param count The number of elements to be copied.
917      * @param d the source data array
918      */
copy1DRangeFromUnchecked(int off, int count, float[] d)919     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
920         copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
921     }
922 
923 
924     /**
925      * Copy an array into part of this Allocation.  This variant is type checked
926      * and will generate exceptions if the Allocation type does not
927      * match the component type of the array passed in.
928      *
929      * @param off The offset of the first element to be copied.
930      * @param count The number of elements to be copied.
931      * @param array The source data array.
932      */
copy1DRangeFrom(int off, int count, Object array)933     public void copy1DRangeFrom(int off, int count, Object array) {
934         copy1DRangeFromUnchecked(off, count, array,
935                                  validateObjectIsPrimitiveArray(array, true),
936                                  java.lang.reflect.Array.getLength(array));
937     }
938 
939     /**
940      * Copy an array into part of this Allocation.  This variant is type checked
941      * and will generate exceptions if the Allocation type is not a 32 bit
942      * integer type.
943      *
944      * @param off The offset of the first element to be copied.
945      * @param count The number of elements to be copied.
946      * @param d the source data array
947      */
copy1DRangeFrom(int off, int count, int[] d)948     public void copy1DRangeFrom(int off, int count, int[] d) {
949         validateIsInt32();
950         copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
951     }
952 
953     /**
954      * Copy an array into part of this Allocation.  This variant is type checked
955      * and will generate exceptions if the Allocation type is not a 16 bit
956      * integer type.
957      *
958      * @param off The offset of the first element to be copied.
959      * @param count The number of elements to be copied.
960      * @param d the source data array
961      */
copy1DRangeFrom(int off, int count, short[] d)962     public void copy1DRangeFrom(int off, int count, short[] d) {
963         validateIsInt16();
964         copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
965     }
966 
967     /**
968      * Copy an array into part of this Allocation.  This variant is type checked
969      * and will generate exceptions if the Allocation type is not an 8 bit
970      * integer type.
971      *
972      * @param off The offset of the first element to be copied.
973      * @param count The number of elements to be copied.
974      * @param d the source data array
975      */
copy1DRangeFrom(int off, int count, byte[] d)976     public void copy1DRangeFrom(int off, int count, byte[] d) {
977         validateIsInt8();
978         copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
979     }
980 
981     /**
982      * Copy an array into part of this Allocation.  This variant is type checked
983      * and will generate exceptions if the Allocation type is not a 32 bit float
984      * type.
985      *
986      * @param off The offset of the first element to be copied.
987      * @param count The number of elements to be copied.
988      * @param d the source data array.
989      */
copy1DRangeFrom(int off, int count, float[] d)990     public void copy1DRangeFrom(int off, int count, float[] d) {
991         validateIsFloat32();
992         copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
993     }
994 
995      /**
996      * Copy part of an Allocation into this Allocation.
997      *
998      * @param off The offset of the first element to be copied.
999      * @param count The number of elements to be copied.
1000      * @param data the source data allocation.
1001      * @param dataOff off The offset of the first element in data to
1002      *          be copied.
1003      */
copy1DRangeFrom(int off, int count, Allocation data, int dataOff)1004     public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
1005         Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
1006         mRS.nAllocationData2D(getIDSafe(), off, 0,
1007                               mSelectedLOD, mSelectedFace.mID,
1008                               count, 1, data.getID(mRS), dataOff, 0,
1009                               data.mSelectedLOD, data.mSelectedFace.mID);
1010     }
1011 
validate2DRange(int xoff, int yoff, int w, int h)1012     private void validate2DRange(int xoff, int yoff, int w, int h) {
1013         if (mAdaptedAllocation != null) {
1014 
1015         } else {
1016 
1017             if (xoff < 0 || yoff < 0) {
1018                 throw new RSIllegalArgumentException("Offset cannot be negative.");
1019             }
1020             if (h < 0 || w < 0) {
1021                 throw new RSIllegalArgumentException("Height or width cannot be negative.");
1022             }
1023             if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
1024                 throw new RSIllegalArgumentException("Updated region larger than allocation.");
1025             }
1026         }
1027     }
1028 
copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array, Element.DataType dt, int arrayLen)1029     void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array,
1030                                   Element.DataType dt, int arrayLen) {
1031         Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
1032         mRS.validate();
1033         validate2DRange(xoff, yoff, w, h);
1034         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
1035                               array, arrayLen * dt.mSize, dt);
1036         Trace.traceEnd(RenderScript.TRACE_TAG);
1037     }
1038 
1039     /**
1040      * Copy from an array into a rectangular region in this Allocation.  The
1041      * array is assumed to be tightly packed.
1042      *
1043      * @param xoff X offset of the region to update in this Allocation
1044      * @param yoff Y offset of the region to update in this Allocation
1045      * @param w Width of the region to update
1046      * @param h Height of the region to update
1047      * @param array Data to be placed into the Allocation
1048      */
copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array)1049     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) {
1050         Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1051         copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
1052                                  validateObjectIsPrimitiveArray(array, true),
1053                                  java.lang.reflect.Array.getLength(array));
1054         Trace.traceEnd(RenderScript.TRACE_TAG);
1055     }
1056 
1057     /**
1058      * Copy from an array into a rectangular region in this Allocation.  The
1059      * array is assumed to be tightly packed.
1060      *
1061      * @param xoff X offset of the region to update in this Allocation
1062      * @param yoff Y offset of the region to update in this Allocation
1063      * @param w Width of the region to update
1064      * @param h Height of the region to update
1065      * @param data to be placed into the Allocation
1066      */
copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data)1067     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
1068         validateIsInt8();
1069         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1070                                  Element.DataType.SIGNED_8, data.length);
1071     }
1072 
1073     /**
1074      * Copy from an array into a rectangular region in this Allocation.  The
1075      * array is assumed to be tightly packed.
1076      *
1077      * @param xoff X offset of the region to update in this Allocation
1078      * @param yoff Y offset of the region to update in this Allocation
1079      * @param w Width of the region to update
1080      * @param h Height of the region to update
1081      * @param data to be placed into the Allocation
1082      */
copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data)1083     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
1084         validateIsInt16();
1085         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1086                                  Element.DataType.SIGNED_16, data.length);
1087     }
1088 
1089     /**
1090      * Copy from an array into a rectangular region in this Allocation.  The
1091      * array is assumed to be tightly packed.
1092      *
1093      * @param xoff X offset of the region to update in this Allocation
1094      * @param yoff Y offset of the region to update in this Allocation
1095      * @param w Width of the region to update
1096      * @param h Height of the region to update
1097      * @param data to be placed into the Allocation
1098      */
copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data)1099     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
1100         validateIsInt32();
1101         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1102                                  Element.DataType.SIGNED_32, data.length);
1103     }
1104 
1105     /**
1106      * Copy from an array into a rectangular region in this Allocation.  The
1107      * array is assumed to be tightly packed.
1108      *
1109      * @param xoff X offset of the region to update in this Allocation
1110      * @param yoff Y offset of the region to update in this Allocation
1111      * @param w Width of the region to update
1112      * @param h Height of the region to update
1113      * @param data to be placed into the Allocation
1114      */
copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data)1115     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
1116         validateIsFloat32();
1117         copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1118                                  Element.DataType.FLOAT_32, data.length);
1119     }
1120 
1121     /**
1122      * Copy a rectangular region from an Allocation into a rectangular region in
1123      * this Allocation.
1124      *
1125      * @param xoff X offset of the region in this Allocation
1126      * @param yoff Y offset of the region in this Allocation
1127      * @param w Width of the region to update.
1128      * @param h Height of the region to update.
1129      * @param data source Allocation.
1130      * @param dataXoff X offset in source Allocation
1131      * @param dataYoff Y offset in source Allocation
1132      */
copy2DRangeFrom(int xoff, int yoff, int w, int h, Allocation data, int dataXoff, int dataYoff)1133     public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
1134                                 Allocation data, int dataXoff, int dataYoff) {
1135         Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1136         mRS.validate();
1137         validate2DRange(xoff, yoff, w, h);
1138         mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
1139                               mSelectedLOD, mSelectedFace.mID,
1140                               w, h, data.getID(mRS), dataXoff, dataYoff,
1141                               data.mSelectedLOD, data.mSelectedFace.mID);
1142         Trace.traceEnd(RenderScript.TRACE_TAG);
1143     }
1144 
1145     /**
1146      * Copy a {@link android.graphics.Bitmap} into an Allocation.  The height
1147      * and width of the update will use the height and width of the {@link
1148      * android.graphics.Bitmap}.
1149      *
1150      * @param xoff X offset of the region to update in this Allocation
1151      * @param yoff Y offset of the region to update in this Allocation
1152      * @param data the Bitmap to be copied
1153      */
copy2DRangeFrom(int xoff, int yoff, Bitmap data)1154     public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
1155         Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1156         mRS.validate();
1157         if (data.getConfig() == null) {
1158             Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888);
1159             Canvas c = new Canvas(newBitmap);
1160             c.drawBitmap(data, 0, 0, null);
1161             copy2DRangeFrom(xoff, yoff, newBitmap);
1162             return;
1163         }
1164         validateBitmapFormat(data);
1165         validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
1166         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
1167         Trace.traceEnd(RenderScript.TRACE_TAG);
1168     }
1169 
validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d)1170     private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) {
1171         if (mAdaptedAllocation != null) {
1172 
1173         } else {
1174 
1175             if (xoff < 0 || yoff < 0 || zoff < 0) {
1176                 throw new RSIllegalArgumentException("Offset cannot be negative.");
1177             }
1178             if (h < 0 || w < 0 || d < 0) {
1179                 throw new RSIllegalArgumentException("Height or width cannot be negative.");
1180             }
1181             if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
1182                 throw new RSIllegalArgumentException("Updated region larger than allocation.");
1183             }
1184         }
1185     }
1186 
1187     /**
1188      * @hide
1189      *
1190      */
copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, Object array, Element.DataType dt, int arrayLen)1191     private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
1192                                           Object array, Element.DataType dt, int arrayLen) {
1193         Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
1194         mRS.validate();
1195         validate3DRange(xoff, yoff, zoff, w, h, d);
1196         mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
1197                               array, arrayLen * dt.mSize, dt);
1198         Trace.traceEnd(RenderScript.TRACE_TAG);
1199     }
1200 
1201     /**
1202      * @hide
1203      * Copy a rectangular region from the array into the allocation.
1204      * The array is assumed to be tightly packed.
1205      *
1206      * @param xoff X offset of the region to update in this Allocation
1207      * @param yoff Y offset of the region to update in this Allocation
1208      * @param zoff Z offset of the region to update in this Allocation
1209      * @param w Width of the region to update
1210      * @param h Height of the region to update
1211      * @param d Depth of the region to update
1212      * @param data to be placed into the allocation
1213      */
copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array)1214     public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
1215         Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
1216         copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
1217                                  validateObjectIsPrimitiveArray(array, true),
1218                                  java.lang.reflect.Array.getLength(array));
1219         Trace.traceEnd(RenderScript.TRACE_TAG);
1220     }
1221 
1222     /**
1223      * @hide
1224      * Copy a rectangular region into the allocation from another
1225      * allocation.
1226      *
1227      * @param xoff X offset of the region to update in this Allocation
1228      * @param yoff Y offset of the region to update in this Allocation
1229      * @param zoff Z offset of the region to update in this Allocation
1230      * @param w Width of the region to update.
1231      * @param h Height of the region to update.
1232      * @param d Depth of the region to update.
1233      * @param data source allocation.
1234      * @param dataXoff X offset of the region in the source Allocation
1235      * @param dataYoff Y offset of the region in the source Allocation
1236      * @param dataZoff Z offset of the region in the source Allocation
1237      */
copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Allocation data, int dataXoff, int dataYoff, int dataZoff)1238     public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d,
1239                                 Allocation data, int dataXoff, int dataYoff, int dataZoff) {
1240         mRS.validate();
1241         validate3DRange(xoff, yoff, zoff, w, h, d);
1242         mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
1243                               w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff,
1244                               data.mSelectedLOD);
1245     }
1246 
1247 
1248     /**
1249      * Copy from the Allocation into a {@link android.graphics.Bitmap}.  The
1250      * bitmap must match the dimensions of the Allocation.
1251      *
1252      * @param b The bitmap to be set from the Allocation.
1253      */
copyTo(Bitmap b)1254     public void copyTo(Bitmap b) {
1255         Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
1256         mRS.validate();
1257         validateBitmapFormat(b);
1258         validateBitmapSize(b);
1259         mRS.nAllocationCopyToBitmap(getID(mRS), b);
1260         Trace.traceEnd(RenderScript.TRACE_TAG);
1261     }
1262 
copyTo(Object array, Element.DataType dt, int arrayLen)1263     private void copyTo(Object array, Element.DataType dt, int arrayLen) {
1264         Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
1265         if (dt.mSize * arrayLen < mSize) {
1266             throw new RSIllegalArgumentException(
1267                 "Size of output array cannot be smaller than size of allocation.");
1268         }
1269         mRS.validate();
1270         mRS.nAllocationRead(getID(mRS), array, dt);
1271         Trace.traceEnd(RenderScript.TRACE_TAG);
1272     }
1273 
1274     /**
1275      * Copy from the Allocation into an array.  The array must be at
1276      * least as large as the Allocation.  The
1277      * {@link android.renderscript.Element} must match the component
1278      * type of the array passed in.
1279      *
1280      * @param array The array to be set from the Allocation.
1281      */
copyTo(Object array)1282     public void copyTo(Object array) {
1283         copyTo(array, validateObjectIsPrimitiveArray(array, true),
1284                java.lang.reflect.Array.getLength(array));
1285     }
1286 
1287     /**
1288      * Copy from the Allocation into a byte array.  The array must be at least
1289      * as large as the Allocation.  The allocation must be of an 8 bit integer
1290      * {@link android.renderscript.Element} type.
1291      *
1292      * @param d The array to be set from the Allocation.
1293      */
copyTo(byte[] d)1294     public void copyTo(byte[] d) {
1295         validateIsInt8();
1296         copyTo(d, Element.DataType.SIGNED_8, d.length);
1297     }
1298 
1299     /**
1300      * Copy from the Allocation into a short array.  The array must be at least
1301      * as large as the Allocation.  The allocation must be of an 16 bit integer
1302      * {@link android.renderscript.Element} type.
1303      *
1304      * @param d The array to be set from the Allocation.
1305      */
copyTo(short[] d)1306     public void copyTo(short[] d) {
1307         validateIsInt16();
1308         copyTo(d, Element.DataType.SIGNED_16, d.length);
1309     }
1310 
1311     /**
1312      * Copy from the Allocation into a int array.  The array must be at least as
1313      * large as the Allocation.  The allocation must be of an 32 bit integer
1314      * {@link android.renderscript.Element} type.
1315      *
1316      * @param d The array to be set from the Allocation.
1317      */
copyTo(int[] d)1318     public void copyTo(int[] d) {
1319         validateIsInt32();
1320         copyTo(d, Element.DataType.SIGNED_32, d.length);
1321     }
1322 
1323     /**
1324      * Copy from the Allocation into a float array.  The array must be at least
1325      * as large as the Allocation.  The allocation must be of an 32 bit float
1326      * {@link android.renderscript.Element} type.
1327      *
1328      * @param d The array to be set from the Allocation.
1329      */
copyTo(float[] d)1330     public void copyTo(float[] d) {
1331         validateIsFloat32();
1332         copyTo(d, Element.DataType.FLOAT_32, d.length);
1333     }
1334 
1335     /**
1336      * Resize a 1D allocation.  The contents of the allocation are preserved.
1337      * If new elements are allocated objects are created with null contents and
1338      * the new region is otherwise undefined.
1339      *
1340      * <p>If the new region is smaller the references of any objects outside the
1341      * new region will be released.</p>
1342      *
1343      * <p>A new type will be created with the new dimension.</p>
1344      *
1345      * @param dimX The new size of the allocation.
1346      *
1347      * @deprecated RenderScript objects should be immutable once created.  The
1348      * replacement is to create a new allocation and copy the contents. This
1349      * function will throw an exception if API 21 or higher is used.
1350      */
resize(int dimX)1351     public synchronized void resize(int dimX) {
1352         if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 21) {
1353             throw new RSRuntimeException("Resize is not allowed in API 21+.");
1354         }
1355         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
1356             throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
1357         }
1358         mRS.nAllocationResize1D(getID(mRS), dimX);
1359         mRS.finish();  // Necessary because resize is fifoed and update is async.
1360 
1361         long typeID = mRS.nAllocationGetType(getID(mRS));
1362         mType = new Type(typeID, mRS);
1363         mType.updateFromNative();
1364         updateCacheInfo(mType);
1365     }
1366 
1367 
1368     // creation
1369 
1370     static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
1371     static {
1372         mBitmapOptions.inScaled = false;
1373     }
1374 
1375     /**
1376      * Creates a new Allocation with the given {@link
1377      * android.renderscript.Type}, mipmap flag, and usage flags.
1378      *
1379      * @param type RenderScript type describing data layout
1380      * @param mips specifies desired mipmap behaviour for the
1381      *             allocation
1382      * @param usage bit field specifying how the Allocation is
1383      *              utilized
1384      */
createTyped(RenderScript rs, Type type, MipmapControl mips, int usage)1385     static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
1386         Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped");
1387         rs.validate();
1388         if (type.getID(rs) == 0) {
1389             throw new RSInvalidStateException("Bad Type");
1390         }
1391         long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
1392         if (id == 0) {
1393             throw new RSRuntimeException("Allocation creation failed.");
1394         }
1395         Trace.traceEnd(RenderScript.TRACE_TAG);
1396         return new Allocation(id, rs, type, usage);
1397     }
1398 
1399     /**
1400      * Creates an Allocation with the size specified by the type and no mipmaps
1401      * generated by default
1402      *
1403      * @param rs Context to which the allocation will belong.
1404      * @param type renderscript type describing data layout
1405      * @param usage bit field specifying how the allocation is
1406      *              utilized
1407      *
1408      * @return allocation
1409      */
createTyped(RenderScript rs, Type type, int usage)1410     static public Allocation createTyped(RenderScript rs, Type type, int usage) {
1411         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
1412     }
1413 
1414     /**
1415      * Creates an Allocation for use by scripts with a given {@link
1416      * android.renderscript.Type} and no mipmaps
1417      *
1418      * @param rs Context to which the Allocation will belong.
1419      * @param type RenderScript Type describing data layout
1420      *
1421      * @return allocation
1422      */
createTyped(RenderScript rs, Type type)1423     static public Allocation createTyped(RenderScript rs, Type type) {
1424         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
1425     }
1426 
1427     /**
1428      * Creates an Allocation with a specified number of given elements
1429      *
1430      * @param rs Context to which the Allocation will belong.
1431      * @param e Element to use in the Allocation
1432      * @param count the number of Elements in the Allocation
1433      * @param usage bit field specifying how the Allocation is
1434      *              utilized
1435      *
1436      * @return allocation
1437      */
createSized(RenderScript rs, Element e, int count, int usage)1438     static public Allocation createSized(RenderScript rs, Element e,
1439                                          int count, int usage) {
1440         Trace.traceBegin(RenderScript.TRACE_TAG, "createSized");
1441         rs.validate();
1442         Type.Builder b = new Type.Builder(rs, e);
1443         b.setX(count);
1444         Type t = b.create();
1445 
1446         long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
1447         if (id == 0) {
1448             throw new RSRuntimeException("Allocation creation failed.");
1449         }
1450         Trace.traceEnd(RenderScript.TRACE_TAG);
1451         return new Allocation(id, rs, t, usage);
1452     }
1453 
1454     /**
1455      * Creates an Allocation with a specified number of given elements
1456      *
1457      * @param rs Context to which the Allocation will belong.
1458      * @param e Element to use in the Allocation
1459      * @param count the number of Elements in the Allocation
1460      *
1461      * @return allocation
1462      */
createSized(RenderScript rs, Element e, int count)1463     static public Allocation createSized(RenderScript rs, Element e, int count) {
1464         return createSized(rs, e, count, USAGE_SCRIPT);
1465     }
1466 
elementFromBitmap(RenderScript rs, Bitmap b)1467     static Element elementFromBitmap(RenderScript rs, Bitmap b) {
1468         final Bitmap.Config bc = b.getConfig();
1469         if (bc == Bitmap.Config.ALPHA_8) {
1470             return Element.A_8(rs);
1471         }
1472         if (bc == Bitmap.Config.ARGB_4444) {
1473             return Element.RGBA_4444(rs);
1474         }
1475         if (bc == Bitmap.Config.ARGB_8888) {
1476             return Element.RGBA_8888(rs);
1477         }
1478         if (bc == Bitmap.Config.RGB_565) {
1479             return Element.RGB_565(rs);
1480         }
1481         throw new RSInvalidStateException("Bad bitmap type: " + bc);
1482     }
1483 
typeFromBitmap(RenderScript rs, Bitmap b, MipmapControl mip)1484     static Type typeFromBitmap(RenderScript rs, Bitmap b,
1485                                        MipmapControl mip) {
1486         Element e = elementFromBitmap(rs, b);
1487         Type.Builder tb = new Type.Builder(rs, e);
1488         tb.setX(b.getWidth());
1489         tb.setY(b.getHeight());
1490         tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
1491         return tb.create();
1492     }
1493 
1494     /**
1495      * Creates an Allocation from a {@link android.graphics.Bitmap}.
1496      *
1497      * @param rs Context to which the allocation will belong.
1498      * @param b Bitmap source for the allocation data
1499      * @param mips specifies desired mipmap behaviour for the
1500      *             allocation
1501      * @param usage bit field specifying how the allocation is
1502      *              utilized
1503      *
1504      * @return Allocation containing bitmap data
1505      *
1506      */
createFromBitmap(RenderScript rs, Bitmap b, MipmapControl mips, int usage)1507     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
1508                                               MipmapControl mips,
1509                                               int usage) {
1510         Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap");
1511         rs.validate();
1512 
1513         // WAR undocumented color formats
1514         if (b.getConfig() == null) {
1515             if ((usage & USAGE_SHARED) != 0) {
1516                 throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config.");
1517             }
1518             Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
1519             Canvas c = new Canvas(newBitmap);
1520             c.drawBitmap(b, 0, 0, null);
1521             return createFromBitmap(rs, newBitmap, mips, usage);
1522         }
1523 
1524         Type t = typeFromBitmap(rs, b, mips);
1525 
1526         // enable optimized bitmap path only with no mipmap and script-only usage
1527         if (mips == MipmapControl.MIPMAP_NONE &&
1528             t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
1529             usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) {
1530             long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
1531             if (id == 0) {
1532                 throw new RSRuntimeException("Load failed.");
1533             }
1534 
1535             // keep a reference to the Bitmap around to prevent GC
1536             Allocation alloc = new Allocation(id, rs, t, usage);
1537             alloc.setBitmap(b);
1538             return alloc;
1539         }
1540 
1541 
1542         long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
1543         if (id == 0) {
1544             throw new RSRuntimeException("Load failed.");
1545         }
1546         Trace.traceEnd(RenderScript.TRACE_TAG);
1547         return new Allocation(id, rs, t, usage);
1548     }
1549 
1550     /**
1551      * Returns the handle to a raw buffer that is being managed by the screen
1552      * compositor. This operation is only valid for Allocations with {@link
1553      * #USAGE_IO_INPUT}.
1554      *
1555      * @return Surface object associated with allocation
1556      *
1557      */
getSurface()1558     public Surface getSurface() {
1559         if ((mUsage & USAGE_IO_INPUT) == 0) {
1560             throw new RSInvalidStateException("Allocation is not a surface texture.");
1561         }
1562         return mRS.nAllocationGetSurface(getID(mRS));
1563     }
1564 
1565     /**
1566      * Associate a {@link android.view.Surface} with this Allocation. This
1567      * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}.
1568      *
1569      * @param sur Surface to associate with allocation
1570      */
setSurface(Surface sur)1571     public void setSurface(Surface sur) {
1572         mRS.validate();
1573         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
1574             throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
1575         }
1576 
1577         mRS.nAllocationSetSurface(getID(mRS), sur);
1578     }
1579 
1580     /**
1581      * Creates an Allocation from a {@link android.graphics.Bitmap}.
1582      *
1583      * <p>With target API version 18 or greater, this Allocation will be created
1584      * with {@link #USAGE_SHARED}, {@link #USAGE_SCRIPT}, and {@link
1585      * #USAGE_GRAPHICS_TEXTURE}. With target API version 17 or lower, this
1586      * Allocation will be created with {@link #USAGE_GRAPHICS_TEXTURE}.</p>
1587      *
1588      * @param rs Context to which the allocation will belong.
1589      * @param b bitmap source for the allocation data
1590      *
1591      * @return Allocation containing bitmap data
1592      *
1593      */
createFromBitmap(RenderScript rs, Bitmap b)1594     static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
1595         if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
1596             return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1597                                     USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
1598         }
1599         return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1600                                 USAGE_GRAPHICS_TEXTURE);
1601     }
1602 
1603     /**
1604      * Creates a cubemap Allocation from a {@link android.graphics.Bitmap}
1605      * containing the horizontal list of cube faces. Each face must be a square,
1606      * have the same size as all other faces, and have a width that is a power
1607      * of 2.
1608      *
1609      * @param rs Context to which the allocation will belong.
1610      * @param b Bitmap with cubemap faces layed out in the following
1611      *          format: right, left, top, bottom, front, back
1612      * @param mips specifies desired mipmap behaviour for the cubemap
1613      * @param usage bit field specifying how the cubemap is utilized
1614      *
1615      * @return allocation containing cubemap data
1616      *
1617      */
createCubemapFromBitmap(RenderScript rs, Bitmap b, MipmapControl mips, int usage)1618     static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
1619                                                      MipmapControl mips,
1620                                                      int usage) {
1621         rs.validate();
1622 
1623         int height = b.getHeight();
1624         int width = b.getWidth();
1625 
1626         if (width % 6 != 0) {
1627             throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
1628         }
1629         if (width / 6 != height) {
1630             throw new RSIllegalArgumentException("Only square cube map faces supported");
1631         }
1632         boolean isPow2 = (height & (height - 1)) == 0;
1633         if (!isPow2) {
1634             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
1635         }
1636 
1637         Element e = elementFromBitmap(rs, b);
1638         Type.Builder tb = new Type.Builder(rs, e);
1639         tb.setX(height);
1640         tb.setY(height);
1641         tb.setFaces(true);
1642         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
1643         Type t = tb.create();
1644 
1645         long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
1646         if(id == 0) {
1647             throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
1648         }
1649         return new Allocation(id, rs, t, usage);
1650     }
1651 
1652     /**
1653      * Creates a non-mipmapped cubemap Allocation for use as a graphics texture
1654      * from a {@link android.graphics.Bitmap} containing the horizontal list of
1655      * cube faces. Each face must be a square, have the same size as all other
1656      * faces, and have a width that is a power of 2.
1657      *
1658      * @param rs Context to which the allocation will belong.
1659      * @param b bitmap with cubemap faces layed out in the following
1660      *          format: right, left, top, bottom, front, back
1661      *
1662      * @return allocation containing cubemap data
1663      *
1664      */
createCubemapFromBitmap(RenderScript rs, Bitmap b)1665     static public Allocation createCubemapFromBitmap(RenderScript rs,
1666                                                      Bitmap b) {
1667         return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1668                                        USAGE_GRAPHICS_TEXTURE);
1669     }
1670 
1671     /**
1672      * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap}
1673      * objects containing the cube faces. Each face must be a square, have the
1674      * same size as all other faces, and have a width that is a power of 2.
1675      *
1676      * @param rs Context to which the allocation will belong.
1677      * @param xpos cubemap face in the positive x direction
1678      * @param xneg cubemap face in the negative x direction
1679      * @param ypos cubemap face in the positive y direction
1680      * @param yneg cubemap face in the negative y direction
1681      * @param zpos cubemap face in the positive z direction
1682      * @param zneg cubemap face in the negative z direction
1683      * @param mips specifies desired mipmap behaviour for the cubemap
1684      * @param usage bit field specifying how the cubemap is utilized
1685      *
1686      * @return allocation containing cubemap data
1687      *
1688      */
createCubemapFromCubeFaces(RenderScript rs, Bitmap xpos, Bitmap xneg, Bitmap ypos, Bitmap yneg, Bitmap zpos, Bitmap zneg, MipmapControl mips, int usage)1689     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
1690                                                         Bitmap xpos,
1691                                                         Bitmap xneg,
1692                                                         Bitmap ypos,
1693                                                         Bitmap yneg,
1694                                                         Bitmap zpos,
1695                                                         Bitmap zneg,
1696                                                         MipmapControl mips,
1697                                                         int usage) {
1698         int height = xpos.getHeight();
1699         if (xpos.getWidth() != height ||
1700             xneg.getWidth() != height || xneg.getHeight() != height ||
1701             ypos.getWidth() != height || ypos.getHeight() != height ||
1702             yneg.getWidth() != height || yneg.getHeight() != height ||
1703             zpos.getWidth() != height || zpos.getHeight() != height ||
1704             zneg.getWidth() != height || zneg.getHeight() != height) {
1705             throw new RSIllegalArgumentException("Only square cube map faces supported");
1706         }
1707         boolean isPow2 = (height & (height - 1)) == 0;
1708         if (!isPow2) {
1709             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
1710         }
1711 
1712         Element e = elementFromBitmap(rs, xpos);
1713         Type.Builder tb = new Type.Builder(rs, e);
1714         tb.setX(height);
1715         tb.setY(height);
1716         tb.setFaces(true);
1717         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
1718         Type t = tb.create();
1719         Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
1720 
1721         AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
1722         adapter.setFace(Type.CubemapFace.POSITIVE_X);
1723         adapter.copyFrom(xpos);
1724         adapter.setFace(Type.CubemapFace.NEGATIVE_X);
1725         adapter.copyFrom(xneg);
1726         adapter.setFace(Type.CubemapFace.POSITIVE_Y);
1727         adapter.copyFrom(ypos);
1728         adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
1729         adapter.copyFrom(yneg);
1730         adapter.setFace(Type.CubemapFace.POSITIVE_Z);
1731         adapter.copyFrom(zpos);
1732         adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
1733         adapter.copyFrom(zneg);
1734 
1735         return cubemap;
1736     }
1737 
1738     /**
1739      * Creates a non-mipmapped cubemap Allocation for use as a sampler input
1740      * from 6 {@link android.graphics.Bitmap} objects containing the cube
1741      * faces. Each face must be a square, have the same size as all other faces,
1742      * and have a width that is a power of 2.
1743      *
1744      * @param rs Context to which the allocation will belong.
1745      * @param xpos cubemap face in the positive x direction
1746      * @param xneg cubemap face in the negative x direction
1747      * @param ypos cubemap face in the positive y direction
1748      * @param yneg cubemap face in the negative y direction
1749      * @param zpos cubemap face in the positive z direction
1750      * @param zneg cubemap face in the negative z direction
1751      *
1752      * @return allocation containing cubemap data
1753      *
1754      */
createCubemapFromCubeFaces(RenderScript rs, Bitmap xpos, Bitmap xneg, Bitmap ypos, Bitmap yneg, Bitmap zpos, Bitmap zneg)1755     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
1756                                                         Bitmap xpos,
1757                                                         Bitmap xneg,
1758                                                         Bitmap ypos,
1759                                                         Bitmap yneg,
1760                                                         Bitmap zpos,
1761                                                         Bitmap zneg) {
1762         return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
1763                                           zpos, zneg, MipmapControl.MIPMAP_NONE,
1764                                           USAGE_GRAPHICS_TEXTURE);
1765     }
1766 
1767     /**
1768      * Creates an Allocation from the Bitmap referenced
1769      * by resource ID.
1770      *
1771      * @param rs Context to which the allocation will belong.
1772      * @param res application resources
1773      * @param id resource id to load the data from
1774      * @param mips specifies desired mipmap behaviour for the
1775      *             allocation
1776      * @param usage bit field specifying how the allocation is
1777      *              utilized
1778      *
1779      * @return Allocation containing resource data
1780      *
1781      */
createFromBitmapResource(RenderScript rs, Resources res, int id, MipmapControl mips, int usage)1782     static public Allocation createFromBitmapResource(RenderScript rs,
1783                                                       Resources res,
1784                                                       int id,
1785                                                       MipmapControl mips,
1786                                                       int usage) {
1787 
1788         rs.validate();
1789         if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) {
1790             throw new RSIllegalArgumentException("Unsupported usage specified.");
1791         }
1792         Bitmap b = BitmapFactory.decodeResource(res, id);
1793         Allocation alloc = createFromBitmap(rs, b, mips, usage);
1794         b.recycle();
1795         return alloc;
1796     }
1797 
1798     /**
1799      * Creates a non-mipmapped Allocation to use as a graphics texture from the
1800      * {@link android.graphics.Bitmap} referenced by resource ID.
1801      *
1802      * <p>With target API version 18 or greater, this allocation will be created
1803      * with {@link #USAGE_SCRIPT} and {@link #USAGE_GRAPHICS_TEXTURE}. With
1804      * target API version 17 or lower, this allocation will be created with
1805      * {@link #USAGE_GRAPHICS_TEXTURE}.</p>
1806      *
1807      * @param rs Context to which the allocation will belong.
1808      * @param res application resources
1809      * @param id resource id to load the data from
1810      *
1811      * @return Allocation containing resource data
1812      *
1813      */
createFromBitmapResource(RenderScript rs, Resources res, int id)1814     static public Allocation createFromBitmapResource(RenderScript rs,
1815                                                       Resources res,
1816                                                       int id) {
1817         if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
1818             return createFromBitmapResource(rs, res, id,
1819                                             MipmapControl.MIPMAP_NONE,
1820                                             USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
1821         }
1822         return createFromBitmapResource(rs, res, id,
1823                                         MipmapControl.MIPMAP_NONE,
1824                                         USAGE_GRAPHICS_TEXTURE);
1825     }
1826 
1827     /**
1828      * Creates an Allocation containing string data encoded in UTF-8 format.
1829      *
1830      * @param rs Context to which the allocation will belong.
1831      * @param str string to create the allocation from
1832      * @param usage bit field specifying how the allocaiton is
1833      *              utilized
1834      *
1835      */
createFromString(RenderScript rs, String str, int usage)1836     static public Allocation createFromString(RenderScript rs,
1837                                               String str,
1838                                               int usage) {
1839         rs.validate();
1840         byte[] allocArray = null;
1841         try {
1842             allocArray = str.getBytes("UTF-8");
1843             Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
1844             alloc.copyFrom(allocArray);
1845             return alloc;
1846         }
1847         catch (Exception e) {
1848             throw new RSRuntimeException("Could not convert string to utf-8.");
1849         }
1850     }
1851 
1852     /**
1853      * Interface to handle notification when new buffers are available via
1854      * {@link #USAGE_IO_INPUT}. An application will receive one notification
1855      * when a buffer is available. Additional buffers will not trigger new
1856      * notifications until a buffer is processed.
1857      */
1858     public interface OnBufferAvailableListener {
onBufferAvailable(Allocation a)1859         public void onBufferAvailable(Allocation a);
1860     }
1861 
1862     /**
1863      * Set a notification handler for {@link #USAGE_IO_INPUT}.
1864      *
1865      * @param callback instance of the OnBufferAvailableListener
1866      *                 class to be called when buffer arrive.
1867      */
setOnBufferAvailableListener(OnBufferAvailableListener callback)1868     public void setOnBufferAvailableListener(OnBufferAvailableListener callback) {
1869         synchronized(mAllocationMap) {
1870             mAllocationMap.put(new Long(getID(mRS)), this);
1871             mBufferNotifier = callback;
1872         }
1873     }
1874 
sendBufferNotification(long id)1875     static void sendBufferNotification(long id) {
1876         synchronized(mAllocationMap) {
1877             Allocation a = mAllocationMap.get(new Long(id));
1878 
1879             if ((a != null) && (a.mBufferNotifier != null)) {
1880                 a.mBufferNotifier.onBufferAvailable(a);
1881             }
1882         }
1883     }
1884 
1885 }
1886