OSDN Git Service

[RenderScript] Implement APIs for better multi-frame process support.
authorMiao Wang <miaowang@google.com>
Tue, 27 Oct 2015 00:44:10 +0000 (17:44 -0700)
committerMiao Wang <miaowang@google.com>
Tue, 26 Jan 2016 22:40:44 +0000 (14:40 -0800)
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

rs/java/android/renderscript/Allocation.java
rs/java/android/renderscript/RenderScript.java
rs/jni/android_renderscript_RenderScript.cpp

index a71ba63..4bda87e 100644 (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;
@@ -278,6 +282,17 @@ public class Allocation extends BaseObj {
     }
 
     /**
+     * @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);
         }
@@ -2090,6 +2110,108 @@ public class Allocation extends BaseObj {
 
     /**
      * @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.
      * 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
@@ -2107,6 +2229,27 @@ public class Allocation extends BaseObj {
     }
 
     /**
+     * @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
      * #USAGE_IO_INPUT}.
@@ -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);
     }
 
     /**
index 4788223..51fc7dd 100644 (file)
@@ -484,7 +484,6 @@ public class RenderScript {
         rsnAllocationCopyToBitmap(mContext, alloc, bmp);
     }
 
-
     native void rsnAllocationSyncAll(long con, long alloc, int src);
     synchronized void nAllocationSyncAll(long alloc, int src) {
         validate();
@@ -497,6 +496,16 @@ public class RenderScript {
         return rsnAllocationGetByteBuffer(mContext, alloc, stride, xBytesSize, dimY, dimZ);
     }
 
+    native void rsnAllocationSetupBufferQueue(long con, long alloc, int numAlloc);
+    synchronized void nAllocationSetupBufferQueue(long alloc, int numAlloc) {
+        validate();
+        rsnAllocationSetupBufferQueue(mContext, alloc, numAlloc);
+    }
+    native void rsnAllocationShareBufferQueue(long con, long alloc1, long alloc2);
+    synchronized void nAllocationShareBufferQueue(long alloc1, long alloc2) {
+        validate();
+        rsnAllocationShareBufferQueue(mContext, alloc1, alloc2);
+    }
     native Surface rsnAllocationGetSurface(long con, long alloc);
     synchronized Surface nAllocationGetSurface(long alloc) {
         validate();
@@ -512,13 +521,12 @@ public class RenderScript {
         validate();
         rsnAllocationIoSend(mContext, alloc);
     }
-    native void rsnAllocationIoReceive(long con, long alloc);
-    synchronized void nAllocationIoReceive(long alloc) {
+    native long rsnAllocationIoReceive(long con, long alloc);
+    synchronized long nAllocationIoReceive(long alloc) {
         validate();
-        rsnAllocationIoReceive(mContext, alloc);
+        return rsnAllocationIoReceive(mContext, alloc);
     }
 
-
     native void rsnAllocationGenerateMipmaps(long con, long alloc);
     synchronized void nAllocationGenerateMipmaps(long alloc) {
         validate();
index 398d89b..3dff37b 100644 (file)
@@ -1223,6 +1223,27 @@ nAllocationSyncAll(JNIEnv *_env, jobject _this, jlong con, jlong a, jint bits)
     rsAllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits);
 }
 
+static void
+nAllocationSetupBufferQueue(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint numAlloc)
+{
+    if (kLogApi) {
+        ALOGD("nAllocationSetupBufferQueue, con(%p), alloc(%p), numAlloc(%d)", (RsContext)con,
+              (RsAllocation)alloc, numAlloc);
+    }
+    rsAllocationSetupBufferQueue((RsContext)con, (RsAllocation)alloc, (uint32_t)numAlloc);
+}
+
+static void
+nAllocationShareBufferQueue(JNIEnv *_env, jobject _this, jlong con, jlong alloc1, jlong alloc2)
+{
+    if (kLogApi) {
+        ALOGD("nAllocationShareBufferQueue, con(%p), alloc1(%p), alloc2(%p)", (RsContext)con,
+              (RsAllocation)alloc1, (RsAllocation)alloc2);
+    }
+
+    rsAllocationShareBufferQueue((RsContext)con, (RsAllocation)alloc1, (RsAllocation)alloc2);
+}
+
 static jobject
 nAllocationGetSurface(JNIEnv *_env, jobject _this, jlong con, jlong a)
 {
@@ -1265,16 +1286,15 @@ nAllocationIoSend(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
     rsAllocationIoSend((RsContext)con, (RsAllocation)alloc);
 }
 
-static void
+static jlong
 nAllocationIoReceive(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
 {
     if (kLogApi) {
         ALOGD("nAllocationIoReceive, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
     }
-    rsAllocationIoReceive((RsContext)con, (RsAllocation)alloc);
+    return (jlong) rsAllocationIoReceive((RsContext)con, (RsAllocation)alloc);
 }
 
-
 static void
 nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
 {
@@ -2856,10 +2876,12 @@ static const JNINativeMethod methods[] = {
 {"rsnAllocationCopyToBitmap",        "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
 
 {"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
+{"rsnAllocationSetupBufferQueue",    "(JJI)V",                                (void*)nAllocationSetupBufferQueue },
+{"rsnAllocationShareBufferQueue",    "(JJJ)V",                                (void*)nAllocationShareBufferQueue },
 {"rsnAllocationGetSurface",          "(JJ)Landroid/view/Surface;",            (void*)nAllocationGetSurface },
 {"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
 {"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
-{"rsnAllocationIoReceive",           "(JJ)V",                                 (void*)nAllocationIoReceive },
+{"rsnAllocationIoReceive",           "(JJ)J",                                 (void*)nAllocationIoReceive },
 {"rsnAllocationData1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationData1D },
 {"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
 {"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationData2D },