summaryrefslogtreecommitdiffstats
path: root/rs/java/android/renderscript/Allocation.java
diff options
context:
space:
mode:
authorTim Murray <timmurray@google.com>2013-12-17 13:28:17 -0800
committerTim Murray <timmurray@google.com>2013-12-17 13:28:17 -0800
commitd1576fb039f018ea4d55abbb2c03d542011be399 (patch)
treee69fc47ea873621e2106d69e3d08c6d8e5d7fc93 /rs/java/android/renderscript/Allocation.java
parent0a11eb10ff08ad7a683cfc7c458b6625b955df2c (diff)
downloadframeworks_base-d1576fb039f018ea4d55abbb2c03d542011be399.zip
frameworks_base-d1576fb039f018ea4d55abbb2c03d542011be399.tar.gz
frameworks_base-d1576fb039f018ea4d55abbb2c03d542011be399.tar.bz2
Move RenderScript from graphics/ to new fw/base subdirectory rs.
Change-Id: I30b6633578f063840e1bdbcc9ba513b727912a6d
Diffstat (limited to 'rs/java/android/renderscript/Allocation.java')
-rw-r--r--rs/java/android/renderscript/Allocation.java1865
1 files changed, 1865 insertions, 0 deletions
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
new file mode 100644
index 0000000..45dd25a
--- /dev/null
+++ b/rs/java/android/renderscript/Allocation.java
@@ -0,0 +1,1865 @@
+/*
+ * Copyright (C) 2008-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import java.util.HashMap;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.view.Surface;
+import android.util.Log;
+import android.graphics.Canvas;
+import android.os.Trace;
+
+/**
+ * <p> This class provides the primary method through which data is passed to
+ * and from RenderScript kernels. An Allocation provides the backing store for
+ * a given {@link android.renderscript.Type}. </p>
+ *
+ * <p>An Allocation also contains a set of usage flags that denote how the
+ * Allocation could be used. For example, an Allocation may have usage flags
+ * specifying that it can be used from a script as well as input to a {@link
+ * android.renderscript.Sampler}. A developer must synchronize across these
+ * different usages using {@link android.renderscript.Allocation#syncAll} in
+ * order to ensure that different users of the Allocation have a consistent view
+ * of memory. For example, in the case where an Allocation is used as the output
+ * of one kernel and as Sampler input in a later kernel, a developer must call
+ * {@link #syncAll syncAll(Allocation.USAGE_SCRIPT)} prior to launching the
+ * second kernel to ensure correctness.
+ *
+ * <p>An Allocation can be populated with the {@link #copyFrom} routines. For
+ * more complex Element types, the {@link #copyFromUnchecked} methods can be
+ * used to copy from byte arrays or similar constructs.</p>
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about creating an application that uses RenderScript, read the
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
+ * </div>
+ **/
+public class Allocation extends BaseObj {
+ Type mType;
+ Bitmap mBitmap;
+ int mUsage;
+ Allocation mAdaptedAllocation;
+ int mSize;
+
+ boolean mConstrainedLOD;
+ boolean mConstrainedFace;
+ boolean mConstrainedY;
+ boolean mConstrainedZ;
+ boolean mReadAllowed = true;
+ boolean mWriteAllowed = true;
+ int mSelectedY;
+ int mSelectedZ;
+ int mSelectedLOD;
+ Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
+
+ int mCurrentDimX;
+ int mCurrentDimY;
+ int mCurrentDimZ;
+ int mCurrentCount;
+ static HashMap<Long, Allocation> mAllocationMap =
+ new HashMap<Long, Allocation>();
+ OnBufferAvailableListener mBufferNotifier;
+
+ private Element.DataType validateObjectIsPrimitiveArray(Object d, boolean checkType) {
+ final Class c = d.getClass();
+ if (!c.isArray()) {
+ throw new RSIllegalArgumentException("Object passed is not an array of primitives.");
+ }
+ final Class cmp = c.getComponentType();
+ if (!cmp.isPrimitive()) {
+ throw new RSIllegalArgumentException("Object passed is not an Array of primitives.");
+ }
+
+ if (cmp == Long.TYPE) {
+ if (checkType) {
+ validateIsInt64();
+ return mType.mElement.mType;
+ }
+ return Element.DataType.SIGNED_64;
+ }
+
+ if (cmp == Integer.TYPE) {
+ if (checkType) {
+ validateIsInt32();
+ return mType.mElement.mType;
+ }
+ return Element.DataType.SIGNED_32;
+ }
+
+ if (cmp == Short.TYPE) {
+ if (checkType) {
+ validateIsInt16();
+ return mType.mElement.mType;
+ }
+ return Element.DataType.SIGNED_16;
+ }
+
+ if (cmp == Byte.TYPE) {
+ if (checkType) {
+ validateIsInt8();
+ return mType.mElement.mType;
+ }
+ return Element.DataType.SIGNED_8;
+ }
+
+ if (cmp == Float.TYPE) {
+ if (checkType) {
+ validateIsFloat32();
+ }
+ return Element.DataType.FLOAT_32;
+ }
+
+ if (cmp == Double.TYPE) {
+ if (checkType) {
+ validateIsFloat64();
+ }
+ return Element.DataType.FLOAT_64;
+ }
+ return null;
+ }
+
+
+ /**
+ * The usage of the Allocation. These signal to RenderScript where to place
+ * the Allocation in memory.
+ *
+ */
+
+ /**
+ * The Allocation will be bound to and accessed by scripts.
+ */
+ public static final int USAGE_SCRIPT = 0x0001;
+
+ /**
+ * The Allocation will be used as a texture source by one or more graphics
+ * programs.
+ *
+ */
+ public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
+
+ /**
+ * The Allocation will be used as a graphics mesh.
+ *
+ * This was deprecated in API level 16.
+ *
+ */
+ public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
+
+
+ /**
+ * The Allocation will be used as the source of shader constants by one or
+ * more programs.
+ *
+ * This was deprecated in API level 16.
+ *
+ */
+ public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
+
+ /**
+ * The Allocation will be used as a target for offscreen rendering
+ *
+ * This was deprecated in API level 16.
+ *
+ */
+ public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
+
+ /**
+ * The Allocation will be used as a {@link android.view.Surface}
+ * consumer. This usage will cause the Allocation to be created
+ * as read-only.
+ *
+ */
+ public static final int USAGE_IO_INPUT = 0x0020;
+
+ /**
+ * The Allocation will be used as a {@link android.view.Surface}
+ * producer. The dimensions and format of the {@link
+ * android.view.Surface} will be forced to those of the
+ * Allocation.
+ *
+ */
+ public static final int USAGE_IO_OUTPUT = 0x0040;
+
+ /**
+ * The Allocation's backing store will be inherited from another object
+ * (usually a {@link android.graphics.Bitmap}); copying to or from the
+ * original source Bitmap will cause a synchronization rather than a full
+ * copy. {@link #syncAll} may also be used to synchronize the Allocation
+ * and the source Bitmap.
+ *
+ * <p>This is set by default for allocations created with {@link
+ * #createFromBitmap} in API version 18 and higher.</p>
+ *
+ */
+ public static final int USAGE_SHARED = 0x0080;
+
+ /**
+ * Controls mipmap behavior when using the bitmap creation and update
+ * functions.
+ */
+ public enum MipmapControl {
+ /**
+ * No mipmaps will be generated and the type generated from the incoming
+ * bitmap will not contain additional LODs.
+ */
+ MIPMAP_NONE(0),
+
+ /**
+ * A full mipmap chain will be created in script memory. The Type of
+ * the Allocation will contain a full mipmap chain. On upload, the full
+ * chain will be transferred.
+ */
+ MIPMAP_FULL(1),
+
+ /**
+ * The Type of the Allocation will be the same as MIPMAP_NONE. It will
+ * not contain mipmaps. On upload, the allocation data will contain a
+ * full mipmap chain generated from the top level in script memory.
+ */
+ MIPMAP_ON_SYNC_TO_TEXTURE(2);
+
+ int mID;
+ MipmapControl(int id) {
+ mID = id;
+ }
+ }
+
+
+ private long getIDSafe() {
+ if (mAdaptedAllocation != null) {
+ return mAdaptedAllocation.getID(mRS);
+ }
+ return getID(mRS);
+ }
+
+
+ /**
+ * Get the {@link android.renderscript.Element} of the {@link
+ * android.renderscript.Type} of the Allocation.
+ *
+ * @return Element
+ *
+ */
+ public Element getElement() {
+ return mType.getElement();
+ }
+
+ /**
+ * Get the usage flags of the Allocation.
+ *
+ * @return usage this Allocation's set of the USAGE_* flags OR'd together
+ *
+ */
+ public int getUsage() {
+ return mUsage;
+ }
+
+ /**
+ * Get the size of the Allocation in bytes.
+ *
+ * @return size of the Allocation in bytes.
+ *
+ */
+ public int getBytesSize() {
+ return mType.getCount() * mType.getElement().getBytesSize();
+ }
+
+ private void updateCacheInfo(Type t) {
+ mCurrentDimX = t.getX();
+ mCurrentDimY = t.getY();
+ mCurrentDimZ = t.getZ();
+ mCurrentCount = mCurrentDimX;
+ if (mCurrentDimY > 1) {
+ mCurrentCount *= mCurrentDimY;
+ }
+ if (mCurrentDimZ > 1) {
+ mCurrentCount *= mCurrentDimZ;
+ }
+ }
+
+ private void setBitmap(Bitmap b) {
+ mBitmap = b;
+ }
+
+ Allocation(long id, RenderScript rs, Type t, int usage) {
+ super(id, rs);
+ if ((usage & ~(USAGE_SCRIPT |
+ USAGE_GRAPHICS_TEXTURE |
+ USAGE_GRAPHICS_VERTEX |
+ USAGE_GRAPHICS_CONSTANTS |
+ USAGE_GRAPHICS_RENDER_TARGET |
+ USAGE_IO_INPUT |
+ USAGE_IO_OUTPUT |
+ USAGE_SHARED)) != 0) {
+ throw new RSIllegalArgumentException("Unknown usage specified.");
+ }
+
+ if ((usage & USAGE_IO_INPUT) != 0) {
+ mWriteAllowed = false;
+
+ if ((usage & ~(USAGE_IO_INPUT |
+ USAGE_GRAPHICS_TEXTURE |
+ USAGE_SCRIPT)) != 0) {
+ throw new RSIllegalArgumentException("Invalid usage combination.");
+ }
+ }
+
+ mType = t;
+ mUsage = usage;
+
+ if (t != null) {
+ // TODO: A3D doesn't have Type info during creation, so we can't
+ // calculate the size ahead of time. We can possibly add a method
+ // to update the size in the future if it seems reasonable.
+ mSize = mType.getCount() * mType.getElement().getBytesSize();
+ updateCacheInfo(t);
+ }
+ try {
+ RenderScript.registerNativeAllocation.invoke(RenderScript.sRuntime, mSize);
+ } catch (Exception e) {
+ Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e);
+ throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e);
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
+ super.finalize();
+ }
+
+ private void validateIsInt64() {
+ if ((mType.mElement.mType == Element.DataType.SIGNED_64) ||
+ (mType.mElement.mType == Element.DataType.UNSIGNED_64)) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "64 bit integer source does not match allocation type " + mType.mElement.mType);
+ }
+
+ private void validateIsInt32() {
+ if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
+ (mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "32 bit integer source does not match allocation type " + mType.mElement.mType);
+ }
+
+ private void validateIsInt16() {
+ if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
+ (mType.mElement.mType == Element.DataType.UNSIGNED_16)) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "16 bit integer source does not match allocation type " + mType.mElement.mType);
+ }
+
+ private void validateIsInt8() {
+ if ((mType.mElement.mType == Element.DataType.SIGNED_8) ||
+ (mType.mElement.mType == Element.DataType.UNSIGNED_8)) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "8 bit integer source does not match allocation type " + mType.mElement.mType);
+ }
+
+ private void validateIsFloat32() {
+ if (mType.mElement.mType == Element.DataType.FLOAT_32) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "32 bit float source does not match allocation type " + mType.mElement.mType);
+ }
+
+ private void validateIsFloat64() {
+ if (mType.mElement.mType == Element.DataType.FLOAT_64) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "64 bit float source does not match allocation type " + mType.mElement.mType);
+ }
+
+ private void validateIsObject() {
+ if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) ||
+ (mType.mElement.mType == Element.DataType.RS_TYPE) ||
+ (mType.mElement.mType == Element.DataType.RS_ALLOCATION) ||
+ (mType.mElement.mType == Element.DataType.RS_SAMPLER) ||
+ (mType.mElement.mType == Element.DataType.RS_SCRIPT) ||
+ (mType.mElement.mType == Element.DataType.RS_MESH) ||
+ (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) ||
+ (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) ||
+ (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) ||
+ (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "Object source does not match allocation type " + mType.mElement.mType);
+ }
+
+ @Override
+ void updateFromNative() {
+ super.updateFromNative();
+ long typeID = mRS.nAllocationGetType(getID(mRS));
+ if(typeID != 0) {
+ mType = new Type(typeID, mRS);
+ mType.updateFromNative();
+ updateCacheInfo(mType);
+ }
+ }
+
+ /**
+ * Get the {@link android.renderscript.Type} of the Allocation.
+ *
+ * @return Type
+ *
+ */
+ public Type getType() {
+ return mType;
+ }
+
+ /**
+ * Propagate changes from one usage of the Allocation to the
+ * other usages of the Allocation.
+ *
+ */
+ public void syncAll(int srcLocation) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "syncAll");
+ switch (srcLocation) {
+ case USAGE_GRAPHICS_TEXTURE:
+ case USAGE_SCRIPT:
+ if ((mUsage & USAGE_SHARED) != 0) {
+ copyFrom(mBitmap);
+ }
+ break;
+ case USAGE_GRAPHICS_CONSTANTS:
+ case USAGE_GRAPHICS_VERTEX:
+ break;
+ case USAGE_SHARED:
+ if ((mUsage & USAGE_SHARED) != 0) {
+ copyTo(mBitmap);
+ }
+ break;
+ default:
+ throw new RSIllegalArgumentException("Source must be exactly one usage type.");
+ }
+ mRS.validate();
+ mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Send a buffer to the output stream. The contents of the Allocation will
+ * be undefined after this operation. This operation is only valid if {@link
+ * #USAGE_IO_OUTPUT} is set on the Allocation.
+ *
+ *
+ */
+ public void ioSend() {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "ioSend");
+ if ((mUsage & USAGE_IO_OUTPUT) == 0) {
+ throw new RSIllegalArgumentException(
+ "Can only send buffer if IO_OUTPUT usage specified.");
+ }
+ mRS.validate();
+ mRS.nAllocationIoSend(getID(mRS));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Receive the latest input into the Allocation. This operation
+ * is only valid if {@link #USAGE_IO_INPUT} is set on the Allocation.
+ *
+ */
+ public void ioReceive() {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "ioReceive");
+ if ((mUsage & USAGE_IO_INPUT) == 0) {
+ throw new RSIllegalArgumentException(
+ "Can only receive if IO_INPUT usage specified.");
+ }
+ mRS.validate();
+ mRS.nAllocationIoReceive(getID(mRS));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy an array of RS objects to the Allocation.
+ *
+ * @param d Source array.
+ */
+ public void copyFrom(BaseObj[] d) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+ mRS.validate();
+ validateIsObject();
+ if (d.length != mCurrentCount) {
+ throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
+ mCurrentCount + ", array length = " + d.length);
+ }
+ // FIXME: requires 64-bit path
+
+ int i[] = new int[d.length];
+ for (int ct=0; ct < d.length; ct++) {
+ i[ct] = (int)d[ct].getID(mRS);
+ }
+ copy1DRangeFromUnchecked(0, mCurrentCount, i);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ private void validateBitmapFormat(Bitmap b) {
+ Bitmap.Config bc = b.getConfig();
+ if (bc == null) {
+ throw new RSIllegalArgumentException("Bitmap has an unsupported format for this operation");
+ }
+ switch (bc) {
+ case ALPHA_8:
+ if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
+ throw new RSIllegalArgumentException("Allocation kind is " +
+ mType.getElement().mKind + ", type " +
+ mType.getElement().mType +
+ " of " + mType.getElement().getBytesSize() +
+ " bytes, passed bitmap was " + bc);
+ }
+ break;
+ case ARGB_8888:
+ if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
+ (mType.getElement().getBytesSize() != 4)) {
+ throw new RSIllegalArgumentException("Allocation kind is " +
+ mType.getElement().mKind + ", type " +
+ mType.getElement().mType +
+ " of " + mType.getElement().getBytesSize() +
+ " bytes, passed bitmap was " + bc);
+ }
+ break;
+ case RGB_565:
+ if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
+ (mType.getElement().getBytesSize() != 2)) {
+ throw new RSIllegalArgumentException("Allocation kind is " +
+ mType.getElement().mKind + ", type " +
+ mType.getElement().mType +
+ " of " + mType.getElement().getBytesSize() +
+ " bytes, passed bitmap was " + bc);
+ }
+ break;
+ case ARGB_4444:
+ if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
+ (mType.getElement().getBytesSize() != 2)) {
+ throw new RSIllegalArgumentException("Allocation kind is " +
+ mType.getElement().mKind + ", type " +
+ mType.getElement().mType +
+ " of " + mType.getElement().getBytesSize() +
+ " bytes, passed bitmap was " + bc);
+ }
+ break;
+
+ }
+ }
+
+ private void validateBitmapSize(Bitmap b) {
+ if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) {
+ throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
+ }
+ }
+
+ private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+ mRS.validate();
+ if (mCurrentDimZ > 0) {
+ copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
+ } else if (mCurrentDimY > 0) {
+ copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
+ } else {
+ copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
+ }
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
+ *
+ * @param array The source data array
+ */
+ public void copyFromUnchecked(Object array) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+ copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
+ java.lang.reflect.Array.getLength(array));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
+ *
+ * @param d the source data array
+ */
+ public void copyFromUnchecked(int[] d) {
+ copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
+ *
+ * @param d the source data array
+ */
+ public void copyFromUnchecked(short[] d) {
+ copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
+ *
+ * @param d the source data array
+ */
+ public void copyFromUnchecked(byte[] d) {
+ copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
+ *
+ * @param d the source data array
+ */
+ public void copyFromUnchecked(float[] d) {
+ copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
+ }
+
+
+ /**
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} does not match the array's
+ * primitive type.
+ *
+ * @param array The source data array
+ */
+ public void copyFrom(Object array) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+ copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} is not a 32 bit integer type.
+ *
+ * @param d the source data array
+ */
+ public void copyFrom(int[] d) {
+ validateIsInt32();
+ copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} is not a 16 bit integer type.
+ *
+ * @param d the source data array
+ */
+ public void copyFrom(short[] d) {
+ validateIsInt16();
+ copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} is not an 8 bit integer type.
+ *
+ * @param d the source data array
+ */
+ public void copyFrom(byte[] d) {
+ validateIsInt8();
+ copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} is not a 32 bit float type.
+ *
+ * @param d the source data array
+ */
+ public void copyFrom(float[] d) {
+ validateIsFloat32();
+ copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
+ }
+
+ /**
+ * Copy into an Allocation from a {@link android.graphics.Bitmap}. The
+ * height, width, and format of the bitmap must match the existing
+ * allocation.
+ *
+ * <p>If the {@link android.graphics.Bitmap} is the same as the {@link
+ * android.graphics.Bitmap} used to create the Allocation with {@link
+ * #createFromBitmap} and {@link #USAGE_SHARED} is set on the Allocation,
+ * this will synchronize the Allocation with the latest data from the {@link
+ * android.graphics.Bitmap}, potentially avoiding the actual copy.</p>
+ *
+ * @param b the source bitmap
+ */
+ public void copyFrom(Bitmap b) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+ mRS.validate();
+ if (b.getConfig() == null) {
+ Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(newBitmap);
+ c.drawBitmap(b, 0, 0, null);
+ copyFrom(newBitmap);
+ return;
+ }
+ validateBitmapSize(b);
+ validateBitmapFormat(b);
+ mRS.nAllocationCopyFromBitmap(getID(mRS), b);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy an Allocation from an Allocation. The types of both allocations
+ * must be identical.
+ *
+ * @param a the source allocation
+ */
+ public void copyFrom(Allocation a) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+ mRS.validate();
+ if (!mType.equals(a.getType())) {
+ throw new RSIllegalArgumentException("Types of allocations must match.");
+ }
+ copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * This is only intended to be used by auto-generated code reflected from
+ * the RenderScript script files and should not be used by developers.
+ *
+ * @param xoff
+ * @param fp
+ */
+ public void setFromFieldPacker(int xoff, FieldPacker fp) {
+ mRS.validate();
+ int eSize = mType.mElement.getBytesSize();
+ final byte[] data = fp.getData();
+
+ int count = data.length / eSize;
+ if ((eSize * count) != data.length) {
+ throw new RSIllegalArgumentException("Field packer length " + data.length +
+ " not divisible by element size " + eSize + ".");
+ }
+ copy1DRangeFromUnchecked(xoff, count, data);
+ }
+
+ /**
+ * This is only intended to be used by auto-generated code reflected from
+ * the RenderScript script files.
+ *
+ * @param xoff
+ * @param component_number
+ * @param fp
+ */
+ public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
+ mRS.validate();
+ if (component_number >= mType.mElement.mElements.length) {
+ throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
+ }
+ if(xoff < 0) {
+ throw new RSIllegalArgumentException("Offset must be >= 0.");
+ }
+
+ final byte[] data = fp.getData();
+ int eSize = mType.mElement.mElements[component_number].getBytesSize();
+ eSize *= mType.mElement.mArraySizes[component_number];
+
+ if (data.length != eSize) {
+ throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
+ " does not match component size " + eSize + ".");
+ }
+
+ mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
+ component_number, data, data.length);
+ }
+
+ private void data1DChecks(int off, int count, int len, int dataSize) {
+ mRS.validate();
+ if(off < 0) {
+ throw new RSIllegalArgumentException("Offset must be >= 0.");
+ }
+ if(count < 1) {
+ throw new RSIllegalArgumentException("Count must be >= 1.");
+ }
+ if((off + count) > mCurrentCount) {
+ throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
+ ", got " + count + " at offset " + off + ".");
+ }
+ if(len < dataSize) {
+ throw new RSIllegalArgumentException("Array too small for allocation type.");
+ }
+ }
+
+ /**
+ * Generate a mipmap chain. This is only valid if the Type of the Allocation
+ * includes mipmaps.
+ *
+ * <p>This function will generate a complete set of mipmaps from the top
+ * level LOD and place them into the script memory space.</p>
+ *
+ * <p>If the Allocation is also using other memory spaces, a call to {@link
+ * #syncAll syncAll(Allocation.USAGE_SCRIPT)} is required.</p>
+ */
+ public void generateMipmaps() {
+ mRS.nAllocationGenerateMipmaps(getID(mRS));
+ }
+
+ private void copy1DRangeFromUnchecked(int off, int count, Object array,
+ Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
+ final int dataSize = mType.mElement.getBytesSize() * count;
+ data1DChecks(off, count, arrayLen * dt.mSize, dataSize);
+ mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param array The source data array
+ */
+ public void copy1DRangeFromUnchecked(int off, int count, Object array) {
+ copy1DRangeFromUnchecked(off, count, array,
+ validateObjectIsPrimitiveArray(array, false),
+ java.lang.reflect.Array.getLength(array));
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param d the source data array
+ */
+ public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
+ copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param d the source data array
+ */
+ public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
+ copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param d the source data array
+ */
+ public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
+ copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param d the source data array
+ */
+ public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
+ copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
+ }
+
+
+ /**
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type does not
+ * match the component type of the array passed in.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param array The source data array.
+ */
+ public void copy1DRangeFrom(int off, int count, Object array) {
+ copy1DRangeFromUnchecked(off, count, array,
+ validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type is not a 32 bit
+ * integer type.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param d the source data array
+ */
+ public void copy1DRangeFrom(int off, int count, int[] d) {
+ validateIsInt32();
+ copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type is not a 16 bit
+ * integer type.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param d the source data array
+ */
+ public void copy1DRangeFrom(int off, int count, short[] d) {
+ validateIsInt16();
+ copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type is not an 8 bit
+ * integer type.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param d the source data array
+ */
+ public void copy1DRangeFrom(int off, int count, byte[] d) {
+ validateIsInt8();
+ copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type is not a 32 bit float
+ * type.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param d the source data array.
+ */
+ public void copy1DRangeFrom(int off, int count, float[] d) {
+ validateIsFloat32();
+ copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
+ }
+
+ /**
+ * Copy part of an Allocation into this Allocation.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param data the source data allocation.
+ * @param dataOff off The offset of the first element in data to
+ * be copied.
+ */
+ public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
+ mRS.nAllocationData2D(getIDSafe(), off, 0,
+ mSelectedLOD, mSelectedFace.mID,
+ count, 1, data.getID(mRS), dataOff, 0,
+ data.mSelectedLOD, data.mSelectedFace.mID);
+ }
+
+ private void validate2DRange(int xoff, int yoff, int w, int h) {
+ if (mAdaptedAllocation != null) {
+
+ } else {
+
+ if (xoff < 0 || yoff < 0) {
+ throw new RSIllegalArgumentException("Offset cannot be negative.");
+ }
+ if (h < 0 || w < 0) {
+ throw new RSIllegalArgumentException("Height or width cannot be negative.");
+ }
+ if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
+ throw new RSIllegalArgumentException("Updated region larger than allocation.");
+ }
+ }
+ }
+
+ void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array,
+ Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
+ mRS.validate();
+ validate2DRange(xoff, yoff, w, h);
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
+ array, arrayLen * dt.mSize, dt);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param array Data to be placed into the Allocation
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
+ validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
+ validateIsInt8();
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+ Element.DataType.SIGNED_8, data.length);
+ }
+
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
+ validateIsInt16();
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+ Element.DataType.SIGNED_16, data.length);
+ }
+
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
+ validateIsInt32();
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+ Element.DataType.SIGNED_32, data.length);
+ }
+
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
+ validateIsFloat32();
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+ Element.DataType.FLOAT_32, data.length);
+ }
+
+ /**
+ * Copy a rectangular region from an Allocation into a rectangular region in
+ * this Allocation.
+ *
+ * @param xoff X offset of the region in this Allocation
+ * @param yoff Y offset of the region in this Allocation
+ * @param w Width of the region to update.
+ * @param h Height of the region to update.
+ * @param data source Allocation.
+ * @param dataXoff X offset in source Allocation
+ * @param dataYoff Y offset in source Allocation
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
+ Allocation data, int dataXoff, int dataYoff) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+ mRS.validate();
+ validate2DRange(xoff, yoff, w, h);
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
+ mSelectedLOD, mSelectedFace.mID,
+ w, h, data.getID(mRS), dataXoff, dataYoff,
+ data.mSelectedLOD, data.mSelectedFace.mID);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy a {@link android.graphics.Bitmap} into an Allocation. The height
+ * and width of the update will use the height and width of the {@link
+ * android.graphics.Bitmap}.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param data the Bitmap to be copied
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+ mRS.validate();
+ if (data.getConfig() == null) {
+ Bitmap newBitmap = Bitmap.createBitmap(data.getWidth(), data.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(newBitmap);
+ c.drawBitmap(data, 0, 0, null);
+ copy2DRangeFrom(xoff, yoff, newBitmap);
+ return;
+ }
+ validateBitmapFormat(data);
+ validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ private void validate3DRange(int xoff, int yoff, int zoff, int w, int h, int d) {
+ if (mAdaptedAllocation != null) {
+
+ } else {
+
+ if (xoff < 0 || yoff < 0 || zoff < 0) {
+ throw new RSIllegalArgumentException("Offset cannot be negative.");
+ }
+ if (h < 0 || w < 0 || d < 0) {
+ throw new RSIllegalArgumentException("Height or width cannot be negative.");
+ }
+ if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
+ throw new RSIllegalArgumentException("Updated region larger than allocation.");
+ }
+ }
+ }
+
+ /**
+ * @hide
+ *
+ */
+ private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
+ Object array, Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
+ mRS.validate();
+ validate3DRange(xoff, yoff, zoff, w, h, d);
+ mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
+ array, arrayLen * dt.mSize, dt);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * @hide
+ * Copy a rectangular region from the array into the allocation.
+ * The array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param zoff Z offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param d Depth of the region to update
+ * @param data to be placed into the allocation
+ */
+ public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
+ copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
+ validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * @hide
+ * Copy a rectangular region into the allocation from another
+ * allocation.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param zoff Z offset of the region to update in this Allocation
+ * @param w Width of the region to update.
+ * @param h Height of the region to update.
+ * @param d Depth of the region to update.
+ * @param data source allocation.
+ * @param dataXoff X offset of the region in the source Allocation
+ * @param dataYoff Y offset of the region in the source Allocation
+ * @param dataZoff Z offset of the region in the source Allocation
+ */
+ public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d,
+ Allocation data, int dataXoff, int dataYoff, int dataZoff) {
+ mRS.validate();
+ validate3DRange(xoff, yoff, zoff, w, h, d);
+ mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
+ w, h, d, data.getID(mRS), dataXoff, dataYoff, dataZoff,
+ data.mSelectedLOD);
+ }
+
+
+ /**
+ * Copy from the Allocation into a {@link android.graphics.Bitmap}. The
+ * bitmap must match the dimensions of the Allocation.
+ *
+ * @param b The bitmap to be set from the Allocation.
+ */
+ public void copyTo(Bitmap b) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
+ mRS.validate();
+ validateBitmapFormat(b);
+ validateBitmapSize(b);
+ mRS.nAllocationCopyToBitmap(getID(mRS), b);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ private void copyTo(Object array, Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
+ mRS.validate();
+ mRS.nAllocationRead(getID(mRS), array, dt);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy from the Allocation into an array. The array must be at
+ * least as large as the Allocation. The
+ * {@link android.renderscript.Element} must match the component
+ * type of the array passed in.
+ *
+ * @param array The array to be set from the Allocation.
+ */
+ public void copyTo(Object array) {
+ copyTo(array, validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
+ }
+
+ /**
+ * Copy from the Allocation into a byte array. The array must be at least
+ * as large as the Allocation. The allocation must be of an 8 bit integer
+ * {@link android.renderscript.Element} type.
+ *
+ * @param d The array to be set from the Allocation.
+ */
+ public void copyTo(byte[] d) {
+ validateIsInt8();
+ copyTo(d, Element.DataType.SIGNED_8, d.length);
+ }
+
+ /**
+ * Copy from the Allocation into a short array. The array must be at least
+ * as large as the Allocation. The allocation must be of an 16 bit integer
+ * {@link android.renderscript.Element} type.
+ *
+ * @param d The array to be set from the Allocation.
+ */
+ public void copyTo(short[] d) {
+ validateIsInt16();
+ copyTo(d, Element.DataType.SIGNED_16, d.length);
+ }
+
+ /**
+ * Copy from the Allocation into a int array. The array must be at least as
+ * large as the Allocation. The allocation must be of an 32 bit integer
+ * {@link android.renderscript.Element} type.
+ *
+ * @param d The array to be set from the Allocation.
+ */
+ public void copyTo(int[] d) {
+ validateIsInt32();
+ copyTo(d, Element.DataType.SIGNED_32, d.length);
+ }
+
+ /**
+ * Copy from the Allocation into a float array. The array must be at least
+ * as large as the Allocation. The allocation must be of an 32 bit float
+ * {@link android.renderscript.Element} type.
+ *
+ * @param d The array to be set from the Allocation.
+ */
+ public void copyTo(float[] d) {
+ validateIsFloat32();
+ copyTo(d, Element.DataType.FLOAT_32, d.length);
+ }
+
+ /**
+ * Resize a 1D allocation. The contents of the allocation are preserved.
+ * If new elements are allocated objects are created with null contents and
+ * the new region is otherwise undefined.
+ *
+ * <p>If the new region is smaller the references of any objects outside the
+ * new region will be released.</p>
+ *
+ * <p>A new type will be created with the new dimension.</p>
+ *
+ * @param dimX The new size of the allocation.
+ *
+ * @deprecated RenderScript objects should be immutable once created. The
+ * replacement is to create a new allocation and copy the contents.
+ */
+ public synchronized void resize(int dimX) {
+ if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
+ throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
+ }
+ mRS.nAllocationResize1D(getID(mRS), dimX);
+ mRS.finish(); // Necessary because resize is fifoed and update is async.
+
+ long typeID = mRS.nAllocationGetType(getID(mRS));
+ mType = new Type(typeID, mRS);
+ mType.updateFromNative();
+ updateCacheInfo(mType);
+ }
+
+
+ // creation
+
+ static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
+ static {
+ mBitmapOptions.inScaled = false;
+ }
+
+ /**
+ * Creates a new Allocation with the given {@link
+ * android.renderscript.Type}, mipmap flag, and usage flags.
+ *
+ * @param type RenderScript type describing data layout
+ * @param mips specifies desired mipmap behaviour for the
+ * allocation
+ * @param usage bit field specifying how the Allocation is
+ * utilized
+ */
+ static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "createTyped");
+ rs.validate();
+ if (type.getID(rs) == 0) {
+ throw new RSInvalidStateException("Bad Type");
+ }
+ long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
+ if (id == 0) {
+ throw new RSRuntimeException("Allocation creation failed.");
+ }
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ return new Allocation(id, rs, type, usage);
+ }
+
+ /**
+ * Creates an Allocation with the size specified by the type and no mipmaps
+ * generated by default
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param type renderscript type describing data layout
+ * @param usage bit field specifying how the allocation is
+ * utilized
+ *
+ * @return allocation
+ */
+ static public Allocation createTyped(RenderScript rs, Type type, int usage) {
+ return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
+ }
+
+ /**
+ * Creates an Allocation for use by scripts with a given {@link
+ * android.renderscript.Type} and no mipmaps
+ *
+ * @param rs Context to which the Allocation will belong.
+ * @param type RenderScript Type describing data layout
+ *
+ * @return allocation
+ */
+ static public Allocation createTyped(RenderScript rs, Type type) {
+ return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
+ }
+
+ /**
+ * Creates an Allocation with a specified number of given elements
+ *
+ * @param rs Context to which the Allocation will belong.
+ * @param e Element to use in the Allocation
+ * @param count the number of Elements in the Allocation
+ * @param usage bit field specifying how the Allocation is
+ * utilized
+ *
+ * @return allocation
+ */
+ static public Allocation createSized(RenderScript rs, Element e,
+ int count, int usage) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "createSized");
+ rs.validate();
+ Type.Builder b = new Type.Builder(rs, e);
+ b.setX(count);
+ Type t = b.create();
+
+ long id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
+ if (id == 0) {
+ throw new RSRuntimeException("Allocation creation failed.");
+ }
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ return new Allocation(id, rs, t, usage);
+ }
+
+ /**
+ * Creates an Allocation with a specified number of given elements
+ *
+ * @param rs Context to which the Allocation will belong.
+ * @param e Element to use in the Allocation
+ * @param count the number of Elements in the Allocation
+ *
+ * @return allocation
+ */
+ static public Allocation createSized(RenderScript rs, Element e, int count) {
+ return createSized(rs, e, count, USAGE_SCRIPT);
+ }
+
+ static Element elementFromBitmap(RenderScript rs, Bitmap b) {
+ final Bitmap.Config bc = b.getConfig();
+ if (bc == Bitmap.Config.ALPHA_8) {
+ return Element.A_8(rs);
+ }
+ if (bc == Bitmap.Config.ARGB_4444) {
+ return Element.RGBA_4444(rs);
+ }
+ if (bc == Bitmap.Config.ARGB_8888) {
+ return Element.RGBA_8888(rs);
+ }
+ if (bc == Bitmap.Config.RGB_565) {
+ return Element.RGB_565(rs);
+ }
+ throw new RSInvalidStateException("Bad bitmap type: " + bc);
+ }
+
+ static Type typeFromBitmap(RenderScript rs, Bitmap b,
+ MipmapControl mip) {
+ Element e = elementFromBitmap(rs, b);
+ Type.Builder tb = new Type.Builder(rs, e);
+ tb.setX(b.getWidth());
+ tb.setY(b.getHeight());
+ tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
+ return tb.create();
+ }
+
+ /**
+ * Creates an Allocation from a {@link android.graphics.Bitmap}.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param b Bitmap source for the allocation data
+ * @param mips specifies desired mipmap behaviour for the
+ * allocation
+ * @param usage bit field specifying how the allocation is
+ * utilized
+ *
+ * @return Allocation containing bitmap data
+ *
+ */
+ static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
+ MipmapControl mips,
+ int usage) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "createFromBitmap");
+ rs.validate();
+
+ // WAR undocumented color formats
+ if (b.getConfig() == null) {
+ if ((usage & USAGE_SHARED) != 0) {
+ throw new RSIllegalArgumentException("USAGE_SHARED cannot be used with a Bitmap that has a null config.");
+ }
+ Bitmap newBitmap = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(newBitmap);
+ c.drawBitmap(b, 0, 0, null);
+ return createFromBitmap(rs, newBitmap, mips, usage);
+ }
+
+ Type t = typeFromBitmap(rs, b, mips);
+
+ // enable optimized bitmap path only with no mipmap and script-only usage
+ if (mips == MipmapControl.MIPMAP_NONE &&
+ t.getElement().isCompatible(Element.RGBA_8888(rs)) &&
+ usage == (USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE)) {
+ long id = rs.nAllocationCreateBitmapBackedAllocation(t.getID(rs), mips.mID, b, usage);
+ if (id == 0) {
+ throw new RSRuntimeException("Load failed.");
+ }
+
+ // keep a reference to the Bitmap around to prevent GC
+ Allocation alloc = new Allocation(id, rs, t, usage);
+ alloc.setBitmap(b);
+ return alloc;
+ }
+
+
+ long id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
+ if (id == 0) {
+ throw new RSRuntimeException("Load failed.");
+ }
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ return new Allocation(id, rs, t, usage);
+ }
+
+ /**
+ * Returns the handle to a raw buffer that is being managed by the screen
+ * compositor. This operation is only valid for Allocations with {@link
+ * #USAGE_IO_INPUT}.
+ *
+ * @return Surface object associated with allocation
+ *
+ */
+ public Surface getSurface() {
+ if ((mUsage & USAGE_IO_INPUT) == 0) {
+ throw new RSInvalidStateException("Allocation is not a surface texture.");
+ }
+ return mRS.nAllocationGetSurface(getID(mRS));
+ }
+
+ /**
+ * Associate a {@link android.view.Surface} with this Allocation. This
+ * operation is only valid for Allocations with {@link #USAGE_IO_OUTPUT}.
+ *
+ * @param sur Surface to associate with allocation
+ */
+ public void setSurface(Surface sur) {
+ mRS.validate();
+ if ((mUsage & USAGE_IO_OUTPUT) == 0) {
+ throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
+ }
+
+ mRS.nAllocationSetSurface(getID(mRS), sur);
+ }
+
+ /**
+ * Creates an Allocation from a {@link android.graphics.Bitmap}.
+ *
+ * <p>With target API version 18 or greater, this Allocation will be created
+ * with {@link #USAGE_SHARED}, {@link #USAGE_SCRIPT}, and {@link
+ * #USAGE_GRAPHICS_TEXTURE}. With target API version 17 or lower, this
+ * Allocation will be created with {@link #USAGE_GRAPHICS_TEXTURE}.</p>
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param b bitmap source for the allocation data
+ *
+ * @return Allocation containing bitmap data
+ *
+ */
+ static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
+ if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
+ return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
+ USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
+ }
+ return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
+ USAGE_GRAPHICS_TEXTURE);
+ }
+
+ /**
+ * Creates a cubemap Allocation from a {@link android.graphics.Bitmap}
+ * containing the horizontal list of cube faces. Each face must be a square,
+ * have the same size as all other faces, and have a width that is a power
+ * of 2.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param b Bitmap with cubemap faces layed out in the following
+ * format: right, left, top, bottom, front, back
+ * @param mips specifies desired mipmap behaviour for the cubemap
+ * @param usage bit field specifying how the cubemap is utilized
+ *
+ * @return allocation containing cubemap data
+ *
+ */
+ static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
+ MipmapControl mips,
+ int usage) {
+ rs.validate();
+
+ int height = b.getHeight();
+ int width = b.getWidth();
+
+ if (width % 6 != 0) {
+ throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
+ }
+ if (width / 6 != height) {
+ throw new RSIllegalArgumentException("Only square cube map faces supported");
+ }
+ boolean isPow2 = (height & (height - 1)) == 0;
+ if (!isPow2) {
+ throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
+ }
+
+ Element e = elementFromBitmap(rs, b);
+ Type.Builder tb = new Type.Builder(rs, e);
+ tb.setX(height);
+ tb.setY(height);
+ tb.setFaces(true);
+ tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
+ Type t = tb.create();
+
+ long id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
+ if(id == 0) {
+ throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
+ }
+ return new Allocation(id, rs, t, usage);
+ }
+
+ /**
+ * Creates a non-mipmapped cubemap Allocation for use as a graphics texture
+ * from a {@link android.graphics.Bitmap} containing the horizontal list of
+ * cube faces. Each face must be a square, have the same size as all other
+ * faces, and have a width that is a power of 2.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param b bitmap with cubemap faces layed out in the following
+ * format: right, left, top, bottom, front, back
+ *
+ * @return allocation containing cubemap data
+ *
+ */
+ static public Allocation createCubemapFromBitmap(RenderScript rs,
+ Bitmap b) {
+ return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
+ USAGE_GRAPHICS_TEXTURE);
+ }
+
+ /**
+ * Creates a cubemap Allocation from 6 {@link android.graphics.Bitmap}
+ * objects containing the cube faces. Each face must be a square, have the
+ * same size as all other faces, and have a width that is a power of 2.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param xpos cubemap face in the positive x direction
+ * @param xneg cubemap face in the negative x direction
+ * @param ypos cubemap face in the positive y direction
+ * @param yneg cubemap face in the negative y direction
+ * @param zpos cubemap face in the positive z direction
+ * @param zneg cubemap face in the negative z direction
+ * @param mips specifies desired mipmap behaviour for the cubemap
+ * @param usage bit field specifying how the cubemap is utilized
+ *
+ * @return allocation containing cubemap data
+ *
+ */
+ static public Allocation createCubemapFromCubeFaces(RenderScript rs,
+ Bitmap xpos,
+ Bitmap xneg,
+ Bitmap ypos,
+ Bitmap yneg,
+ Bitmap zpos,
+ Bitmap zneg,
+ MipmapControl mips,
+ int usage) {
+ int height = xpos.getHeight();
+ if (xpos.getWidth() != height ||
+ xneg.getWidth() != height || xneg.getHeight() != height ||
+ ypos.getWidth() != height || ypos.getHeight() != height ||
+ yneg.getWidth() != height || yneg.getHeight() != height ||
+ zpos.getWidth() != height || zpos.getHeight() != height ||
+ zneg.getWidth() != height || zneg.getHeight() != height) {
+ throw new RSIllegalArgumentException("Only square cube map faces supported");
+ }
+ boolean isPow2 = (height & (height - 1)) == 0;
+ if (!isPow2) {
+ throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
+ }
+
+ Element e = elementFromBitmap(rs, xpos);
+ Type.Builder tb = new Type.Builder(rs, e);
+ tb.setX(height);
+ tb.setY(height);
+ tb.setFaces(true);
+ tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
+ Type t = tb.create();
+ Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
+
+ AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
+ adapter.setFace(Type.CubemapFace.POSITIVE_X);
+ adapter.copyFrom(xpos);
+ adapter.setFace(Type.CubemapFace.NEGATIVE_X);
+ adapter.copyFrom(xneg);
+ adapter.setFace(Type.CubemapFace.POSITIVE_Y);
+ adapter.copyFrom(ypos);
+ adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
+ adapter.copyFrom(yneg);
+ adapter.setFace(Type.CubemapFace.POSITIVE_Z);
+ adapter.copyFrom(zpos);
+ adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
+ adapter.copyFrom(zneg);
+
+ return cubemap;
+ }
+
+ /**
+ * Creates a non-mipmapped cubemap Allocation for use as a sampler input
+ * from 6 {@link android.graphics.Bitmap} objects containing the cube
+ * faces. Each face must be a square, have the same size as all other faces,
+ * and have a width that is a power of 2.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param xpos cubemap face in the positive x direction
+ * @param xneg cubemap face in the negative x direction
+ * @param ypos cubemap face in the positive y direction
+ * @param yneg cubemap face in the negative y direction
+ * @param zpos cubemap face in the positive z direction
+ * @param zneg cubemap face in the negative z direction
+ *
+ * @return allocation containing cubemap data
+ *
+ */
+ static public Allocation createCubemapFromCubeFaces(RenderScript rs,
+ Bitmap xpos,
+ Bitmap xneg,
+ Bitmap ypos,
+ Bitmap yneg,
+ Bitmap zpos,
+ Bitmap zneg) {
+ return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
+ zpos, zneg, MipmapControl.MIPMAP_NONE,
+ USAGE_GRAPHICS_TEXTURE);
+ }
+
+ /**
+ * Creates an Allocation from the Bitmap referenced
+ * by resource ID.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param res application resources
+ * @param id resource id to load the data from
+ * @param mips specifies desired mipmap behaviour for the
+ * allocation
+ * @param usage bit field specifying how the allocation is
+ * utilized
+ *
+ * @return Allocation containing resource data
+ *
+ */
+ static public Allocation createFromBitmapResource(RenderScript rs,
+ Resources res,
+ int id,
+ MipmapControl mips,
+ int usage) {
+
+ rs.validate();
+ if ((usage & (USAGE_SHARED | USAGE_IO_INPUT | USAGE_IO_OUTPUT)) != 0) {
+ throw new RSIllegalArgumentException("Unsupported usage specified.");
+ }
+ Bitmap b = BitmapFactory.decodeResource(res, id);
+ Allocation alloc = createFromBitmap(rs, b, mips, usage);
+ b.recycle();
+ return alloc;
+ }
+
+ /**
+ * Creates a non-mipmapped Allocation to use as a graphics texture from the
+ * {@link android.graphics.Bitmap} referenced by resource ID.
+ *
+ * <p>With target API version 18 or greater, this allocation will be created
+ * with {@link #USAGE_SCRIPT} and {@link #USAGE_GRAPHICS_TEXTURE}. With
+ * target API version 17 or lower, this allocation will be created with
+ * {@link #USAGE_GRAPHICS_TEXTURE}.</p>
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param res application resources
+ * @param id resource id to load the data from
+ *
+ * @return Allocation containing resource data
+ *
+ */
+ static public Allocation createFromBitmapResource(RenderScript rs,
+ Resources res,
+ int id) {
+ if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
+ return createFromBitmapResource(rs, res, id,
+ MipmapControl.MIPMAP_NONE,
+ USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
+ }
+ return createFromBitmapResource(rs, res, id,
+ MipmapControl.MIPMAP_NONE,
+ USAGE_GRAPHICS_TEXTURE);
+ }
+
+ /**
+ * Creates an Allocation containing string data encoded in UTF-8 format.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param str string to create the allocation from
+ * @param usage bit field specifying how the allocaiton is
+ * utilized
+ *
+ */
+ static public Allocation createFromString(RenderScript rs,
+ String str,
+ int usage) {
+ rs.validate();
+ byte[] allocArray = null;
+ try {
+ allocArray = str.getBytes("UTF-8");
+ Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
+ alloc.copyFrom(allocArray);
+ return alloc;
+ }
+ catch (Exception e) {
+ throw new RSRuntimeException("Could not convert string to utf-8.");
+ }
+ }
+
+ /**
+ * Interface to handle notification when new buffers are available via
+ * {@link #USAGE_IO_INPUT}. An application will receive one notification
+ * when a buffer is available. Additional buffers will not trigger new
+ * notifications until a buffer is processed.
+ */
+ public interface OnBufferAvailableListener {
+ public void onBufferAvailable(Allocation a);
+ }
+
+ /**
+ * Set a notification handler for {@link #USAGE_IO_INPUT}.
+ *
+ * @param callback instance of the OnBufferAvailableListener
+ * class to be called when buffer arrive.
+ */
+ public void setOnBufferAvailableListener(OnBufferAvailableListener callback) {
+ synchronized(mAllocationMap) {
+ mAllocationMap.put(new Long(getID(mRS)), this);
+ mBufferNotifier = callback;
+ }
+ }
+
+ static void sendBufferNotification(int id) {
+ synchronized(mAllocationMap) {
+ Allocation a = mAllocationMap.get(new Long(id));
+
+ if ((a != null) && (a.mBufferNotifier != null)) {
+ a.mBufferNotifier.onBufferAvailable(a);
+ }
+ }
+ }
+
+}