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