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