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