Loading core/java/android/view/ViewRootImpl.java +88 −50 Original line number Diff line number Diff line Loading @@ -758,6 +758,12 @@ public final class ViewRootImpl implements ViewParent, */ private boolean mWaitForBlastSyncComplete = false; /** * Keeps track of the last frame number that was attempted to draw. Should only be accessed on * the RenderThread. */ private long mRtLastAttemptedDrawFrameNum = 0; /** * Keeps track of whether a traverse was triggered while the UI thread was paused. This can * occur when the client is waiting on another process to submit the transaction that Loading Loading @@ -3974,16 +3980,60 @@ public final class ViewRootImpl implements ViewParent, } /** * The callback will run on the render thread. * Only call this on the UI Thread. */ void clearBlastSync() { mNextDrawUseBlastSync = false; mWaitForBlastSyncComplete = false; if (DEBUG_BLAST) { Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused + " due to a previous skipped traversal."); } if (mRequestedTraverseWhilePaused) { mRequestedTraverseWhilePaused = false; scheduleTraversals(); } } /** * @hide */ private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler, boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) { return frameNr -> { public boolean isHardwareEnabled() { return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); } private boolean addFrameCompleteCallbackIfNeeded(boolean reportNextDraw) { if (!isHardwareEnabled()) { return false; } if (!mNextDrawUseBlastSync && !reportNextDraw) { return false; } if (DEBUG_BLAST) { Log.d(mTag, "Creating frameCompleteCallback"); } mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> { long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum(); if (DEBUG_BLAST) { Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr); Log.d(mTag, "Received frameCompleteCallback " + " lastAcquiredFrameNum=" + frameNr + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum); } handler.postAtFrontOfQueue(() -> { boolean frameWasNotDrawn = frameNr != mRtLastAttemptedDrawFrameNum; // If frame wasn't drawn, clear out the next transaction so it doesn't affect the next // draw attempt. The next transaction and transaction complete callback were only set // for the current draw attempt. if (frameWasNotDrawn) { mBlastBufferQueue.setNextTransaction(null); mBlastBufferQueue.setTransactionCompleteCallback(mRtLastAttemptedDrawFrameNum, null); } mHandler.postAtFrontOfQueue(() -> { if (mNextDrawUseBlastSync) { // We don't need to synchronize mRtBLASTSyncTransaction here since we're // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync Loading @@ -3993,49 +4043,45 @@ public final class ViewRootImpl implements ViewParent, } if (reportNextDraw) { // TODO: Use the frame number pendingDrawFinished(); } if (commitCallbacks != null) { for (int i = 0; i < commitCallbacks.size(); i++) { commitCallbacks.get(i).run(); } if (frameWasNotDrawn) { clearBlastSync(); } }); }; } /** * @hide */ public boolean isHardwareEnabled() { return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); }); return true; } private boolean addFrameCompleteCallbackIfNeeded() { private void addFrameCommitCallbackIfNeeded() { if (!isHardwareEnabled()) { return false; return; } ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); final boolean needFrameCompleteCallback = mNextDrawUseBlastSync || mReportNextDraw || (commitCallbacks != null && commitCallbacks.size() > 0); if (needFrameCompleteCallback) { if (DEBUG_BLAST) { Log.d(mTag, "Creating frameCompleteCallback" + " mNextDrawUseBlastSync=" + mNextDrawUseBlastSync + " mReportNextDraw=" + mReportNextDraw + " commitCallbacks size=" + (commitCallbacks == null ? 0 : commitCallbacks.size())); } mAttachInfo.mThreadedRenderer.setFrameCompleteCallback( createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw, commitCallbacks)); return true; final boolean needFrameCommitCallback = (commitCallbacks != null && commitCallbacks.size() > 0); if (!needFrameCommitCallback) { return; } return false; if (DEBUG_DRAW) { Log.d(mTag, "Creating frameCommitCallback" + " commitCallbacks size=" + commitCallbacks.size()); } mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> { if (DEBUG_DRAW) { Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer); } mHandler.postAtFrontOfQueue(() -> { for (int i = 0; i < commitCallbacks.size(); i++) { commitCallbacks.get(i).run(); } }); }); } private void addFrameCallbackIfNeeded() { Loading Loading @@ -4065,6 +4111,8 @@ public final class ViewRootImpl implements ViewParent, + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync); } mRtLastAttemptedDrawFrameNum = frame; if (needsCallbackForBlur) { mBlurRegionAggregator .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates); Loading @@ -4087,18 +4135,7 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_BLAST) { Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame); } mHandler.postAtFrontOfQueue(() -> { mNextDrawUseBlastSync = false; mWaitForBlastSyncComplete = false; if (DEBUG_BLAST) { Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused + " due to a previous skipped traversal."); } if (mRequestedTraverseWhilePaused) { mRequestedTraverseWhilePaused = false; scheduleTraversals(); } }); mHandler.postAtFrontOfQueue(this::clearBlastSync); }); } else if (reportNextDraw) { // If we need to report next draw, wait for adapter to flush its shadow queue Loading @@ -4124,8 +4161,9 @@ public final class ViewRootImpl implements ViewParent, mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(); addFrameCallbackIfNeeded(); addFrameCommitCallbackIfNeeded(); boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(mReportNextDraw); try { boolean canUseAsync = draw(fullRedrawNeeded); Loading core/jni/android_graphics_BLASTBufferQueue.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -139,6 +139,11 @@ static void nativeSetTransactionCompleteCallback(JNIEnv* env, jclass clazz, jlon } } static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) { sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); return queue->getLastAcquiredFrameNum(); } static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ // clang-format off Loading @@ -151,7 +156,8 @@ static const JNINativeMethod gMethods[] = { {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction}, {"nativeSetTransactionCompleteCallback", "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V", (void*)nativeSetTransactionCompleteCallback} (void*)nativeSetTransactionCompleteCallback}, {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum}, // clang-format on }; Loading graphics/java/android/graphics/BLASTBufferQueue.java +4 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ public final class BLASTBufferQueue { long frameNumber); private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber, TransactionCompleteCallback callback); private static native long nativeGetLastAcquiredFrameNum(long ptr); /** * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)} Loading Loading @@ -145,4 +146,7 @@ public final class BLASTBufferQueue { nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber); } public long getLastAcquiredFrameNum() { return nativeGetLastAcquiredFrameNum(mNativeObject); } } graphics/java/android/graphics/HardwareRenderer.java +28 −5 Original line number Diff line number Diff line Loading @@ -388,7 +388,8 @@ public class HardwareRenderer { */ public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor, @NonNull Runnable frameCommitCallback) { setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback)); nSetFrameCommitCallback(mNativeProxy, didProduceBuffer -> executor.execute(frameCommitCallback)); return this; } Loading Loading @@ -608,6 +609,11 @@ public class HardwareRenderer { return mOpaque; } /** @hide */ public void setFrameCommitCallback(FrameCommitCallback callback) { nSetFrameCommitCallback(mNativeProxy, callback); } /** @hide */ public void setFrameCompleteCallback(FrameCompleteCallback callback) { nSetFrameCompleteCallback(mNativeProxy, callback); Loading Loading @@ -896,13 +902,27 @@ public class HardwareRenderer { * * @hide */ public interface FrameCompleteCallback { public interface FrameCommitCallback { /** * Invoked after a new frame was drawn * * @param didProduceBuffer The draw successfully produced a new buffer. */ void onFrameCommit(boolean didProduceBuffer); } /** * Invoked after a frame draw * Interface used to be notified when RenderThread has finished an attempt to draw. This doesn't * mean a new frame has drawn, specifically if there's nothing new to draw, but only that * RenderThread had a chance to draw a frame. * * @param frameNr The id of the frame that was drawn. * @hide */ void onFrameComplete(long frameNr); public interface FrameCompleteCallback { /** * Invoked after a frame draw was attempted. */ void onFrameComplete(); } /** Loading Loading @@ -1391,6 +1411,9 @@ public class HardwareRenderer { private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback); private static native void nSetFrameCommitCallback(long nativeProxy, FrameCommitCallback callback); private static native void nSetFrameCompleteCallback(long nativeProxy, FrameCompleteCallback callback); Loading libs/hwui/jni/android_graphics_HardwareRenderer.cpp +41 −13 Original line number Diff line number Diff line Loading @@ -72,6 +72,10 @@ struct { jmethodID onFrameDraw; } gFrameDrawingCallback; struct { jmethodID onFrameCommit; } gFrameCommitCallback; struct { jmethodID onFrameComplete; } gFrameCompleteCallback; Loading Loading @@ -101,22 +105,21 @@ private: JavaVM* mVm; }; class FrameCompleteWrapper : public LightRefBase<FrameCompleteWrapper> { class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> { public: explicit FrameCompleteWrapper(JNIEnv* env, jobject jobject) { explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) { env->GetJavaVM(&mVm); mObject = env->NewGlobalRef(jobject); LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref"); } ~FrameCompleteWrapper() { releaseObject(); } ~FrameCommitWrapper() { releaseObject(); } void onFrameComplete(int64_t frameNr) { void onFrameCommit(bool didProduceBuffer) { if (mObject) { ATRACE_FORMAT("frameComplete %" PRId64, frameNr); getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, frameNr); ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer); getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit, didProduceBuffer); releaseObject(); } } Loading Loading @@ -607,15 +610,33 @@ static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env, } } static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); if (!callback) { proxy->setFrameCommitCallback(nullptr); } else { sp<FrameCommitWrapper> wrapper = new FrameCommitWrapper{env, callback}; proxy->setFrameCommitCallback( [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); }); } } static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); if (!callback) { proxy->setFrameCompleteCallback(nullptr); } else { sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback}; proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) { wrapper->onFrameComplete(frameNr); RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); JavaVM* vm = nullptr; LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM"); auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback)); proxy->setFrameCompleteCallback([globalCallbackRef]() { JNIEnv* env = getenv(globalCallbackRef->vm()); env->CallVoidMethod(globalCallbackRef->object(), gFrameCompleteCallback.onFrameComplete); }); } } Loading Loading @@ -907,6 +928,8 @@ static const JNINativeMethod gMethods[] = { (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback}, {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCallback}, {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCommitCallback}, {"nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCompleteCallback}, Loading Loading @@ -974,10 +997,15 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) { gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass, "onFrameDraw", "(J)V"); jclass frameCommitClass = FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback"); gFrameCommitCallback.onFrameCommit = GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V"); jclass frameCompleteClass = FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCompleteCallback"); gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "(J)V"); gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V"); void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE); fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface"); Loading Loading
core/java/android/view/ViewRootImpl.java +88 −50 Original line number Diff line number Diff line Loading @@ -758,6 +758,12 @@ public final class ViewRootImpl implements ViewParent, */ private boolean mWaitForBlastSyncComplete = false; /** * Keeps track of the last frame number that was attempted to draw. Should only be accessed on * the RenderThread. */ private long mRtLastAttemptedDrawFrameNum = 0; /** * Keeps track of whether a traverse was triggered while the UI thread was paused. This can * occur when the client is waiting on another process to submit the transaction that Loading Loading @@ -3974,16 +3980,60 @@ public final class ViewRootImpl implements ViewParent, } /** * The callback will run on the render thread. * Only call this on the UI Thread. */ void clearBlastSync() { mNextDrawUseBlastSync = false; mWaitForBlastSyncComplete = false; if (DEBUG_BLAST) { Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused + " due to a previous skipped traversal."); } if (mRequestedTraverseWhilePaused) { mRequestedTraverseWhilePaused = false; scheduleTraversals(); } } /** * @hide */ private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler, boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) { return frameNr -> { public boolean isHardwareEnabled() { return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); } private boolean addFrameCompleteCallbackIfNeeded(boolean reportNextDraw) { if (!isHardwareEnabled()) { return false; } if (!mNextDrawUseBlastSync && !reportNextDraw) { return false; } if (DEBUG_BLAST) { Log.d(mTag, "Creating frameCompleteCallback"); } mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> { long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum(); if (DEBUG_BLAST) { Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr); Log.d(mTag, "Received frameCompleteCallback " + " lastAcquiredFrameNum=" + frameNr + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum); } handler.postAtFrontOfQueue(() -> { boolean frameWasNotDrawn = frameNr != mRtLastAttemptedDrawFrameNum; // If frame wasn't drawn, clear out the next transaction so it doesn't affect the next // draw attempt. The next transaction and transaction complete callback were only set // for the current draw attempt. if (frameWasNotDrawn) { mBlastBufferQueue.setNextTransaction(null); mBlastBufferQueue.setTransactionCompleteCallback(mRtLastAttemptedDrawFrameNum, null); } mHandler.postAtFrontOfQueue(() -> { if (mNextDrawUseBlastSync) { // We don't need to synchronize mRtBLASTSyncTransaction here since we're // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync Loading @@ -3993,49 +4043,45 @@ public final class ViewRootImpl implements ViewParent, } if (reportNextDraw) { // TODO: Use the frame number pendingDrawFinished(); } if (commitCallbacks != null) { for (int i = 0; i < commitCallbacks.size(); i++) { commitCallbacks.get(i).run(); } if (frameWasNotDrawn) { clearBlastSync(); } }); }; } /** * @hide */ public boolean isHardwareEnabled() { return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); }); return true; } private boolean addFrameCompleteCallbackIfNeeded() { private void addFrameCommitCallbackIfNeeded() { if (!isHardwareEnabled()) { return false; return; } ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); final boolean needFrameCompleteCallback = mNextDrawUseBlastSync || mReportNextDraw || (commitCallbacks != null && commitCallbacks.size() > 0); if (needFrameCompleteCallback) { if (DEBUG_BLAST) { Log.d(mTag, "Creating frameCompleteCallback" + " mNextDrawUseBlastSync=" + mNextDrawUseBlastSync + " mReportNextDraw=" + mReportNextDraw + " commitCallbacks size=" + (commitCallbacks == null ? 0 : commitCallbacks.size())); } mAttachInfo.mThreadedRenderer.setFrameCompleteCallback( createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw, commitCallbacks)); return true; final boolean needFrameCommitCallback = (commitCallbacks != null && commitCallbacks.size() > 0); if (!needFrameCommitCallback) { return; } return false; if (DEBUG_DRAW) { Log.d(mTag, "Creating frameCommitCallback" + " commitCallbacks size=" + commitCallbacks.size()); } mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> { if (DEBUG_DRAW) { Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer); } mHandler.postAtFrontOfQueue(() -> { for (int i = 0; i < commitCallbacks.size(); i++) { commitCallbacks.get(i).run(); } }); }); } private void addFrameCallbackIfNeeded() { Loading Loading @@ -4065,6 +4111,8 @@ public final class ViewRootImpl implements ViewParent, + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync); } mRtLastAttemptedDrawFrameNum = frame; if (needsCallbackForBlur) { mBlurRegionAggregator .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates); Loading @@ -4087,18 +4135,7 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_BLAST) { Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame); } mHandler.postAtFrontOfQueue(() -> { mNextDrawUseBlastSync = false; mWaitForBlastSyncComplete = false; if (DEBUG_BLAST) { Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused + " due to a previous skipped traversal."); } if (mRequestedTraverseWhilePaused) { mRequestedTraverseWhilePaused = false; scheduleTraversals(); } }); mHandler.postAtFrontOfQueue(this::clearBlastSync); }); } else if (reportNextDraw) { // If we need to report next draw, wait for adapter to flush its shadow queue Loading @@ -4124,8 +4161,9 @@ public final class ViewRootImpl implements ViewParent, mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(); addFrameCallbackIfNeeded(); addFrameCommitCallbackIfNeeded(); boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(mReportNextDraw); try { boolean canUseAsync = draw(fullRedrawNeeded); Loading
core/jni/android_graphics_BLASTBufferQueue.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -139,6 +139,11 @@ static void nativeSetTransactionCompleteCallback(JNIEnv* env, jclass clazz, jlon } } static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) { sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); return queue->getLastAcquiredFrameNum(); } static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ // clang-format off Loading @@ -151,7 +156,8 @@ static const JNINativeMethod gMethods[] = { {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction}, {"nativeSetTransactionCompleteCallback", "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V", (void*)nativeSetTransactionCompleteCallback} (void*)nativeSetTransactionCompleteCallback}, {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum}, // clang-format on }; Loading
graphics/java/android/graphics/BLASTBufferQueue.java +4 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ public final class BLASTBufferQueue { long frameNumber); private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber, TransactionCompleteCallback callback); private static native long nativeGetLastAcquiredFrameNum(long ptr); /** * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)} Loading Loading @@ -145,4 +146,7 @@ public final class BLASTBufferQueue { nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber); } public long getLastAcquiredFrameNum() { return nativeGetLastAcquiredFrameNum(mNativeObject); } }
graphics/java/android/graphics/HardwareRenderer.java +28 −5 Original line number Diff line number Diff line Loading @@ -388,7 +388,8 @@ public class HardwareRenderer { */ public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor, @NonNull Runnable frameCommitCallback) { setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback)); nSetFrameCommitCallback(mNativeProxy, didProduceBuffer -> executor.execute(frameCommitCallback)); return this; } Loading Loading @@ -608,6 +609,11 @@ public class HardwareRenderer { return mOpaque; } /** @hide */ public void setFrameCommitCallback(FrameCommitCallback callback) { nSetFrameCommitCallback(mNativeProxy, callback); } /** @hide */ public void setFrameCompleteCallback(FrameCompleteCallback callback) { nSetFrameCompleteCallback(mNativeProxy, callback); Loading Loading @@ -896,13 +902,27 @@ public class HardwareRenderer { * * @hide */ public interface FrameCompleteCallback { public interface FrameCommitCallback { /** * Invoked after a new frame was drawn * * @param didProduceBuffer The draw successfully produced a new buffer. */ void onFrameCommit(boolean didProduceBuffer); } /** * Invoked after a frame draw * Interface used to be notified when RenderThread has finished an attempt to draw. This doesn't * mean a new frame has drawn, specifically if there's nothing new to draw, but only that * RenderThread had a chance to draw a frame. * * @param frameNr The id of the frame that was drawn. * @hide */ void onFrameComplete(long frameNr); public interface FrameCompleteCallback { /** * Invoked after a frame draw was attempted. */ void onFrameComplete(); } /** Loading Loading @@ -1391,6 +1411,9 @@ public class HardwareRenderer { private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback); private static native void nSetFrameCommitCallback(long nativeProxy, FrameCommitCallback callback); private static native void nSetFrameCompleteCallback(long nativeProxy, FrameCompleteCallback callback); Loading
libs/hwui/jni/android_graphics_HardwareRenderer.cpp +41 −13 Original line number Diff line number Diff line Loading @@ -72,6 +72,10 @@ struct { jmethodID onFrameDraw; } gFrameDrawingCallback; struct { jmethodID onFrameCommit; } gFrameCommitCallback; struct { jmethodID onFrameComplete; } gFrameCompleteCallback; Loading Loading @@ -101,22 +105,21 @@ private: JavaVM* mVm; }; class FrameCompleteWrapper : public LightRefBase<FrameCompleteWrapper> { class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> { public: explicit FrameCompleteWrapper(JNIEnv* env, jobject jobject) { explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) { env->GetJavaVM(&mVm); mObject = env->NewGlobalRef(jobject); LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref"); } ~FrameCompleteWrapper() { releaseObject(); } ~FrameCommitWrapper() { releaseObject(); } void onFrameComplete(int64_t frameNr) { void onFrameCommit(bool didProduceBuffer) { if (mObject) { ATRACE_FORMAT("frameComplete %" PRId64, frameNr); getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, frameNr); ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer); getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit, didProduceBuffer); releaseObject(); } } Loading Loading @@ -607,15 +610,33 @@ static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env, } } static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); if (!callback) { proxy->setFrameCommitCallback(nullptr); } else { sp<FrameCommitWrapper> wrapper = new FrameCommitWrapper{env, callback}; proxy->setFrameCommitCallback( [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); }); } } static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); if (!callback) { proxy->setFrameCompleteCallback(nullptr); } else { sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback}; proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) { wrapper->onFrameComplete(frameNr); RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); JavaVM* vm = nullptr; LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM"); auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback)); proxy->setFrameCompleteCallback([globalCallbackRef]() { JNIEnv* env = getenv(globalCallbackRef->vm()); env->CallVoidMethod(globalCallbackRef->object(), gFrameCompleteCallback.onFrameComplete); }); } } Loading Loading @@ -907,6 +928,8 @@ static const JNINativeMethod gMethods[] = { (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback}, {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCallback}, {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCommitCallback}, {"nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCompleteCallback}, Loading Loading @@ -974,10 +997,15 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) { gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass, "onFrameDraw", "(J)V"); jclass frameCommitClass = FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback"); gFrameCommitCallback.onFrameCommit = GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V"); jclass frameCompleteClass = FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCompleteCallback"); gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "(J)V"); gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V"); void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE); fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface"); Loading