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