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/renderscript/index.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     * @hide
975     * @param dimX The new size of the allocation.
976     * @param dimY The new size of the allocation.
977     */
978    public void resize(int dimX, int dimY) {
979        if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
980            throw new RSInvalidStateException(
981                "Resize only support for 2D allocations at this time.");
982        }
983        if (mType.getY() == 0) {
984            throw new RSInvalidStateException(
985                "Resize only support for 2D allocations at this time.");
986        }
987        mRS.nAllocationResize2D(getID(mRS), dimX, dimY);
988        mRS.finish();  // Necessary because resize is fifoed and update is async.
989
990        int typeID = mRS.nAllocationGetType(getID(mRS));
991        mType = new Type(typeID, mRS);
992        mType.updateFromNative();
993        updateCacheInfo(mType);
994    }
995
996
997
998    // creation
999
1000    static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
1001    static {
1002        mBitmapOptions.inScaled = false;
1003    }
1004
1005    /**
1006     *
1007     * @param type renderscript type describing data layout
1008     * @param mips specifies desired mipmap behaviour for the
1009     *             allocation
1010     * @param usage bit field specifying how the allocation is
1011     *              utilized
1012     */
1013    static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
1014        rs.validate();
1015        if (type.getID(rs) == 0) {
1016            throw new RSInvalidStateException("Bad Type");
1017        }
1018        int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
1019        if (id == 0) {
1020            throw new RSRuntimeException("Allocation creation failed.");
1021        }
1022        return new Allocation(id, rs, type, usage);
1023    }
1024
1025    /**
1026     * Creates a renderscript allocation with the size specified by
1027     * the type and no mipmaps generated by default
1028     *
1029     * @param rs Context to which the allocation will belong.
1030     * @param type renderscript type describing data layout
1031     * @param usage bit field specifying how the allocation is
1032     *              utilized
1033     *
1034     * @return allocation
1035     */
1036    static public Allocation createTyped(RenderScript rs, Type type, int usage) {
1037        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
1038    }
1039
1040    /**
1041     * Creates a renderscript allocation for use by the script with
1042     * the size specified by the type and no mipmaps generated by
1043     * default
1044     *
1045     * @param rs Context to which the allocation will belong.
1046     * @param type renderscript type describing data layout
1047     *
1048     * @return allocation
1049     */
1050    static public Allocation createTyped(RenderScript rs, Type type) {
1051        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
1052    }
1053
1054    /**
1055     * Creates a renderscript allocation with a specified number of
1056     * given elements
1057     *
1058     * @param rs Context to which the allocation will belong.
1059     * @param e describes what each element of an allocation is
1060     * @param count specifies the number of element in the allocation
1061     * @param usage bit field specifying how the allocation is
1062     *              utilized
1063     *
1064     * @return allocation
1065     */
1066    static public Allocation createSized(RenderScript rs, Element e,
1067                                         int count, int usage) {
1068        rs.validate();
1069        Type.Builder b = new Type.Builder(rs, e);
1070        b.setX(count);
1071        Type t = b.create();
1072
1073        int id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
1074        if (id == 0) {
1075            throw new RSRuntimeException("Allocation creation failed.");
1076        }
1077        return new Allocation(id, rs, t, usage);
1078    }
1079
1080    /**
1081     * Creates a renderscript allocation with a specified number of
1082     * given elements
1083     *
1084     * @param rs Context to which the allocation will belong.
1085     * @param e describes what each element of an allocation is
1086     * @param count specifies the number of element in the allocation
1087     *
1088     * @return allocation
1089     */
1090    static public Allocation createSized(RenderScript rs, Element e, int count) {
1091        return createSized(rs, e, count, USAGE_SCRIPT);
1092    }
1093
1094    static Element elementFromBitmap(RenderScript rs, Bitmap b) {
1095        final Bitmap.Config bc = b.getConfig();
1096        if (bc == Bitmap.Config.ALPHA_8) {
1097            return Element.A_8(rs);
1098        }
1099        if (bc == Bitmap.Config.ARGB_4444) {
1100            return Element.RGBA_4444(rs);
1101        }
1102        if (bc == Bitmap.Config.ARGB_8888) {
1103            return Element.RGBA_8888(rs);
1104        }
1105        if (bc == Bitmap.Config.RGB_565) {
1106            return Element.RGB_565(rs);
1107        }
1108        throw new RSInvalidStateException("Bad bitmap type: " + bc);
1109    }
1110
1111    static Type typeFromBitmap(RenderScript rs, Bitmap b,
1112                                       MipmapControl mip) {
1113        Element e = elementFromBitmap(rs, b);
1114        Type.Builder tb = new Type.Builder(rs, e);
1115        tb.setX(b.getWidth());
1116        tb.setY(b.getHeight());
1117        tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
1118        return tb.create();
1119    }
1120
1121    /**
1122     * Creates a renderscript allocation from a bitmap
1123     *
1124     * @param rs Context to which the allocation will belong.
1125     * @param b bitmap source for the allocation data
1126     * @param mips specifies desired mipmap behaviour for the
1127     *             allocation
1128     * @param usage bit field specifying how the allocation is
1129     *              utilized
1130     *
1131     * @return renderscript allocation containing bitmap data
1132     *
1133     */
1134    static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
1135                                              MipmapControl mips,
1136                                              int usage) {
1137        rs.validate();
1138        Type t = typeFromBitmap(rs, b, mips);
1139
1140        int id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
1141        if (id == 0) {
1142            throw new RSRuntimeException("Load failed.");
1143        }
1144        return new Allocation(id, rs, t, usage);
1145    }
1146
1147    /**
1148     *
1149     *
1150     * @hide
1151     *
1152     */
1153    public SurfaceTexture getSurfaceTexture() {
1154        if ((mUsage & USAGE_IO_INPUT) == 0) {
1155            throw new RSInvalidStateException("Allocation is not a surface texture.");
1156        }
1157
1158        int id = mRS.nAllocationGetSurfaceTextureID(getID(mRS));
1159        SurfaceTexture st = new SurfaceTexture(id);
1160        mRS.nAllocationGetSurfaceTextureID2(getID(mRS), st);
1161
1162        return st;
1163    }
1164
1165    /**
1166     * For allocations used with io operations, returns the handle
1167     * onto a raw buffer that is being managed by the screen
1168     * compositor.
1169     *
1170     * @return Surface object associated with allocation
1171     *
1172     */
1173    public Surface getSurface() {
1174        return new Surface(getSurfaceTexture());
1175    }
1176
1177    /**
1178     * Associate a surface for io output with this allocation
1179     *
1180     * @param sur Surface to associate with allocation
1181     */
1182    public void setSurface(Surface sur) {
1183        mRS.validate();
1184        if ((mUsage & USAGE_IO_OUTPUT) == 0) {
1185            throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
1186        }
1187
1188        mRS.nAllocationSetSurface(getID(mRS), sur);
1189    }
1190
1191    /**
1192     * @hide
1193     */
1194    public void setSurfaceTexture(SurfaceTexture st) {
1195        mRS.validate();
1196        if ((mUsage & USAGE_IO_OUTPUT) == 0) {
1197            throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
1198        }
1199
1200        Surface s = new Surface(st);
1201        mRS.nAllocationSetSurface(getID(mRS), s);
1202    }
1203
1204    /**
1205     * Creates a non-mipmapped renderscript allocation to use as a
1206     * graphics texture
1207     *
1208     * @param rs Context to which the allocation will belong.
1209     * @param b bitmap source for the allocation data
1210     *
1211     * @return renderscript allocation containing bitmap data
1212     *
1213     */
1214    static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
1215        return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1216                                USAGE_GRAPHICS_TEXTURE);
1217    }
1218
1219    /**
1220     * Creates a cubemap allocation from a bitmap containing the
1221     * horizontal list of cube faces. Each individual face must be
1222     * the same size and power of 2
1223     *
1224     * @param rs Context to which the allocation will belong.
1225     * @param b bitmap with cubemap faces layed out in the following
1226     *          format: right, left, top, bottom, front, back
1227     * @param mips specifies desired mipmap behaviour for the cubemap
1228     * @param usage bit field specifying how the cubemap is utilized
1229     *
1230     * @return allocation containing cubemap data
1231     *
1232     */
1233    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
1234                                                     MipmapControl mips,
1235                                                     int usage) {
1236        rs.validate();
1237
1238        int height = b.getHeight();
1239        int width = b.getWidth();
1240
1241        if (width % 6 != 0) {
1242            throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
1243        }
1244        if (width / 6 != height) {
1245            throw new RSIllegalArgumentException("Only square cube map faces supported");
1246        }
1247        boolean isPow2 = (height & (height - 1)) == 0;
1248        if (!isPow2) {
1249            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
1250        }
1251
1252        Element e = elementFromBitmap(rs, b);
1253        Type.Builder tb = new Type.Builder(rs, e);
1254        tb.setX(height);
1255        tb.setY(height);
1256        tb.setFaces(true);
1257        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
1258        Type t = tb.create();
1259
1260        int id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
1261        if(id == 0) {
1262            throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
1263        }
1264        return new Allocation(id, rs, t, usage);
1265    }
1266
1267    /**
1268     * Creates a non-mipmapped cubemap allocation for use as a
1269     * graphics texture from a bitmap containing the horizontal list
1270     * of cube faces. Each individual face must be the same size and
1271     * power of 2
1272     *
1273     * @param rs Context to which the allocation will belong.
1274     * @param b bitmap with cubemap faces layed out in the following
1275     *          format: right, left, top, bottom, front, back
1276     *
1277     * @return allocation containing cubemap data
1278     *
1279     */
1280    static public Allocation createCubemapFromBitmap(RenderScript rs,
1281                                                     Bitmap b) {
1282        return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1283                                       USAGE_GRAPHICS_TEXTURE);
1284    }
1285
1286    /**
1287     * Creates a cubemap allocation from 6 bitmaps containing
1288     * the cube faces. All the faces must be the same size and
1289     * power of 2
1290     *
1291     * @param rs Context to which the allocation will belong.
1292     * @param xpos cubemap face in the positive x direction
1293     * @param xneg cubemap face in the negative x direction
1294     * @param ypos cubemap face in the positive y direction
1295     * @param yneg cubemap face in the negative y direction
1296     * @param zpos cubemap face in the positive z direction
1297     * @param zneg cubemap face in the negative z direction
1298     * @param mips specifies desired mipmap behaviour for the cubemap
1299     * @param usage bit field specifying how the cubemap is utilized
1300     *
1301     * @return allocation containing cubemap data
1302     *
1303     */
1304    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
1305                                                        Bitmap xpos,
1306                                                        Bitmap xneg,
1307                                                        Bitmap ypos,
1308                                                        Bitmap yneg,
1309                                                        Bitmap zpos,
1310                                                        Bitmap zneg,
1311                                                        MipmapControl mips,
1312                                                        int usage) {
1313        int height = xpos.getHeight();
1314        if (xpos.getWidth() != height ||
1315            xneg.getWidth() != height || xneg.getHeight() != height ||
1316            ypos.getWidth() != height || ypos.getHeight() != height ||
1317            yneg.getWidth() != height || yneg.getHeight() != height ||
1318            zpos.getWidth() != height || zpos.getHeight() != height ||
1319            zneg.getWidth() != height || zneg.getHeight() != height) {
1320            throw new RSIllegalArgumentException("Only square cube map faces supported");
1321        }
1322        boolean isPow2 = (height & (height - 1)) == 0;
1323        if (!isPow2) {
1324            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
1325        }
1326
1327        Element e = elementFromBitmap(rs, xpos);
1328        Type.Builder tb = new Type.Builder(rs, e);
1329        tb.setX(height);
1330        tb.setY(height);
1331        tb.setFaces(true);
1332        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
1333        Type t = tb.create();
1334        Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
1335
1336        AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
1337        adapter.setFace(Type.CubemapFace.POSITIVE_X);
1338        adapter.copyFrom(xpos);
1339        adapter.setFace(Type.CubemapFace.NEGATIVE_X);
1340        adapter.copyFrom(xneg);
1341        adapter.setFace(Type.CubemapFace.POSITIVE_Y);
1342        adapter.copyFrom(ypos);
1343        adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
1344        adapter.copyFrom(yneg);
1345        adapter.setFace(Type.CubemapFace.POSITIVE_Z);
1346        adapter.copyFrom(zpos);
1347        adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
1348        adapter.copyFrom(zneg);
1349
1350        return cubemap;
1351    }
1352
1353    /**
1354     * Creates a non-mipmapped cubemap allocation for use as a
1355     * graphics texture from 6 bitmaps containing
1356     * the cube faces. All the faces must be the same size and
1357     * power of 2
1358     *
1359     * @param rs Context to which the allocation will belong.
1360     * @param xpos cubemap face in the positive x direction
1361     * @param xneg cubemap face in the negative x direction
1362     * @param ypos cubemap face in the positive y direction
1363     * @param yneg cubemap face in the negative y direction
1364     * @param zpos cubemap face in the positive z direction
1365     * @param zneg cubemap face in the negative z direction
1366     *
1367     * @return allocation containing cubemap data
1368     *
1369     */
1370    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
1371                                                        Bitmap xpos,
1372                                                        Bitmap xneg,
1373                                                        Bitmap ypos,
1374                                                        Bitmap yneg,
1375                                                        Bitmap zpos,
1376                                                        Bitmap zneg) {
1377        return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
1378                                          zpos, zneg, MipmapControl.MIPMAP_NONE,
1379                                          USAGE_GRAPHICS_TEXTURE);
1380    }
1381
1382    /**
1383     * Creates a renderscript allocation from the bitmap referenced
1384     * by resource id
1385     *
1386     * @param rs Context to which the allocation will belong.
1387     * @param res application resources
1388     * @param id resource id to load the data from
1389     * @param mips specifies desired mipmap behaviour for the
1390     *             allocation
1391     * @param usage bit field specifying how the allocation is
1392     *              utilized
1393     *
1394     * @return renderscript allocation containing resource data
1395     *
1396     */
1397    static public Allocation createFromBitmapResource(RenderScript rs,
1398                                                      Resources res,
1399                                                      int id,
1400                                                      MipmapControl mips,
1401                                                      int usage) {
1402
1403        rs.validate();
1404        Bitmap b = BitmapFactory.decodeResource(res, id);
1405        Allocation alloc = createFromBitmap(rs, b, mips, usage);
1406        b.recycle();
1407        return alloc;
1408    }
1409
1410    /**
1411     * Creates a non-mipmapped renderscript allocation to use as a
1412     * graphics texture from the bitmap referenced by resource id
1413     *
1414     * @param rs Context to which the allocation will belong.
1415     * @param res application resources
1416     * @param id resource id to load the data from
1417     *
1418     * @return renderscript allocation containing resource data
1419     *
1420     */
1421    static public Allocation createFromBitmapResource(RenderScript rs,
1422                                                      Resources res,
1423                                                      int id) {
1424        return createFromBitmapResource(rs, res, id,
1425                                        MipmapControl.MIPMAP_NONE,
1426                                        USAGE_GRAPHICS_TEXTURE);
1427    }
1428
1429    /**
1430     * Creates a renderscript allocation containing string data
1431     * encoded in UTF-8 format
1432     *
1433     * @param rs Context to which the allocation will belong.
1434     * @param str string to create the allocation from
1435     * @param usage bit field specifying how the allocaiton is
1436     *              utilized
1437     *
1438     */
1439    static public Allocation createFromString(RenderScript rs,
1440                                              String str,
1441                                              int usage) {
1442        rs.validate();
1443        byte[] allocArray = null;
1444        try {
1445            allocArray = str.getBytes("UTF-8");
1446            Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
1447            alloc.copyFrom(allocArray);
1448            return alloc;
1449        }
1450        catch (Exception e) {
1451            throw new RSRuntimeException("Could not convert string to utf-8.");
1452        }
1453    }
1454}
1455
1456
1457