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