diff options
author | Mihai Popa <popam@google.com> | 2018-02-23 16:10:11 +0000 |
---|---|---|
committer | John Reck <jreck@google.com> | 2018-02-26 11:23:27 -0800 |
commit | 9568800d90e917e28ae2bc4ae1ca5dcaaf60675b (patch) | |
tree | 43cc506388f3c094741838b830964c35d48f0777 | |
parent | 99ef04f7173677ac52bf952979085e97e25f858c (diff) |
[Magnifier-26] Wire up frame callback for realsies
Test: none yet
Bug: 73810478
Bug: 72041926
Change-Id: I7154ed4b3d2cd820dc8c8ff55eed130be87d1606
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 5 | ||||
-rw-r--r-- | core/java/android/widget/Magnifier.java | 35 | ||||
-rw-r--r-- | core/jni/android_view_ThreadedRenderer.cpp | 49 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.h | 6 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 1 |
7 files changed, 90 insertions, 18 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 6da51d15e6ab..db19681840d7 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -1008,10 +1008,8 @@ public final class ThreadedRenderer { final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L; mFrameInfo.setVsync(vsync, vsync); mFrameInfo.addFlags(1 << 2 /* VSYNC */); - // TODO: remove this fence - nFence(mNativeProxy); if (callback != null) { - callback.onFrameDraw(mSurface.getNextFrameNumber()); + nSetFrameCallback(mNativeProxy, callback); } nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length); } @@ -1184,6 +1182,7 @@ public final class ThreadedRenderer { private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode); private static native void nSetContentDrawBounds(long nativeProxy, int left, int top, int right, int bottom); + private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback); private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer); private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver); diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index 64279655f799..68ce3d9cb2e1 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -471,12 +471,12 @@ public final class Magnifier { * Destroys this instance. */ public void destroy() { - mRenderer.destroy(); - mSurface.destroy(); - mSurfaceControl.destroy(); - mSurfaceSession.kill(); - mBitmapRenderNode.destroy(); synchronized (mLock) { + mRenderer.destroy(); + mSurface.destroy(); + mSurfaceControl.destroy(); + mSurfaceSession.kill(); + mBitmapRenderNode.destroy(); mHandler.removeCallbacks(mMagnifierUpdater); if (mBitmap != null) { mBitmap.recycle(); @@ -518,17 +518,22 @@ public final class Magnifier { final int pendingY = mWindowPositionY; callback = frame -> { - mRenderer.setLightCenter(mDisplay, pendingX, pendingY); - // Show or move the window at the content draw frame. - SurfaceControl.openTransaction(); - mSurfaceControl.deferTransactionUntil(mSurface, frame); - if (updateWindowPosition) { - mSurfaceControl.setPosition(pendingX, pendingY); - } - if (firstDraw) { - mSurfaceControl.show(); + synchronized (mLock) { + if (!mSurface.isValid()) { + return; + } + mRenderer.setLightCenter(mDisplay, pendingX, pendingY); + // Show or move the window at the content draw frame. + SurfaceControl.openTransaction(); + mSurfaceControl.deferTransactionUntil(mSurface, frame); + if (updateWindowPosition) { + mSurfaceControl.setPosition(pendingX, pendingY); + } + if (firstDraw) { + mSurfaceControl.show(); + } + SurfaceControl.closeTransaction(); } - SurfaceControl.closeTransaction(); }; } else { callback = null; diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 9f3475abe564..13e0e4a6bdb7 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -68,6 +68,10 @@ struct { jmethodID callback; } gFrameMetricsObserverClassInfo; +struct { + jmethodID onFrameDraw; +} gFrameDrawingCallback; + static JNIEnv* getenv(JavaVM* vm) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { @@ -849,6 +853,44 @@ static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env, proxy->setContentDrawBounds(left, top, right, bottom); } +class JGlobalRefHolder { +public: + JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {} + + virtual ~JGlobalRefHolder() { + getenv(mVm)->DeleteGlobalRef(mObject); + mObject = nullptr; + } + + jobject object() { return mObject; } + JavaVM* vm() { return mVm; } + +private: + JGlobalRefHolder(const JGlobalRefHolder&) = delete; + void operator=(const JGlobalRefHolder&) = delete; + + JavaVM* mVm; + jobject mObject; +}; + +static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env, + jobject clazz, jlong proxyPtr, jobject frameCallback) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + if (!frameCallback) { + proxy->setFrameCallback(nullptr); + } else { + 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(frameCallback)); + proxy->setFrameCallback([globalCallbackRef](int64_t frameNr) { + JNIEnv* env = getenv(globalCallbackRef->vm()); + env->CallVoidMethod(globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw, + static_cast<jlong>(frameNr)); + }); + } +} + static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env, jobject clazz, jobject jsurface, jint left, jint top, jint right, jint bottom, jobject jbitmap) { @@ -1034,6 +1076,8 @@ static const JNINativeMethod gMethods[] = { { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode}, { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode}, { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds}, + { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V", + (void*)android_view_ThreadedRenderer_setFrameCallback}, { "nAddFrameMetricsObserver", "(JLandroid/view/FrameMetricsObserver;)J", (void*)android_view_ThreadedRenderer_addFrameMetricsObserver }, @@ -1078,6 +1122,11 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) { gFrameMetricsObserverClassInfo.timingDataBuffer = GetFieldIDOrDie( env, metricsClass, "mTimingData", "[J"); + jclass frameCallbackClass = FindClassOrDie(env, + "android/view/ThreadedRenderer$FrameDrawingCallback"); + gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass, + "onFrameDraw", "(J)V"); + return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index 8372331c0352..778e7689d0f9 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -94,12 +94,20 @@ void DrawFrameTask::run() { // Grab a copy of everything we need CanvasContext* context = mContext; + std::function<void(int64_t)> callback = std::move(mFrameCallback); // From this point on anything in "this" is *UNSAFE TO ACCESS* if (canUnblockUiThread) { unblockUiThread(); } + // Even if we aren't drawing this vsync pulse the next frame number will still be accurate + if (CC_UNLIKELY(callback)) { + context->enqueueFrameWork([callback, frameNr = context->getFrameNumber()]() { + callback(frameNr); + }); + } + if (CC_LIKELY(canDrawThisFrame)) { context->draw(); } else { diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h index ea51ae4a42b7..d8c43e0d8ca8 100644 --- a/libs/hwui/renderthread/DrawFrameTask.h +++ b/libs/hwui/renderthread/DrawFrameTask.h @@ -74,6 +74,10 @@ public: void run(); + void setFrameCallback(std::function<void(int64_t)>&& callback) { + mFrameCallback = std::move(callback); + } + private: void postAndWait(); bool syncFrameState(TreeInfo& info); @@ -96,6 +100,8 @@ private: int64_t mSyncQueued; int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE]; + + std::function<void(int64_t)> mFrameCallback; }; } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 79e46ed9e65f..4be7a57daedf 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -270,6 +270,10 @@ void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) mDrawFrameTask.setContentDrawBounds(left, top, right, bottom); } +void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) { + mDrawFrameTask.setFrameCallback(std::move(callback)); +} + void RenderProxy::serializeDisplayListTree() { mRenderThread.queue().post([=]() { mContext->serializeDisplayListTree(); }); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index bc57d9255ad5..3425c5c68a72 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -115,6 +115,7 @@ public: ANDROID_API void removeRenderNode(RenderNode* node); ANDROID_API void drawRenderNode(RenderNode* node); ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom); + ANDROID_API void setFrameCallback(std::function<void(int64_t)>&& callback); ANDROID_API void addFrameMetricsObserver(FrameMetricsObserver* observer); ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer); |