diff options
Diffstat (limited to 'libs/hwui/WebViewFunctorManager.cpp')
-rw-r--r-- | libs/hwui/WebViewFunctorManager.cpp | 145 |
1 files changed, 143 insertions, 2 deletions
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp index 68541b4b31f0..974c8635b3df 100644 --- a/libs/hwui/WebViewFunctorManager.cpp +++ b/libs/hwui/WebViewFunctorManager.cpp @@ -18,6 +18,7 @@ #include <private/hwui/WebViewFunctor.h> #include "Properties.h" +#include "renderthread/CanvasContext.h" #include "renderthread/RenderThread.h" #include <log/log.h> @@ -26,6 +27,35 @@ namespace android::uirenderer { +namespace { +class ScopedCurrentFunctor { +public: + ScopedCurrentFunctor(WebViewFunctor* functor) { + ALOG_ASSERT(!sCurrentFunctor); + ALOG_ASSERT(functor); + sCurrentFunctor = functor; + } + ~ScopedCurrentFunctor() { + ALOG_ASSERT(sCurrentFunctor); + sCurrentFunctor = nullptr; + } + + static ASurfaceControl* getSurfaceControl() { + ALOG_ASSERT(sCurrentFunctor); + return sCurrentFunctor->getSurfaceControl(); + } + static void mergeTransaction(ASurfaceTransaction* transaction) { + ALOG_ASSERT(sCurrentFunctor); + sCurrentFunctor->mergeTransaction(transaction); + } + +private: + static WebViewFunctor* sCurrentFunctor; +}; + +WebViewFunctor* ScopedCurrentFunctor::sCurrentFunctor = nullptr; +} // namespace + RenderMode WebViewFunctor_queryPlatformRenderMode() { auto pipelineType = Properties::getRenderPipelineType(); switch (pipelineType) { @@ -83,7 +113,31 @@ void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { if (!mHasContext) { mHasContext = true; } - mCallbacks.gles.draw(mFunctor, mData, drawInfo); + ScopedCurrentFunctor currentFunctor(this); + + WebViewOverlayData overlayParams = { + .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; + int32_t rgid = activeContext->getSurfaceControlGenerationId(); + if (mParentSurfaceControlGenerationId != rgid) { + reparentSurfaceControl(rootSurfaceControl); + mParentSurfaceControlGenerationId = rgid; + } + } + } + } + + mCallbacks.gles.draw(mFunctor, mData, drawInfo, overlayParams); } void WebViewFunctor::initVk(const VkFunctorInitParams& params) { @@ -98,7 +152,16 @@ void WebViewFunctor::initVk(const VkFunctorInitParams& params) { void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) { ATRACE_NAME("WebViewFunctor::drawVk"); - mCallbacks.vk.draw(mFunctor, mData, params); + ScopedCurrentFunctor currentFunctor(this); + + WebViewOverlayData overlayParams = { + .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); } void WebViewFunctor::postDrawVk() { @@ -118,13 +181,91 @@ 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() { + 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(); + mParentSurfaceControlGenerationId = activeContext->getSurfaceControlGenerationId(); + mSurfaceControl = funcs.createFunc(rootSurfaceControl, "Webview Overlay SurfaceControl"); + ASurfaceTransaction* transaction = funcs.transactionCreateFunc(); + activeContext->prepareSurfaceControlForWebview(); + funcs.transactionSetZOrderFunc(transaction, mSurfaceControl, -1); + funcs.transactionSetVisibilityFunc(transaction, mSurfaceControl, + ASURFACE_TRANSACTION_VISIBILITY_SHOW); + funcs.transactionApplyFunc(transaction); + funcs.transactionDeleteFunc(transaction); + return mSurfaceControl; +} + +void WebViewFunctor::mergeTransaction(ASurfaceTransaction* transaction) { + 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); + } +} + +void WebViewFunctor::reparentSurfaceControl(ASurfaceControl* parent) { + ATRACE_NAME("WebViewFunctor::reparentSurfaceControl"); + if (mSurfaceControl == nullptr) return; + + auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions(); + ASurfaceTransaction* transaction = funcs.transactionCreateFunc(); + funcs.transactionReparentFunc(transaction, mSurfaceControl, parent); + mergeTransaction(transaction); + funcs.transactionDeleteFunc(transaction); +} + WebViewFunctorManager& WebViewFunctorManager::instance() { static WebViewFunctorManager sInstance; return sInstance; } +static void validateCallbacks(const WebViewFunctorCallbacks& callbacks) { + // TODO: Should we do a stack peek to see if this is really webview? + LOG_ALWAYS_FATAL_IF(callbacks.onSync == nullptr, "onSync is null"); + LOG_ALWAYS_FATAL_IF(callbacks.onContextDestroyed == nullptr, "onContextDestroyed is null"); + LOG_ALWAYS_FATAL_IF(callbacks.onDestroyed == nullptr, "onDestroyed is null"); + LOG_ALWAYS_FATAL_IF(callbacks.removeOverlays == nullptr, "removeOverlays is null"); + switch (auto mode = WebViewFunctor_queryPlatformRenderMode()) { + case RenderMode::OpenGL_ES: + LOG_ALWAYS_FATAL_IF(callbacks.gles.draw == nullptr, "gles.draw is null"); + break; + case RenderMode::Vulkan: + LOG_ALWAYS_FATAL_IF(callbacks.vk.initialize == nullptr, "vk.initialize is null"); + LOG_ALWAYS_FATAL_IF(callbacks.vk.draw == nullptr, "vk.draw is null"); + LOG_ALWAYS_FATAL_IF(callbacks.vk.postDraw == nullptr, "vk.postDraw is null"); + break; + default: + LOG_ALWAYS_FATAL("unknown platform mode? %d", (int)mode); + break; + } +} + int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks, RenderMode functorMode) { + validateCallbacks(callbacks); auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode); int id = object->id(); auto handle = object->createHandle(); |