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