Allocation.java revision c089c2fc00054d6dde24b98e78226923a5364564
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     * 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        if (mCurrentDimY > 0) {
492            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
493        } else {
494            copy1DRangeFromUnchecked(0, mCurrentCount, d);
495        }
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(short[] d) {
505        mRS.validate();
506        if (mCurrentDimY > 0) {
507            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
508        } else {
509            copy1DRangeFromUnchecked(0, mCurrentCount, d);
510        }
511    }
512    /**
513     * Copy an allocation from an array.  This variant is not type
514     * checked which allows an application to fill in structured
515     * data from an array.
516     *
517     * @param d the source data array
518     */
519    public void copyFromUnchecked(byte[] d) {
520        mRS.validate();
521        if (mCurrentDimY > 0) {
522            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
523        } else {
524            copy1DRangeFromUnchecked(0, mCurrentCount, d);
525        }
526    }
527    /**
528     * Copy an allocation from an array.  This variant is not type
529     * checked which allows an application to fill in structured
530     * data from an array.
531     *
532     * @param d the source data array
533     */
534    public void copyFromUnchecked(float[] d) {
535        mRS.validate();
536        if (mCurrentDimY > 0) {
537            copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
538        } else {
539            copy1DRangeFromUnchecked(0, mCurrentCount, d);
540        }
541    }
542
543    /**
544     * Copy an allocation from an array.  This variant is type
545     * checked and will generate exceptions if the Allocation type
546     * is not a 32 bit integer type.
547     *
548     * @param d the source data array
549     */
550    public void copyFrom(int[] d) {
551        mRS.validate();
552        if (mCurrentDimY > 0) {
553            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
554        } else {
555            copy1DRangeFrom(0, mCurrentCount, d);
556        }
557    }
558
559    /**
560     * Copy an allocation from an array.  This variant is type
561     * checked and will generate exceptions if the Allocation type
562     * is not a 16 bit integer type.
563     *
564     * @param d the source data array
565     */
566    public void copyFrom(short[] d) {
567        mRS.validate();
568        if (mCurrentDimY > 0) {
569            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
570        } else {
571            copy1DRangeFrom(0, mCurrentCount, d);
572        }
573    }
574
575    /**
576     * Copy an allocation from an array.  This variant is type
577     * checked and will generate exceptions if the Allocation type
578     * is not a 8 bit integer type.
579     *
580     * @param d the source data array
581     */
582    public void copyFrom(byte[] d) {
583        mRS.validate();
584        if (mCurrentDimY > 0) {
585            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
586        } else {
587            copy1DRangeFrom(0, mCurrentCount, d);
588        }
589    }
590
591    /**
592     * Copy an allocation from an array.  This variant is type
593     * checked and will generate exceptions if the Allocation type
594     * is not a 32 bit float type.
595     *
596     * @param d the source data array
597     */
598    public void copyFrom(float[] d) {
599        mRS.validate();
600        if (mCurrentDimY > 0) {
601            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
602        } else {
603            copy1DRangeFrom(0, mCurrentCount, d);
604        }
605    }
606
607    /**
608     * Copy an allocation from a bitmap.  The height, width, and
609     * format of the bitmap must match the existing allocation.
610     *
611     * @param b the source bitmap
612     */
613    public void copyFrom(Bitmap b) {
614        mRS.validate();
615        validateBitmapSize(b);
616        validateBitmapFormat(b);
617        mRS.nAllocationCopyFromBitmap(getID(mRS), b);
618    }
619
620    /**
621     * Copy an allocation from an allocation.  The types of both allocations
622     * must be identical.
623     *
624     * @param a the source allocation
625     */
626    public void copyFrom(Allocation a) {
627        mRS.validate();
628        if (!mType.equals(a.getType())) {
629            throw new RSIllegalArgumentException("Types of allocations must match.");
630        }
631        copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
632    }
633
634
635    /**
636     * This is only intended to be used by auto-generate code reflected from the
637     * renderscript script files.
638     *
639     * @param xoff
640     * @param fp
641     */
642    public void setFromFieldPacker(int xoff, FieldPacker fp) {
643        mRS.validate();
644        int eSize = mType.mElement.getBytesSize();
645        final byte[] data = fp.getData();
646
647        int count = data.length / eSize;
648        if ((eSize * count) != data.length) {
649            throw new RSIllegalArgumentException("Field packer length " + data.length +
650                                               " not divisible by element size " + eSize + ".");
651        }
652        copy1DRangeFromUnchecked(xoff, count, data);
653    }
654
655    /**
656     * This is only intended to be used by auto-generate code reflected from the
657     * renderscript script files.
658     *
659     * @param xoff
660     * @param component_number
661     * @param fp
662     */
663    public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
664        mRS.validate();
665        if (component_number >= mType.mElement.mElements.length) {
666            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
667        }
668        if(xoff < 0) {
669            throw new RSIllegalArgumentException("Offset must be >= 0.");
670        }
671
672        final byte[] data = fp.getData();
673        int eSize = mType.mElement.mElements[component_number].getBytesSize();
674        eSize *= mType.mElement.mArraySizes[component_number];
675
676        if (data.length != eSize) {
677            throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
678                                               " does not match component size " + eSize + ".");
679        }
680
681        mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
682                                     component_number, data, data.length);
683    }
684
685    private void data1DChecks(int off, int count, int len, int dataSize) {
686        mRS.validate();
687        if(off < 0) {
688            throw new RSIllegalArgumentException("Offset must be >= 0.");
689        }
690        if(count < 1) {
691            throw new RSIllegalArgumentException("Count must be >= 1.");
692        }
693        if((off + count) > mCurrentCount) {
694            throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
695                                               ", got " + count + " at offset " + off + ".");
696        }
697        if(len < dataSize) {
698            throw new RSIllegalArgumentException("Array too small for allocation type.");
699        }
700    }
701
702    /**
703     * Generate a mipmap chain.  Requires the type of the allocation
704     * include mipmaps.
705     *
706     * This function will generate a complete set of mipmaps from
707     * the top level lod and place them into the script memoryspace.
708     *
709     * If the allocation is also using other memory spaces a
710     * followup sync will be required.
711     */
712    public void generateMipmaps() {
713        mRS.nAllocationGenerateMipmaps(getID(mRS));
714    }
715
716    /**
717     * Copy part of an allocation from an array.  This variant is
718     * not type checked which allows an application to fill in
719     * structured data from an array.
720     *
721     * @param off The offset of the first element to be copied.
722     * @param count The number of elements to be copied.
723     * @param d the source data array
724     */
725    public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
726        int dataSize = mType.mElement.getBytesSize() * count;
727        data1DChecks(off, count, d.length * 4, dataSize);
728        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
729    }
730    /**
731     * Copy part of an allocation from an array.  This variant is
732     * not type checked which allows an application to fill in
733     * structured data from an array.
734     *
735     * @param off The offset of the first element to be copied.
736     * @param count The number of elements to be copied.
737     * @param d the source data array
738     */
739    public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
740        int dataSize = mType.mElement.getBytesSize() * count;
741        data1DChecks(off, count, d.length * 2, dataSize);
742        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
743    }
744    /**
745     * Copy part of an allocation from an array.  This variant is
746     * not type checked which allows an application to fill in
747     * structured data from an array.
748     *
749     * @param off The offset of the first element to be copied.
750     * @param count The number of elements to be copied.
751     * @param d the source data array
752     */
753    public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
754        int dataSize = mType.mElement.getBytesSize() * count;
755        data1DChecks(off, count, d.length, dataSize);
756        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
757    }
758    /**
759     * Copy part of an allocation from an array.  This variant is
760     * not type checked which allows an application to fill in
761     * structured data from an array.
762     *
763     * @param off The offset of the first element to be copied.
764     * @param count The number of elements to be copied.
765     * @param d the source data array
766     */
767    public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
768        int dataSize = mType.mElement.getBytesSize() * count;
769        data1DChecks(off, count, d.length * 4, dataSize);
770        mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
771    }
772
773    /**
774     * Copy part of an allocation from an array.  This variant is
775     * type checked and will generate exceptions if the Allocation
776     * type is not a 32 bit integer type.
777     *
778     * @param off The offset of the first element to be copied.
779     * @param count The number of elements to be copied.
780     * @param d the source data array
781     */
782    public void copy1DRangeFrom(int off, int count, int[] d) {
783        validateIsInt32();
784        copy1DRangeFromUnchecked(off, count, d);
785    }
786
787    /**
788     * Copy part of an allocation from an array.  This variant is
789     * type checked and will generate exceptions if the Allocation
790     * type is not a 16 bit integer type.
791     *
792     * @param off The offset of the first element to be copied.
793     * @param count The number of elements to be copied.
794     * @param d the source data array
795     */
796    public void copy1DRangeFrom(int off, int count, short[] d) {
797        validateIsInt16();
798        copy1DRangeFromUnchecked(off, count, d);
799    }
800
801    /**
802     * Copy part of an allocation from an array.  This variant is
803     * type checked and will generate exceptions if the Allocation
804     * type is not a 8 bit integer type.
805     *
806     * @param off The offset of the first element to be copied.
807     * @param count The number of elements to be copied.
808     * @param d the source data array
809     */
810    public void copy1DRangeFrom(int off, int count, byte[] d) {
811        validateIsInt8();
812        copy1DRangeFromUnchecked(off, count, d);
813    }
814
815    /**
816     * Copy part of an allocation from an array.  This variant is
817     * type checked and will generate exceptions if the Allocation
818     * type is not a 32 bit float type.
819     *
820     * @param off The offset of the first element to be copied.
821     * @param count The number of elements to be copied.
822     * @param d the source data array.
823     */
824    public void copy1DRangeFrom(int off, int count, float[] d) {
825        validateIsFloat32();
826        copy1DRangeFromUnchecked(off, count, d);
827    }
828
829     /**
830     * Copy part of an allocation from another allocation.
831     *
832     * @param off The offset of the first element to be copied.
833     * @param count The number of elements to be copied.
834     * @param data the source data allocation.
835     * @param dataOff off The offset of the first element in data to
836     *          be copied.
837     */
838    public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
839        mRS.nAllocationData2D(getIDSafe(), off, 0,
840                              mSelectedLOD, mSelectedFace.mID,
841                              count, 1, data.getID(mRS), dataOff, 0,
842                              data.mSelectedLOD, data.mSelectedFace.mID);
843    }
844
845    private void validate2DRange(int xoff, int yoff, int w, int h) {
846        if (mAdaptedAllocation != null) {
847
848        } else {
849
850            if (xoff < 0 || yoff < 0) {
851                throw new RSIllegalArgumentException("Offset cannot be negative.");
852            }
853            if (h < 0 || w < 0) {
854                throw new RSIllegalArgumentException("Height or width cannot be negative.");
855            }
856            if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
857                throw new RSIllegalArgumentException("Updated region larger than allocation.");
858            }
859        }
860    }
861
862    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, byte[] data) {
863        mRS.validate();
864        validate2DRange(xoff, yoff, w, h);
865        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
866                              w, h, data, data.length);
867    }
868
869    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, short[] data) {
870        mRS.validate();
871        validate2DRange(xoff, yoff, w, h);
872        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
873                              w, h, data, data.length * 2);
874    }
875
876    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, int[] data) {
877        mRS.validate();
878        validate2DRange(xoff, yoff, w, h);
879        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
880                              w, h, data, data.length * 4);
881    }
882
883    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, float[] data) {
884        mRS.validate();
885        validate2DRange(xoff, yoff, w, h);
886        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
887                              w, h, data, data.length * 4);
888    }
889
890
891    /**
892     * Copy a rectangular region from the array into the allocation.
893     * The incoming array is assumed to be tightly packed.
894     *
895     * @param xoff X offset of the region to update
896     * @param yoff Y offset of the region to update
897     * @param w Width of the incoming region to update
898     * @param h Height of the incoming region to update
899     * @param data to be placed into the allocation
900     */
901    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
902        validateIsInt8();
903        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
904    }
905
906    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
907        validateIsInt16();
908        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
909    }
910
911    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
912        validateIsInt32();
913        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
914    }
915
916    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
917        validateIsFloat32();
918        copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
919    }
920
921    /**
922     * Copy a rectangular region into the allocation from another
923     * allocation.
924     *
925     * @param xoff X offset of the region to update.
926     * @param yoff Y offset of the region to update.
927     * @param w Width of the incoming region to update.
928     * @param h Height of the incoming region to update.
929     * @param data source allocation.
930     * @param dataXoff X offset in data of the region to update.
931     * @param dataYoff Y offset in data of the region to update.
932     */
933    public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
934                                Allocation data, int dataXoff, int dataYoff) {
935        mRS.validate();
936        validate2DRange(xoff, yoff, w, h);
937        mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
938                              mSelectedLOD, mSelectedFace.mID,
939                              w, h, data.getID(mRS), dataXoff, dataYoff,
940                              data.mSelectedLOD, data.mSelectedFace.mID);
941    }
942
943    /**
944     * Copy a bitmap into an allocation.  The height and width of
945     * the update will use the height and width of the incoming
946     * bitmap.
947     *
948     * @param xoff X offset of the region to update
949     * @param yoff Y offset of the region to update
950     * @param data the bitmap to be copied
951     */
952    public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
953        mRS.validate();
954        validateBitmapFormat(data);
955        validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
956        mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
957    }
958
959
960    /**
961     * Copy from the Allocation into a Bitmap.  The bitmap must
962     * match the dimensions of the Allocation.
963     *
964     * @param b The bitmap to be set from the Allocation.
965     */
966    public void copyTo(Bitmap b) {
967        mRS.validate();
968        validateBitmapFormat(b);
969        validateBitmapSize(b);
970        mRS.nAllocationCopyToBitmap(getID(mRS), b);
971    }
972
973    /**
974     * Copy from the Allocation into a byte array.  The array must
975     * be at least as large as the Allocation.  The allocation must
976     * be of an 8 bit elemental type.
977     *
978     * @param d The array to be set from the Allocation.
979     */
980    public void copyTo(byte[] d) {
981        validateIsInt8();
982        mRS.validate();
983        mRS.nAllocationRead(getID(mRS), d);
984    }
985
986    /**
987     * Copy from the Allocation into a short array.  The array must
988     * be at least as large as the Allocation.  The allocation must
989     * be of an 16 bit elemental type.
990     *
991     * @param d The array to be set from the Allocation.
992     */
993    public void copyTo(short[] d) {
994        validateIsInt16();
995        mRS.validate();
996        mRS.nAllocationRead(getID(mRS), d);
997    }
998
999    /**
1000     * Copy from the Allocation into a int array.  The array must be
1001     * at least as large as the Allocation.  The allocation must be
1002     * of an 32 bit elemental type.
1003     *
1004     * @param d The array to be set from the Allocation.
1005     */
1006    public void copyTo(int[] d) {
1007        validateIsInt32();
1008        mRS.validate();
1009        mRS.nAllocationRead(getID(mRS), d);
1010    }
1011
1012    /**
1013     * Copy from the Allocation into a float array.  The array must
1014     * be at least as large as the Allocation.  The allocation must
1015     * be of an 32 bit float elemental type.
1016     *
1017     * @param d The array to be set from the Allocation.
1018     */
1019    public void copyTo(float[] d) {
1020        validateIsFloat32();
1021        mRS.validate();
1022        mRS.nAllocationRead(getID(mRS), d);
1023    }
1024
1025    /**
1026     * Resize a 1D allocation.  The contents of the allocation are
1027     * preserved.  If new elements are allocated objects are created
1028     * with null contents and the new region is otherwise undefined.
1029     *
1030     * If the new region is smaller the references of any objects
1031     * outside the new region will be released.
1032     *
1033     * A new type will be created with the new dimension.
1034     *
1035     * @param dimX The new size of the allocation.
1036     */
1037    public synchronized void resize(int dimX) {
1038        if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
1039            throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
1040        }
1041        mRS.nAllocationResize1D(getID(mRS), dimX);
1042        mRS.finish();  // Necessary because resize is fifoed and update is async.
1043
1044        int typeID = mRS.nAllocationGetType(getID(mRS));
1045        mType = new Type(typeID, mRS);
1046        mType.updateFromNative();
1047        updateCacheInfo(mType);
1048    }
1049
1050    /**
1051     * Resize a 2D allocation.  The contents of the allocation are
1052     * preserved.  If new elements are allocated objects are created
1053     * with null contents and the new region is otherwise undefined.
1054     *
1055     * If the new region is smaller the references of any objects
1056     * outside the new region will be released.
1057     *
1058     * A new type will be created with the new dimension.
1059     *
1060     * @param dimX The new size of the allocation.
1061     * @param dimY The new size of the allocation.
1062     */
1063    public synchronized void resize(int dimX, int dimY) {
1064        if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
1065            throw new RSInvalidStateException(
1066                "Resize only support for 2D allocations at this time.");
1067        }
1068        if (mType.getY() == 0) {
1069            throw new RSInvalidStateException(
1070                "Resize only support for 2D allocations at this time.");
1071        }
1072        mRS.nAllocationResize2D(getID(mRS), dimX, dimY);
1073        mRS.finish();  // Necessary because resize is fifoed and update is async.
1074
1075        int typeID = mRS.nAllocationGetType(getID(mRS));
1076        mType = new Type(typeID, mRS);
1077        mType.updateFromNative();
1078        updateCacheInfo(mType);
1079    }
1080
1081
1082
1083    // creation
1084
1085    static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
1086    static {
1087        mBitmapOptions.inScaled = false;
1088    }
1089
1090    /**
1091     *
1092     * @param type renderscript type describing data layout
1093     * @param mips specifies desired mipmap behaviour for the
1094     *             allocation
1095     * @param usage bit field specifying how the allocation is
1096     *              utilized
1097     */
1098    static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
1099        rs.validate();
1100        if (type.getID(rs) == 0) {
1101            throw new RSInvalidStateException("Bad Type");
1102        }
1103        int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
1104        if (id == 0) {
1105            throw new RSRuntimeException("Allocation creation failed.");
1106        }
1107        return new Allocation(id, rs, type, usage);
1108    }
1109
1110    /**
1111     * Creates a renderscript allocation with the size specified by
1112     * the type and no mipmaps generated by default
1113     *
1114     * @param rs Context to which the allocation will belong.
1115     * @param type renderscript type describing data layout
1116     * @param usage bit field specifying how the allocation is
1117     *              utilized
1118     *
1119     * @return allocation
1120     */
1121    static public Allocation createTyped(RenderScript rs, Type type, int usage) {
1122        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
1123    }
1124
1125    /**
1126     * Creates a renderscript allocation for use by the script with
1127     * the size specified by the type and no mipmaps generated by
1128     * default
1129     *
1130     * @param rs Context to which the allocation will belong.
1131     * @param type renderscript type describing data layout
1132     *
1133     * @return allocation
1134     */
1135    static public Allocation createTyped(RenderScript rs, Type type) {
1136        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
1137    }
1138
1139    /**
1140     * Creates a renderscript allocation with a specified number of
1141     * given elements
1142     *
1143     * @param rs Context to which the allocation will belong.
1144     * @param e describes what each element of an allocation is
1145     * @param count specifies the number of element in the allocation
1146     * @param usage bit field specifying how the allocation is
1147     *              utilized
1148     *
1149     * @return allocation
1150     */
1151    static public Allocation createSized(RenderScript rs, Element e,
1152                                         int count, int usage) {
1153        rs.validate();
1154        Type.Builder b = new Type.Builder(rs, e);
1155        b.setX(count);
1156        Type t = b.create();
1157
1158        int id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
1159        if (id == 0) {
1160            throw new RSRuntimeException("Allocation creation failed.");
1161        }
1162        return new Allocation(id, rs, t, usage);
1163    }
1164
1165    /**
1166     * Creates a renderscript allocation with a specified number of
1167     * given elements
1168     *
1169     * @param rs Context to which the allocation will belong.
1170     * @param e describes what each element of an allocation is
1171     * @param count specifies the number of element in the allocation
1172     *
1173     * @return allocation
1174     */
1175    static public Allocation createSized(RenderScript rs, Element e, int count) {
1176        return createSized(rs, e, count, USAGE_SCRIPT);
1177    }
1178
1179    static Element elementFromBitmap(RenderScript rs, Bitmap b) {
1180        final Bitmap.Config bc = b.getConfig();
1181        if (bc == Bitmap.Config.ALPHA_8) {
1182            return Element.A_8(rs);
1183        }
1184        if (bc == Bitmap.Config.ARGB_4444) {
1185            return Element.RGBA_4444(rs);
1186        }
1187        if (bc == Bitmap.Config.ARGB_8888) {
1188            return Element.RGBA_8888(rs);
1189        }
1190        if (bc == Bitmap.Config.RGB_565) {
1191            return Element.RGB_565(rs);
1192        }
1193        throw new RSInvalidStateException("Bad bitmap type: " + bc);
1194    }
1195
1196    static Type typeFromBitmap(RenderScript rs, Bitmap b,
1197                                       MipmapControl mip) {
1198        Element e = elementFromBitmap(rs, b);
1199        Type.Builder tb = new Type.Builder(rs, e);
1200        tb.setX(b.getWidth());
1201        tb.setY(b.getHeight());
1202        tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
1203        return tb.create();
1204    }
1205
1206    /**
1207     * Creates a renderscript allocation from a bitmap
1208     *
1209     * @param rs Context to which the allocation will belong.
1210     * @param b bitmap source for the allocation data
1211     * @param mips specifies desired mipmap behaviour for the
1212     *             allocation
1213     * @param usage bit field specifying how the allocation is
1214     *              utilized
1215     *
1216     * @return renderscript allocation containing bitmap data
1217     *
1218     */
1219    static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
1220                                              MipmapControl mips,
1221                                              int usage) {
1222        rs.validate();
1223        Type t = typeFromBitmap(rs, b, mips);
1224
1225        // enable optimized bitmap path only with no mipmap and script-only usage
1226        if (mips == MipmapControl.MIPMAP_NONE &&
1227            t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
1228            usage == (USAGE_SHARED | USAGE_SCRIPT)) {
1229            int id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
1230            if (id == 0) {
1231                throw new RSRuntimeException("Load failed.");
1232            }
1233
1234            // keep a reference to the Bitmap around to prevent GC
1235            Allocation alloc = new Allocation(id, rs, t, usage);
1236            alloc.setBitmap(b);
1237            return alloc;
1238        }
1239
1240
1241        int id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
1242        if (id == 0) {
1243            throw new RSRuntimeException("Load failed.");
1244        }
1245        return new Allocation(id, rs, t, usage);
1246    }
1247
1248    /**
1249     * For allocations used with io operations, returns the handle
1250     * onto a raw buffer that is being managed by the screen
1251     * compositor.
1252     *
1253     * @return Surface object associated with allocation
1254     *
1255     */
1256    public Surface getSurface() {
1257        if ((mUsage & USAGE_IO_INPUT) == 0) {
1258            throw new RSInvalidStateException("Allocation is not a surface texture.");
1259        }
1260        return mRS.nAllocationGetSurface(getID(mRS));
1261    }
1262
1263    /**
1264     * @hide
1265     */
1266    public void setSurfaceTexture(SurfaceTexture st) {
1267        setSurface(new Surface(st));
1268    }
1269
1270    /**
1271     * Associate a surface for io output with this allocation
1272     *
1273     * @param sur Surface to associate with allocation
1274     */
1275    public void setSurface(Surface sur) {
1276        mRS.validate();
1277        if ((mUsage & USAGE_IO_OUTPUT) == 0) {
1278            throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
1279        }
1280
1281        mRS.nAllocationSetSurface(getID(mRS), sur);
1282    }
1283
1284    /**
1285     * Creates a RenderScript allocation from a bitmap.
1286     *
1287     * With target API version 18 or greater, this allocation will be
1288     * created with USAGE_SHARED. With target API version 17 or lower,
1289     * this allocation will be created with USAGE_GRAPHICS_TEXTURE.
1290     *
1291     * @param rs Context to which the allocation will belong.
1292     * @param b bitmap source for the allocation data
1293     *
1294     * @return renderscript allocation containing bitmap data
1295     *
1296     */
1297    static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
1298        if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
1299            return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1300                                    USAGE_SHARED | USAGE_SCRIPT);
1301        }
1302        return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1303                                USAGE_GRAPHICS_TEXTURE);
1304    }
1305
1306    /**
1307     * Creates a cubemap allocation from a bitmap containing the
1308     * horizontal list of cube faces. Each individual face must be
1309     * the same size and power of 2
1310     *
1311     * @param rs Context to which the allocation will belong.
1312     * @param b bitmap with cubemap faces layed out in the following
1313     *          format: right, left, top, bottom, front, back
1314     * @param mips specifies desired mipmap behaviour for the cubemap
1315     * @param usage bit field specifying how the cubemap is utilized
1316     *
1317     * @return allocation containing cubemap data
1318     *
1319     */
1320    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
1321                                                     MipmapControl mips,
1322                                                     int usage) {
1323        rs.validate();
1324
1325        int height = b.getHeight();
1326        int width = b.getWidth();
1327
1328        if (width % 6 != 0) {
1329            throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
1330        }
1331        if (width / 6 != height) {
1332            throw new RSIllegalArgumentException("Only square cube map faces supported");
1333        }
1334        boolean isPow2 = (height & (height - 1)) == 0;
1335        if (!isPow2) {
1336            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
1337        }
1338
1339        Element e = elementFromBitmap(rs, b);
1340        Type.Builder tb = new Type.Builder(rs, e);
1341        tb.setX(height);
1342        tb.setY(height);
1343        tb.setFaces(true);
1344        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
1345        Type t = tb.create();
1346
1347        int id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
1348        if(id == 0) {
1349            throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
1350        }
1351        return new Allocation(id, rs, t, usage);
1352    }
1353
1354    /**
1355     * Creates a non-mipmapped cubemap allocation for use as a
1356     * graphics texture from a bitmap containing the horizontal list
1357     * of cube faces. Each individual face must be the same size and
1358     * power of 2
1359     *
1360     * @param rs Context to which the allocation will belong.
1361     * @param b bitmap with cubemap faces layed out in the following
1362     *          format: right, left, top, bottom, front, back
1363     *
1364     * @return allocation containing cubemap data
1365     *
1366     */
1367    static public Allocation createCubemapFromBitmap(RenderScript rs,
1368                                                     Bitmap b) {
1369        return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1370                                       USAGE_GRAPHICS_TEXTURE);
1371    }
1372
1373    /**
1374     * Creates a cubemap allocation from 6 bitmaps containing
1375     * the cube faces. All the faces must be the same size and
1376     * power of 2
1377     *
1378     * @param rs Context to which the allocation will belong.
1379     * @param xpos cubemap face in the positive x direction
1380     * @param xneg cubemap face in the negative x direction
1381     * @param ypos cubemap face in the positive y direction
1382     * @param yneg cubemap face in the negative y direction
1383     * @param zpos cubemap face in the positive z direction
1384     * @param zneg cubemap face in the negative z direction
1385     * @param mips specifies desired mipmap behaviour for the cubemap
1386     * @param usage bit field specifying how the cubemap is utilized
1387     *
1388     * @return allocation containing cubemap data
1389     *
1390     */
1391    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
1392                                                        Bitmap xpos,
1393                                                        Bitmap xneg,
1394                                                        Bitmap ypos,
1395                                                        Bitmap yneg,
1396                                                        Bitmap zpos,
1397                                                        Bitmap zneg,
1398                                                        MipmapControl mips,
1399                                                        int usage) {
1400        int height = xpos.getHeight();
1401        if (xpos.getWidth() != height ||
1402            xneg.getWidth() != height || xneg.getHeight() != height ||
1403            ypos.getWidth() != height || ypos.getHeight() != height ||
1404            yneg.getWidth() != height || yneg.getHeight() != height ||
1405            zpos.getWidth() != height || zpos.getHeight() != height ||
1406            zneg.getWidth() != height || zneg.getHeight() != height) {
1407            throw new RSIllegalArgumentException("Only square cube map faces supported");
1408        }
1409        boolean isPow2 = (height & (height - 1)) == 0;
1410        if (!isPow2) {
1411            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
1412        }
1413
1414        Element e = elementFromBitmap(rs, xpos);
1415        Type.Builder tb = new Type.Builder(rs, e);
1416        tb.setX(height);
1417        tb.setY(height);
1418        tb.setFaces(true);
1419        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
1420        Type t = tb.create();
1421        Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
1422
1423        AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
1424        adapter.setFace(Type.CubemapFace.POSITIVE_X);
1425        adapter.copyFrom(xpos);
1426        adapter.setFace(Type.CubemapFace.NEGATIVE_X);
1427        adapter.copyFrom(xneg);
1428        adapter.setFace(Type.CubemapFace.POSITIVE_Y);
1429        adapter.copyFrom(ypos);
1430        adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
1431        adapter.copyFrom(yneg);
1432        adapter.setFace(Type.CubemapFace.POSITIVE_Z);
1433        adapter.copyFrom(zpos);
1434        adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
1435        adapter.copyFrom(zneg);
1436
1437        return cubemap;
1438    }
1439
1440    /**
1441     * Creates a non-mipmapped cubemap allocation for use as a
1442     * graphics texture from 6 bitmaps containing
1443     * the cube faces. All the faces must be the same size and
1444     * power of 2
1445     *
1446     * @param rs Context to which the allocation will belong.
1447     * @param xpos cubemap face in the positive x direction
1448     * @param xneg cubemap face in the negative x direction
1449     * @param ypos cubemap face in the positive y direction
1450     * @param yneg cubemap face in the negative y direction
1451     * @param zpos cubemap face in the positive z direction
1452     * @param zneg cubemap face in the negative z direction
1453     *
1454     * @return allocation containing cubemap data
1455     *
1456     */
1457    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
1458                                                        Bitmap xpos,
1459                                                        Bitmap xneg,
1460                                                        Bitmap ypos,
1461                                                        Bitmap yneg,
1462                                                        Bitmap zpos,
1463                                                        Bitmap zneg) {
1464        return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
1465                                          zpos, zneg, MipmapControl.MIPMAP_NONE,
1466                                          USAGE_GRAPHICS_TEXTURE);
1467    }
1468
1469    /**
1470     * Creates a renderscript allocation from the bitmap referenced
1471     * by resource id
1472     *
1473     * @param rs Context to which the allocation will belong.
1474     * @param res application resources
1475     * @param id resource id to load the data from
1476     * @param mips specifies desired mipmap behaviour for the
1477     *             allocation
1478     * @param usage bit field specifying how the allocation is
1479     *              utilized
1480     *
1481     * @return renderscript allocation containing resource data
1482     *
1483     */
1484    static public Allocation createFromBitmapResource(RenderScript rs,
1485                                                      Resources res,
1486                                                      int id,
1487                                                      MipmapControl mips,
1488                                                      int usage) {
1489
1490        rs.validate();
1491        Bitmap b = BitmapFactory.decodeResource(res, id);
1492        Allocation alloc = createFromBitmap(rs, b, mips, usage);
1493        b.recycle();
1494        return alloc;
1495    }
1496
1497    /**
1498     * Creates a non-mipmapped renderscript allocation to use as a
1499     * graphics texture from the bitmap referenced by resource id
1500     *
1501     * With target API version 18 or greater, this allocation will be
1502     * created with USAGE_SHARED. With target API version 17 or lower,
1503     * this allocation will be created with USAGE_GRAPHICS_TEXTURE.
1504     *
1505     * @param rs Context to which the allocation will belong.
1506     * @param res application resources
1507     * @param id resource id to load the data from
1508     *
1509     * @return renderscript allocation containing resource data
1510     *
1511     */
1512    static public Allocation createFromBitmapResource(RenderScript rs,
1513                                                      Resources res,
1514                                                      int id) {
1515        if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
1516            return createFromBitmapResource(rs, res, id,
1517                                            MipmapControl.MIPMAP_NONE,
1518                                            USAGE_SHARED | USAGE_SCRIPT);
1519        }
1520        return createFromBitmapResource(rs, res, id,
1521                                        MipmapControl.MIPMAP_NONE,
1522                                        USAGE_GRAPHICS_TEXTURE);
1523    }
1524
1525    /**
1526     * Creates a renderscript allocation containing string data
1527     * encoded in UTF-8 format
1528     *
1529     * @param rs Context to which the allocation will belong.
1530     * @param str string to create the allocation from
1531     * @param usage bit field specifying how the allocaiton is
1532     *              utilized
1533     *
1534     */
1535    static public Allocation createFromString(RenderScript rs,
1536                                              String str,
1537                                              int usage) {
1538        rs.validate();
1539        byte[] allocArray = null;
1540        try {
1541            allocArray = str.getBytes("UTF-8");
1542            Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
1543            alloc.copyFrom(allocArray);
1544            return alloc;
1545        }
1546        catch (Exception e) {
1547            throw new RSRuntimeException("Could not convert string to utf-8.");
1548        }
1549    }
1550}
1551
1552
1553