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