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