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