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