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.nio.ByteBuffer;
20import java.util.HashMap;
21
22import android.content.res.Resources;
23import android.graphics.Bitmap;
24import android.graphics.BitmapFactory;
25import android.graphics.Canvas;
26import android.os.Trace;
27import android.util.Log;
28import android.view.Surface;
29
30/**
31 * <p> This class provides the primary method through which data is passed to
32 * and from RenderScript kernels.  An Allocation provides the backing store for
33 * a given {@link android.renderscript.Type}.  </p>
34 *
35 * <p>An Allocation also contains a set of usage flags that denote how the
36 * Allocation could be used. For example, an Allocation may have usage flags
37 * specifying that it can be used from a script as well as input to a {@link
38 * android.renderscript.Sampler}. A developer must synchronize across these
39 * different usages using {@link android.renderscript.Allocation#syncAll} in
40 * order to ensure that different users of the Allocation have a consistent view
41 * of memory. For example, in the case where an Allocation is used as the output
42 * of one kernel and as Sampler input in a later kernel, a developer must call
43 * {@link #syncAll syncAll(Allocation.USAGE_SCRIPT)} prior to launching the
44 * second kernel to ensure correctness.
45 *
46 * <p>An Allocation can be populated with the {@link #copyFrom} routines. For
47 * more complex Element types, the {@link #copyFromUnchecked} methods can be
48 * used to copy from byte arrays or similar constructs.</p>
49 *
50 * <div class="special reference">
51 * <h3>Developer Guides</h3>
52 * <p>For more information about creating an application that uses RenderScript, read the
53 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
54 * </div>
55 **/
56
57public class Allocation extends BaseObj {
58    private static final int MAX_NUMBER_IO_INPUT_ALLOC = 16;
59
60    Type mType;
61    boolean mOwningType = false;
62    Bitmap mBitmap;
63    int mUsage;
64    Allocation mAdaptedAllocation;
65    int mSize;
66    MipmapControl mMipmapControl;
67
68    long mTimeStamp = -1;
69    boolean mReadAllowed = true;
70    boolean mWriteAllowed = true;
71    boolean mAutoPadding = false;
72    int mSelectedX;
73    int mSelectedY;
74    int mSelectedZ;
75    int mSelectedLOD;
76    int mSelectedArray[];
77    Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
78
79    int mCurrentDimX;
80    int mCurrentDimY;
81    int mCurrentDimZ;
82    int mCurrentCount;
83    static HashMap<Long, Allocation> mAllocationMap =
84            new HashMap<Long, Allocation>();
85    OnBufferAvailableListener mBufferNotifier;
86
87    private Surface mGetSurfaceSurface = null;
88    private ByteBuffer mByteBuffer = null;
89    private long mByteBufferStride = -1;
90
91    private Element.DataType validateObjectIsPrimitiveArray(Object d, boolean checkType) {
92        final Class c = d.getClass();
93        if (!c.isArray()) {
94            throw new RSIllegalArgumentException("Object passed is not an array of primitives.");
95        }
96        final Class cmp = c.getComponentType();
97        if (!cmp.isPrimitive()) {
98            throw new RSIllegalArgumentException("Object passed is not an Array of primitives.");
99        }
100
101        if (cmp == Long.TYPE) {
102            if (checkType) {
103                validateIsInt64();
104                return mType.mElement.mType;
105            }
106            return Element.DataType.SIGNED_64;
107        }
108
109        if (cmp == Integer.TYPE) {
110            if (checkType) {
111                validateIsInt32();
112                return mType.mElement.mType;
113            }
114            return Element.DataType.SIGNED_32;
115        }
116
117        if (cmp == Short.TYPE) {
118            if (checkType) {
119                validateIsInt16OrFloat16();
120                return mType.mElement.mType;
121            }
122            return Element.DataType.SIGNED_16;
123        }
124
125        if (cmp == Byte.TYPE) {
126            if (checkType) {
127                validateIsInt8();
128                return mType.mElement.mType;
129            }
130            return Element.DataType.SIGNED_8;
131        }
132
133        if (cmp == Float.TYPE) {
134            if (checkType) {
135                validateIsFloat32();
136            }
137            return Element.DataType.FLOAT_32;
138        }
139
140        if (cmp == Double.TYPE) {
141            if (checkType) {
142                validateIsFloat64();
143            }
144            return Element.DataType.FLOAT_64;
145        }
146
147        throw new RSIllegalArgumentException("Parameter of type " + cmp.getSimpleName() +
148            "[] is not compatible with data type " + mType.mElement.mType.name() +
149            " of allocation");
150    }
151
152
153    /**
154     * The usage of the Allocation.  These signal to RenderScript where to place
155     * the Allocation in memory.
156     *
157     */
158
159    /**
160     * The Allocation will be bound to and accessed by scripts.
161     */
162    public static final int USAGE_SCRIPT = 0x0001;
163
164    /**
165     * The Allocation will be used as a texture source by one or more graphics
166     * programs.
167     *
168     */
169    public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
170
171    /**
172     * The Allocation will be used as a graphics mesh.
173     *
174     * This was deprecated in API level 16.
175     *
176     */
177    public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
178
179
180    /**
181     * The Allocation will be used as the source of shader constants by one or
182     * more programs.
183     *
184     * This was deprecated in API level 16.
185     *
186     */
187    public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
188
189    /**
190     * The Allocation will be used as a target for offscreen rendering
191     *
192     * This was deprecated in API level 16.
193     *
194     */
195    public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
196
197    /**
198     * The Allocation will be used as a {@link android.view.Surface}
199     * consumer.  This usage will cause the Allocation to be created
200     * as read-only.
201     *
202     */
203    public static final int USAGE_IO_INPUT = 0x0020;
204
205    /**
206     * The Allocation will be used as a {@link android.view.Surface}
207     * producer.  The dimensions and format of the {@link
208     * android.view.Surface} will be forced to those of the
209     * Allocation.
210     *
211     */
212    public static final int USAGE_IO_OUTPUT = 0x0040;
213
214    /**
215     * The Allocation's backing store will be inherited from another object
216     * (usually a {@link android.graphics.Bitmap}); copying to or from the
217     * original source Bitmap will cause a synchronization rather than a full
218     * copy.  {@link #syncAll} may also be used to synchronize the Allocation
219     * and the source Bitmap.
220     *
221     * <p>This is set by default for allocations created with {@link
222     * #createFromBitmap} in API version 18 and higher.</p>
223     *
224     */
225    public static final int USAGE_SHARED = 0x0080;
226
227    /**
228     * Controls mipmap behavior when using the bitmap creation and update
229     * functions.
230     */
231    public enum MipmapControl {
232        /**
233         * No mipmaps will be generated and the type generated from the incoming
234         * bitmap will not contain additional LODs.
235         */
236        MIPMAP_NONE(0),
237
238        /**
239         * A full mipmap chain will be created in script memory.  The Type of
240         * the Allocation will contain a full mipmap chain.  On upload, the full
241         * chain will be transferred.
242         */
243        MIPMAP_FULL(1),
244
245        /**
246         * The Type of the Allocation will be the same as MIPMAP_NONE.  It will
247         * not contain mipmaps.  On upload, the allocation data will contain a
248         * full mipmap chain generated from the top level in script memory.
249         */
250        MIPMAP_ON_SYNC_TO_TEXTURE(2);
251
252        int mID;
253        MipmapControl(int id) {
254            mID = id;
255        }
256    }
257
258
259    private long getIDSafe() {
260        if (mAdaptedAllocation != null) {
261            return mAdaptedAllocation.getID(mRS);
262        }
263        return getID(mRS);
264    }
265
266
267   /**
268     * Get the {@link android.renderscript.Element} of the {@link
269     * android.renderscript.Type} of the Allocation.
270     *
271     * @return Element
272     *
273     */
274    public Element getElement() {
275        return mType.getElement();
276    }
277
278    /**
279     * Get the usage flags of the Allocation.
280     *
281     * @return usage this Allocation's set of the USAGE_* flags OR'd together
282     *
283     */
284    public int getUsage() {
285        return mUsage;
286    }
287
288    /**
289     * @hide
290     * Get the Mipmap control flag of the Allocation.
291     *
292     * @return the Mipmap control flag of the Allocation
293     *
294     */
295    public MipmapControl getMipmap() {
296        return mMipmapControl;
297    }
298
299    /**
300     * Specifies the mapping between the Allocation's cells and an array's elements
301     * when data is copied from the Allocation to the array, or vice-versa.
302     *
303     * Only applies to an Allocation whose Element is a vector of length 3 (such as
304     * {@link Element#U8_3} or {@link Element#RGB_888}). Enabling this feature may make
305     * copying data from the Allocation to an array or vice-versa less efficient.
306     *
307     * <p> Vec3 Element cells are stored in an Allocation as Vec4 Element cells with
308     * the same {@link android.renderscript.Element.DataType}, with the fourth vector
309     * component treated as padding. When this feature is enabled, only the data components,
310     * i.e. the first 3 vector components of each cell, will be mapped between the array
311     * and the Allocation. When disabled, explicit mapping of the padding components
312     * is required, as described in the following example.
313     *
314     * <p> For example, when copying an integer array to an Allocation of two {@link
315     * Element#I32_3} cells using {@link #copyFrom(int[])}:
316     * <p> When disabled:
317     *     The array must have at least 8 integers, with the first 4 integers copied
318     *     to the first cell of the Allocation, and the next 4 integers copied to
319     *     the second cell. The 4th and 8th integers are mapped as the padding components.
320     *
321     * <p> When enabled:
322     *     The array just needs to have at least 6 integers, with the first 3 integers
323     *     copied to the the first cell as data components, and the next 3 copied to
324     *     the second cell. There is no mapping for the padding components.
325     *
326     * <p> Similarly, when copying a byte array to an Allocation of two {@link
327     * Element#I32_3} cells, using {@link #copyFromUnchecked(int[])}:
328     * <p> When disabled:
329     *     The array must have at least 32 bytes, with the first 16 bytes copied
330     *     to the first cell of the Allocation, and the next 16 bytes copied to
331     *     the second cell. The 13th-16th and 29th-32nd bytes are mapped as padding
332     *     components.
333     *
334     * <p> When enabled:
335     *     The array just needs to have at least 24 bytes, with the first 12 bytes copied
336     *     to the first cell of the Allocation, and the next 12 bytes copied to
337     *     the second cell. There is no mapping for the padding components.
338     *
339     * <p> Similar to copying data to an Allocation from an array, when copying data from an
340     * Allocation to an array, the padding components for Vec3 Element cells will not be
341     * copied/mapped to the array if AutoPadding is enabled.
342     *
343     * <p> Default: Disabled.
344     *
345     * @param useAutoPadding True: enable AutoPadding; False: disable AutoPadding
346     *
347     */
348    public void setAutoPadding(boolean useAutoPadding) {
349        mAutoPadding = useAutoPadding;
350    }
351
352    /**
353     * Get the size of the Allocation in bytes.
354     *
355     * @return size of the Allocation in bytes.
356     *
357     */
358    public int getBytesSize() {
359        if (mType.mDimYuv != 0) {
360            return (int)Math.ceil(mType.getCount() * mType.getElement().getBytesSize() * 1.5);
361        }
362        return mType.getCount() * mType.getElement().getBytesSize();
363    }
364
365    private void updateCacheInfo(Type t) {
366        mCurrentDimX = t.getX();
367        mCurrentDimY = t.getY();
368        mCurrentDimZ = t.getZ();
369        mCurrentCount = mCurrentDimX;
370        if (mCurrentDimY > 1) {
371            mCurrentCount *= mCurrentDimY;
372        }
373        if (mCurrentDimZ > 1) {
374            mCurrentCount *= mCurrentDimZ;
375        }
376    }
377
378    private void setBitmap(Bitmap b) {
379        mBitmap = b;
380    }
381
382    Allocation(long id, RenderScript rs, Type t, int usage) {
383        super(id, rs);
384        if ((usage & ~(USAGE_SCRIPT |
385                       USAGE_GRAPHICS_TEXTURE |
386                       USAGE_GRAPHICS_VERTEX |
387                       USAGE_GRAPHICS_CONSTANTS |
388                       USAGE_GRAPHICS_RENDER_TARGET |
389                       USAGE_IO_INPUT |
390                       USAGE_IO_OUTPUT |
391                       USAGE_SHARED)) != 0) {
392            throw new RSIllegalArgumentException("Unknown usage specified.");
393        }
394
395        if ((usage & USAGE_IO_INPUT) != 0) {
396            mWriteAllowed = false;
397
398            if ((usage & ~(USAGE_IO_INPUT |
399                           USAGE_GRAPHICS_TEXTURE |
400                           USAGE_SCRIPT)) != 0) {
401                throw new RSIllegalArgumentException("Invalid usage combination.");
402            }
403        }
404
405        mType = t;
406        mUsage = usage;
407
408        if (t != null) {
409            // TODO: A3D doesn't have Type info during creation, so we can't
410            // calculate the size ahead of time. We can possibly add a method
411            // to update the size in the future if it seems reasonable.
412            mSize = mType.getCount() * mType.getElement().getBytesSize();
413            updateCacheInfo(t);
414        }
415        try {
416            RenderScript.registerNativeAllocation.invoke(RenderScript.sRuntime, mSize);
417        } catch (Exception e) {
418            Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e);
419            throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e);
420        }
421        guard.open("destroy");
422    }
423
424    Allocation(long id, RenderScript rs, Type t, boolean owningType, int usage, MipmapControl mips) {
425        this(id, rs, t, usage);
426        mOwningType = owningType;
427        mMipmapControl = mips;
428    }
429
430    protected void finalize() throws Throwable {
431        RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
432        super.finalize();
433    }
434
435    private void validateIsInt64() {
436        if ((mType.mElement.mType == Element.DataType.SIGNED_64) ||
437            (mType.mElement.mType == Element.DataType.UNSIGNED_64)) {
438            return;
439        }
440        throw new RSIllegalArgumentException(
441            "64 bit integer source does not match allocation type " + mType.mElement.mType);
442    }
443
444    private void validateIsInt32() {
445        if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
446            (mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
447            return;
448        }
449        throw new RSIllegalArgumentException(
450            "32 bit integer source does not match allocation type " + mType.mElement.mType);
451    }
452
453    private void validateIsInt16OrFloat16() {
454        if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
455            (mType.mElement.mType == Element.DataType.UNSIGNED_16) ||
456            (mType.mElement.mType == Element.DataType.FLOAT_16)) {
457            return;
458        }
459        throw new RSIllegalArgumentException(
460            "16 bit integer source does not match allocation type " + mType.mElement.mType);
461    }
462
463    private void validateIsInt8() {
464        if ((mType.mElement.mType == Element.DataType.SIGNED_8) ||
465            (mType.mElement.mType == Element.DataType.UNSIGNED_8)) {
466            return;
467        }
468        throw new RSIllegalArgumentException(
469            "8 bit integer source does not match allocation type " + mType.mElement.mType);
470    }
471
472    private void validateIsFloat32() {
473        if (mType.mElement.mType == Element.DataType.FLOAT_32) {
474            return;
475        }
476        throw new RSIllegalArgumentException(
477            "32 bit float source does not match allocation type " + mType.mElement.mType);
478    }
479
480    private void validateIsFloat64() {
481        if (mType.mElement.mType == Element.DataType.FLOAT_64) {
482            return;
483        }
484        throw new RSIllegalArgumentException(
485            "64 bit float source does not match allocation type " + mType.mElement.mType);
486    }
487
488    private void validateIsObject() {
489        if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) ||
490            (mType.mElement.mType == Element.DataType.RS_TYPE) ||
491            (mType.mElement.mType == Element.DataType.RS_ALLOCATION) ||
492            (mType.mElement.mType == Element.DataType.RS_SAMPLER) ||
493            (mType.mElement.mType == Element.DataType.RS_SCRIPT) ||
494            (mType.mElement.mType == Element.DataType.RS_MESH) ||
495            (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) ||
496            (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) ||
497            (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) ||
498            (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) {
499            return;
500        }
501        throw new RSIllegalArgumentException(
502            "Object source does not match allocation type " + mType.mElement.mType);
503    }
504
505    @Override
506    void updateFromNative() {
507        super.updateFromNative();
508        long typeID = mRS.nAllocationGetType(getID(mRS));
509        if(typeID != 0) {
510            mType = new Type(typeID, mRS);
511            mType.updateFromNative();
512            updateCacheInfo(mType);
513        }
514    }
515
516    /**
517     * Get the {@link android.renderscript.Type} of the Allocation.
518     *
519     * @return Type
520     *
521     */
522    public Type getType() {
523        return mType;
524    }
525
526    /**
527     * Propagate changes from one usage of the Allocation to the
528     * other usages of the Allocation.
529     *
530     */
531    public void syncAll(int srcLocation) {
532        try {
533            Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll");
534            switch (srcLocation) {
535                case USAGE_GRAPHICS_TEXTURE:
536                case USAGE_SCRIPT:
537                    if ((mUsage & USAGE_SHARED) != 0) {
538                        copyFrom(mBitmap);
539                    }
540                    break;
541                case USAGE_GRAPHICS_CONSTANTS:
542                case USAGE_GRAPHICS_VERTEX:
543                    break;
544                case USAGE_SHARED:
545                    if ((mUsage & USAGE_SHARED) != 0) {
546                        copyTo(mBitmap);
547                    }
548                    break;
549                default:
550                    throw new RSIllegalArgumentException("Source must be exactly one usage type.");
551            }
552            mRS.validate();
553            mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
554        } finally {
555            Trace.traceEnd(RenderScript.TRACE_TAG);
556        }
557    }
558
559    /**
560     * Send a buffer to the output stream.  The contents of the Allocation will
561     * be undefined after this operation. This operation is only valid if {@link
562     * #USAGE_IO_OUTPUT} is set on the Allocation.
563     *
564     *
565     */
566    public void ioSend() {
567        try {
568            Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend");
569            if ((mUsage & USAGE_IO_OUTPUT) == 0) {
570                throw new RSIllegalArgumentException(
571                    "Can only send buffer if IO_OUTPUT usage specified.");
572            }
573            mRS.validate();
574            mRS.nAllocationIoSend(getID(mRS));
575        } finally {
576            Trace.traceEnd(RenderScript.TRACE_TAG);
577        }
578    }
579
580    /**
581     * Receive the latest input into the Allocation. This operation
582     * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation.
583     *
584     */
585    public void ioReceive() {
586        try {
587            Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive");
588            if ((mUsage & USAGE_IO_INPUT) == 0) {
589                throw new RSIllegalArgumentException(
590                    "Can only receive if IO_INPUT usage specified.");
591            }
592            mRS.validate();
593            mTimeStamp = mRS.nAllocationIoReceive(getID(mRS));
594        } finally {
595            Trace.traceEnd(RenderScript.TRACE_TAG);
596        }
597    }
598
599    /**
600     * Copy an array of RS objects to the Allocation.
601     *
602     * @param d Source array.
603     */
604    public void copyFrom(BaseObj[] d) {
605        try {
606            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
607            mRS.validate();
608            validateIsObject();
609            if (d.length != mCurrentCount) {
610                throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
611                                                      mCurrentCount + ", array length = " + d.length);
612            }
613
614            if (RenderScript.sPointerSize == 8) {
615                long i[] = new long[d.length * 4];
616                for (int ct=0; ct < d.length; ct++) {
617                    i[ct * 4] = d[ct].getID(mRS);
618                }
619                copy1DRangeFromUnchecked(0, mCurrentCount, i);
620            } else {
621                int i[] = new int[d.length];
622                for (int ct=0; ct < d.length; ct++) {
623                    i[ct] = (int) d[ct].getID(mRS);
624                }
625                copy1DRangeFromUnchecked(0, mCurrentCount, i);
626            }
627        } finally {
628            Trace.traceEnd(RenderScript.TRACE_TAG);
629        }
630    }
631
632    private void validateBitmapFormat(Bitmap b) {
633        Bitmap.Config bc = b.getConfig();
634        if (bc == null) {
635            throw new RSIllegalArgumentException("Bitmap has an unsupported format for this operation");
636        }
637        switch (bc) {
638        case ALPHA_8:
639            if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
640                throw new RSIllegalArgumentException("Allocation kind is " +
641                                                     mType.getElement().mKind + ", type " +
642                                                     mType.getElement().mType +
643                                                     " of " + mType.getElement().getBytesSize() +
644                                                     " bytes, passed bitmap was " + bc);
645            }
646            break;
647        case ARGB_8888:
648            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
649                (mType.getElement().getBytesSize() != 4)) {
650                throw new RSIllegalArgumentException("Allocation kind is " +
651                                                     mType.getElement().mKind + ", type " +
652                                                     mType.getElement().mType +
653                                                     " of " + mType.getElement().getBytesSize() +
654                                                     " bytes, passed bitmap was " + bc);
655            }
656            break;
657        case RGB_565:
658            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
659                (mType.getElement().getBytesSize() != 2)) {
660                throw new RSIllegalArgumentException("Allocation kind is " +
661                                                     mType.getElement().mKind + ", type " +
662                                                     mType.getElement().mType +
663                                                     " of " + mType.getElement().getBytesSize() +
664                                                     " bytes, passed bitmap was " + bc);
665            }
666            break;
667        case ARGB_4444:
668            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
669                (mType.getElement().getBytesSize() != 2)) {
670                throw new RSIllegalArgumentException("Allocation kind is " +
671                                                     mType.getElement().mKind + ", type " +
672                                                     mType.getElement().mType +
673                                                     " of " + mType.getElement().getBytesSize() +
674                                                     " bytes, passed bitmap was " + bc);
675            }
676            break;
677
678        }
679    }
680
681    private void validateBitmapSize(Bitmap b) {
682        if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) {
683            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
684        }
685    }
686
687    private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
688        try {
689            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
690            mRS.validate();
691            if (mCurrentDimZ > 0) {
692                copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
693            } else if (mCurrentDimY > 0) {
694                copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
695            } else {
696                copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
697            }
698        } finally {
699            Trace.traceEnd(RenderScript.TRACE_TAG);
700        }
701    }
702
703
704    /**
705     * Copy into this Allocation from an array. This method does not guarantee
706     * that the Allocation is compatible with the input buffer; it copies memory
707     * without reinterpretation.
708     *
709     * <p> If the Allocation does not have Vec3 Elements, then the size of the
710     * array in bytes must be at least the size of the Allocation {@link
711     * #getBytesSize getBytesSize()}.
712     *
713     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
714     * is disabled, then the size of the array in bytes must be at least the size
715     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
716     * the cells must be part of the array.
717     *
718     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
719     * is enabled, then the size of the array in bytes must be at least 3/4 the size
720     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
721     * the cells must not be part of the array.
722     *
723     * @param array The source array
724     */
725    public void copyFromUnchecked(Object array) {
726        try {
727            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
728            copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
729                              java.lang.reflect.Array.getLength(array));
730        } finally {
731            Trace.traceEnd(RenderScript.TRACE_TAG);
732        }
733    }
734
735    /**
736     * Copy into this Allocation from an array. This method does not guarantee
737     * that the Allocation is compatible with the input buffer; it copies memory
738     * without reinterpretation.
739     *
740     * <p> If the Allocation does not have Vec3 Elements, then the size of the
741     * array in bytes must be at least the size of the Allocation {@link
742     * #getBytesSize getBytesSize()}.
743     *
744     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
745     * is disabled, then the size of the array in bytes must be at least the size
746     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
747     * the cells must be part of the array.
748     *
749     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
750     * is enabled, then the size of the array in bytes must be at least 3/4 the size
751     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
752     * the cells must not be part of the array.
753     *
754     * @param d the source array
755     */
756    public void copyFromUnchecked(int[] d) {
757        copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
758    }
759
760    /**
761     * Copy into this Allocation from an array. This method does not guarantee
762     * that the Allocation is compatible with the input buffer; it copies memory
763     * without reinterpretation.
764     *
765     * <p> If the Allocation does not have Vec3 Elements, then the size of the
766     * array in bytes must be at least the size of the Allocation {@link
767     * #getBytesSize getBytesSize()}.
768     *
769     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
770     * is disabled, then the size of the array in bytes must be at least the size
771     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
772     * the cells must be part of the array.
773     *
774     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
775     * is enabled, then the size of the array in bytes must be at least 3/4 the size
776     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
777     * the cells must not be part of the array.
778     *
779     * @param d the source array
780     */
781    public void copyFromUnchecked(short[] d) {
782        copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
783    }
784
785    /**
786     * Copy into this Allocation from an array. This method does not guarantee
787     * that the Allocation is compatible with the input buffer; it copies memory
788     * without reinterpretation.
789     *
790     * <p> If the Allocation does not have Vec3 Elements, then the size of the
791     * array in bytes must be at least the size of the Allocation {@link
792     * #getBytesSize getBytesSize()}.
793     *
794     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
795     * is disabled, then the size of the array in bytes must be at least the size
796     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
797     * the cells must be part of the array.
798     *
799     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
800     * is enabled, then the size of the array in bytes must be at least 3/4 the size
801     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
802     * the cells must not be part of the array.
803     *
804     * @param d the source array
805     */
806    public void copyFromUnchecked(byte[] d) {
807        copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
808    }
809
810    /**
811     * Copy into this Allocation from an array. This method does not guarantee
812     * that the Allocation is compatible with the input buffer; it copies memory
813     * without reinterpretation.
814     *
815     * <p> If the Allocation does not have Vec3 Elements, then the size of the
816     * array in bytes must be at least the size of the Allocation {@link
817     * #getBytesSize getBytesSize()}.
818     *
819     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
820     * is disabled, then the size of the array in bytes must be at least the size
821     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
822     * the cells must be part of the array.
823     *
824     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
825     * is enabled, then the size of the array in bytes must be at least 3/4 the size
826     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
827     * the cells must not be part of the array.
828     *
829     * @param d the source array
830     */
831    public void copyFromUnchecked(float[] d) {
832        copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
833    }
834
835
836    /**
837     * Copy into this Allocation from an array.  This variant is type checked
838     * and will generate exceptions if the Allocation's {@link
839     * android.renderscript.Element} does not match the array's
840     * primitive type.
841     *
842     * <p> If the Allocation does not have Vec3 Elements, then the size of the
843     * array in bytes must be at least the size of the Allocation {@link
844     * #getBytesSize getBytesSize()}.
845     *
846     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
847     * is disabled, then the size of the array in bytes must be at least the size
848     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
849     * the cells must be part of the array.
850     *
851     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
852     * is enabled, then the size of the array in bytes must be at least 3/4 the size
853     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
854     * the cells must not be part of the array.
855     *
856     * @param array The source array
857     */
858    public void copyFrom(Object array) {
859        try {
860            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
861            copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
862                              java.lang.reflect.Array.getLength(array));
863        } finally {
864            Trace.traceEnd(RenderScript.TRACE_TAG);
865        }
866    }
867
868    /**
869     * Copy into this Allocation from an array.  This variant is type checked
870     * and will generate exceptions if the Allocation's {@link
871     * android.renderscript.Element} is not a 32 bit integer nor a vector of 32 bit
872     * integers {@link android.renderscript.Element.DataType}.
873     *
874     * <p> If the Allocation does not have Vec3 Elements, then the size of the
875     * array in bytes must be at least the size of the Allocation {@link
876     * #getBytesSize getBytesSize()}.
877     *
878     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
879     * is disabled, then the size of the array in bytes must be at least the size
880     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
881     * the cells must be part of the array.
882     *
883     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
884     * is enabled, then the size of the array in bytes must be at least 3/4 the size
885     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
886     * the cells must not be part of the array.
887     *
888     * @param d the source array
889     */
890    public void copyFrom(int[] d) {
891        validateIsInt32();
892        copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
893    }
894
895    /**
896     * Copy into this Allocation from an array.  This variant is type checked
897     * and will generate exceptions if the Allocation's {@link
898     * android.renderscript.Element} is not a 16 bit integer nor a vector of 16 bit
899     * integers {@link android.renderscript.Element.DataType}.
900     *
901     * <p> If the Allocation does not have Vec3 Elements, then the size of the
902     * array in bytes must be at least the size of the Allocation {@link
903     * #getBytesSize getBytesSize()}.
904     *
905     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
906     * is disabled, then the size of the array in bytes must be at least the size
907     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
908     * the cells must be part of the array.
909     *
910     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
911     * is enabled, then the size of the array in bytes must be at least 3/4 the size
912     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
913     * the cells must not be part of the array.
914     *
915     * @param d the source array
916     */
917    public void copyFrom(short[] d) {
918        validateIsInt16OrFloat16();
919        copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
920    }
921
922    /**
923     * Copy into this Allocation from an array.  This variant is type checked
924     * and will generate exceptions if the Allocation's {@link
925     * android.renderscript.Element} is not an 8 bit integer nor a vector of 8 bit
926     * integers {@link android.renderscript.Element.DataType}.
927     *
928     * <p> If the Allocation does not have Vec3 Elements, then the size of the
929     * array in bytes must be at least the size of the Allocation {@link
930     * #getBytesSize getBytesSize()}.
931     *
932     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
933     * is disabled, then the size of the array in bytes must be at least the size
934     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
935     * the cells must be part of the array.
936     *
937     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
938     * is enabled, then the size of the array in bytes must be at least 3/4 the size
939     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
940     * the cells must not be part of the array.
941     *
942     * @param d the source array
943     */
944    public void copyFrom(byte[] d) {
945        validateIsInt8();
946        copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
947    }
948
949    /**
950     * Copy into this Allocation from an array.  This variant is type checked
951     * and will generate exceptions if the Allocation's {@link
952     * android.renderscript.Element} is neither a 32 bit float nor a vector of
953     * 32 bit floats {@link android.renderscript.Element.DataType}.
954     *
955     * <p> If the Allocation does not have Vec3 Elements, then the size of the
956     * array in bytes must be at least the size of the Allocation {@link
957     * #getBytesSize getBytesSize()}.
958     *
959     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
960     * is disabled, then the size of the array in bytes must be at least the size
961     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
962     * the cells must be part of the array.
963     *
964     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
965     * is enabled, then the size of the array in bytes must be at least 3/4 the size
966     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
967     * the cells must not be part of the array.
968     *
969     * @param d the source array
970     */
971    public void copyFrom(float[] d) {
972        validateIsFloat32();
973        copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
974    }
975
976    /**
977     * Copy into an Allocation from a {@link android.graphics.Bitmap}.  The
978     * height, width, and format of the bitmap must match the existing
979     * allocation.
980     *
981     * <p>If the {@link android.graphics.Bitmap} is the same as the {@link
982     * android.graphics.Bitmap} used to create the Allocation with {@link
983     * #createFromBitmap} and {@link #USAGE_SHARED} is set on the Allocation,
984     * this will synchronize the Allocation with the latest data from the {@link
985     * android.graphics.Bitmap}, potentially avoiding the actual copy.</p>
986     *
987     * @param b the source bitmap
988     */
989    public void copyFrom(Bitmap b) {
990        try {
991            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
992            mRS.validate();
993            if (b.getConfig() == null) {
994                Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
995                Canvas c = new Canvas(newBitmap);
996                c.drawBitmap(b, 0, 0, null);
997                copyFrom(newBitmap);
998                return;
999            }
1000            validateBitmapSize(b);
1001            validateBitmapFormat(b);
1002            mRS.nAllocationCopyFromBitmap(getID(mRS), b);
1003        } finally {
1004            Trace.traceEnd(RenderScript.TRACE_TAG);
1005        }
1006    }
1007
1008    /**
1009     * Copy an Allocation from an Allocation.  The types of both allocations
1010     * must be identical.
1011     *
1012     * @param a the source allocation
1013     */
1014    public void copyFrom(Allocation a) {
1015        try {
1016            Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
1017            mRS.validate();
1018            if (!mType.equals(a.getType())) {
1019                throw new RSIllegalArgumentException("Types of allocations must match.");
1020            }
1021            copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
1022        } finally {
1023            Trace.traceEnd(RenderScript.TRACE_TAG);
1024        }
1025    }
1026
1027    /**
1028     * This is only intended to be used by auto-generated code reflected from
1029     * the RenderScript script files and should not be used by developers.
1030     *
1031     * @param xoff
1032     * @param fp
1033     */
1034    public void setFromFieldPacker(int xoff, FieldPacker fp) {
1035        mRS.validate();
1036        int eSize = mType.mElement.getBytesSize();
1037        final byte[] data = fp.getData();
1038        int data_length = fp.getPos();
1039
1040        int count = data_length / eSize;
1041        if ((eSize * count) != data_length) {
1042            throw new RSIllegalArgumentException("Field packer length " + data_length +
1043                                               " not divisible by element size " + eSize + ".");
1044        }
1045        copy1DRangeFromUnchecked(xoff, count, data);
1046    }
1047
1048
1049    /**
1050     * This is only intended to be used by auto-generated code reflected from
1051     * the RenderScript script files and should not be used by developers.
1052     *
1053     * @param xoff
1054     * @param component_number
1055     * @param fp
1056     */
1057    public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
1058        setFromFieldPacker(xoff, 0, 0, component_number, fp);
1059    }
1060
1061    /**
1062     * This is only intended to be used by auto-generated code reflected from
1063     * the RenderScript script files and should not be used by developers.
1064     *
1065     * @param xoff
1066     * @param yoff
1067     * @param zoff
1068     * @param component_number
1069     * @param fp
1070     */
1071    public void setFromFieldPacker(int xoff, int yoff, int zoff, int component_number, FieldPacker fp) {
1072        mRS.validate();
1073        if (component_number >= mType.mElement.mElements.length) {
1074            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
1075        }
1076        if(xoff < 0) {
1077            throw new RSIllegalArgumentException("Offset x must be >= 0.");
1078        }
1079        if(yoff < 0) {
1080            throw new RSIllegalArgumentException("Offset y must be >= 0.");
1081        }
1082        if(zoff < 0) {
1083            throw new RSIllegalArgumentException("Offset z must be >= 0.");
1084        }
1085
1086        final byte[] data = fp.getData();
1087        int data_length = fp.getPos();
1088        int eSize = mType.mElement.mElements[component_number].getBytesSize();
1089        eSize *= mType.mElement.mArraySizes[component_number];
1090
1091        if (data_length != eSize) {
1092            throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
1093                                               " does not match component size " + eSize + ".");
1094        }
1095
1096        mRS.nAllocationElementData(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
1097                                   component_number, data, data_length);
1098    }
1099
1100    private void data1DChecks(int off, int count, int len, int dataSize, boolean usePadding) {
1101        mRS.validate();
1102        if(off < 0) {
1103            throw new RSIllegalArgumentException("Offset must be >= 0.");
1104        }
1105        if(count < 1) {
1106            throw new RSIllegalArgumentException("Count must be >= 1.");
1107        }
1108        if((off + count) > mCurrentCount) {
1109            throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
1110                                               ", got " + count + " at offset " + off + ".");
1111        }
1112        if(usePadding) {
1113            if(len < dataSize / 4 * 3) {
1114                throw new RSIllegalArgumentException("Array too small for allocation type.");
1115            }
1116        } else {
1117            if(len < dataSize) {
1118                throw new RSIllegalArgumentException("Array too small for allocation type.");
1119            }
1120        }
1121    }
1122
1123    /**
1124     * Generate a mipmap chain. This is only valid if the Type of the Allocation
1125     * includes mipmaps.
1126     *
1127     * <p>This function will generate a complete set of mipmaps from the top
1128     * level LOD and place them into the script memory space.</p>
1129     *
1130     * <p>If the Allocation is also using other memory spaces, a call to {@link
1131     * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p>
1132     */
1133    public void generateMipmaps() {
1134        mRS.nAllocationGenerateMipmaps(getID(mRS));
1135    }
1136
1137    private void copy1DRangeFromUnchecked(int off, int count, Object array,
1138                                          Element.DataType dt, int arrayLen) {
1139        try {
1140            Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
1141            final int dataSize = mType.mElement.getBytesSize() * count;
1142            // AutoPadding for Vec3 Element
1143            boolean usePadding = false;
1144            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1145                usePadding = true;
1146            }
1147            data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
1148            mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
1149                                  mType.mElement.mType.mSize, usePadding);
1150        } finally {
1151            Trace.traceEnd(RenderScript.TRACE_TAG);
1152        }
1153    }
1154
1155
1156    /**
1157     * Copy an array into a 1D region of this Allocation.  This method does not
1158     * guarantee that the Allocation is compatible with the input buffer.
1159     *
1160     * <p> The size of the region is: count * {@link #getElement}.{@link
1161     * Element#getBytesSize}.
1162     *
1163     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1164     * array in bytes must be at least the size of the region.
1165     *
1166     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1167     * is disabled, then the size of the array in bytes must be at least the size
1168     * of the region. The padding bytes for the cells must be part of the array.
1169     *
1170     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1171     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1172     * of the region. The padding bytes for the cells must not be part of the array.
1173     *
1174     * @param off The offset of the first element to be copied.
1175     * @param count The number of elements to be copied.
1176     * @param array The source array
1177     */
1178    public void copy1DRangeFromUnchecked(int off, int count, Object array) {
1179        copy1DRangeFromUnchecked(off, count, array,
1180                                 validateObjectIsPrimitiveArray(array, false),
1181                                 java.lang.reflect.Array.getLength(array));
1182    }
1183
1184    /**
1185     * Copy an array into a 1D region of this Allocation.  This method does not
1186     * guarantee that the Allocation is compatible with the input buffer.
1187     *
1188     * <p> The size of the region is: count * {@link #getElement}.{@link
1189     * Element#getBytesSize}.
1190     *
1191     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1192     * array in bytes must be at least the size of the region.
1193     *
1194     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1195     * is disabled, then the size of the array in bytes must be at least the size
1196     * of the region. The padding bytes for the cells must be part of the array.
1197     *
1198     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1199     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1200     * of the region. The padding bytes for the cells must not be part of the array.
1201     *
1202     * @param off The offset of the first element to be copied.
1203     * @param count The number of elements to be copied.
1204     * @param d the source array
1205     */
1206    public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
1207        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
1208    }
1209
1210    /**
1211     * Copy an array into a 1D region of this Allocation.  This method does not
1212     * guarantee that the Allocation is compatible with the input buffer.
1213     *
1214     * <p> The size of the region is: count * {@link #getElement}.{@link
1215     * Element#getBytesSize}.
1216     *
1217     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1218     * array in bytes must be at least the size of the region.
1219     *
1220     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1221     * is disabled, then the size of the array in bytes must be at least the size
1222     * of the region. The padding bytes for the cells must be part of the array.
1223     *
1224     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1225     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1226     * of the region. The padding bytes for the cells must not be part of the array.
1227     *
1228     * @param off The offset of the first element to be copied.
1229     * @param count The number of elements to be copied.
1230     * @param d the source array
1231     */
1232    public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
1233        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
1234    }
1235
1236    /**
1237     * Copy an array into a 1D region of this Allocation.  This method does not
1238     * guarantee that the Allocation is compatible with the input buffer.
1239     *
1240     * <p> The size of the region is: count * {@link #getElement}.{@link
1241     * Element#getBytesSize}.
1242     *
1243     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1244     * array in bytes must be at least the size of the region.
1245     *
1246     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1247     * is disabled, then the size of the array in bytes must be at least the size
1248     * of the region. The padding bytes for the cells must be part of the array.
1249     *
1250     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1251     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1252     * of the region. The padding bytes for the cells must not be part of the array.
1253     *
1254     * @param off The offset of the first element to be copied.
1255     * @param count The number of elements to be copied.
1256     * @param d the source array
1257     */
1258    public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
1259        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
1260    }
1261
1262    /**
1263     * Copy an array into a 1D region of this Allocation.  This method does not
1264     * guarantee that the Allocation is compatible with the input buffer.
1265     *
1266     * <p> The size of the region is: count * {@link #getElement}.{@link
1267     * Element#getBytesSize}.
1268     *
1269     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1270     * array in bytes must be at least the size of the region.
1271     *
1272     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1273     * is disabled, then the size of the array in bytes must be at least the size
1274     * of the region. The padding bytes for the cells must be part of the array.
1275     *
1276     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1277     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1278     * of the region. The padding bytes for the cells must not be part of the array.
1279     *
1280     * @param off The offset of the first element to be copied.
1281     * @param count The number of elements to be copied.
1282     * @param d the source array
1283     */
1284    public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
1285        copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
1286    }
1287
1288    /**
1289     * Copy an array into a 1D region of this Allocation.  This variant is type checked
1290     * and will generate exceptions if the Allocation's {@link
1291     * android.renderscript.Element} does not match the component type
1292     * of the array passed in.
1293     *
1294     * <p> The size of the region is: count * {@link #getElement}.{@link
1295     * Element#getBytesSize}.
1296     *
1297     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1298     * array in bytes must be at least the size of the region.
1299     *
1300     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1301     * is disabled, then the size of the array in bytes must be at least the size
1302     * of the region. The padding bytes for the cells must be part of the array.
1303     *
1304     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1305     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1306     * of the region. The padding bytes for the cells must not be part of the array.
1307     *
1308     * @param off The offset of the first element to be copied.
1309     * @param count The number of elements to be copied.
1310     * @param array The source array.
1311     */
1312    public void copy1DRangeFrom(int off, int count, Object array) {
1313        copy1DRangeFromUnchecked(off, count, array,
1314                                 validateObjectIsPrimitiveArray(array, true),
1315                                 java.lang.reflect.Array.getLength(array));
1316    }
1317
1318    /**
1319     * Copy an array into a 1D region of this Allocation.  This variant is type checked
1320     * and will generate exceptions if the Allocation's {@link
1321     * android.renderscript.Element} is not an 32 bit integer nor a vector of 32 bit
1322     * integers {@link android.renderscript.Element.DataType}.
1323     *
1324     * <p> The size of the region is: count * {@link #getElement}.{@link
1325     * Element#getBytesSize}.
1326     *
1327     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1328     * array in bytes must be at least the size of the region.
1329     *
1330     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1331     * is disabled, then the size of the array in bytes must be at least the size
1332     * of the region. The padding bytes for the cells must be part of the array.
1333     *
1334     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1335     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1336     * of the region. The padding bytes for the cells must not be part of the array.
1337     *
1338     * @param off The offset of the first element to be copied.
1339     * @param count The number of elements to be copied.
1340     * @param d the source array
1341     */
1342    public void copy1DRangeFrom(int off, int count, int[] d) {
1343        validateIsInt32();
1344        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
1345    }
1346
1347    /**
1348     * Copy an array into a 1D region of this Allocation.  This variant is type checked
1349     * and will generate exceptions if the Allocation's {@link
1350     * android.renderscript.Element} is not an 16 bit integer nor a vector of 16 bit
1351     * integers {@link android.renderscript.Element.DataType}.
1352     *
1353     * <p> The size of the region is: count * {@link #getElement}.{@link
1354     * Element#getBytesSize}.
1355     *
1356     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1357     * array in bytes must be at least the size of the region.
1358     *
1359     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1360     * is disabled, then the size of the array in bytes must be at least the size
1361     * of the region. The padding bytes for the cells must be part of the array.
1362     *
1363     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1364     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1365     * of the region. The padding bytes for the cells must not be part of the array.
1366     *
1367     * @param off The offset of the first element to be copied.
1368     * @param count The number of elements to be copied.
1369     * @param d the source array
1370     */
1371    public void copy1DRangeFrom(int off, int count, short[] d) {
1372        validateIsInt16OrFloat16();
1373        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
1374    }
1375
1376    /**
1377     * Copy an array into a 1D region of this Allocation.  This variant is type checked
1378     * and will generate exceptions if the Allocation's {@link
1379     * android.renderscript.Element} is not an 8 bit integer nor a vector of 8 bit
1380     * integers {@link android.renderscript.Element.DataType}.
1381     *
1382     * <p> The size of the region is: count * {@link #getElement}.{@link
1383     * Element#getBytesSize}.
1384     *
1385     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1386     * array in bytes must be at least the size of the region.
1387     *
1388     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1389     * is disabled, then the size of the array in bytes must be at least the size
1390     * of the region. The padding bytes for the cells must be part of the array.
1391     *
1392     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1393     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1394     * of the region. The padding bytes for the cells must not be part of the array.
1395     *
1396     * @param off The offset of the first element to be copied.
1397     * @param count The number of elements to be copied.
1398     * @param d the source array
1399     */
1400    public void copy1DRangeFrom(int off, int count, byte[] d) {
1401        validateIsInt8();
1402        copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
1403    }
1404
1405    /**
1406     * Copy an array into a 1D region of this Allocation.  This variant is type checked
1407     * and will generate exceptions if the Allocation's {@link
1408     * android.renderscript.Element} is neither a 32 bit float nor a vector of
1409     * 32 bit floats {@link android.renderscript.Element.DataType}.
1410     *
1411     * <p> The size of the region is: count * {@link #getElement}.{@link
1412     * Element#getBytesSize}.
1413     *
1414     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1415     * array in bytes must be at least the size of the region.
1416     *
1417     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1418     * is disabled, then the size of the array in bytes must be at least the size
1419     * of the region. The padding bytes for the cells must be part of the array.
1420     *
1421     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1422     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1423     * of the region. The padding bytes for the cells must not be part of the array.
1424     *
1425     * @param off The offset of the first element to be copied.
1426     * @param count The number of elements to be copied.
1427     * @param d the source array.
1428     */
1429    public void copy1DRangeFrom(int off, int count, float[] d) {
1430        validateIsFloat32();
1431        copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
1432    }
1433
1434     /**
1435     * Copy part of an Allocation into this Allocation.
1436     *
1437     * @param off The offset of the first element to be copied.
1438     * @param count The number of elements to be copied.
1439     * @param data the source data allocation.
1440     * @param dataOff off The offset of the first element in data to
1441     *          be copied.
1442     */
1443    public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
1444        Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
1445        mRS.nAllocationData2D(getIDSafe(), off, 0,
1446                              mSelectedLOD, mSelectedFace.mID,
1447                              count, 1, data.getID(mRS), dataOff, 0,
1448                              data.mSelectedLOD, data.mSelectedFace.mID);
1449        Trace.traceEnd(RenderScript.TRACE_TAG);
1450    }
1451
1452    private void validate2DRange(int xoff, int yoff, int w, int h) {
1453        if (mAdaptedAllocation != null) {
1454
1455        } else {
1456
1457            if (xoff < 0 || yoff < 0) {
1458                throw new RSIllegalArgumentException("Offset cannot be negative.");
1459            }
1460            if (h < 0 || w < 0) {
1461                throw new RSIllegalArgumentException("Height or width cannot be negative.");
1462            }
1463            if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
1464                throw new RSIllegalArgumentException("Updated region larger than allocation.");
1465            }
1466        }
1467    }
1468
1469    void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array,
1470                                  Element.DataType dt, int arrayLen) {
1471        try {
1472            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
1473            mRS.validate();
1474            validate2DRange(xoff, yoff, w, h);
1475            final int dataSize = mType.mElement.getBytesSize() * w * h;
1476            // AutoPadding for Vec3 Element
1477            boolean usePadding = false;
1478            int sizeBytes = arrayLen * dt.mSize;
1479            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1480                if (dataSize / 4 * 3 > sizeBytes) {
1481                    throw new RSIllegalArgumentException("Array too small for allocation type.");
1482                }
1483                usePadding = true;
1484                sizeBytes = dataSize;
1485            } else {
1486                if (dataSize > sizeBytes) {
1487                    throw new RSIllegalArgumentException("Array too small for allocation type.");
1488                }
1489            }
1490            mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
1491                                  array, sizeBytes, dt,
1492                                  mType.mElement.mType.mSize, usePadding);
1493        } finally {
1494            Trace.traceEnd(RenderScript.TRACE_TAG);
1495        }
1496    }
1497
1498    /**
1499     * Copy from an array into a rectangular region in this Allocation.  The
1500     * array is assumed to be tightly packed. This variant is type checked
1501     * and will generate exceptions if the Allocation's {@link
1502     * android.renderscript.Element} does not match the input data type.
1503     *
1504     * <p> The size of the region is: w * h * {@link #getElement}.{@link
1505     * Element#getBytesSize}.
1506     *
1507     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1508     * array in bytes must be at least the size of the region.
1509     *
1510     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1511     * is disabled, then the size of the array in bytes must be at least the size
1512     * of the region. The padding bytes for the cells must be part of the array.
1513     *
1514     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1515     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1516     * of the region. The padding bytes for the cells must not be part of the array.
1517     *
1518     * @param xoff X offset of the region to update in this Allocation
1519     * @param yoff Y offset of the region to update in this Allocation
1520     * @param w Width of the region to update
1521     * @param h Height of the region to update
1522     * @param array Data to be placed into the Allocation
1523     */
1524    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) {
1525        try {
1526            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1527            copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
1528                                     validateObjectIsPrimitiveArray(array, true),
1529                                     java.lang.reflect.Array.getLength(array));
1530        } finally {
1531            Trace.traceEnd(RenderScript.TRACE_TAG);
1532        }
1533    }
1534
1535    /**
1536     * Copy from an array into a rectangular region in this Allocation.  The
1537     * array is assumed to be tightly packed. This variant is type checked
1538     * and will generate exceptions if the Allocation's {@link
1539     * android.renderscript.Element} is not an 8 bit integer nor a vector of 8 bit
1540     * integers {@link android.renderscript.Element.DataType}.
1541     *
1542     * <p> The size of the region is: w * h * {@link #getElement}.{@link
1543     * Element#getBytesSize}.
1544     *
1545     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1546     * array in bytes must be at least the size of the region.
1547     *
1548     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1549     * is disabled, then the size of the array in bytes must be at least the size
1550     * of the region. The padding bytes for the cells must be part of the array.
1551     *
1552     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1553     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1554     * of the region. The padding bytes for the cells must not be part of the array.
1555     *
1556     * @param xoff X offset of the region to update in this Allocation
1557     * @param yoff Y offset of the region to update in this Allocation
1558     * @param w Width of the region to update
1559     * @param h Height of the region to update
1560     * @param data to be placed into the Allocation
1561     */
1562    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
1563        validateIsInt8();
1564        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1565                                 Element.DataType.SIGNED_8, data.length);
1566    }
1567
1568    /**
1569     * Copy from an array into a rectangular region in this Allocation.  The
1570     * array is assumed to be tightly packed. This variant is type checked
1571     * and will generate exceptions if the Allocation's {@link
1572     * android.renderscript.Element} is not a 16 bit integer nor a vector of 16 bit
1573     * integers {@link android.renderscript.Element.DataType}.
1574     *
1575     * <p> The size of the region is: w * h * {@link #getElement}.{@link
1576     * Element#getBytesSize}.
1577     *
1578     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1579     * array in bytes must be at least the size of the region.
1580     *
1581     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1582     * is disabled, then the size of the array in bytes must be at least the size
1583     * of the region. The padding bytes for the cells must be part of the array.
1584     *
1585     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1586     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1587     * of the region. The padding bytes for the cells must not be part of the array.
1588     *
1589     * @param xoff X offset of the region to update in this Allocation
1590     * @param yoff Y offset of the region to update in this Allocation
1591     * @param w Width of the region to update
1592     * @param h Height of the region to update
1593     * @param data to be placed into the Allocation
1594     */
1595    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
1596        validateIsInt16OrFloat16();
1597        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1598                                 Element.DataType.SIGNED_16, data.length);
1599    }
1600
1601    /**
1602     * Copy from an array into a rectangular region in this Allocation.  The
1603     * array is assumed to be tightly packed. This variant is type checked
1604     * and will generate exceptions if the Allocation's {@link
1605     * android.renderscript.Element} is not a 32 bit integer nor a vector of 32 bit
1606     * integers {@link android.renderscript.Element.DataType}.
1607     *
1608     * <p> The size of the region is: w * h * {@link #getElement}.{@link
1609     * Element#getBytesSize}.
1610     *
1611     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1612     * array in bytes must be at least the size of the region.
1613     *
1614     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1615     * is disabled, then the size of the array in bytes must be at least the size
1616     * of the region. The padding bytes for the cells must be part of the array.
1617     *
1618     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1619     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1620     * of the region. The padding bytes for the cells must not be part of the array.
1621     *
1622     * @param xoff X offset of the region to update in this Allocation
1623     * @param yoff Y offset of the region to update in this Allocation
1624     * @param w Width of the region to update
1625     * @param h Height of the region to update
1626     * @param data to be placed into the Allocation
1627     */
1628    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
1629        validateIsInt32();
1630        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1631                                 Element.DataType.SIGNED_32, data.length);
1632    }
1633
1634    /**
1635     * Copy from an array into a rectangular region in this Allocation.  The
1636     * array is assumed to be tightly packed. This variant is type checked
1637     * and will generate exceptions if the Allocation's {@link
1638     * android.renderscript.Element} is neither a 32 bit float nor a vector of
1639     * 32 bit floats {@link android.renderscript.Element.DataType}.
1640     *
1641     * <p> The size of the region is: w * h * {@link #getElement}.{@link
1642     * Element#getBytesSize}.
1643     *
1644     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1645     * array in bytes must be at least the size of the region.
1646     *
1647     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1648     * is disabled, then the size of the array in bytes must be at least the size
1649     * of the region. The padding bytes for the cells must be part of the array.
1650     *
1651     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1652     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1653     * of the region. The padding bytes for the cells must not be part of the array.
1654     *
1655     * @param xoff X offset of the region to update in this Allocation
1656     * @param yoff Y offset of the region to update in this Allocation
1657     * @param w Width of the region to update
1658     * @param h Height of the region to update
1659     * @param data to be placed into the Allocation
1660     */
1661    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
1662        validateIsFloat32();
1663        copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
1664                                 Element.DataType.FLOAT_32, data.length);
1665    }
1666
1667    /**
1668     * Copy a rectangular region from an Allocation into a rectangular region in
1669     * this Allocation.
1670     *
1671     * @param xoff X offset of the region in this Allocation
1672     * @param yoff Y offset of the region in this Allocation
1673     * @param w Width of the region to update.
1674     * @param h Height of the region to update.
1675     * @param data source Allocation.
1676     * @param dataXoff X offset in source Allocation
1677     * @param dataYoff Y offset in source Allocation
1678     */
1679    public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
1680                                Allocation data, int dataXoff, int dataYoff) {
1681        try {
1682            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1683            mRS.validate();
1684            validate2DRange(xoff, yoff, w, h);
1685            mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
1686                                  mSelectedLOD, mSelectedFace.mID,
1687                                  w, h, data.getID(mRS), dataXoff, dataYoff,
1688                                  data.mSelectedLOD, data.mSelectedFace.mID);
1689        } finally {
1690            Trace.traceEnd(RenderScript.TRACE_TAG);
1691        }
1692    }
1693
1694    /**
1695     * Copy a {@link android.graphics.Bitmap} into an Allocation.  The height
1696     * and width of the update will use the height and width of the {@link
1697     * android.graphics.Bitmap}.
1698     *
1699     * @param xoff X offset of the region to update in this Allocation
1700     * @param yoff Y offset of the region to update in this Allocation
1701     * @param data the Bitmap to be copied
1702     */
1703    public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
1704        try {
1705            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
1706            mRS.validate();
1707            if (data.getConfig() == null) {
1708                Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888);
1709                Canvas c = new Canvas(newBitmap);
1710                c.drawBitmap(data, 0, 0, null);
1711                copy2DRangeFrom(xoff, yoff, newBitmap);
1712                return;
1713            }
1714            validateBitmapFormat(data);
1715            validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
1716            mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
1717        } finally {
1718            Trace.traceEnd(RenderScript.TRACE_TAG);
1719        }
1720    }
1721
1722    private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) {
1723        if (mAdaptedAllocation != null) {
1724
1725        } else {
1726
1727            if (xoff < 0 || yoff < 0 || zoff < 0) {
1728                throw new RSIllegalArgumentException("Offset cannot be negative.");
1729            }
1730            if (h < 0 || w < 0 || d < 0) {
1731                throw new RSIllegalArgumentException("Height or width cannot be negative.");
1732            }
1733            if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
1734                throw new RSIllegalArgumentException("Updated region larger than allocation.");
1735            }
1736        }
1737    }
1738
1739    /**
1740     * Copy a rectangular region from the array into the allocation.
1741     * The array is assumed to be tightly packed.
1742     *
1743     * The data type of the array is not required to be the same as
1744     * the element data type.
1745     */
1746    private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
1747                                          Object array, Element.DataType dt, int arrayLen) {
1748        try {
1749            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
1750            mRS.validate();
1751            validate3DRange(xoff, yoff, zoff, w, h, d);
1752            final int dataSize = mType.mElement.getBytesSize() * w * h * d;
1753            // AutoPadding for Vec3 Element
1754            boolean usePadding = false;
1755            int sizeBytes = arrayLen * dt.mSize;
1756            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1757                if (dataSize / 4 * 3 > sizeBytes) {
1758                    throw new RSIllegalArgumentException("Array too small for allocation type.");
1759                }
1760                usePadding = true;
1761                sizeBytes = dataSize;
1762            } else {
1763                if (dataSize > sizeBytes) {
1764                    throw new RSIllegalArgumentException("Array too small for allocation type.");
1765                }
1766            }
1767            mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
1768                                  array, sizeBytes, dt,
1769                                  mType.mElement.mType.mSize, usePadding);
1770        } finally {
1771            Trace.traceEnd(RenderScript.TRACE_TAG);
1772        }
1773    }
1774
1775    /**
1776     * Copy from an array into a 3D region in this Allocation.  The
1777     * array is assumed to be tightly packed. This variant is type checked
1778     * and will generate exceptions if the Allocation's {@link
1779     * android.renderscript.Element} does not match the input data type.
1780     *
1781     * <p> The size of the region is: w * h * d * {@link #getElement}.{@link
1782     * Element#getBytesSize}.
1783     *
1784     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1785     * array in bytes must be at least the size of the region.
1786     *
1787     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1788     * is disabled, then the size of the array in bytes must be at least the size
1789     * of the region. The padding bytes for the cells must be part of the array.
1790     *
1791     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1792     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1793     * of the region. The padding bytes for the cells must not be part of the array.
1794     *
1795     * @param xoff X offset of the region to update in this Allocation
1796     * @param yoff Y offset of the region to update in this Allocation
1797     * @param zoff Z offset of the region to update in this Allocation
1798     * @param w Width of the region to update
1799     * @param h Height of the region to update
1800     * @param d Depth of the region to update
1801     * @param array to be placed into the allocation
1802     */
1803    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
1804        try {
1805            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
1806            copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
1807                                     validateObjectIsPrimitiveArray(array, true),
1808                                     java.lang.reflect.Array.getLength(array));
1809        } finally {
1810            Trace.traceEnd(RenderScript.TRACE_TAG);
1811        }
1812    }
1813
1814    /**
1815     * Copy a rectangular region into the allocation from another
1816     * allocation.
1817     *
1818     * @param xoff X offset of the region to update in this Allocation
1819     * @param yoff Y offset of the region to update in this Allocation
1820     * @param zoff Z offset of the region to update in this Allocation
1821     * @param w Width of the region to update.
1822     * @param h Height of the region to update.
1823     * @param d Depth of the region to update.
1824     * @param data source allocation.
1825     * @param dataXoff X offset of the region in the source Allocation
1826     * @param dataYoff Y offset of the region in the source Allocation
1827     * @param dataZoff Z offset of the region in the source Allocation
1828     */
1829    public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d,
1830                                Allocation data, int dataXoff, int dataYoff, int dataZoff) {
1831        mRS.validate();
1832        validate3DRange(xoff, yoff, zoff, w, h, d);
1833        mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
1834                              w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff,
1835                              data.mSelectedLOD);
1836    }
1837
1838
1839    /**
1840     * Copy from the Allocation into a {@link android.graphics.Bitmap}.  The
1841     * bitmap must match the dimensions of the Allocation.
1842     *
1843     * @param b The bitmap to be set from the Allocation.
1844     */
1845    public void copyTo(Bitmap b) {
1846        try {
1847            Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
1848            mRS.validate();
1849            validateBitmapFormat(b);
1850            validateBitmapSize(b);
1851            mRS.nAllocationCopyToBitmap(getID(mRS), b);
1852        } finally {
1853            Trace.traceEnd(RenderScript.TRACE_TAG);
1854        }
1855    }
1856
1857    private void copyTo(Object array, Element.DataType dt, int arrayLen) {
1858        try {
1859            Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
1860            mRS.validate();
1861            boolean usePadding = false;
1862            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
1863                usePadding = true;
1864            }
1865            if (usePadding) {
1866                if (dt.mSize * arrayLen < mSize / 4 * 3) {
1867                    throw new RSIllegalArgumentException(
1868                        "Size of output array cannot be smaller than size of allocation.");
1869                }
1870            } else {
1871                if (dt.mSize * arrayLen < mSize) {
1872                    throw new RSIllegalArgumentException(
1873                        "Size of output array cannot be smaller than size of allocation.");
1874                }
1875            }
1876            mRS.nAllocationRead(getID(mRS), array, dt, mType.mElement.mType.mSize, usePadding);
1877        } finally {
1878            Trace.traceEnd(RenderScript.TRACE_TAG);
1879        }
1880    }
1881
1882    /**
1883     * Copy from the Allocation into an array. The method is type checked
1884     * and will generate exceptions if the Allocation's {@link
1885     * android.renderscript.Element} does not match the input data type.
1886     *
1887     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1888     * array in bytes must be at least the size of the Allocation {@link
1889     * #getBytesSize getBytesSize()}.
1890     *
1891     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1892     * is disabled, then the size of the array in bytes must be at least the size
1893     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
1894     * the cells will be part of the array.
1895     *
1896     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1897     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1898     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
1899     * the cells must not be part of the array.
1900     *
1901     * @param array The array to be set from the Allocation.
1902     */
1903    public void copyTo(Object array) {
1904        copyTo(array, validateObjectIsPrimitiveArray(array, true),
1905               java.lang.reflect.Array.getLength(array));
1906    }
1907
1908    /**
1909     * Copy from the Allocation into a byte array. This variant is type checked
1910     * and will generate exceptions if the Allocation's {@link
1911     * android.renderscript.Element} is neither an 8 bit integer nor a vector of 8 bit
1912     * integers {@link android.renderscript.Element.DataType}.
1913     *
1914     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1915     * array in bytes must be at least the size of the Allocation {@link
1916     * #getBytesSize getBytesSize()}.
1917     *
1918     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1919     * is disabled, then the size of the array in bytes must be at least the size
1920     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
1921     * the cells will be part of the array.
1922     *
1923     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1924     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1925     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
1926     * the cells must not be part of the array.
1927     *
1928     * @param d The array to be set from the Allocation.
1929     */
1930    public void copyTo(byte[] d) {
1931        validateIsInt8();
1932        copyTo(d, Element.DataType.SIGNED_8, d.length);
1933    }
1934
1935    /**
1936     * Copy from the Allocation into a short array. This variant is type checked
1937     * and will generate exceptions if the Allocation's {@link
1938     * android.renderscript.Element} is not a 16 bit integer nor a vector of 16 bit
1939     * integers {@link android.renderscript.Element.DataType}.
1940     *
1941     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1942     * array in bytes must be at least the size of the Allocation {@link
1943     * #getBytesSize getBytesSize()}.
1944     *
1945     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1946     * is disabled, then the size of the array in bytes must be at least the size
1947     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
1948     * the cells will be part of the array.
1949     *
1950     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1951     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1952     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
1953     * the cells must not be part of the array.
1954     *
1955     * @param d The array to be set from the Allocation.
1956     */
1957    public void copyTo(short[] d) {
1958        validateIsInt16OrFloat16();
1959        copyTo(d, Element.DataType.SIGNED_16, d.length);
1960    }
1961
1962    /**
1963     * Copy from the Allocation into a int array. This variant is type checked
1964     * and will generate exceptions if the Allocation's {@link
1965     * android.renderscript.Element} is not a 32 bit integer nor a vector of 32 bit
1966     * integers {@link android.renderscript.Element.DataType}.
1967     *
1968     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1969     * array in bytes must be at least the size of the Allocation {@link
1970     * #getBytesSize getBytesSize()}.
1971     *
1972     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1973     * is disabled, then the size of the array in bytes must be at least the size
1974     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
1975     * the cells will be part of the array.
1976     *
1977     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
1978     * is enabled, then the size of the array in bytes must be at least 3/4 the size
1979     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
1980     * the cells must not be part of the array.
1981     *
1982     * @param d The array to be set from the Allocation.
1983     */
1984    public void copyTo(int[] d) {
1985        validateIsInt32();
1986        copyTo(d, Element.DataType.SIGNED_32, d.length);
1987    }
1988
1989    /**
1990     * Copy from the Allocation into a float array. This variant is type checked
1991     * and will generate exceptions if the Allocation's {@link
1992     * android.renderscript.Element} is neither a 32 bit float nor a vector of
1993     * 32 bit floats {@link android.renderscript.Element.DataType}.
1994     *
1995     * <p> If the Allocation does not have Vec3 Elements, then the size of the
1996     * array in bytes must be at least the size of the Allocation {@link
1997     * #getBytesSize getBytesSize()}.
1998     *
1999     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2000     * is disabled, then the size of the array in bytes must be at least the size
2001     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
2002     * the cells will be part of the array.
2003     *
2004     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2005     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2006     * of the Allocation {@link #getBytesSize getBytesSize()}. The padding bytes for
2007     * the cells must not be part of the array.
2008     *
2009     * @param d The array to be set from the Allocation.
2010     */
2011    public void copyTo(float[] d) {
2012        validateIsFloat32();
2013        copyTo(d, Element.DataType.FLOAT_32, d.length);
2014    }
2015
2016    /**
2017     * @hide
2018     *
2019     * This is only intended to be used by auto-generated code reflected from
2020     * the RenderScript script files and should not be used by developers.
2021     *
2022     * @param xoff
2023     * @param yoff
2024     * @param zoff
2025     * @param component_number
2026     * @param fp
2027     */
2028    public void copyToFieldPacker(int xoff, int yoff, int zoff, int component_number, FieldPacker fp) {
2029        mRS.validate();
2030        if (component_number >= mType.mElement.mElements.length) {
2031            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
2032        }
2033        if(xoff < 0) {
2034            throw new RSIllegalArgumentException("Offset x must be >= 0.");
2035        }
2036        if(yoff < 0) {
2037            throw new RSIllegalArgumentException("Offset y must be >= 0.");
2038        }
2039        if(zoff < 0) {
2040            throw new RSIllegalArgumentException("Offset z must be >= 0.");
2041        }
2042
2043        final byte[] data = fp.getData();
2044        int data_length = data.length;
2045        int eSize = mType.mElement.mElements[component_number].getBytesSize();
2046        eSize *= mType.mElement.mArraySizes[component_number];
2047
2048        if (data_length != eSize) {
2049            throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
2050                                               " does not match component size " + eSize + ".");
2051        }
2052
2053        mRS.nAllocationElementRead(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
2054                                   component_number, data, data_length);
2055    }
2056    /**
2057     * Resize a 1D allocation.  The contents of the allocation are preserved.
2058     * If new elements are allocated objects are created with null contents and
2059     * the new region is otherwise undefined.
2060     *
2061     * <p>If the new region is smaller the references of any objects outside the
2062     * new region will be released.</p>
2063     *
2064     * <p>A new type will be created with the new dimension.</p>
2065     *
2066     * @param dimX The new size of the allocation.
2067     *
2068     * @deprecated RenderScript objects should be immutable once created.  The
2069     * replacement is to create a new allocation and copy the contents. This
2070     * function will throw an exception if API 21 or higher is used.
2071     */
2072    public synchronized void resize(int dimX) {
2073        if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 21) {
2074            throw new RSRuntimeException("Resize is not allowed in API 21+.");
2075        }
2076        if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
2077            throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
2078        }
2079        mRS.nAllocationResize1D(getID(mRS), dimX);
2080        mRS.finish();  // Necessary because resize is fifoed and update is async.
2081
2082        long typeID = mRS.nAllocationGetType(getID(mRS));
2083        // Sets zero the mID so that the finalizer of the old mType value won't
2084        // destroy the native object that is being reused.
2085        mType.setID(0);
2086        mType = new Type(typeID, mRS);
2087        mType.updateFromNative();
2088        updateCacheInfo(mType);
2089    }
2090
2091    private void copy1DRangeToUnchecked(int off, int count, Object array,
2092                                        Element.DataType dt, int arrayLen) {
2093        try {
2094            Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeToUnchecked");
2095            final int dataSize = mType.mElement.getBytesSize() * count;
2096            // AutoPadding for Vec3 Element
2097            boolean usePadding = false;
2098            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
2099                usePadding = true;
2100            }
2101            data1DChecks(off, count, arrayLen * dt.mSize, dataSize, usePadding);
2102            mRS.nAllocationRead1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt,
2103                                  mType.mElement.mType.mSize, usePadding);
2104        } finally {
2105            Trace.traceEnd(RenderScript.TRACE_TAG);
2106        }
2107    }
2108
2109    /**
2110     * Copy a 1D region of this Allocation into an array.  This method does not
2111     * guarantee that the Allocation is compatible with the input buffer.
2112     *
2113     * <p> The size of the region is: count * {@link #getElement}.{@link
2114     * Element#getBytesSize}.
2115     *
2116     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2117     * array in bytes must be at least the size of the region.
2118     *
2119     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2120     * is disabled, then the size of the array in bytes must be at least the size
2121     * of the region. The padding bytes for the cells must be part of the array.
2122     *
2123     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2124     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2125     * of the region. The padding bytes for the cells must not be part of the array.
2126     *
2127     * @param off The offset of the first element to be copied.
2128     * @param count The number of elements to be copied.
2129     * @param array The dest array
2130     */
2131    public void copy1DRangeToUnchecked(int off, int count, Object array) {
2132        copy1DRangeToUnchecked(off, count, array,
2133                               validateObjectIsPrimitiveArray(array, false),
2134                               java.lang.reflect.Array.getLength(array));
2135    }
2136
2137    /**
2138     * Copy a 1D region of this Allocation into an array.  This method does not
2139     * guarantee that the Allocation is compatible with the input buffer.
2140     *
2141     * <p> The size of the region is: count * {@link #getElement}.{@link
2142     * Element#getBytesSize}.
2143     *
2144     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2145     * array in bytes must be at least the size of the region.
2146     *
2147     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2148     * is disabled, then the size of the array in bytes must be at least the size
2149     * of the region. The padding bytes for the cells must be part of the array.
2150     *
2151     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2152     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2153     * of the region. The padding bytes for the cells must not be part of the array.
2154     *
2155     * @param off The offset of the first element to be copied.
2156     * @param count The number of elements to be copied.
2157     * @param d the source array
2158     */
2159    public void copy1DRangeToUnchecked(int off, int count, int[] d) {
2160        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
2161    }
2162
2163    /**
2164     * Copy a 1D region of this Allocation into an array.  This method does not
2165     * guarantee that the Allocation is compatible with the input buffer.
2166     *
2167     * <p> The size of the region is: count * {@link #getElement}.{@link
2168     * Element#getBytesSize}.
2169     *
2170     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2171     * array in bytes must be at least the size of the region.
2172     *
2173     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2174     * is disabled, then the size of the array in bytes must be at least the size
2175     * of the region. The padding bytes for the cells must be part of the array.
2176     *
2177     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2178     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2179     * of the region. The padding bytes for the cells must not be part of the array.
2180     *
2181     * @param off The offset of the first element to be copied.
2182     * @param count The number of elements to be copied.
2183     * @param d the source array
2184     */
2185    public void copy1DRangeToUnchecked(int off, int count, short[] d) {
2186        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
2187    }
2188
2189    /**
2190     * Copy a 1D region of this Allocation into an array.  This method does not
2191     * guarantee that the Allocation is compatible with the input buffer.
2192     *
2193     * <p> The size of the region is: count * {@link #getElement}.{@link
2194     * Element#getBytesSize}.
2195     *
2196     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2197     * array in bytes must be at least the size of the region.
2198     *
2199     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2200     * is disabled, then the size of the array in bytes must be at least the size
2201     * of the region. The padding bytes for the cells must be part of the array.
2202     *
2203     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2204     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2205     * of the region. The padding bytes for the cells must not be part of the array.
2206     *
2207     * @param off The offset of the first element to be copied.
2208     * @param count The number of elements to be copied.
2209     * @param d the source array
2210     */
2211    public void copy1DRangeToUnchecked(int off, int count, byte[] d) {
2212        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
2213    }
2214
2215    /**
2216     * Copy a 1D region of this Allocation into an array.  This method does not
2217     * guarantee that the Allocation is compatible with the input buffer.
2218     *
2219     * <p> The size of the region is: count * {@link #getElement}.{@link
2220     * Element#getBytesSize}.
2221     *
2222     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2223     * array in bytes must be at least the size of the region.
2224     *
2225     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2226     * is disabled, then the size of the array in bytes must be at least the size
2227     * of the region. The padding bytes for the cells must be part of the array.
2228     *
2229     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2230     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2231     * of the region. The padding bytes for the cells must not be part of the array.
2232     *
2233     * @param off The offset of the first element to be copied.
2234     * @param count The number of elements to be copied.
2235     * @param d the source array
2236     */
2237    public void copy1DRangeToUnchecked(int off, int count, float[] d) {
2238        copy1DRangeToUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
2239    }
2240
2241    /**
2242     * Copy a 1D region of this Allocation into an array.  This method is type checked
2243     * and will generate exceptions if the Allocation's {@link
2244     * android.renderscript.Element} does not match the component type
2245     * of the array passed in.
2246     *
2247     * <p> The size of the region is: count * {@link #getElement}.{@link
2248     * Element#getBytesSize}.
2249     *
2250     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2251     * array in bytes must be at least the size of the region.
2252     *
2253     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2254     * is disabled, then the size of the array in bytes must be at least the size
2255     * of the region. The padding bytes for the cells must be part of the array.
2256     *
2257     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2258     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2259     * of the region. The padding bytes for the cells must not be part of the array.
2260     *
2261     * @param off The offset of the first element to be copied.
2262     * @param count The number of elements to be copied.
2263     * @param array The source array.
2264     */
2265    public void copy1DRangeTo(int off, int count, Object array) {
2266        copy1DRangeToUnchecked(off, count, array,
2267                               validateObjectIsPrimitiveArray(array, true),
2268                               java.lang.reflect.Array.getLength(array));
2269    }
2270
2271    /**
2272     * Copy a 1D region of this Allocation into an array. This variant is type checked
2273     * and will generate exceptions if the Allocation's {@link
2274     * android.renderscript.Element} is neither a 32 bit integer nor a vector of 32 bit
2275     * integers {@link android.renderscript.Element.DataType}.
2276     *
2277     * <p> The size of the region is: count * {@link #getElement}.{@link
2278     * Element#getBytesSize}.
2279     *
2280     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2281     * array in bytes must be at least the size of the region.
2282     *
2283     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2284     * is disabled, then the size of the array in bytes must be at least the size
2285     * of the region. The padding bytes for the cells must be part of the array.
2286     *
2287     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2288     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2289     * of the region. The padding bytes for the cells must not be part of the array.
2290     *
2291     * @param off The offset of the first element to be copied.
2292     * @param count The number of elements to be copied.
2293     * @param d the source array
2294     */
2295    public void copy1DRangeTo(int off, int count, int[] d) {
2296        validateIsInt32();
2297        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
2298    }
2299
2300    /**
2301     * Copy a 1D region of this Allocation into an array. This variant is type checked
2302     * and will generate exceptions if the Allocation's {@link
2303     * android.renderscript.Element} is neither a 16 bit integer nor a vector of 16 bit
2304     * integers {@link android.renderscript.Element.DataType}.
2305     *
2306     * <p> The size of the region is: count * {@link #getElement}.{@link
2307     * Element#getBytesSize}.
2308     *
2309     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2310     * array in bytes must be at least the size of the region.
2311     *
2312     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2313     * is disabled, then the size of the array in bytes must be at least the size
2314     * of the region. The padding bytes for the cells must be part of the array.
2315     *
2316     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2317     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2318     * of the region. The padding bytes for the cells must not be part of the array.
2319     *
2320     * @param off The offset of the first element to be copied.
2321     * @param count The number of elements to be copied.
2322     * @param d the source array
2323     */
2324    public void copy1DRangeTo(int off, int count, short[] d) {
2325        validateIsInt16OrFloat16();
2326        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
2327    }
2328
2329    /**
2330     * Copy a 1D region of this Allocation into an array. This variant is type checked
2331     * and will generate exceptions if the Allocation's {@link
2332     * android.renderscript.Element} is neither an 8 bit integer nor a vector of 8 bit
2333     * integers {@link android.renderscript.Element.DataType}.
2334     *
2335     * <p> The size of the region is: count * {@link #getElement}.{@link
2336     * Element#getBytesSize}.
2337     *
2338     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2339     * array in bytes must be at least the size of the region.
2340     *
2341     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2342     * is disabled, then the size of the array in bytes must be at least the size
2343     * of the region. The padding bytes for the cells must be part of the array.
2344     *
2345     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2346     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2347     * of the region. The padding bytes for the cells must not be part of the array.
2348     *
2349     * @param off The offset of the first element to be copied.
2350     * @param count The number of elements to be copied.
2351     * @param d the source array
2352     */
2353    public void copy1DRangeTo(int off, int count, byte[] d) {
2354        validateIsInt8();
2355        copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
2356    }
2357
2358    /**
2359     * Copy a 1D region of this Allocation into an array. This variant is type checked
2360     * and will generate exceptions if the Allocation's {@link
2361     * android.renderscript.Element} is neither a 32 bit float nor a vector of
2362     * 32 bit floats {@link android.renderscript.Element.DataType}.
2363     *
2364     * <p> The size of the region is: count * {@link #getElement}.{@link
2365     * Element#getBytesSize}.
2366     *
2367     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2368     * array in bytes must be at least the size of the region.
2369     *
2370     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2371     * is disabled, then the size of the array in bytes must be at least the size
2372     * of the region. The padding bytes for the cells must be part of the array.
2373     *
2374     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2375     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2376     * of the region. The padding bytes for the cells must not be part of the array.
2377     *
2378     * @param off The offset of the first element to be copied.
2379     * @param count The number of elements to be copied.
2380     * @param d the source array.
2381     */
2382    public void copy1DRangeTo(int off, int count, float[] d) {
2383        validateIsFloat32();
2384        copy1DRangeToUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
2385    }
2386
2387
2388    void copy2DRangeToUnchecked(int xoff, int yoff, int w, int h, Object array,
2389                                Element.DataType dt, int arrayLen) {
2390        try {
2391            Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeToUnchecked");
2392            mRS.validate();
2393            validate2DRange(xoff, yoff, w, h);
2394            final int dataSize = mType.mElement.getBytesSize() * w * h;
2395            // AutoPadding for Vec3 Element
2396            boolean usePadding = false;
2397            int sizeBytes = arrayLen * dt.mSize;
2398            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
2399                if (dataSize / 4 * 3 > sizeBytes) {
2400                    throw new RSIllegalArgumentException("Array too small for allocation type.");
2401                }
2402                usePadding = true;
2403                sizeBytes = dataSize;
2404            } else {
2405                if (dataSize > sizeBytes) {
2406                    throw new RSIllegalArgumentException("Array too small for allocation type.");
2407                }
2408            }
2409            mRS.nAllocationRead2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
2410                                  array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
2411        } finally {
2412            Trace.traceEnd(RenderScript.TRACE_TAG);
2413        }
2414    }
2415
2416    /**
2417     * Copy from a rectangular region in this Allocation into an array. This
2418     * method is type checked and will generate exceptions if the Allocation's
2419     * {@link android.renderscript.Element} does not match the component type
2420     * of the array passed in.
2421     *
2422     * <p> The size of the region is: w * h * {@link #getElement}.{@link
2423     * Element#getBytesSize}.
2424     *
2425     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2426     * array in bytes must be at least the size of the region.
2427     *
2428     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2429     * is disabled, then the size of the array in bytes must be at least the size
2430     * of the region. The padding bytes for the cells must be part of the array.
2431     *
2432     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2433     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2434     * of the region. The padding bytes for the cells must not be part of the array.
2435     *
2436     * @param xoff X offset of the region to copy in this Allocation
2437     * @param yoff Y offset of the region to copy in this Allocation
2438     * @param w Width of the region to copy
2439     * @param h Height of the region to copy
2440     * @param array Dest Array to be copied into
2441     */
2442    public void copy2DRangeTo(int xoff, int yoff, int w, int h, Object array) {
2443        copy2DRangeToUnchecked(xoff, yoff, w, h, array,
2444                               validateObjectIsPrimitiveArray(array, true),
2445                               java.lang.reflect.Array.getLength(array));
2446    }
2447
2448    /**
2449     * Copy from a rectangular region in this Allocation into an array. This
2450     * variant is type checked and will generate exceptions if the Allocation's
2451     * {@link android.renderscript.Element} is neither an 8 bit integer nor a vector
2452     * of 8 bit integers {@link android.renderscript.Element.DataType}.
2453     *
2454     * <p> The size of the region is: w * h * {@link #getElement}.{@link
2455     * Element#getBytesSize}.
2456     *
2457     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2458     * array in bytes must be at least the size of the region.
2459     *
2460     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2461     * is disabled, then the size of the array in bytes must be at least the size
2462     * of the region. The padding bytes for the cells must be part of the array.
2463     *
2464     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2465     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2466     * of the region. The padding bytes for the cells must not be part of the array.
2467     *
2468     * @param xoff X offset of the region to copy in this Allocation
2469     * @param yoff Y offset of the region to copy in this Allocation
2470     * @param w Width of the region to copy
2471     * @param h Height of the region to copy
2472     * @param data Dest Array to be copied into
2473     */
2474    public void copy2DRangeTo(int xoff, int yoff, int w, int h, byte[] data) {
2475        validateIsInt8();
2476        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
2477                               Element.DataType.SIGNED_8, data.length);
2478    }
2479
2480    /**
2481     * Copy from a rectangular region in this Allocation into an array. This
2482     * variant is type checked and will generate exceptions if the Allocation's
2483     * {@link android.renderscript.Element} is neither a 16 bit integer nor a vector
2484     * of 16 bit integers {@link android.renderscript.Element.DataType}.
2485     *
2486     * <p> The size of the region is: w * h * {@link #getElement}.{@link
2487     * Element#getBytesSize}.
2488     *
2489     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2490     * array in bytes must be at least the size of the region.
2491     *
2492     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2493     * is disabled, then the size of the array in bytes must be at least the size
2494     * of the region. The padding bytes for the cells must be part of the array.
2495     *
2496     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2497     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2498     * of the region. The padding bytes for the cells must not be part of the array.
2499     *
2500     * @param xoff X offset of the region to copy in this Allocation
2501     * @param yoff Y offset of the region to copy in this Allocation
2502     * @param w Width of the region to copy
2503     * @param h Height of the region to copy
2504     * @param data Dest Array to be copied into
2505     */
2506    public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) {
2507        validateIsInt16OrFloat16();
2508        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
2509                               Element.DataType.SIGNED_16, data.length);
2510    }
2511
2512    /**
2513     * Copy from a rectangular region in this Allocation into an array. This
2514     * variant is type checked and will generate exceptions if the Allocation's
2515     * {@link android.renderscript.Element} is neither a 32 bit integer nor a vector
2516     * of 32 bit integers {@link android.renderscript.Element.DataType}.
2517     *
2518     * <p> The size of the region is: w * h * {@link #getElement}.{@link
2519     * Element#getBytesSize}.
2520     *
2521     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2522     * array in bytes must be at least the size of the region.
2523     *
2524     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2525     * is disabled, then the size of the array in bytes must be at least the size
2526     * of the region. The padding bytes for the cells must be part of the array.
2527     *
2528     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2529     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2530     * of the region. The padding bytes for the cells must not be part of the array.
2531     *
2532     * @param xoff X offset of the region to copy in this Allocation
2533     * @param yoff Y offset of the region to copy in this Allocation
2534     * @param w Width of the region to copy
2535     * @param h Height of the region to copy
2536     * @param data Dest Array to be copied into
2537     */
2538    public void copy2DRangeTo(int xoff, int yoff, int w, int h, int[] data) {
2539        validateIsInt32();
2540        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
2541                               Element.DataType.SIGNED_32, data.length);
2542    }
2543
2544    /**
2545     * Copy from a rectangular region in this Allocation into an array. This
2546     * variant is type checked and will generate exceptions if the Allocation's
2547     * {@link android.renderscript.Element} is neither a 32 bit float nor a vector
2548     * of 32 bit floats {@link android.renderscript.Element.DataType}.
2549     *
2550     * <p> The size of the region is: w * h * {@link #getElement}.{@link
2551     * Element#getBytesSize}.
2552     *
2553     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2554     * array in bytes must be at least the size of the region.
2555     *
2556     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2557     * is disabled, then the size of the array in bytes must be at least the size
2558     * of the region. The padding bytes for the cells must be part of the array.
2559     *
2560     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2561     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2562     * of the region. The padding bytes for the cells must not be part of the array.
2563     *
2564     * @param xoff X offset of the region to copy in this Allocation
2565     * @param yoff Y offset of the region to copy in this Allocation
2566     * @param w Width of the region to copy
2567     * @param h Height of the region to copy
2568     * @param data Dest Array to be copied into
2569     */
2570    public void copy2DRangeTo(int xoff, int yoff, int w, int h, float[] data) {
2571        validateIsFloat32();
2572        copy2DRangeToUnchecked(xoff, yoff, w, h, data,
2573                               Element.DataType.FLOAT_32, data.length);
2574    }
2575
2576
2577    /**
2578     * Copy from a 3D region in this Allocation into an array. This method does
2579     * not guarantee that the Allocation is compatible with the input buffer.
2580     * The array is assumed to be tightly packed.
2581     *
2582     * The data type of the array is not required to be the same as
2583     * the element data type.
2584     */
2585    private void copy3DRangeToUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
2586                                        Object array, Element.DataType dt, int arrayLen) {
2587        try {
2588            Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeToUnchecked");
2589            mRS.validate();
2590            validate3DRange(xoff, yoff, zoff, w, h, d);
2591            final int dataSize = mType.mElement.getBytesSize() * w * h * d;
2592            // AutoPadding for Vec3 Element
2593            boolean usePadding = false;
2594            int sizeBytes = arrayLen * dt.mSize;
2595            if (mAutoPadding && (mType.getElement().getVectorSize() == 3)) {
2596                if (dataSize / 4 * 3 > sizeBytes) {
2597                    throw new RSIllegalArgumentException("Array too small for allocation type.");
2598                }
2599                usePadding = true;
2600                sizeBytes = dataSize;
2601            } else {
2602                if (dataSize > sizeBytes) {
2603                    throw new RSIllegalArgumentException("Array too small for allocation type.");
2604                }
2605            }
2606            mRS.nAllocationRead3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
2607                                  array, sizeBytes, dt, mType.mElement.mType.mSize, usePadding);
2608        } finally {
2609            Trace.traceEnd(RenderScript.TRACE_TAG);
2610        }
2611    }
2612
2613    /*
2614     * Copy from a 3D region in this Allocation into an array. This
2615     * method is type checked and will generate exceptions if the Allocation's
2616     * {@link android.renderscript.Element} does not match the component type
2617     * of the array passed in.
2618     *
2619     * <p> The size of the region is: w * h * d * {@link #getElement}.{@link
2620     * Element#getBytesSize}.
2621     *
2622     * <p> If the Allocation does not have Vec3 Elements, then the size of the
2623     * array in bytes must be at least the size of the region.
2624     *
2625     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2626     * is disabled, then the size of the array in bytes must be at least the size
2627     * of the region. The padding bytes for the cells must be part of the array.
2628     *
2629     * <p> If the Allocation has Vec3 Elements and {@link #setAutoPadding AutoPadding}
2630     * is enabled, then the size of the array in bytes must be at least 3/4 the size
2631     * of the region. The padding bytes for the cells must not be part of the array.
2632     *
2633     * @param xoff X offset of the region to copy in this Allocation
2634     * @param yoff Y offset of the region to copy in this Allocation
2635     * @param zoff Z offset of the region to copy in this Allocation
2636     * @param w Width of the region to copy
2637     * @param h Height of the region to copy
2638     * @param d Depth of the region to copy
2639     * @param array Dest Array to be copied into
2640     */
2641    public void copy3DRangeTo(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
2642        copy3DRangeToUnchecked(xoff, yoff, zoff, w, h, d, array,
2643                                 validateObjectIsPrimitiveArray(array, true),
2644                                 java.lang.reflect.Array.getLength(array));
2645    }
2646
2647    // creation
2648
2649    static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
2650    static {
2651        mBitmapOptions.inScaled = false;
2652    }
2653
2654    /**
2655     * Creates a new Allocation with the given {@link
2656     * android.renderscript.Type}, mipmap flag, and usage flags.
2657     *
2658     * @param type RenderScript type describing data layout
2659     * @param mips specifies desired mipmap behaviour for the
2660     *             allocation
2661     * @param usage bit field specifying how the Allocation is
2662     *              utilized
2663     */
2664    static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
2665        try {
2666            Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped");
2667            rs.validate();
2668            if (type.getID(rs) == 0) {
2669                throw new RSInvalidStateException("Bad Type");
2670            }
2671            // TODO: What if there is an exception after this? The native allocation would leak.
2672            long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
2673            if (id == 0) {
2674                throw new RSRuntimeException("Allocation creation failed.");
2675            }
2676            return new Allocation(id, rs, type, false, usage, mips);
2677        } finally {
2678            Trace.traceEnd(RenderScript.TRACE_TAG);
2679        }
2680    }
2681
2682    /**
2683     * Creates an Allocation with the size specified by the type and no mipmaps
2684     * generated by default
2685     *
2686     * @param rs Context to which the allocation will belong.
2687     * @param type renderscript type describing data layout
2688     * @param usage bit field specifying how the allocation is
2689     *              utilized
2690     *
2691     * @return allocation
2692     */
2693    static public Allocation createTyped(RenderScript rs, Type type, int usage) {
2694        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
2695    }
2696
2697    /**
2698     * Creates an Allocation for use by scripts with a given {@link
2699     * android.renderscript.Type} and no mipmaps
2700     *
2701     * @param rs Context to which the Allocation will belong.
2702     * @param type RenderScript Type describing data layout
2703     *
2704     * @return allocation
2705     */
2706    static public Allocation createTyped(RenderScript rs, Type type) {
2707        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
2708    }
2709
2710    /**
2711     * Creates an Allocation with a specified number of given elements
2712     *
2713     * @param rs Context to which the Allocation will belong.
2714     * @param e Element to use in the Allocation
2715     * @param count the number of Elements in the Allocation
2716     * @param usage bit field specifying how the Allocation is
2717     *              utilized
2718     *
2719     * @return allocation
2720     */
2721    static public Allocation createSized(RenderScript rs, Element e,
2722                                         int count, int usage) {
2723        try {
2724            Trace.traceBegin(RenderScript.TRACE_TAG, "createSized");
2725            rs.validate();
2726            Type.Builder b = new Type.Builder(rs, e);
2727            b.setX(count);
2728            Type t = b.create();
2729
2730            long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
2731            if (id == 0) {
2732                throw new RSRuntimeException("Allocation creation failed.");
2733            }
2734            return new Allocation(id, rs, t, true, usage, MipmapControl.MIPMAP_NONE);
2735        } finally {
2736            Trace.traceEnd(RenderScript.TRACE_TAG);
2737        }
2738    }
2739
2740    /**
2741     * Creates an Allocation with a specified number of given elements
2742     *
2743     * @param rs Context to which the Allocation will belong.
2744     * @param e Element to use in the Allocation
2745     * @param count the number of Elements in the Allocation
2746     *
2747     * @return allocation
2748     */
2749    static public Allocation createSized(RenderScript rs, Element e, int count) {
2750        return createSized(rs, e, count, USAGE_SCRIPT);
2751    }
2752
2753    static Element elementFromBitmap(RenderScript rs, Bitmap b) {
2754        final Bitmap.Config bc = b.getConfig();
2755        if (bc == Bitmap.Config.ALPHA_8) {
2756            return Element.A_8(rs);
2757        }
2758        if (bc == Bitmap.Config.ARGB_4444) {
2759            return Element.RGBA_4444(rs);
2760        }
2761        if (bc == Bitmap.Config.ARGB_8888) {
2762            return Element.RGBA_8888(rs);
2763        }
2764        if (bc == Bitmap.Config.RGB_565) {
2765            return Element.RGB_565(rs);
2766        }
2767        throw new RSInvalidStateException("Bad bitmap type: " + bc);
2768    }
2769
2770    static Type typeFromBitmap(RenderScript rs, Bitmap b,
2771                                       MipmapControl mip) {
2772        Element e = elementFromBitmap(rs, b);
2773        Type.Builder tb = new Type.Builder(rs, e);
2774        tb.setX(b.getWidth());
2775        tb.setY(b.getHeight());
2776        tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
2777        return tb.create();
2778    }
2779
2780    /**
2781     * Creates an Allocation from a {@link android.graphics.Bitmap}.
2782     *
2783     * @param rs Context to which the allocation will belong.
2784     * @param b Bitmap source for the allocation data
2785     * @param mips specifies desired mipmap behaviour for the
2786     *             allocation
2787     * @param usage bit field specifying how the allocation is
2788     *              utilized
2789     *
2790     * @return Allocation containing bitmap data
2791     *
2792     */
2793    static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
2794                                              MipmapControl mips,
2795                                              int usage) {
2796        try {
2797            Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap");
2798            rs.validate();
2799
2800            // WAR undocumented color formats
2801            if (b.getConfig() == null) {
2802                if ((usage & USAGE_SHARED) != 0) {
2803                    throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config.");
2804                }
2805                Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
2806                Canvas c = new Canvas(newBitmap);
2807                c.drawBitmap(b, 0, 0, null);
2808                return createFromBitmap(rs, newBitmap, mips, usage);
2809            }
2810
2811            Type t = typeFromBitmap(rs, b, mips);
2812
2813            // enable optimized bitmap path only with no mipmap and script-only usage
2814            if (mips == MipmapControl.MIPMAP_NONE &&
2815                 t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
2816                 usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) {
2817                long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
2818                if (id == 0) {
2819                    throw new RSRuntimeException("Load failed.");
2820                }
2821
2822                // keep a reference to the Bitmap around to prevent GC
2823                Allocation alloc = new Allocation(id, rs, t, true, usage, mips);
2824                alloc.setBitmap(b);
2825                return alloc;
2826            }
2827
2828
2829            long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
2830            if (id == 0) {
2831                throw new RSRuntimeException("Load failed.");
2832            }
2833            return new Allocation(id, rs, t, true, usage, mips);
2834        } finally {
2835            Trace.traceEnd(RenderScript.TRACE_TAG);
2836        }
2837    }
2838
2839    /**
2840     * Gets or creates a ByteBuffer that contains the raw data of the current Allocation.
2841     * <p> If the Allocation is created with USAGE_IO_INPUT, the returned ByteBuffer
2842     * would contain the up-to-date data as READ ONLY.
2843     * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
2844     * the Allocation has certain alignment. The size of each row including padding,
2845     * called stride, can be queried using the {@link #getStride()} method.
2846     *
2847     * Note: Operating on the ByteBuffer of a destroyed Allocation will triger errors.
2848     *
2849     * @return ByteBuffer The ByteBuffer associated with raw data pointer of the Allocation.
2850     */
2851    public ByteBuffer getByteBuffer() {
2852        // Create a new ByteBuffer if it is not initialized or using IO_INPUT.
2853        if (mType.hasFaces()) {
2854            throw new RSInvalidStateException("Cubemap is not supported for getByteBuffer().");
2855        }
2856        if (mType.getYuv() == android.graphics.ImageFormat.NV21 ||
2857            mType.getYuv() == android.graphics.ImageFormat.YV12 ||
2858            mType.getYuv() == android.graphics.ImageFormat.YUV_420_888 ) {
2859            throw new RSInvalidStateException("YUV format is not supported for getByteBuffer().");
2860        }
2861        if (mByteBuffer == null || (mUsage & USAGE_IO_INPUT) != 0) {
2862            int xBytesSize = mType.getX() * mType.getElement().getBytesSize();
2863            long[] stride = new long[1];
2864            mByteBuffer = mRS.nAllocationGetByteBuffer(getID(mRS), stride, xBytesSize, mType.getY(), mType.getZ());
2865            mByteBufferStride = stride[0];
2866        }
2867        if ((mUsage & USAGE_IO_INPUT) != 0) {
2868            return mByteBuffer.asReadOnlyBuffer();
2869        }
2870        return mByteBuffer;
2871    }
2872
2873    /**
2874     * Creates a new Allocation Array with the given {@link
2875     * android.renderscript.Type}, and usage flags.
2876     * Note: If the input allocation is of usage: USAGE_IO_INPUT,
2877     * the created Allocation will be sharing the same BufferQueue.
2878     *
2879     * @param rs RenderScript context
2880     * @param t RenderScript type describing data layout
2881     * @param usage bit field specifying how the Allocation is
2882     *              utilized
2883     * @param numAlloc Number of Allocations in the array.
2884     * @return Allocation[]
2885     */
2886    public static Allocation[] createAllocations(RenderScript rs, Type t, int usage, int numAlloc) {
2887        try {
2888            Trace.traceBegin(RenderScript.TRACE_TAG, "createAllocations");
2889            rs.validate();
2890            if (t.getID(rs) == 0) {
2891                throw new RSInvalidStateException("Bad Type");
2892            }
2893
2894            Allocation[] mAllocationArray = new Allocation[numAlloc];
2895            mAllocationArray[0] = createTyped(rs, t, usage);
2896            if ((usage & USAGE_IO_INPUT) != 0) {
2897                if (numAlloc > MAX_NUMBER_IO_INPUT_ALLOC) {
2898                    throw new RSIllegalArgumentException("Exceeds the max number of Allocations allowed: " +
2899                                                         MAX_NUMBER_IO_INPUT_ALLOC);
2900                }
2901                mAllocationArray[0].setupBufferQueue(numAlloc);;
2902            }
2903
2904            for (int i=1; i<numAlloc; i++) {
2905                mAllocationArray[i] = createFromAllocation(rs, mAllocationArray[0]);
2906            }
2907            return mAllocationArray;
2908        } finally {
2909            Trace.traceEnd(RenderScript.TRACE_TAG);
2910        }
2911    }
2912
2913    /**
2914     * Creates a new Allocation with the given {@link
2915     * android.renderscript.Allocation}. The same data layout of
2916     * the input Allocation will be applied.
2917     * <p> If the input allocation is of usage: USAGE_IO_INPUT, the created
2918     * Allocation will be sharing the same BufferQueue.
2919     *
2920     * @param rs Context to which the allocation will belong.
2921     * @param alloc RenderScript Allocation describing data layout.
2922     * @return Allocation sharing the same data structure.
2923     */
2924    static Allocation createFromAllocation(RenderScript rs, Allocation alloc) {
2925        try {
2926            Trace.traceBegin(RenderScript.TRACE_TAG, "createFromAllcation");
2927            rs.validate();
2928            if (alloc.getID(rs) == 0) {
2929                throw new RSInvalidStateException("Bad input Allocation");
2930            }
2931
2932            Type type = alloc.getType();
2933            int usage = alloc.getUsage();
2934            MipmapControl mips = alloc.getMipmap();
2935            long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
2936            if (id == 0) {
2937                throw new RSRuntimeException("Allocation creation failed.");
2938            }
2939            Allocation outAlloc = new Allocation(id, rs, type, false, usage, mips);
2940            if ((usage & USAGE_IO_INPUT) != 0) {
2941                outAlloc.shareBufferQueue(alloc);
2942            }
2943            return outAlloc;
2944        } finally {
2945            Trace.traceEnd(RenderScript.TRACE_TAG);
2946        }
2947    }
2948
2949    /**
2950     * Initialize BufferQueue with specified max number of buffers.
2951     */
2952    void setupBufferQueue(int numAlloc) {
2953        mRS.validate();
2954        if ((mUsage & USAGE_IO_INPUT) == 0) {
2955            throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
2956        }
2957        mRS.nAllocationSetupBufferQueue(getID(mRS), numAlloc);
2958    }
2959
2960    /**
2961     * Share the BufferQueue with another {@link #USAGE_IO_INPUT} Allocation.
2962     *
2963     * @param alloc Allocation to associate with allocation
2964     */
2965    void shareBufferQueue(Allocation alloc) {
2966        mRS.validate();
2967        if ((mUsage & USAGE_IO_INPUT) == 0) {
2968            throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
2969        }
2970        mGetSurfaceSurface = alloc.getSurface();
2971        mRS.nAllocationShareBufferQueue(getID(mRS), alloc.getID(mRS));
2972    }
2973
2974    /**
2975     * Gets the stride of the Allocation.
2976     * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
2977     * the Allocation has certain alignment. The size of each row including such
2978     * padding is called stride.
2979     *
2980     * @return the stride. For 1D Allocation, the stride will be the number of
2981     *         bytes of this Allocation. For 2D and 3D Allocations, the stride
2982     *         will be the stride in X dimension measuring in bytes.
2983     */
2984    public long getStride() {
2985        if (mByteBufferStride == -1) {
2986            getByteBuffer();
2987        }
2988        return mByteBufferStride;
2989    }
2990
2991    /**
2992     * Get the timestamp for the most recent buffer held by this Allocation.
2993     * The timestamp is guaranteed to be unique and monotonically increasing.
2994     * Default value: -1. The timestamp will be updated after each {@link
2995     * #ioReceive ioReceive()} call.
2996     *
2997     * It can be used to identify the images by comparing the unique timestamps
2998     * when used with {@link android.hardware.camera2} APIs.
2999     * Example steps:
3000     *   1. Save {@link android.hardware.camera2.TotalCaptureResult} when the
3001     *      capture is completed.
3002     *   2. Get the timestamp after {@link #ioReceive ioReceive()} call.
3003     *   3. Comparing totalCaptureResult.get(CaptureResult.SENSOR_TIMESTAMP) with
3004     *      alloc.getTimeStamp().
3005     * @return long Timestamp associated with the buffer held by the Allocation.
3006     */
3007    public long getTimeStamp() {
3008        return mTimeStamp;
3009    }
3010
3011    /**
3012     * Returns the handle to a raw buffer that is being managed by the screen
3013     * compositor. This operation is only valid for Allocations with {@link
3014     * #USAGE_IO_INPUT}.
3015     *
3016     * @return Surface object associated with allocation
3017     *
3018     */
3019    public Surface getSurface() {
3020        if ((mUsage & USAGE_IO_INPUT) == 0) {
3021            throw new RSInvalidStateException("Allocation is not a surface texture.");
3022        }
3023
3024        if (mGetSurfaceSurface == null) {
3025            mGetSurfaceSurface = mRS.nAllocationGetSurface(getID(mRS));
3026        }
3027
3028        return mGetSurfaceSurface;
3029    }
3030
3031    /**
3032     * Associate a {@link android.view.Surface} with this Allocation. This
3033     * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}.
3034     *
3035     * @param sur Surface to associate with allocation
3036     */
3037    public void setSurface(Surface sur) {
3038        mRS.validate();
3039        if ((mUsage & USAGE_IO_OUTPUT) == 0) {
3040            throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
3041        }
3042
3043        mRS.nAllocationSetSurface(getID(mRS), sur);
3044    }
3045
3046    /**
3047     * Creates an Allocation from a {@link android.graphics.Bitmap}.
3048     *
3049     * <p>With target API version 18 or greater, this Allocation will be created
3050     * with {@link #USAGE_SHARED}, {@link #USAGE_SCRIPT}, and {@link
3051     * #USAGE_GRAPHICS_TEXTURE}. With target API version 17 or lower, this
3052     * Allocation will be created with {@link #USAGE_GRAPHICS_TEXTURE}.</p>
3053     *
3054     * @param rs Context to which the allocation will belong.
3055     * @param b bitmap source for the allocation data
3056     *
3057     * @return Allocation containing bitmap data
3058     *
3059     */
3060    static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
3061        if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
3062            return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
3063                                    USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
3064        }
3065        return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
3066                                USAGE_GRAPHICS_TEXTURE);
3067    }
3068
3069    /**
3070     * Creates a cubemap Allocation from a {@link android.graphics.Bitmap}
3071     * containing the horizontal list of cube faces. Each face must be a square,
3072     * have the same size as all other faces, and have a width that is a power
3073     * of 2.
3074     *
3075     * @param rs Context to which the allocation will belong.
3076     * @param b Bitmap with cubemap faces layed out in the following
3077     *          format: right, left, top, bottom, front, back
3078     * @param mips specifies desired mipmap behaviour for the cubemap
3079     * @param usage bit field specifying how the cubemap is utilized
3080     *
3081     * @return allocation containing cubemap data
3082     *
3083     */
3084    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
3085                                                     MipmapControl mips,
3086                                                     int usage) {
3087        rs.validate();
3088
3089        int height = b.getHeight();
3090        int width = b.getWidth();
3091
3092        if (width % 6 != 0) {
3093            throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
3094        }
3095        if (width / 6 != height) {
3096            throw new RSIllegalArgumentException("Only square cube map faces supported");
3097        }
3098        boolean isPow2 = (height & (height - 1)) == 0;
3099        if (!isPow2) {
3100            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
3101        }
3102
3103        Element e = elementFromBitmap(rs, b);
3104        Type.Builder tb = new Type.Builder(rs, e);
3105        tb.setX(height);
3106        tb.setY(height);
3107        tb.setFaces(true);
3108        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
3109        Type t = tb.create();
3110
3111        long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
3112        if(id == 0) {
3113            throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
3114        }
3115        return new Allocation(id, rs, t, true, usage, mips);
3116    }
3117
3118    /**
3119     * Creates a non-mipmapped cubemap Allocation for use as a graphics texture
3120     * from a {@link android.graphics.Bitmap} containing the horizontal list of
3121     * cube faces. Each face must be a square, have the same size as all other
3122     * faces, and have a width that is a power of 2.
3123     *
3124     * @param rs Context to which the allocation will belong.
3125     * @param b bitmap with cubemap faces layed out in the following
3126     *          format: right, left, top, bottom, front, back
3127     *
3128     * @return allocation containing cubemap data
3129     *
3130     */
3131    static public Allocation createCubemapFromBitmap(RenderScript rs,
3132                                                     Bitmap b) {
3133        return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
3134                                       USAGE_GRAPHICS_TEXTURE);
3135    }
3136
3137    /**
3138     * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap}
3139     * objects containing the cube faces. Each face must be a square, have the
3140     * same size as all other faces, and have a width that is a power of 2.
3141     *
3142     * @param rs Context to which the allocation will belong.
3143     * @param xpos cubemap face in the positive x direction
3144     * @param xneg cubemap face in the negative x direction
3145     * @param ypos cubemap face in the positive y direction
3146     * @param yneg cubemap face in the negative y direction
3147     * @param zpos cubemap face in the positive z direction
3148     * @param zneg cubemap face in the negative z direction
3149     * @param mips specifies desired mipmap behaviour for the cubemap
3150     * @param usage bit field specifying how the cubemap is utilized
3151     *
3152     * @return allocation containing cubemap data
3153     *
3154     */
3155    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
3156                                                        Bitmap xpos,
3157                                                        Bitmap xneg,
3158                                                        Bitmap ypos,
3159                                                        Bitmap yneg,
3160                                                        Bitmap zpos,
3161                                                        Bitmap zneg,
3162                                                        MipmapControl mips,
3163                                                        int usage) {
3164        int height = xpos.getHeight();
3165        if (xpos.getWidth() != height ||
3166            xneg.getWidth() != height || xneg.getHeight() != height ||
3167            ypos.getWidth() != height || ypos.getHeight() != height ||
3168            yneg.getWidth() != height || yneg.getHeight() != height ||
3169            zpos.getWidth() != height || zpos.getHeight() != height ||
3170            zneg.getWidth() != height || zneg.getHeight() != height) {
3171            throw new RSIllegalArgumentException("Only square cube map faces supported");
3172        }
3173        boolean isPow2 = (height & (height - 1)) == 0;
3174        if (!isPow2) {
3175            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
3176        }
3177
3178        Element e = elementFromBitmap(rs, xpos);
3179        Type.Builder tb = new Type.Builder(rs, e);
3180        tb.setX(height);
3181        tb.setY(height);
3182        tb.setFaces(true);
3183        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
3184        Type t = tb.create();
3185        Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
3186
3187        AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
3188        adapter.setFace(Type.CubemapFace.POSITIVE_X);
3189        adapter.copyFrom(xpos);
3190        adapter.setFace(Type.CubemapFace.NEGATIVE_X);
3191        adapter.copyFrom(xneg);
3192        adapter.setFace(Type.CubemapFace.POSITIVE_Y);
3193        adapter.copyFrom(ypos);
3194        adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
3195        adapter.copyFrom(yneg);
3196        adapter.setFace(Type.CubemapFace.POSITIVE_Z);
3197        adapter.copyFrom(zpos);
3198        adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
3199        adapter.copyFrom(zneg);
3200
3201        return cubemap;
3202    }
3203
3204    /**
3205     * Creates a non-mipmapped cubemap Allocation for use as a sampler input
3206     * from 6 {@link android.graphics.Bitmap} objects containing the cube
3207     * faces. Each face must be a square, have the same size as all other faces,
3208     * and have a width that is a power of 2.
3209     *
3210     * @param rs Context to which the allocation will belong.
3211     * @param xpos cubemap face in the positive x direction
3212     * @param xneg cubemap face in the negative x direction
3213     * @param ypos cubemap face in the positive y direction
3214     * @param yneg cubemap face in the negative y direction
3215     * @param zpos cubemap face in the positive z direction
3216     * @param zneg cubemap face in the negative z direction
3217     *
3218     * @return allocation containing cubemap data
3219     *
3220     */
3221    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
3222                                                        Bitmap xpos,
3223                                                        Bitmap xneg,
3224                                                        Bitmap ypos,
3225                                                        Bitmap yneg,
3226                                                        Bitmap zpos,
3227                                                        Bitmap zneg) {
3228        return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
3229                                          zpos, zneg, MipmapControl.MIPMAP_NONE,
3230                                          USAGE_GRAPHICS_TEXTURE);
3231    }
3232
3233    /**
3234     * Creates an Allocation from the Bitmap referenced
3235     * by resource ID.
3236     *
3237     * @param rs Context to which the allocation will belong.
3238     * @param res application resources
3239     * @param id resource id to load the data from
3240     * @param mips specifies desired mipmap behaviour for the
3241     *             allocation
3242     * @param usage bit field specifying how the allocation is
3243     *              utilized
3244     *
3245     * @return Allocation containing resource data
3246     *
3247     */
3248    static public Allocation createFromBitmapResource(RenderScript rs,
3249                                                      Resources res,
3250                                                      int id,
3251                                                      MipmapControl mips,
3252                                                      int usage) {
3253
3254        rs.validate();
3255        if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) {
3256            throw new RSIllegalArgumentException("Unsupported usage specified.");
3257        }
3258        Bitmap b = BitmapFactory.decodeResource(res, id);
3259        Allocation alloc = createFromBitmap(rs, b, mips, usage);
3260        b.recycle();
3261        return alloc;
3262    }
3263
3264    /**
3265     * Creates a non-mipmapped Allocation to use as a graphics texture from the
3266     * {@link android.graphics.Bitmap} referenced by resource ID.
3267     *
3268     * <p>With target API version 18 or greater, this allocation will be created
3269     * with {@link #USAGE_SCRIPT} and {@link #USAGE_GRAPHICS_TEXTURE}. With
3270     * target API version 17 or lower, this allocation will be created with
3271     * {@link #USAGE_GRAPHICS_TEXTURE}.</p>
3272     *
3273     * @param rs Context to which the allocation will belong.
3274     * @param res application resources
3275     * @param id resource id to load the data from
3276     *
3277     * @return Allocation containing resource data
3278     *
3279     */
3280    static public Allocation createFromBitmapResource(RenderScript rs,
3281                                                      Resources res,
3282                                                      int id) {
3283        if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
3284            return createFromBitmapResource(rs, res, id,
3285                                            MipmapControl.MIPMAP_NONE,
3286                                            USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
3287        }
3288        return createFromBitmapResource(rs, res, id,
3289                                        MipmapControl.MIPMAP_NONE,
3290                                        USAGE_GRAPHICS_TEXTURE);
3291    }
3292
3293    /**
3294     * Creates an Allocation containing string data encoded in UTF-8 format.
3295     *
3296     * @param rs Context to which the allocation will belong.
3297     * @param str string to create the allocation from
3298     * @param usage bit field specifying how the allocaiton is
3299     *              utilized
3300     *
3301     */
3302    static public Allocation createFromString(RenderScript rs,
3303                                              String str,
3304                                              int usage) {
3305        rs.validate();
3306        byte[] allocArray = null;
3307        try {
3308            allocArray = str.getBytes("UTF-8");
3309            Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
3310            alloc.copyFrom(allocArray);
3311            return alloc;
3312        }
3313        catch (Exception e) {
3314            throw new RSRuntimeException("Could not convert string to utf-8.");
3315        }
3316    }
3317
3318    /**
3319     * Interface to handle notification when new buffers are available via
3320     * {@link #USAGE_IO_INPUT}. An application will receive one notification
3321     * when a buffer is available. Additional buffers will not trigger new
3322     * notifications until a buffer is processed.
3323     */
3324    public interface OnBufferAvailableListener {
3325        public void onBufferAvailable(Allocation a);
3326    }
3327
3328    /**
3329     * Set a notification handler for {@link #USAGE_IO_INPUT}.
3330     *
3331     * @param callback instance of the OnBufferAvailableListener
3332     *                 class to be called when buffer arrive.
3333     */
3334    public void setOnBufferAvailableListener(OnBufferAvailableListener callback) {
3335        synchronized(mAllocationMap) {
3336            mAllocationMap.put(new Long(getID(mRS)), this);
3337            mBufferNotifier = callback;
3338        }
3339    }
3340
3341    static void sendBufferNotification(long id) {
3342        synchronized(mAllocationMap) {
3343            Allocation a = mAllocationMap.get(new Long(id));
3344
3345            if ((a != null) && (a.mBufferNotifier != null)) {
3346                a.mBufferNotifier.onBufferAvailable(a);
3347            }
3348        }
3349    }
3350
3351    /**
3352     * For USAGE_IO_OUTPUT, destroy() implies setSurface(null).
3353     *
3354     */
3355    @Override
3356    public void destroy() {
3357        if((mUsage & USAGE_IO_OUTPUT) != 0) {
3358            setSurface(null);
3359        }
3360
3361        if (mType != null && mOwningType) {
3362            mType.destroy();
3363        }
3364
3365        super.destroy();
3366    }
3367
3368}
3369