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