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