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 android.content.res.Resources;
     22 import android.content.res.AssetManager;
     23 import android.graphics.Bitmap;
     24 import android.graphics.BitmapFactory;
     25 import android.view.Surface;
     26 import android.graphics.SurfaceTexture;
     27 import android.util.Log;
     28 import android.util.TypedValue;
     29 
     30 /**
     31  * <p>
     32  * Memory allocation class for renderscript.  An allocation combines a
     33  * {@link android.renderscript.Type} with the memory to provide storage for user data and objects.
     34  * This implies that all memory in Renderscript is typed.
     35  * </p>
     36  *
     37  * <p>Allocations are the primary way data moves into and out of scripts. Memory is user
     38  * synchronized and it's possible for allocations to exist in multiple memory spaces
     39  * concurrently. Currently those spaces are:</p>
     40  * <ul>
     41  * <li>Script: accessable by RS scripts.</li>
     42  * <li>Graphics Texture: accessable as a graphics texture.</li>
     43  * <li>Graphics Vertex: accessable as graphical vertex data.</li>
     44  * <li>Graphics Constants: Accessable as constants in user shaders</li>
     45  * </ul>
     46  * </p>
     47  * <p>
     48  * For example, when creating a allocation for a texture, the user can
     49  * specify its memory spaces as both script and textures. This means that it can both
     50  * be used as script binding and as a GPU texture for rendering. To maintain
     51  * synchronization if a script modifies an allocation used by other targets it must
     52  * call a synchronizing function to push the updates to the memory, otherwise the results
     53  * are undefined.
     54  * </p>
     55  * <p>By default, Android system side updates are always applied to the script accessable
     56  * memory. If this is not present, they are then applied to the various HW
     57  * memory types.  A {@link android.renderscript.Allocation#syncAll syncAll()}
     58  * call is necessary after the script data is updated to
     59  * keep the other memory spaces in sync.</p>
     60  *
     61  * <p>Allocation data is uploaded in one of two primary ways. For simple
     62  * arrays there are copyFrom() functions that take an array from the control code and
     63  * copy it to the slave memory store. Both type checked and unchecked copies are provided.
     64  * The unchecked variants exist to allow apps to copy over arrays of structures from a
     65  * control language that does not support structures.</p>
     66  *
     67  * <div class="special reference">
     68  * <h3>Developer Guides</h3>
     69  * <p>For more information about creating an application that uses Renderscript, read the
     70  * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
     71  * </div>
     72  **/
     73 public class Allocation extends BaseObj {
     74     Type mType;
     75     Bitmap mBitmap;
     76     int mUsage;
     77     Allocation mAdaptedAllocation;
     78 
     79     boolean mConstrainedLOD;
     80     boolean mConstrainedFace;
     81     boolean mConstrainedY;
     82     boolean mConstrainedZ;
     83     boolean mReadAllowed = true;
     84     boolean mWriteAllowed = true;
     85     int mSelectedY;
     86     int mSelectedZ;
     87     int mSelectedLOD;
     88     Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
     89 
     90     int mCurrentDimX;
     91     int mCurrentDimY;
     92     int mCurrentDimZ;
     93     int mCurrentCount;
     94 
     95 
     96     /**
     97      * The usage of the allocation.  These signal to renderscript
     98      * where to place the allocation in memory.
     99      *
    100      * SCRIPT The allocation will be bound to and accessed by
    101      * scripts.
    102      */
    103     public static final int USAGE_SCRIPT = 0x0001;
    104 
    105     /**
    106      * GRAPHICS_TEXTURE The allocation will be used as a texture
    107      * source by one or more graphics programs.
    108      *
    109      */
    110     public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
    111 
    112     /**
    113      * GRAPHICS_VERTEX The allocation will be used as a graphics
    114      * mesh.
    115      *
    116      */
    117     public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
    118 
    119 
    120     /**
    121      * GRAPHICS_CONSTANTS The allocation will be used as the source
    122      * of shader constants by one or more programs.
    123      *
    124      */
    125     public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
    126 
    127     /**
    128      * USAGE_GRAPHICS_RENDER_TARGET The allocation will be used as a
    129      * target for offscreen rendering
    130      *
    131      */
    132     public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
    133 
    134     /**
    135      * USAGE_IO_INPUT The allocation will be used as SurfaceTexture
    136      * consumer.  This usage will cause the allocation to be created
    137      * read only.
    138      *
    139      */
    140     public static final int USAGE_IO_INPUT = 0x0020;
    141 
    142     /**
    143      * USAGE_IO_OUTPUT The allocation will be used as a
    144      * SurfaceTexture producer.  The dimensions and format of the
    145      * SurfaceTexture will be forced to those of the allocation.
    146      *
    147      */
    148     public static final int USAGE_IO_OUTPUT = 0x0040;
    149 
    150     /**
    151      * Controls mipmap behavior when using the bitmap creation and
    152      * update functions.
    153      */
    154     public enum MipmapControl {
    155         /**
    156          * No mipmaps will be generated and the type generated from the
    157          * incoming bitmap will not contain additional LODs.
    158          */
    159         MIPMAP_NONE(0),
    160 
    161         /**
    162          * A Full mipmap chain will be created in script memory.  The
    163          * type of the allocation will contain a full mipmap chain.  On
    164          * upload to graphics the full chain will be transfered.
    165          */
    166         MIPMAP_FULL(1),
    167 
    168         /**
    169          * The type of the allocation will be the same as MIPMAP_NONE.
    170          * It will not contain mipmaps.  On upload to graphics the
    171          * graphics copy of the allocation data will contain a full
    172          * mipmap chain generated from the top level in script memory.
    173          */
    174         MIPMAP_ON_SYNC_TO_TEXTURE(2);
    175 
    176         int mID;
    177         MipmapControl(int id) {
    178             mID = id;
    179         }
    180     }
    181 
    182 
    183     private int getIDSafe() {
    184         if (mAdaptedAllocation != null) {
    185             return mAdaptedAllocation.getID(mRS);
    186         }
    187         return getID(mRS);
    188     }
    189 
    190 
    191    /**
    192      * Get the element of the type of the Allocation.
    193      *
    194      * @return Element that describes the structure of data in the
    195      *         allocation
    196      *
    197      */
    198     public Element getElement() {
    199         return mType.getElement();
    200     }
    201 
    202     /**
    203      * Get the usage flags of the Allocation.
    204      *
    205      * @return usage flags associated with the allocation. e.g.
    206      *         script, texture, etc.
    207      *
    208      */
    209     public int getUsage() {
    210         return mUsage;
    211     }
    212 
    213     /**
    214      * Get the size of the Allocation in bytes.
    215      *
    216      * @return size of the Allocation in bytes.
    217      *
    218      */
    219     public int getBytesSize() {
    220         return mType.getCount() * mType.getElement().getBytesSize();
    221     }
    222 
    223     private void updateCacheInfo(Type t) {
    224         mCurrentDimX = t.getX();
    225         mCurrentDimY = t.getY();
    226         mCurrentDimZ = t.getZ();
    227         mCurrentCount = mCurrentDimX;
    228         if (mCurrentDimY > 1) {
    229             mCurrentCount *= mCurrentDimY;
    230         }
    231         if (mCurrentDimZ > 1) {
    232             mCurrentCount *= mCurrentDimZ;
    233         }
    234     }
    235 
    236     Allocation(int id, RenderScript rs, Type t, int usage) {
    237         super(id, rs);
    238         if ((usage & ~(USAGE_SCRIPT |
    239                        USAGE_GRAPHICS_TEXTURE |
    240                        USAGE_GRAPHICS_VERTEX |
    241                        USAGE_GRAPHICS_CONSTANTS |
    242                        USAGE_GRAPHICS_RENDER_TARGET |
    243                        USAGE_IO_INPUT |
    244                        USAGE_IO_OUTPUT)) != 0) {
    245             throw new RSIllegalArgumentException("Unknown usage specified.");
    246         }
    247 
    248         if ((usage & USAGE_IO_INPUT) != 0) {
    249             mWriteAllowed = false;
    250 
    251             if ((usage & ~(USAGE_IO_INPUT |
    252                            USAGE_GRAPHICS_TEXTURE |
    253                            USAGE_SCRIPT)) != 0) {
    254                 throw new RSIllegalArgumentException("Invalid usage combination.");
    255             }
    256         }
    257 
    258         mType = t;
    259         mUsage = usage;
    260 
    261         if (t != null) {
    262             updateCacheInfo(t);
    263         }
    264     }
    265 
    266     private void validateIsInt32() {
    267         if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
    268             (mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
    269             return;
    270         }
    271         throw new RSIllegalArgumentException(
    272             "32 bit integer source does not match allocation type " + mType.mElement.mType);
    273     }
    274 
    275     private void validateIsInt16() {
    276         if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
    277             (mType.mElement.mType == Element.DataType.UNSIGNED_16)) {
    278             return;
    279         }
    280         throw new RSIllegalArgumentException(
    281             "16 bit integer source does not match allocation type " + mType.mElement.mType);
    282     }
    283 
    284     private void validateIsInt8() {
    285         if ((mType.mElement.mType == Element.DataType.SIGNED_8) ||
    286             (mType.mElement.mType == Element.DataType.UNSIGNED_8)) {
    287             return;
    288         }
    289         throw new RSIllegalArgumentException(
    290             "8 bit integer source does not match allocation type " + mType.mElement.mType);
    291     }
    292 
    293     private void validateIsFloat32() {
    294         if (mType.mElement.mType == Element.DataType.FLOAT_32) {
    295             return;
    296         }
    297         throw new RSIllegalArgumentException(
    298             "32 bit float source does not match allocation type " + mType.mElement.mType);
    299     }
    300 
    301     private void validateIsObject() {
    302         if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) ||
    303             (mType.mElement.mType == Element.DataType.RS_TYPE) ||
    304             (mType.mElement.mType == Element.DataType.RS_ALLOCATION) ||
    305             (mType.mElement.mType == Element.DataType.RS_SAMPLER) ||
    306             (mType.mElement.mType == Element.DataType.RS_SCRIPT) ||
    307             (mType.mElement.mType == Element.DataType.RS_MESH) ||
    308             (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) ||
    309             (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) ||
    310             (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) ||
    311             (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) {
    312             return;
    313         }
    314         throw new RSIllegalArgumentException(
    315             "Object source does not match allocation type " + mType.mElement.mType);
    316     }
    317 
    318     @Override
    319     void updateFromNative() {
    320         super.updateFromNative();
    321         int typeID = mRS.nAllocationGetType(getID(mRS));
    322         if(typeID != 0) {
    323             mType = new Type(typeID, mRS);
    324             mType.updateFromNative();
    325             updateCacheInfo(mType);
    326         }
    327     }
    328 
    329     /**
    330      * Get the type of the Allocation.
    331      *
    332      * @return Type
    333      *
    334      */
    335     public Type getType() {
    336         return mType;
    337     }
    338 
    339     /**
    340      * Propagate changes from one usage of the allocation to the
    341      * remaining usages of the allocation.
    342      *
    343      */
    344     public void syncAll(int srcLocation) {
    345         switch (srcLocation) {
    346         case USAGE_SCRIPT:
    347         case USAGE_GRAPHICS_CONSTANTS:
    348         case USAGE_GRAPHICS_TEXTURE:
    349         case USAGE_GRAPHICS_VERTEX:
    350             break;
    351         default:
    352             throw new RSIllegalArgumentException("Source must be exactly one usage type.");
    353         }
    354         mRS.validate();
    355         mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
    356     }
    357 
    358     /**
    359      * Send a buffer to the output stream.  The contents of the
    360      * Allocation will be undefined after this operation.
    361      *
    362      */
    363     public void ioSend() {
    364         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
    365             throw new RSIllegalArgumentException(
    366                 "Can only send buffer if IO_OUTPUT usage specified.");
    367         }
    368         mRS.validate();
    369         mRS.nAllocationIoSend(getID(mRS));
    370     }
    371 
    372     /**
    373      * Delete once code is updated.
    374      * @hide
    375      */
    376     public void ioSendOutput() {
    377         ioSend();
    378     }
    379 
    380     /**
    381      * Receive the latest input into the Allocation.
    382      *
    383      */
    384     public void ioReceive() {
    385         if ((mUsage & USAGE_IO_INPUT) == 0) {
    386             throw new RSIllegalArgumentException(
    387                 "Can only receive if IO_INPUT usage specified.");
    388         }
    389         mRS.validate();
    390         mRS.nAllocationIoReceive(getID(mRS));
    391     }
    392 
    393     /**
    394      * Copy an array of RS objects to the allocation.
    395      *
    396      * @param d Source array.
    397      */
    398     public void copyFrom(BaseObj[] d) {
    399         mRS.validate();
    400         validateIsObject();
    401         if (d.length != mCurrentCount) {
    402             throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
    403                                                  mCurrentCount + ", array length = " + d.length);
    404         }
    405         int i[] = new int[d.length];
    406         for (int ct=0; ct < d.length; ct++) {
    407             i[ct] = d[ct].getID(mRS);
    408         }
    409         copy1DRangeFromUnchecked(0, mCurrentCount, i);
    410     }
    411 
    412     private void validateBitmapFormat(Bitmap b) {
    413         Bitmap.Config bc = b.getConfig();
    414         switch (bc) {
    415         case ALPHA_8:
    416             if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
    417                 throw new RSIllegalArgumentException("Allocation kind is " +
    418                                                      mType.getElement().mKind + ", type " +
    419                                                      mType.getElement().mType +
    420                                                      " of " + mType.getElement().getBytesSize() +
    421                                                      " bytes, passed bitmap was " + bc);
    422             }
    423             break;
    424         case ARGB_8888:
    425             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
    426                 (mType.getElement().getBytesSize() != 4)) {
    427                 throw new RSIllegalArgumentException("Allocation kind is " +
    428                                                      mType.getElement().mKind + ", type " +
    429                                                      mType.getElement().mType +
    430                                                      " of " + mType.getElement().getBytesSize() +
    431                                                      " bytes, passed bitmap was " + bc);
    432             }
    433             break;
    434         case RGB_565:
    435             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
    436                 (mType.getElement().getBytesSize() != 2)) {
    437                 throw new RSIllegalArgumentException("Allocation kind is " +
    438                                                      mType.getElement().mKind + ", type " +
    439                                                      mType.getElement().mType +
    440                                                      " of " + mType.getElement().getBytesSize() +
    441                                                      " bytes, passed bitmap was " + bc);
    442             }
    443             break;
    444         case ARGB_4444:
    445             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
    446                 (mType.getElement().getBytesSize() != 2)) {
    447                 throw new RSIllegalArgumentException("Allocation kind is " +
    448                                                      mType.getElement().mKind + ", type " +
    449                                                      mType.getElement().mType +
    450                                                      " of " + mType.getElement().getBytesSize() +
    451                                                      " bytes, passed bitmap was " + bc);
    452             }
    453             break;
    454 
    455         }
    456     }
    457 
    458     private void validateBitmapSize(Bitmap b) {
    459         if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) {
    460             throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
    461         }
    462     }
    463 
    464     /**
    465      * Copy an allocation from an array.  This variant is not type
    466      * checked which allows an application to fill in structured
    467      * data from an array.
    468      *
    469      * @param d the source data array
    470      */
    471     public void copyFromUnchecked(int[] d) {
    472         mRS.validate();
    473         copy1DRangeFromUnchecked(0, mCurrentCount, d);
    474     }
    475     /**
    476      * Copy an allocation from an array.  This variant is not type
    477      * checked which allows an application to fill in structured
    478      * data from an array.
    479      *
    480      * @param d the source data array
    481      */
    482     public void copyFromUnchecked(short[] d) {
    483         mRS.validate();
    484         copy1DRangeFromUnchecked(0, mCurrentCount, d);
    485     }
    486     /**
    487      * Copy an allocation from an array.  This variant is not type
    488      * checked which allows an application to fill in structured
    489      * data from an array.
    490      *
    491      * @param d the source data array
    492      */
    493     public void copyFromUnchecked(byte[] d) {
    494         mRS.validate();
    495         copy1DRangeFromUnchecked(0, mCurrentCount, d);
    496     }
    497     /**
    498      * Copy an allocation from an array.  This variant is not type
    499      * checked which allows an application to fill in structured
    500      * data from an array.
    501      *
    502      * @param d the source data array
    503      */
    504     public void copyFromUnchecked(float[] d) {
    505         mRS.validate();
    506         copy1DRangeFromUnchecked(0, mCurrentCount, d);
    507     }
    508 
    509     /**
    510      * Copy an allocation from an array.  This variant is type
    511      * checked and will generate exceptions if the Allocation type
    512      * is not a 32 bit integer type.
    513      *
    514      * @param d the source data array
    515      */
    516     public void copyFrom(int[] d) {
    517         mRS.validate();
    518         copy1DRangeFrom(0, mCurrentCount, d);
    519     }
    520 
    521     /**
    522      * Copy an allocation from an array.  This variant is type
    523      * checked and will generate exceptions if the Allocation type
    524      * is not a 16 bit integer type.
    525      *
    526      * @param d the source data array
    527      */
    528     public void copyFrom(short[] d) {
    529         mRS.validate();
    530         copy1DRangeFrom(0, mCurrentCount, d);
    531     }
    532 
    533     /**
    534      * Copy an allocation from an array.  This variant is type
    535      * checked and will generate exceptions if the Allocation type
    536      * is not a 8 bit integer type.
    537      *
    538      * @param d the source data array
    539      */
    540     public void copyFrom(byte[] d) {
    541         mRS.validate();
    542         copy1DRangeFrom(0, mCurrentCount, d);
    543     }
    544 
    545     /**
    546      * Copy an allocation from an array.  This variant is type
    547      * checked and will generate exceptions if the Allocation type
    548      * is not a 32 bit float type.
    549      *
    550      * @param d the source data array
    551      */
    552     public void copyFrom(float[] d) {
    553         mRS.validate();
    554         copy1DRangeFrom(0, mCurrentCount, d);
    555     }
    556 
    557     /**
    558      * Copy an allocation from a bitmap.  The height, width, and
    559      * format of the bitmap must match the existing allocation.
    560      *
    561      * @param b the source bitmap
    562      */
    563     public void copyFrom(Bitmap b) {
    564         mRS.validate();
    565         validateBitmapSize(b);
    566         validateBitmapFormat(b);
    567         mRS.nAllocationCopyFromBitmap(getID(mRS), b);
    568     }
    569 
    570     /**
    571      * This is only intended to be used by auto-generate code reflected from the
    572      * renderscript script files.
    573      *
    574      * @param xoff
    575      * @param fp
    576      */
    577     public void setFromFieldPacker(int xoff, FieldPacker fp) {
    578         mRS.validate();
    579         int eSize = mType.mElement.getBytesSize();
    580         final byte[] data = fp.getData();
    581 
    582         int count = data.length / eSize;
    583         if ((eSize * count) != data.length) {
    584             throw new RSIllegalArgumentException("Field packer length " + data.length +
    585                                                " not divisible by element size " + eSize + ".");
    586         }
    587         copy1DRangeFromUnchecked(xoff, count, data);
    588     }
    589 
    590     /**
    591      * This is only intended to be used by auto-generate code reflected from the
    592      * renderscript script files.
    593      *
    594      * @param xoff
    595      * @param component_number
    596      * @param fp
    597      */
    598     public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
    599         mRS.validate();
    600         if (component_number >= mType.mElement.mElements.length) {
    601             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
    602         }
    603         if(xoff < 0) {
    604             throw new RSIllegalArgumentException("Offset must be >= 0.");
    605         }
    606 
    607         final byte[] data = fp.getData();
    608         int eSize = mType.mElement.mElements[component_number].getBytesSize();
    609         eSize *= mType.mElement.mArraySizes[component_number];
    610 
    611         if (data.length != eSize) {
    612             throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
    613                                                " does not match component size " + eSize + ".");
    614         }
    615 
    616         mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
    617                                      component_number, data, data.length);
    618     }
    619 
    620     private void data1DChecks(int off, int count, int len, int dataSize) {
    621         mRS.validate();
    622         if(off < 0) {
    623             throw new RSIllegalArgumentException("Offset must be >= 0.");
    624         }
    625         if(count < 1) {
    626             throw new RSIllegalArgumentException("Count must be >= 1.");
    627         }
    628         if((off + count) > mCurrentCount) {
    629             throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
    630                                                ", got " + count + " at offset " + off + ".");
    631         }
    632         if(len < dataSize) {
    633             throw new RSIllegalArgumentException("Array too small for allocation type.");
    634         }
    635     }
    636 
    637     /**
    638      * Generate a mipmap chain.  Requires the type of the allocation
    639      * include mipmaps.
    640      *
    641      * This function will generate a complete set of mipmaps from
    642      * the top level lod and place them into the script memoryspace.
    643      *
    644      * If the allocation is also using other memory spaces a
    645      * followup sync will be required.
    646      */
    647     public void generateMipmaps() {
    648         mRS.nAllocationGenerateMipmaps(getID(mRS));
    649     }
    650 
    651     /**
    652      * Copy part of an allocation from an array.  This variant is
    653      * not type checked which allows an application to fill in
    654      * structured data from an array.
    655      *
    656      * @param off The offset of the first element to be copied.
    657      * @param count The number of elements to be copied.
    658      * @param d the source data array
    659      */
    660     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
    661         int dataSize = mType.mElement.getBytesSize() * count;
    662         data1DChecks(off, count, d.length * 4, dataSize);
    663         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
    664     }
    665     /**
    666      * Copy part of an allocation from an array.  This variant is
    667      * not type checked which allows an application to fill in
    668      * structured data from an array.
    669      *
    670      * @param off The offset of the first element to be copied.
    671      * @param count The number of elements to be copied.
    672      * @param d the source data array
    673      */
    674     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
    675         int dataSize = mType.mElement.getBytesSize() * count;
    676         data1DChecks(off, count, d.length * 2, dataSize);
    677         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
    678     }
    679     /**
    680      * Copy part of an allocation from an array.  This variant is
    681      * not type checked which allows an application to fill in
    682      * structured data from an array.
    683      *
    684      * @param off The offset of the first element to be copied.
    685      * @param count The number of elements to be copied.
    686      * @param d the source data array
    687      */
    688     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
    689         int dataSize = mType.mElement.getBytesSize() * count;
    690         data1DChecks(off, count, d.length, dataSize);
    691         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
    692     }
    693     /**
    694      * Copy part of an allocation from an array.  This variant is
    695      * not type checked which allows an application to fill in
    696      * structured data from an array.
    697      *
    698      * @param off The offset of the first element to be copied.
    699      * @param count The number of elements to be copied.
    700      * @param d the source data array
    701      */
    702     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
    703         int dataSize = mType.mElement.getBytesSize() * count;
    704         data1DChecks(off, count, d.length * 4, dataSize);
    705         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
    706     }
    707 
    708     /**
    709      * Copy part of an allocation from an array.  This variant is
    710      * type checked and will generate exceptions if the Allocation
    711      * type is not a 32 bit integer type.
    712      *
    713      * @param off The offset of the first element to be copied.
    714      * @param count The number of elements to be copied.
    715      * @param d the source data array
    716      */
    717     public void copy1DRangeFrom(int off, int count, int[] d) {
    718         validateIsInt32();
    719         copy1DRangeFromUnchecked(off, count, d);
    720     }
    721 
    722     /**
    723      * Copy part of an allocation from an array.  This variant is
    724      * type checked and will generate exceptions if the Allocation
    725      * type is not a 16 bit integer type.
    726      *
    727      * @param off The offset of the first element to be copied.
    728      * @param count The number of elements to be copied.
    729      * @param d the source data array
    730      */
    731     public void copy1DRangeFrom(int off, int count, short[] d) {
    732         validateIsInt16();
    733         copy1DRangeFromUnchecked(off, count, d);
    734     }
    735 
    736     /**
    737      * Copy part of an allocation from an array.  This variant is
    738      * type checked and will generate exceptions if the Allocation
    739      * type is not a 8 bit integer type.
    740      *
    741      * @param off The offset of the first element to be copied.
    742      * @param count The number of elements to be copied.
    743      * @param d the source data array
    744      */
    745     public void copy1DRangeFrom(int off, int count, byte[] d) {
    746         validateIsInt8();
    747         copy1DRangeFromUnchecked(off, count, d);
    748     }
    749 
    750     /**
    751      * Copy part of an allocation from an array.  This variant is
    752      * type checked and will generate exceptions if the Allocation
    753      * type is not a 32 bit float type.
    754      *
    755      * @param off The offset of the first element to be copied.
    756      * @param count The number of elements to be copied.
    757      * @param d the source data array.
    758      */
    759     public void copy1DRangeFrom(int off, int count, float[] d) {
    760         validateIsFloat32();
    761         copy1DRangeFromUnchecked(off, count, d);
    762     }
    763 
    764      /**
    765      * Copy part of an allocation from another allocation.
    766      *
    767      * @param off The offset of the first element to be copied.
    768      * @param count The number of elements to be copied.
    769      * @param data the source data allocation.
    770      * @param dataOff off The offset of the first element in data to
    771      *          be copied.
    772      */
    773     public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
    774         mRS.nAllocationData2D(getIDSafe(), off, 0,
    775                               mSelectedLOD, mSelectedFace.mID,
    776                               count, 1, data.getID(mRS), dataOff, 0,
    777                               data.mSelectedLOD, data.mSelectedFace.mID);
    778     }
    779 
    780     private void validate2DRange(int xoff, int yoff, int w, int h) {
    781         if (mAdaptedAllocation != null) {
    782 
    783         } else {
    784 
    785             if (xoff < 0 || yoff < 0) {
    786                 throw new RSIllegalArgumentException("Offset cannot be negative.");
    787             }
    788             if (h < 0 || w < 0) {
    789                 throw new RSIllegalArgumentException("Height or width cannot be negative.");
    790             }
    791             if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
    792                 throw new RSIllegalArgumentException("Updated region larger than allocation.");
    793             }
    794         }
    795     }
    796 
    797     /**
    798      * Copy a rectangular region from the array into the allocation.
    799      * The incoming array is assumed to be tightly packed.
    800      *
    801      * @param xoff X offset of the region to update
    802      * @param yoff Y offset of the region to update
    803      * @param w Width of the incoming region to update
    804      * @param h Height of the incoming region to update
    805      * @param data to be placed into the allocation
    806      */
    807     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
    808         mRS.validate();
    809         validate2DRange(xoff, yoff, w, h);
    810         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
    811                               w, h, data, data.length);
    812     }
    813 
    814     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
    815         mRS.validate();
    816         validate2DRange(xoff, yoff, w, h);
    817         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
    818                               w, h, data, data.length * 2);
    819     }
    820 
    821     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
    822         mRS.validate();
    823         validate2DRange(xoff, yoff, w, h);
    824         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
    825                               w, h, data, data.length * 4);
    826     }
    827 
    828     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
    829         mRS.validate();
    830         validate2DRange(xoff, yoff, w, h);
    831         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
    832                               w, h, data, data.length * 4);
    833     }
    834 
    835     /**
    836      * Copy a rectangular region into the allocation from another
    837      * allocation.
    838      *
    839      * @param xoff X offset of the region to update.
    840      * @param yoff Y offset of the region to update.
    841      * @param w Width of the incoming region to update.
    842      * @param h Height of the incoming region to update.
    843      * @param data source allocation.
    844      * @param dataXoff X offset in data of the region to update.
    845      * @param dataYoff Y offset in data of the region to update.
    846      */
    847     public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
    848                                 Allocation data, int dataXoff, int dataYoff) {
    849         mRS.validate();
    850         validate2DRange(xoff, yoff, w, h);
    851         mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
    852                               mSelectedLOD, mSelectedFace.mID,
    853                               w, h, data.getID(mRS), dataXoff, dataYoff,
    854                               data.mSelectedLOD, data.mSelectedFace.mID);
    855     }
    856 
    857     /**
    858      * Copy a bitmap into an allocation.  The height and width of
    859      * the update will use the height and width of the incoming
    860      * bitmap.
    861      *
    862      * @param xoff X offset of the region to update
    863      * @param yoff Y offset of the region to update
    864      * @param data the bitmap to be copied
    865      */
    866     public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
    867         mRS.validate();
    868         validateBitmapFormat(data);
    869         validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
    870         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
    871     }
    872 
    873 
    874     /**
    875      * Copy from the Allocation into a Bitmap.  The bitmap must
    876      * match the dimensions of the Allocation.
    877      *
    878      * @param b The bitmap to be set from the Allocation.
    879      */
    880     public void copyTo(Bitmap b) {
    881         mRS.validate();
    882         validateBitmapFormat(b);
    883         validateBitmapSize(b);
    884         mRS.nAllocationCopyToBitmap(getID(mRS), b);
    885     }
    886 
    887     /**
    888      * Copy from the Allocation into a byte array.  The array must
    889      * be at least as large as the Allocation.  The allocation must
    890      * be of an 8 bit elemental type.
    891      *
    892      * @param d The array to be set from the Allocation.
    893      */
    894     public void copyTo(byte[] d) {
    895         validateIsInt8();
    896         mRS.validate();
    897         mRS.nAllocationRead(getID(mRS), d);
    898     }
    899 
    900     /**
    901      * Copy from the Allocation into a short array.  The array must
    902      * be at least as large as the Allocation.  The allocation must
    903      * be of an 16 bit elemental type.
    904      *
    905      * @param d The array to be set from the Allocation.
    906      */
    907     public void copyTo(short[] d) {
    908         validateIsInt16();
    909         mRS.validate();
    910         mRS.nAllocationRead(getID(mRS), d);
    911     }
    912 
    913     /**
    914      * Copy from the Allocation into a int array.  The array must be
    915      * at least as large as the Allocation.  The allocation must be
    916      * of an 32 bit elemental type.
    917      *
    918      * @param d The array to be set from the Allocation.
    919      */
    920     public void copyTo(int[] d) {
    921         validateIsInt32();
    922         mRS.validate();
    923         mRS.nAllocationRead(getID(mRS), d);
    924     }
    925 
    926     /**
    927      * Copy from the Allocation into a float array.  The array must
    928      * be at least as large as the Allocation.  The allocation must
    929      * be of an 32 bit float elemental type.
    930      *
    931      * @param d The array to be set from the Allocation.
    932      */
    933     public void copyTo(float[] d) {
    934         validateIsFloat32();
    935         mRS.validate();
    936         mRS.nAllocationRead(getID(mRS), d);
    937     }
    938 
    939     /**
    940      * Resize a 1D allocation.  The contents of the allocation are
    941      * preserved.  If new elements are allocated objects are created
    942      * with null contents and the new region is otherwise undefined.
    943      *
    944      * If the new region is smaller the references of any objects
    945      * outside the new region will be released.
    946      *
    947      * A new type will be created with the new dimension.
    948      *
    949      * @param dimX The new size of the allocation.
    950      */
    951     public synchronized void resize(int dimX) {
    952         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
    953             throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
    954         }
    955         mRS.nAllocationResize1D(getID(mRS), dimX);
    956         mRS.finish();  // Necessary because resize is fifoed and update is async.
    957 
    958         int typeID = mRS.nAllocationGetType(getID(mRS));
    959         mType = new Type(typeID, mRS);
    960         mType.updateFromNative();
    961         updateCacheInfo(mType);
    962     }
    963 
    964     /**
    965      * Resize a 2D allocation.  The contents of the allocation are
    966      * preserved.  If new elements are allocated objects are created
    967      * with null contents and the new region is otherwise undefined.
    968      *
    969      * If the new region is smaller the references of any objects
    970      * outside the new region will be released.
    971      *
    972      * A new type will be created with the new dimension.
    973      *
    974      * @hide
    975      * @param dimX The new size of the allocation.
    976      * @param dimY The new size of the allocation.
    977      */
    978     public void resize(int dimX, int dimY) {
    979         if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
    980             throw new RSInvalidStateException(
    981                 "Resize only support for 2D allocations at this time.");
    982         }
    983         if (mType.getY() == 0) {
    984             throw new RSInvalidStateException(
    985                 "Resize only support for 2D allocations at this time.");
    986         }
    987         mRS.nAllocationResize2D(getID(mRS), dimX, dimY);
    988         mRS.finish();  // Necessary because resize is fifoed and update is async.
    989 
    990         int typeID = mRS.nAllocationGetType(getID(mRS));
    991         mType = new Type(typeID, mRS);
    992         mType.updateFromNative();
    993         updateCacheInfo(mType);
    994     }
    995 
    996 
    997 
    998     // creation
    999 
   1000     static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
   1001     static {
   1002         mBitmapOptions.inScaled = false;
   1003     }
   1004 
   1005     /**
   1006      *
   1007      * @param type renderscript type describing data layout
   1008      * @param mips specifies desired mipmap behaviour for the
   1009      *             allocation
   1010      * @param usage bit field specifying how the allocation is
   1011      *              utilized
   1012      */
   1013     static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
   1014         rs.validate();
   1015         if (type.getID(rs) == 0) {
   1016             throw new RSInvalidStateException("Bad Type");
   1017         }
   1018         int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
   1019         if (id == 0) {
   1020             throw new RSRuntimeException("Allocation creation failed.");
   1021         }
   1022         return new Allocation(id, rs, type, usage);
   1023     }
   1024 
   1025     /**
   1026      * Creates a renderscript allocation with the size specified by
   1027      * the type and no mipmaps generated by default
   1028      *
   1029      * @param rs Context to which the allocation will belong.
   1030      * @param type renderscript type describing data layout
   1031      * @param usage bit field specifying how the allocation is
   1032      *              utilized
   1033      *
   1034      * @return allocation
   1035      */
   1036     static public Allocation createTyped(RenderScript rs, Type type, int usage) {
   1037         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
   1038     }
   1039 
   1040     /**
   1041      * Creates a renderscript allocation for use by the script with
   1042      * the size specified by the type and no mipmaps generated by
   1043      * default
   1044      *
   1045      * @param rs Context to which the allocation will belong.
   1046      * @param type renderscript type describing data layout
   1047      *
   1048      * @return allocation
   1049      */
   1050     static public Allocation createTyped(RenderScript rs, Type type) {
   1051         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
   1052     }
   1053 
   1054     /**
   1055      * Creates a renderscript allocation with a specified number of
   1056      * given elements
   1057      *
   1058      * @param rs Context to which the allocation will belong.
   1059      * @param e describes what each element of an allocation is
   1060      * @param count specifies the number of element in the allocation
   1061      * @param usage bit field specifying how the allocation is
   1062      *              utilized
   1063      *
   1064      * @return allocation
   1065      */
   1066     static public Allocation createSized(RenderScript rs, Element e,
   1067                                          int count, int usage) {
   1068         rs.validate();
   1069         Type.Builder b = new Type.Builder(rs, e);
   1070         b.setX(count);
   1071         Type t = b.create();
   1072 
   1073         int id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
   1074         if (id == 0) {
   1075             throw new RSRuntimeException("Allocation creation failed.");
   1076         }
   1077         return new Allocation(id, rs, t, usage);
   1078     }
   1079 
   1080     /**
   1081      * Creates a renderscript allocation with a specified number of
   1082      * given elements
   1083      *
   1084      * @param rs Context to which the allocation will belong.
   1085      * @param e describes what each element of an allocation is
   1086      * @param count specifies the number of element in the allocation
   1087      *
   1088      * @return allocation
   1089      */
   1090     static public Allocation createSized(RenderScript rs, Element e, int count) {
   1091         return createSized(rs, e, count, USAGE_SCRIPT);
   1092     }
   1093 
   1094     static Element elementFromBitmap(RenderScript rs, Bitmap b) {
   1095         final Bitmap.Config bc = b.getConfig();
   1096         if (bc == Bitmap.Config.ALPHA_8) {
   1097             return Element.A_8(rs);
   1098         }
   1099         if (bc == Bitmap.Config.ARGB_4444) {
   1100             return Element.RGBA_4444(rs);
   1101         }
   1102         if (bc == Bitmap.Config.ARGB_8888) {
   1103             return Element.RGBA_8888(rs);
   1104         }
   1105         if (bc == Bitmap.Config.RGB_565) {
   1106             return Element.RGB_565(rs);
   1107         }
   1108         throw new RSInvalidStateException("Bad bitmap type: " + bc);
   1109     }
   1110 
   1111     static Type typeFromBitmap(RenderScript rs, Bitmap b,
   1112                                        MipmapControl mip) {
   1113         Element e = elementFromBitmap(rs, b);
   1114         Type.Builder tb = new Type.Builder(rs, e);
   1115         tb.setX(b.getWidth());
   1116         tb.setY(b.getHeight());
   1117         tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
   1118         return tb.create();
   1119     }
   1120 
   1121     /**
   1122      * Creates a renderscript allocation from a bitmap
   1123      *
   1124      * @param rs Context to which the allocation will belong.
   1125      * @param b bitmap source for the allocation data
   1126      * @param mips specifies desired mipmap behaviour for the
   1127      *             allocation
   1128      * @param usage bit field specifying how the allocation is
   1129      *              utilized
   1130      *
   1131      * @return renderscript allocation containing bitmap data
   1132      *
   1133      */
   1134     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
   1135                                               MipmapControl mips,
   1136                                               int usage) {
   1137         rs.validate();
   1138         Type t = typeFromBitmap(rs, b, mips);
   1139 
   1140         int id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
   1141         if (id == 0) {
   1142             throw new RSRuntimeException("Load failed.");
   1143         }
   1144         return new Allocation(id, rs, t, usage);
   1145     }
   1146 
   1147     /**
   1148      *
   1149      *
   1150      * @hide
   1151      *
   1152      */
   1153     public SurfaceTexture getSurfaceTexture() {
   1154         if ((mUsage & USAGE_IO_INPUT) == 0) {
   1155             throw new RSInvalidStateException("Allocation is not a surface texture.");
   1156         }
   1157 
   1158         int id = mRS.nAllocationGetSurfaceTextureID(getID(mRS));
   1159         SurfaceTexture st = new SurfaceTexture(id);
   1160         mRS.nAllocationGetSurfaceTextureID2(getID(mRS), st);
   1161 
   1162         return st;
   1163     }
   1164 
   1165     /**
   1166      * For allocations used with io operations, returns the handle
   1167      * onto a raw buffer that is being managed by the screen
   1168      * compositor.
   1169      *
   1170      * @return Surface object associated with allocation
   1171      *
   1172      */
   1173     public Surface getSurface() {
   1174         return new Surface(getSurfaceTexture());
   1175     }
   1176 
   1177     /**
   1178      * Associate a surface for io output with this allocation
   1179      *
   1180      * @param sur Surface to associate with allocation
   1181      */
   1182     public void setSurface(Surface sur) {
   1183         mRS.validate();
   1184         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
   1185             throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
   1186         }
   1187 
   1188         mRS.nAllocationSetSurface(getID(mRS), sur);
   1189     }
   1190 
   1191     /**
   1192      * @hide
   1193      */
   1194     public void setSurfaceTexture(SurfaceTexture st) {
   1195         mRS.validate();
   1196         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
   1197             throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
   1198         }
   1199 
   1200         Surface s = new Surface(st);
   1201         mRS.nAllocationSetSurface(getID(mRS), s);
   1202     }
   1203 
   1204     /**
   1205      * Creates a non-mipmapped renderscript allocation to use as a
   1206      * graphics texture
   1207      *
   1208      * @param rs Context to which the allocation will belong.
   1209      * @param b bitmap source for the allocation data
   1210      *
   1211      * @return renderscript allocation containing bitmap data
   1212      *
   1213      */
   1214     static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
   1215         return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
   1216                                 USAGE_GRAPHICS_TEXTURE);
   1217     }
   1218 
   1219     /**
   1220      * Creates a cubemap allocation from a bitmap containing the
   1221      * horizontal list of cube faces. Each individual face must be
   1222      * the same size and power of 2
   1223      *
   1224      * @param rs Context to which the allocation will belong.
   1225      * @param b bitmap with cubemap faces layed out in the following
   1226      *          format: right, left, top, bottom, front, back
   1227      * @param mips specifies desired mipmap behaviour for the cubemap
   1228      * @param usage bit field specifying how the cubemap is utilized
   1229      *
   1230      * @return allocation containing cubemap data
   1231      *
   1232      */
   1233     static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
   1234                                                      MipmapControl mips,
   1235                                                      int usage) {
   1236         rs.validate();
   1237 
   1238         int height = b.getHeight();
   1239         int width = b.getWidth();
   1240 
   1241         if (width % 6 != 0) {
   1242             throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
   1243         }
   1244         if (width / 6 != height) {
   1245             throw new RSIllegalArgumentException("Only square cube map faces supported");
   1246         }
   1247         boolean isPow2 = (height & (height - 1)) == 0;
   1248         if (!isPow2) {
   1249             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
   1250         }
   1251 
   1252         Element e = elementFromBitmap(rs, b);
   1253         Type.Builder tb = new Type.Builder(rs, e);
   1254         tb.setX(height);
   1255         tb.setY(height);
   1256         tb.setFaces(true);
   1257         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
   1258         Type t = tb.create();
   1259 
   1260         int id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
   1261         if(id == 0) {
   1262             throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
   1263         }
   1264         return new Allocation(id, rs, t, usage);
   1265     }
   1266 
   1267     /**
   1268      * Creates a non-mipmapped cubemap allocation for use as a
   1269      * graphics texture from a bitmap containing the horizontal list
   1270      * of cube faces. Each individual face must be the same size and
   1271      * power of 2
   1272      *
   1273      * @param rs Context to which the allocation will belong.
   1274      * @param b bitmap with cubemap faces layed out in the following
   1275      *          format: right, left, top, bottom, front, back
   1276      *
   1277      * @return allocation containing cubemap data
   1278      *
   1279      */
   1280     static public Allocation createCubemapFromBitmap(RenderScript rs,
   1281                                                      Bitmap b) {
   1282         return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
   1283                                        USAGE_GRAPHICS_TEXTURE);
   1284     }
   1285 
   1286     /**
   1287      * Creates a cubemap allocation from 6 bitmaps containing
   1288      * the cube faces. All the faces must be the same size and
   1289      * power of 2
   1290      *
   1291      * @param rs Context to which the allocation will belong.
   1292      * @param xpos cubemap face in the positive x direction
   1293      * @param xneg cubemap face in the negative x direction
   1294      * @param ypos cubemap face in the positive y direction
   1295      * @param yneg cubemap face in the negative y direction
   1296      * @param zpos cubemap face in the positive z direction
   1297      * @param zneg cubemap face in the negative z direction
   1298      * @param mips specifies desired mipmap behaviour for the cubemap
   1299      * @param usage bit field specifying how the cubemap is utilized
   1300      *
   1301      * @return allocation containing cubemap data
   1302      *
   1303      */
   1304     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
   1305                                                         Bitmap xpos,
   1306                                                         Bitmap xneg,
   1307                                                         Bitmap ypos,
   1308                                                         Bitmap yneg,
   1309                                                         Bitmap zpos,
   1310                                                         Bitmap zneg,
   1311                                                         MipmapControl mips,
   1312                                                         int usage) {
   1313         int height = xpos.getHeight();
   1314         if (xpos.getWidth() != height ||
   1315             xneg.getWidth() != height || xneg.getHeight() != height ||
   1316             ypos.getWidth() != height || ypos.getHeight() != height ||
   1317             yneg.getWidth() != height || yneg.getHeight() != height ||
   1318             zpos.getWidth() != height || zpos.getHeight() != height ||
   1319             zneg.getWidth() != height || zneg.getHeight() != height) {
   1320             throw new RSIllegalArgumentException("Only square cube map faces supported");
   1321         }
   1322         boolean isPow2 = (height & (height - 1)) == 0;
   1323         if (!isPow2) {
   1324             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
   1325         }
   1326 
   1327         Element e = elementFromBitmap(rs, xpos);
   1328         Type.Builder tb = new Type.Builder(rs, e);
   1329         tb.setX(height);
   1330         tb.setY(height);
   1331         tb.setFaces(true);
   1332         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
   1333         Type t = tb.create();
   1334         Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
   1335 
   1336         AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
   1337         adapter.setFace(Type.CubemapFace.POSITIVE_X);
   1338         adapter.copyFrom(xpos);
   1339         adapter.setFace(Type.CubemapFace.NEGATIVE_X);
   1340         adapter.copyFrom(xneg);
   1341         adapter.setFace(Type.CubemapFace.POSITIVE_Y);
   1342         adapter.copyFrom(ypos);
   1343         adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
   1344         adapter.copyFrom(yneg);
   1345         adapter.setFace(Type.CubemapFace.POSITIVE_Z);
   1346         adapter.copyFrom(zpos);
   1347         adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
   1348         adapter.copyFrom(zneg);
   1349 
   1350         return cubemap;
   1351     }
   1352 
   1353     /**
   1354      * Creates a non-mipmapped cubemap allocation for use as a
   1355      * graphics texture from 6 bitmaps containing
   1356      * the cube faces. All the faces must be the same size and
   1357      * power of 2
   1358      *
   1359      * @param rs Context to which the allocation will belong.
   1360      * @param xpos cubemap face in the positive x direction
   1361      * @param xneg cubemap face in the negative x direction
   1362      * @param ypos cubemap face in the positive y direction
   1363      * @param yneg cubemap face in the negative y direction
   1364      * @param zpos cubemap face in the positive z direction
   1365      * @param zneg cubemap face in the negative z direction
   1366      *
   1367      * @return allocation containing cubemap data
   1368      *
   1369      */
   1370     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
   1371                                                         Bitmap xpos,
   1372                                                         Bitmap xneg,
   1373                                                         Bitmap ypos,
   1374                                                         Bitmap yneg,
   1375                                                         Bitmap zpos,
   1376                                                         Bitmap zneg) {
   1377         return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
   1378                                           zpos, zneg, MipmapControl.MIPMAP_NONE,
   1379                                           USAGE_GRAPHICS_TEXTURE);
   1380     }
   1381 
   1382     /**
   1383      * Creates a renderscript allocation from the bitmap referenced
   1384      * by resource id
   1385      *
   1386      * @param rs Context to which the allocation will belong.
   1387      * @param res application resources
   1388      * @param id resource id to load the data from
   1389      * @param mips specifies desired mipmap behaviour for the
   1390      *             allocation
   1391      * @param usage bit field specifying how the allocation is
   1392      *              utilized
   1393      *
   1394      * @return renderscript allocation containing resource data
   1395      *
   1396      */
   1397     static public Allocation createFromBitmapResource(RenderScript rs,
   1398                                                       Resources res,
   1399                                                       int id,
   1400                                                       MipmapControl mips,
   1401                                                       int usage) {
   1402 
   1403         rs.validate();
   1404         Bitmap b = BitmapFactory.decodeResource(res, id);
   1405         Allocation alloc = createFromBitmap(rs, b, mips, usage);
   1406         b.recycle();
   1407         return alloc;
   1408     }
   1409 
   1410     /**
   1411      * Creates a non-mipmapped renderscript allocation to use as a
   1412      * graphics texture from the bitmap referenced by resource id
   1413      *
   1414      * @param rs Context to which the allocation will belong.
   1415      * @param res application resources
   1416      * @param id resource id to load the data from
   1417      *
   1418      * @return renderscript allocation containing resource data
   1419      *
   1420      */
   1421     static public Allocation createFromBitmapResource(RenderScript rs,
   1422                                                       Resources res,
   1423                                                       int id) {
   1424         return createFromBitmapResource(rs, res, id,
   1425                                         MipmapControl.MIPMAP_NONE,
   1426                                         USAGE_GRAPHICS_TEXTURE);
   1427     }
   1428 
   1429     /**
   1430      * Creates a renderscript allocation containing string data
   1431      * encoded in UTF-8 format
   1432      *
   1433      * @param rs Context to which the allocation will belong.
   1434      * @param str string to create the allocation from
   1435      * @param usage bit field specifying how the allocaiton is
   1436      *              utilized
   1437      *
   1438      */
   1439     static public Allocation createFromString(RenderScript rs,
   1440                                               String str,
   1441                                               int usage) {
   1442         rs.validate();
   1443         byte[] allocArray = null;
   1444         try {
   1445             allocArray = str.getBytes("UTF-8");
   1446             Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
   1447             alloc.copyFrom(allocArray);
   1448             return alloc;
   1449         }
   1450         catch (Exception e) {
   1451             throw new RSRuntimeException("Could not convert string to utf-8.");
   1452         }
   1453     }
   1454 }
   1455 
   1456 
   1457