[RenderScript] Implement APIs for better multi-frame process support.

Bug: 23535524

 Two APIs added for multiframe processing:
 - createAllocations(...): To create an array of Allocations sharing the
   same Type and Usage. For USAGE_IO_INPUT Allocations, they also share
   the same BufferQueue.
 - getTimeStamp(): API to retrieve the time stamp associated with the
   most recent buffer.

Change-Id: I6b7b35d7dca5e87ee2f3db2ee17cb9cf824bcfe1
This commit is contained in:
Miao Wang
2015-10-26 17:44:10 -07:00
parent ed50f333fb
commit 8c1509249c
3 changed files with 188 additions and 15 deletions

View File

@@ -55,12 +55,16 @@ import android.view.Surface;
**/
public class Allocation extends BaseObj {
private static final int MAX_NUMBER_IO_INPUT_ALLOC = 16;
Type mType;
Bitmap mBitmap;
int mUsage;
Allocation mAdaptedAllocation;
int mSize;
MipmapControl mMipmapControl;
long mTimeStamp = -1;
boolean mReadAllowed = true;
boolean mWriteAllowed = true;
boolean mAutoPadding = false;
@@ -277,6 +281,17 @@ public class Allocation extends BaseObj {
return mUsage;
}
/**
* @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.
* By default: Diabled.
@@ -359,6 +374,11 @@ public class Allocation extends BaseObj {
}
}
Allocation(long id, RenderScript rs, Type t, int usage, MipmapControl mips) {
this(id, rs, t, usage);
mMipmapControl = mips;
}
protected void finalize() throws Throwable {
RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
super.finalize();
@@ -521,7 +541,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);
}
@@ -1890,7 +1910,7 @@ public class Allocation extends BaseObj {
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
return new Allocation(id, rs, type, usage);
return new Allocation(id, rs, type, usage, mips);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -1948,7 +1968,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, usage, MipmapControl.MIPMAP_NONE);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -2037,7 +2057,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, usage, mips);
alloc.setBitmap(b);
return alloc;
}
@@ -2047,7 +2067,7 @@ 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, usage, mips);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -2088,6 +2108,108 @@ public class Allocation extends BaseObj {
return mByteBuffer;
}
/**
* @hide
* 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] = createFromAllcation(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 createFromAllcation(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, 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));
}
/**
* @hide
* Gets the stride of the Allocation.
@@ -2106,6 +2228,27 @@ public class Allocation extends BaseObj {
return mByteBufferStride;
}
/**
* @hide
* 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
@@ -2210,7 +2353,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, usage, mips);
}
/**