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