summaryrefslogtreecommitdiff
path: root/rs/java/android/renderscript/Allocation.java
diff options
context:
space:
mode:
Diffstat (limited to 'rs/java/android/renderscript/Allocation.java')
-rw-r--r--rs/java/android/renderscript/Allocation.java260
1 files changed, 239 insertions, 21 deletions
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 0a5059390449..c0ea1324602b 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -16,14 +16,16 @@
package android.renderscript;
+import java.nio.ByteBuffer;
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;
+import android.util.Log;
+import android.view.Surface;
/**
* <p> This class provides the primary method through which data is passed to
@@ -53,12 +55,17 @@ import android.os.Trace;
**/
public class Allocation extends BaseObj {
+ private static final int MAX_NUMBER_IO_INPUT_ALLOC = 16;
+
Type mType;
+ boolean mOwningType = false;
Bitmap mBitmap;
int mUsage;
Allocation mAdaptedAllocation;
int mSize;
+ MipmapControl mMipmapControl;
+ long mTimeStamp = -1;
boolean mReadAllowed = true;
boolean mWriteAllowed = true;
boolean mAutoPadding = false;
@@ -78,6 +85,8 @@ public class Allocation extends BaseObj {
OnBufferAvailableListener mBufferNotifier;
private Surface mGetSurfaceSurface = null;
+ private ByteBuffer mByteBuffer = null;
+ private long mByteBufferStride = -1;
private Element.DataType validateObjectIsPrimitiveArray(Object d, boolean checkType) {
final Class c = d.getClass();
@@ -107,7 +116,7 @@ public class Allocation extends BaseObj {
if (cmp == Short.TYPE) {
if (checkType) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
return mType.mElement.mType;
}
return Element.DataType.SIGNED_16;
@@ -134,7 +143,10 @@ public class Allocation extends BaseObj {
}
return Element.DataType.FLOAT_64;
}
- return null;
+
+ throw new RSIllegalArgumentException("Parameter of type " + cmp.getSimpleName() +
+ "[] is not compatible with data type " + mType.mElement.mType.name() +
+ " of allocation");
}
@@ -274,8 +286,24 @@ public class Allocation extends BaseObj {
}
/**
- * Enable/Disable AutoPadding for Vec3 elements.
- * By default: Diabled.
+ * @hide
+ * Get the Mipmap control flag of the Allocation.
+ *
+ * @return the Mipmap control flag of the Allocation
+ *
+ */
+ public MipmapControl getMipmap() {
+ return mMipmapControl;
+ }
+
+ /**
+ * Enable/Disable AutoPadding for Vec3 Elements.
+ *
+ * <p> Vec3 Elements, such as {@link Element#U8_3} are treated as Vec4 Elements
+ * with the fourth vector element used as padding. Enabling the AutoPadding feature
+ * will automatically add/remove the padding when you copy to/from an Allocation
+ * with a Vec3 Element.
+ * <p> By default: Disabled.
*
* @param useAutoPadding True: enable AutoPadding; False: disable AutoPadding
*
@@ -353,6 +381,13 @@ public class Allocation extends BaseObj {
Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e);
throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e);
}
+ guard.open("destroy");
+ }
+
+ Allocation(long id, RenderScript rs, Type t, boolean owningType, int usage, MipmapControl mips) {
+ this(id, rs, t, usage);
+ mOwningType = owningType;
+ mMipmapControl = mips;
}
protected void finalize() throws Throwable {
@@ -378,9 +413,10 @@ public class Allocation extends BaseObj {
"32 bit integer source does not match allocation type " + mType.mElement.mType);
}
- private void validateIsInt16() {
+ private void validateIsInt16OrFloat16() {
if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
- (mType.mElement.mType == Element.DataType.UNSIGNED_16)) {
+ (mType.mElement.mType == Element.DataType.UNSIGNED_16) ||
+ (mType.mElement.mType == Element.DataType.FLOAT_16)) {
return;
}
throw new RSIllegalArgumentException(
@@ -517,7 +553,7 @@ public class Allocation extends BaseObj {
"Can only receive if IO_INPUT usage specified.");
}
mRS.validate();
- mRS.nAllocationIoReceive(getID(mRS));
+ mTimeStamp = mRS.nAllocationIoReceive(getID(mRS));
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -727,7 +763,7 @@ public class Allocation extends BaseObj {
* @param d the source data array
*/
public void copyFrom(short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
}
@@ -1036,7 +1072,7 @@ public class Allocation extends BaseObj {
* @param d the source data array
*/
public void copy1DRangeFrom(int off, int count, short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
}
@@ -1180,7 +1216,7 @@ public class Allocation extends BaseObj {
* @param data to be placed into the Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
Element.DataType.SIGNED_16, data.length);
}
@@ -1449,7 +1485,7 @@ public class Allocation extends BaseObj {
* @param d The array to be set from the Allocation.
*/
public void copyTo(short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copyTo(d, Element.DataType.SIGNED_16, d.length);
}
@@ -1505,7 +1541,7 @@ public class Allocation extends BaseObj {
}
final byte[] data = fp.getData();
- int data_length = fp.getPos();
+ int data_length = data.length;
int eSize = mType.mElement.mElements[component_number].getBytesSize();
eSize *= mType.mElement.mArraySizes[component_number];
@@ -1544,6 +1580,9 @@ public class Allocation extends BaseObj {
mRS.finish(); // Necessary because resize is fifoed and update is async.
long typeID = mRS.nAllocationGetType(getID(mRS));
+ // Sets zero the mID so that the finalizer of the old mType value won't
+ // destroy the native object that is being reused.
+ mType.setID(0);
mType = new Type(typeID, mRS);
mType.updateFromNative();
updateCacheInfo(mType);
@@ -1669,7 +1708,7 @@ public class Allocation extends BaseObj {
* @param d the source data array
*/
public void copy1DRangeTo(int off, int count, short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
}
@@ -1770,7 +1809,7 @@ public class Allocation extends BaseObj {
* @param data Dest Array to be copied into
*/
public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy2DRangeToUnchecked(xoff, yoff, w, h, data,
Element.DataType.SIGNED_16, data.length);
}
@@ -1882,11 +1921,12 @@ public class Allocation extends BaseObj {
if (type.getID(rs) == 0) {
throw new RSInvalidStateException("Bad Type");
}
+ // TODO: What if there is an exception after this? The native allocation would leak.
long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
- return new Allocation(id, rs, type, usage);
+ return new Allocation(id, rs, type, false, usage, mips);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -1944,7 +1984,7 @@ public class Allocation extends BaseObj {
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
- return new Allocation(id, rs, t, usage);
+ return new Allocation(id, rs, t, true, usage, MipmapControl.MIPMAP_NONE);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -2033,7 +2073,7 @@ public class Allocation extends BaseObj {
}
// keep a reference to the Bitmap around to prevent GC
- Allocation alloc = new Allocation(id, rs, t, usage);
+ Allocation alloc = new Allocation(id, rs, t, true, usage, mips);
alloc.setBitmap(b);
return alloc;
}
@@ -2043,13 +2083,185 @@ public class Allocation extends BaseObj {
if (id == 0) {
throw new RSRuntimeException("Load failed.");
}
- return new Allocation(id, rs, t, usage);
+ return new Allocation(id, rs, t, true, usage, mips);
+ } finally {
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+ }
+
+ /**
+ * Gets or creates a ByteBuffer that contains the raw data of the current Allocation.
+ * If the Allocation is created with USAGE_IO_INPUT, the returned ByteBuffer
+ * would contain the up-to-date data as READ ONLY.
+ * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
+ * the Allocation has certain alignment. The size of each row including padding,
+ * called stride, can be queried using the {@link #getStride()} method.
+ *
+ * Note: Operating on the ByteBuffer of a destroyed Allocation will triger errors.
+ *
+ * @return ByteBuffer The ByteBuffer associated with raw data pointer of the Allocation.
+ */
+ public ByteBuffer getByteBuffer() {
+ // Create a new ByteBuffer if it is not initialized or using IO_INPUT.
+ if (mType.hasFaces()) {
+ throw new RSInvalidStateException("Cubemap is not supported for getByteBuffer().");
+ }
+ if (mType.getYuv() == android.graphics.ImageFormat.NV21 ||
+ mType.getYuv() == android.graphics.ImageFormat.YV12 ||
+ mType.getYuv() == android.graphics.ImageFormat.YUV_420_888 ) {
+ throw new RSInvalidStateException("YUV format is not supported for getByteBuffer().");
+ }
+ if (mByteBuffer == null || (mUsage & USAGE_IO_INPUT) != 0) {
+ int xBytesSize = mType.getX() * mType.getElement().getBytesSize();
+ long[] stride = new long[1];
+ mByteBuffer = mRS.nAllocationGetByteBuffer(getID(mRS), stride, xBytesSize, mType.getY(), mType.getZ());
+ mByteBufferStride = stride[0];
+ }
+ if ((mUsage & USAGE_IO_INPUT) != 0) {
+ return mByteBuffer.asReadOnlyBuffer();
+ }
+ return mByteBuffer;
+ }
+
+ /**
+ * Creates a new Allocation Array with the given {@link
+ * android.renderscript.Type}, and usage flags.
+ * Note: If the input allocation is of usage: USAGE_IO_INPUT,
+ * the created Allocation will be sharing the same BufferQueue.
+ *
+ * @param rs RenderScript context
+ * @param t RenderScript type describing data layout
+ * @param usage bit field specifying how the Allocation is
+ * utilized
+ * @param numAlloc Number of Allocations in the array.
+ * @return Allocation[]
+ */
+ public static Allocation[] createAllocations(RenderScript rs, Type t, int usage, int numAlloc) {
+ try {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "createAllocations");
+ rs.validate();
+ if (t.getID(rs) == 0) {
+ throw new RSInvalidStateException("Bad Type");
+ }
+
+ Allocation[] mAllocationArray = new Allocation[numAlloc];
+ mAllocationArray[0] = createTyped(rs, t, usage);
+ if ((usage & USAGE_IO_INPUT) != 0) {
+ if (numAlloc > MAX_NUMBER_IO_INPUT_ALLOC) {
+ throw new RSIllegalArgumentException("Exceeds the max number of Allocations allowed: " +
+ MAX_NUMBER_IO_INPUT_ALLOC);
+ }
+ mAllocationArray[0].setupBufferQueue(numAlloc);;
+ }
+
+ for (int i=1; i<numAlloc; i++) {
+ mAllocationArray[i] = createFromAllocation(rs, mAllocationArray[0]);
+ }
+ return mAllocationArray;
+ } finally {
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+ }
+
+ /**
+ * Creates a new Allocation with the given {@link
+ * android.renderscript.Allocation}. The same data layout of
+ * the input Allocation will be applied.
+ * If the input allocation is of usage: USAGE_IO_INPUT, the created
+ * Allocation will be sharing the same BufferQueue.
+ *
+ * @param rs Context to which the allocation will belong.
+ * @param alloc RenderScript Allocation describing data layout.
+ * @return Allocation sharing the same data structure.
+ */
+ static Allocation createFromAllocation(RenderScript rs, Allocation alloc) {
+ try {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "createFromAllcation");
+ rs.validate();
+ if (alloc.getID(rs) == 0) {
+ throw new RSInvalidStateException("Bad input Allocation");
+ }
+
+ Type type = alloc.getType();
+ int usage = alloc.getUsage();
+ MipmapControl mips = alloc.getMipmap();
+ long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
+ if (id == 0) {
+ throw new RSRuntimeException("Allocation creation failed.");
+ }
+ Allocation outAlloc = new Allocation(id, rs, type, false, usage, mips);
+ if ((usage & USAGE_IO_INPUT) != 0) {
+ outAlloc.shareBufferQueue(alloc);
+ }
+ return outAlloc;
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
}
/**
+ * Initialize BufferQueue with specified max number of buffers.
+ */
+ void setupBufferQueue(int numAlloc) {
+ mRS.validate();
+ if ((mUsage & USAGE_IO_INPUT) == 0) {
+ throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
+ }
+ mRS.nAllocationSetupBufferQueue(getID(mRS), numAlloc);
+ }
+
+ /**
+ * Share the BufferQueue with another {@link #USAGE_IO_INPUT} Allocation.
+ *
+ * @param alloc Allocation to associate with allocation
+ */
+ void shareBufferQueue(Allocation alloc) {
+ mRS.validate();
+ if ((mUsage & USAGE_IO_INPUT) == 0) {
+ throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
+ }
+ mGetSurfaceSurface = alloc.getSurface();
+ mRS.nAllocationShareBufferQueue(getID(mRS), alloc.getID(mRS));
+ }
+
+ /**
+ * Gets the stride of the Allocation.
+ * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
+ * the Allocation has certain alignment. The size of each row including such
+ * padding is called stride.
+ *
+ * @return the stride. For 1D Allocation, the stride will be the number of
+ * bytes of this Allocation. For 2D and 3D Allocations, the stride
+ * will be the stride in X dimension measuring in bytes.
+ */
+ public long getStride() {
+ if (mByteBufferStride == -1) {
+ getByteBuffer();
+ }
+ return mByteBufferStride;
+ }
+
+ /**
+ * Get the timestamp for the most recent buffer held by this Allocation.
+ * The timestamp is guaranteed to be unique and monotonically increasing.
+ * Default value: -1. The timestamp will be updated after each {@link
+ * #ioReceive ioReceive()} call.
+ *
+ * It can be used to identify the images by comparing the unique timestamps
+ * when used with {@link android.hardware.camera2} APIs.
+ * Example steps:
+ * 1. Save {@link android.hardware.camera2.TotalCaptureResult} when the
+ * capture is completed.
+ * 2. Get the timestamp after {@link #ioReceive ioReceive()} call.
+ * 3. Comparing totalCaptureResult.get(CaptureResult.SENSOR_TIMESTAMP) with
+ * alloc.getTimeStamp().
+ * @return long Timestamp associated with the buffer held by the Allocation.
+ */
+ public long getTimeStamp() {
+ return mTimeStamp;
+ }
+
+ /**
* 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}.
@@ -2153,7 +2365,7 @@ public class Allocation extends BaseObj {
if(id == 0) {
throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
}
- return new Allocation(id, rs, t, usage);
+ return new Allocation(id, rs, t, true, usage, mips);
}
/**
@@ -2398,6 +2610,12 @@ public class Allocation extends BaseObj {
if((mUsage & USAGE_IO_OUTPUT) != 0) {
setSurface(null);
}
+
+ if (mType != null && mOwningType) {
+ mType.destroy();
+ }
+
super.destroy();
}
+
}