diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 2c81e8986ac6b..4977a6e59ede7 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -2595,6 +2595,16 @@ public final class SurfaceControl implements Parcelable { = sRegistry.registerNativeAllocation(this, mNativeObject); } + /** + * Create a transaction object that wraps a native peer. + * @hide + */ + Transaction(long nativeObject) { + mNativeObject = nativeObject; + mFreeNativeResources = + sRegistry.registerNativeAllocation(this, mNativeObject); + } + private Transaction(Parcel in) { readFromParcel(in); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index be8e51980c3ce..3cfda571ae6a6 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1355,6 +1355,16 @@ public final class ViewRootImpl implements ViewParent, } } + private void addASurfaceTransactionCallback() { + HardwareRenderer.ASurfaceTransactionCallback callback = (nativeTransactionObj, + nativeSurfaceControlObj, + frameNr) -> { + Transaction t = new Transaction(nativeTransactionObj); + mergeWithNextTransaction(t, frameNr); + }; + mAttachInfo.mThreadedRenderer.setASurfaceTransactionCallback(callback); + } + @UnsupportedAppUsage private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) { mAttachInfo.mHardwareAccelerated = false; @@ -1391,6 +1401,7 @@ public final class ViewRootImpl implements ViewParent, final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets; mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent, attrs.getTitle().toString()); + addASurfaceTransactionCallback(); mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl); updateColorModeIfNeeded(attrs.getColorMode()); updateForceDarkMode(); diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index f3dba82287abc..8f1223b5eeaff 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -753,6 +753,11 @@ public class HardwareRenderer { nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater()); } + /** @hide */ + public void setASurfaceTransactionCallback(ASurfaceTransactionCallback callback) { + nSetASurfaceTransactionCallback(mNativeProxy, callback); + } + /** @hide */ public void setFrameCallback(FrameDrawingCallback callback) { nSetFrameCallback(mNativeProxy, callback); @@ -867,6 +872,23 @@ public class HardwareRenderer { session.close(); } + /** + * Interface used to receive callbacks when a transaction needs to be merged. + * + * @hide + */ + public interface ASurfaceTransactionCallback { + /** + * Invoked during a frame drawing. + * + * @param aSurfaceTranactionNativeObj the ASurfaceTransaction native object handle + * @param aSurfaceControlNativeObj ASurfaceControl native object handle + * @param frame The id of the frame being drawn. + */ + void onMergeTransaction(long aSurfaceTranactionNativeObj, + long aSurfaceControlNativeObj, long frame); + } + /** * Interface used to receive callbacks when a frame is being drawn. * @@ -1342,6 +1364,9 @@ public class HardwareRenderer { private static native void nSetPictureCaptureCallback(long nativeProxy, PictureCapturedCallback callback); + private static native void nSetASurfaceTransactionCallback(long nativeProxy, + ASurfaceTransactionCallback callback); + private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback); private static native void nSetFrameCompleteCallback(long nativeProxy, diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp index 671c66f11e321..979678d1c4b62 100644 --- a/libs/hwui/WebViewFunctorManager.cpp +++ b/libs/hwui/WebViewFunctorManager.cpp @@ -18,6 +18,7 @@ #include #include "Properties.h" +#include "renderthread/CanvasContext.h" #include "renderthread/RenderThread.h" #include @@ -115,11 +116,20 @@ void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { ScopedCurrentFunctor currentFunctor(this); WebViewOverlayData overlayParams = { - // TODO: .overlaysMode = OverlaysMode::Disabled, .getSurfaceControl = currentFunctor.getSurfaceControl, .mergeTransaction = currentFunctor.mergeTransaction, }; + + if (!drawInfo.isLayer) { + renderthread::CanvasContext* activeContext = + renderthread::CanvasContext::getActiveContext(); + if (activeContext != nullptr) { + ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl(); + if (rootSurfaceControl) overlayParams.overlaysMode = OverlaysMode::Enabled; + } + } + mCallbacks.gles.draw(mFunctor, mData, drawInfo, overlayParams); } @@ -138,11 +148,12 @@ void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) { ScopedCurrentFunctor currentFunctor(this); WebViewOverlayData overlayParams = { - // TODO .overlaysMode = OverlaysMode::Disabled, .getSurfaceControl = currentFunctor.getSurfaceControl, .mergeTransaction = currentFunctor.mergeTransaction, }; + + // TODO, enable surface control once offscreen mode figured out mCallbacks.vk.draw(mFunctor, mData, params, overlayParams); } @@ -166,15 +177,43 @@ void WebViewFunctor::destroyContext() { void WebViewFunctor::removeOverlays() { ScopedCurrentFunctor currentFunctor(this); mCallbacks.removeOverlays(mFunctor, mData, currentFunctor.mergeTransaction); + if (mSurfaceControl) { + auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions(); + funcs.releaseFunc(mSurfaceControl); + mSurfaceControl = nullptr; + } } ASurfaceControl* WebViewFunctor::getSurfaceControl() { - // TODO - return nullptr; + ATRACE_NAME("WebViewFunctor::getSurfaceControl"); + if (mSurfaceControl != nullptr) return mSurfaceControl; + + renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext(); + LOG_ALWAYS_FATAL_IF(activeContext == nullptr, "Null active canvas context!"); + + ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl(); + LOG_ALWAYS_FATAL_IF(rootSurfaceControl == nullptr, "Null root surface control!"); + + auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions(); + mSurfaceControl = funcs.createFunc(rootSurfaceControl, "Webview Overlay SurfaceControl"); + ASurfaceTransaction* transaction = funcs.transactionCreateFunc(); + funcs.transactionSetVisibilityFunc(transaction, mSurfaceControl, + ASURFACE_TRANSACTION_VISIBILITY_SHOW); + funcs.transactionApplyFunc(transaction); + funcs.transactionDeleteFunc(transaction); + return mSurfaceControl; } void WebViewFunctor::mergeTransaction(ASurfaceTransaction* transaction) { - // TODO + ATRACE_NAME("WebViewFunctor::mergeTransaction"); + if (transaction == nullptr) return; + renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext(); + LOG_ALWAYS_FATAL_IF(activeContext == nullptr, "Null active canvas context!"); + bool done = activeContext->mergeTransaction(transaction, mSurfaceControl); + if (!done) { + auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions(); + funcs.transactionApplyFunc(transaction); + } } WebViewFunctorManager& WebViewFunctorManager::instance() { diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h index 17b936ade45cd..a84cda5505677 100644 --- a/libs/hwui/WebViewFunctorManager.h +++ b/libs/hwui/WebViewFunctorManager.h @@ -91,6 +91,7 @@ private: RenderMode mMode; bool mHasContext = false; bool mCreatedHandle = false; + ASurfaceControl* mSurfaceControl = nullptr; }; class WebViewFunctorManager { diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index d85954116dd1b..dd78d58693147 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -63,6 +63,10 @@ struct { jmethodID closeHintSession; } gHardwareRenderer; +struct { + jmethodID onMergeTransaction; +} gASurfaceTransactionCallback; + struct { jmethodID onFrameDraw; } gFrameDrawingCallback; @@ -509,6 +513,27 @@ static void android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv* } } +static void android_view_ThreadedRenderer_setASurfaceTransactionCallback( + JNIEnv* env, jobject clazz, jlong proxyPtr, jobject aSurfaceTransactionCallback) { + RenderProxy* proxy = reinterpret_cast(proxyPtr); + if (!aSurfaceTransactionCallback) { + proxy->setASurfaceTransactionCallback(nullptr); + } else { + JavaVM* vm = nullptr; + LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM"); + auto globalCallbackRef = std::make_shared( + vm, env->NewGlobalRef(aSurfaceTransactionCallback)); + proxy->setASurfaceTransactionCallback( + [globalCallbackRef](int64_t transObj, int64_t scObj, int64_t frameNr) { + JNIEnv* env = getenv(globalCallbackRef->vm()); + env->CallVoidMethod(globalCallbackRef->object(), + gASurfaceTransactionCallback.onMergeTransaction, + static_cast(transObj), static_cast(scObj), + static_cast(frameNr)); + }); + } +} + static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject frameCallback) { RenderProxy* proxy = reinterpret_cast(proxyPtr); @@ -762,8 +787,7 @@ static const JNINativeMethod gMethods[] = { {"nSetName", "(JLjava/lang/String;)V", (void*)android_view_ThreadedRenderer_setName}, {"nSetSurface", "(JLandroid/view/Surface;Z)V", (void*)android_view_ThreadedRenderer_setSurface}, - {"nSetSurfaceControl", "(JJ)V", - (void*)android_view_ThreadedRenderer_setSurfaceControl}, + {"nSetSurfaceControl", "(JJ)V", (void*)android_view_ThreadedRenderer_setSurfaceControl}, {"nPause", "(J)Z", (void*)android_view_ThreadedRenderer_pause}, {"nSetStopped", "(JZ)V", (void*)android_view_ThreadedRenderer_setStopped}, {"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha}, @@ -804,6 +828,9 @@ static const JNINativeMethod gMethods[] = { {"nSetPictureCaptureCallback", "(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V", (void*)android_view_ThreadedRenderer_setPictureCapturedCallbackJNI}, + {"nSetASurfaceTransactionCallback", + "(JLandroid/graphics/HardwareRenderer$ASurfaceTransactionCallback;)V", + (void*)android_view_ThreadedRenderer_setASurfaceTransactionCallback}, {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCallback}, {"nSetFrameCompleteCallback", @@ -866,6 +893,11 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) { GetStaticMethodIDOrDie(env, hardwareRenderer, "closeHintSession", "(Landroid/os/PerformanceHintManager$Session;)V"); + jclass aSurfaceTransactionCallbackClass = + FindClassOrDie(env, "android/graphics/HardwareRenderer$ASurfaceTransactionCallback"); + gASurfaceTransactionCallback.onMergeTransaction = + GetMethodIDOrDie(env, aSurfaceTransactionCallbackClass, "onMergeTransaction", "(JJJ)V"); + jclass frameCallbackClass = FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameDrawingCallback"); gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass, diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 24821888e2ebd..bba22071ecefd 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -56,6 +56,22 @@ namespace android { namespace uirenderer { namespace renderthread { +namespace { +class ScopedActiveContext { +public: + ScopedActiveContext(CanvasContext* context) { sActiveContext = context; } + + ~ScopedActiveContext() { sActiveContext = nullptr; } + + static CanvasContext* getActiveContext() { return sActiveContext; } + +private: + static CanvasContext* sActiveContext; +}; + +CanvasContext* ScopedActiveContext::sActiveContext = nullptr; +} /* namespace */ + CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory) { auto renderType = Properties::getRenderPipelineType(); @@ -473,6 +489,7 @@ void CanvasContext::draw() { return; } + ScopedActiveContext activeContext(this); mCurrentFrameInfo->set(FrameInfoIndex::FrameInterval) = mRenderThread.timeLord().frameIntervalNanos(); @@ -880,6 +897,17 @@ SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) { return windowDirty; } +CanvasContext* CanvasContext::getActiveContext() { + return ScopedActiveContext::getActiveContext(); +} + +bool CanvasContext::mergeTransaction(ASurfaceTransaction* transaction, ASurfaceControl* control) { + if (!mASurfaceTransactionCallback) return false; + std::invoke(mASurfaceTransactionCallback, reinterpret_cast(transaction), + reinterpret_cast(control), getFrameNumber()); + return true; +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 74f426ead9123..af1ebb288f214 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -109,6 +109,8 @@ public: */ GrDirectContext* getGrContext() const { return mRenderThread.getGrContext(); } + ASurfaceControl* getSurfaceControl() const { return mSurfaceControl; } + // Won't take effect until next EGLSurface creation void setSwapBehavior(SwapBehavior swapBehavior); @@ -201,6 +203,15 @@ public: static void onSurfaceStatsAvailable(void* context, ASurfaceControl* control, ASurfaceControlStats* stats); + void setASurfaceTransactionCallback( + const std::function& callback) { + mASurfaceTransactionCallback = callback; + } + + bool mergeTransaction(ASurfaceTransaction* transaction, ASurfaceControl* control); + + static CanvasContext* getActiveContext(); + private: CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode, IContextFactory* contextFactory, std::unique_ptr renderPipeline); @@ -296,6 +307,8 @@ private: // If set to true, we expect that callbacks into onSurfaceStatsAvailable bool mExpectSurfaceStats = false; + + std::function mASurfaceTransactionCallback; }; } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 9361abd208525..1b4b4b999f687 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -295,6 +295,12 @@ void RenderProxy::setPictureCapturedCallback( [this, cb = callback]() { mContext->setPictureCapturedCallback(cb); }); } +void RenderProxy::setASurfaceTransactionCallback( + const std::function& callback) { + mRenderThread.queue().post( + [this, cb = callback]() { mContext->setASurfaceTransactionCallback(cb); }); +} + void RenderProxy::setFrameCallback(std::function&& callback) { mDrawFrameTask.setFrameCallback(std::move(callback)); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 8d55d3c55570e..288f5554f65aa 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -120,6 +120,8 @@ public: void drawRenderNode(RenderNode* node); void setContentDrawBounds(int left, int top, int right, int bottom); void setPictureCapturedCallback(const std::function&&)>& callback); + void setASurfaceTransactionCallback( + const std::function& callback); void setFrameCallback(std::function&& callback); void setFrameCompleteCallback(std::function&& callback); diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 682baa60a2075..04aa1cb91492d 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -54,6 +54,10 @@ static JVMAttachHook gOnStartHook = nullptr; ASurfaceControlFunctions::ASurfaceControlFunctions() { void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE); + createFunc = (ASC_create)dlsym(handle_, "ASurfaceControl_create"); + LOG_ALWAYS_FATAL_IF(createFunc == nullptr, + "Failed to find required symbol ASurfaceControl_create!"); + acquireFunc = (ASC_acquire) dlsym(handle_, "ASurfaceControl_acquire"); LOG_ALWAYS_FATAL_IF(acquireFunc == nullptr, "Failed to find required symbol ASurfaceControl_acquire!"); @@ -81,6 +85,23 @@ ASurfaceControlFunctions::ASurfaceControlFunctions() { "ASurfaceControlStats_getFrameNumber"); LOG_ALWAYS_FATAL_IF(getFrameNumberFunc == nullptr, "Failed to find required symbol ASurfaceControlStats_getFrameNumber!"); + + transactionCreateFunc = (AST_create)dlsym(handle_, "ASurfaceTransaction_create"); + LOG_ALWAYS_FATAL_IF(transactionCreateFunc == nullptr, + "Failed to find required symbol ASurfaceTransaction_create!"); + + transactionDeleteFunc = (AST_delete)dlsym(handle_, "ASurfaceTransaction_delete"); + LOG_ALWAYS_FATAL_IF(transactionDeleteFunc == nullptr, + "Failed to find required symbol ASurfaceTransaction_delete!"); + + transactionApplyFunc = (AST_apply)dlsym(handle_, "ASurfaceTransaction_apply"); + LOG_ALWAYS_FATAL_IF(transactionApplyFunc == nullptr, + "Failed to find required symbol ASurfaceTransaction_apply!"); + + transactionSetVisibilityFunc = + (AST_setVisibility)dlsym(handle_, "ASurfaceTransaction_setVisibility"); + LOG_ALWAYS_FATAL_IF(transactionSetVisibilityFunc == nullptr, + "Failed to find required symbol ASurfaceTransaction_setVisibility!"); } void RenderThread::frameCallback(int64_t frameTimeNanos, void* data) { diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 9e5bce76e228f..cd9b923f4b3a9 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -79,25 +79,39 @@ struct VsyncSource { virtual ~VsyncSource() {} }; +typedef ASurfaceControl* (*ASC_create)(ASurfaceControl* parent, const char* debug_name); typedef void (*ASC_acquire)(ASurfaceControl* control); typedef void (*ASC_release)(ASurfaceControl* control); typedef void (*ASC_registerSurfaceStatsListener)(ASurfaceControl* control, void* context, ASurfaceControl_SurfaceStatsListener func); typedef void (*ASC_unregisterSurfaceStatsListener)(void* context, - ASurfaceControl_SurfaceStatsListener func); + ASurfaceControl_SurfaceStatsListener func); typedef int64_t (*ASCStats_getAcquireTime)(ASurfaceControlStats* stats); typedef uint64_t (*ASCStats_getFrameNumber)(ASurfaceControlStats* stats); +typedef ASurfaceTransaction* (*AST_create)(); +typedef void (*AST_delete)(ASurfaceTransaction* transaction); +typedef void (*AST_apply)(ASurfaceTransaction* transaction); +typedef void (*AST_setVisibility)(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, int8_t visibility); + struct ASurfaceControlFunctions { ASurfaceControlFunctions(); + + ASC_create createFunc; ASC_acquire acquireFunc; ASC_release releaseFunc; ASC_registerSurfaceStatsListener registerListenerFunc; ASC_unregisterSurfaceStatsListener unregisterListenerFunc; ASCStats_getAcquireTime getAcquireTimeFunc; ASCStats_getFrameNumber getFrameNumberFunc; + + AST_create transactionCreateFunc; + AST_delete transactionDeleteFunc; + AST_apply transactionApplyFunc; + AST_setVisibility transactionSetVisibilityFunc; }; class ChoreographerSource;