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