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