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