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