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