diff options
Diffstat (limited to 'libs/hwui/WebViewFunctorManager.cpp')
-rw-r--r-- | libs/hwui/WebViewFunctorManager.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp new file mode 100644 index 000000000000..20e77b453706 --- /dev/null +++ b/libs/hwui/WebViewFunctorManager.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WebViewFunctorManager.h" + +#include <private/hwui/WebViewFunctor.h> +#include "Properties.h" + +#include <log/log.h> +#include <utils/Trace.h> +#include <atomic> + +namespace android::uirenderer { + +RenderMode WebViewFunctor_queryPlatformRenderMode() { + auto pipelineType = Properties::getRenderPipelineType(); + switch (pipelineType) { + case RenderPipelineType::SkiaGL: + return RenderMode::OpenGL_ES; + case RenderPipelineType::SkiaVulkan: + return RenderMode::Vulkan; + default: + LOG_ALWAYS_FATAL("Unknown render pipeline type: %d", (int)pipelineType); + } +} + +int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode functorMode) { + if (functorMode != RenderMode::OpenGL_ES && functorMode != RenderMode::Vulkan) { + ALOGW("Unknown rendermode %d", (int)functorMode); + return -1; + } + if (functorMode == RenderMode::Vulkan && + WebViewFunctor_queryPlatformRenderMode() != RenderMode::Vulkan) { + ALOGW("Unable to map from GLES platform to a vulkan functor"); + return -1; + } + return WebViewFunctorManager::instance().createFunctor(prototype, functorMode); +} + +void WebViewFunctor_release(int functor) { + WebViewFunctorManager::instance().releaseFunctor(functor); +} + +static std::atomic_int sNextId{1}; + +WebViewFunctor::WebViewFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode) { + mFunctor = sNextId++; + mCallbacks = callbacks; + mMode = functorMode; +} + +WebViewFunctor::~WebViewFunctor() { + destroyContext(); + + ATRACE_NAME("WebViewFunctor::onDestroy"); + mCallbacks.onDestroyed(mFunctor); +} + +void WebViewFunctor::sync(const WebViewSyncData& syncData) const { + ATRACE_NAME("WebViewFunctor::sync"); + mCallbacks.onSync(mFunctor, syncData); +} + +void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { + ATRACE_NAME("WebViewFunctor::drawGl"); + if (!mHasContext) { + mHasContext = true; + } + mCallbacks.gles.draw(mFunctor, drawInfo); +} + +void WebViewFunctor::destroyContext() { + if (mHasContext) { + mHasContext = false; + ATRACE_NAME("WebViewFunctor::onContextDestroyed"); + mCallbacks.onContextDestroyed(mFunctor); + } +} + +WebViewFunctorManager& WebViewFunctorManager::instance() { + static WebViewFunctorManager sInstance; + return sInstance; +} + +int WebViewFunctorManager::createFunctor(const WebViewFunctorCallbacks& callbacks, + RenderMode functorMode) { + auto object = std::make_unique<WebViewFunctor>(callbacks, functorMode); + int id = object->id(); + auto handle = object->createHandle(); + { + std::lock_guard _lock{mLock}; + mActiveFunctors.push_back(std::move(handle)); + mFunctors.push_back(std::move(object)); + } + return id; +} + +void WebViewFunctorManager::releaseFunctor(int functor) { + sp<WebViewFunctor::Handle> toRelease; + { + std::lock_guard _lock{mLock}; + for (auto iter = mActiveFunctors.begin(); iter != mActiveFunctors.end(); iter++) { + if ((*iter)->id() == functor) { + toRelease = std::move(*iter); + mActiveFunctors.erase(iter); + break; + } + } + } +} + +void WebViewFunctorManager::onContextDestroyed() { + // WARNING: SKETCHY + // Because we know that we always remove from mFunctors on RenderThread, the same + // thread that always invokes onContextDestroyed, we know that the functor pointers + // will remain valid without the lock held. + // However, we won't block new functors from being added in the meantime. + mLock.lock(); + const size_t size = mFunctors.size(); + WebViewFunctor* toDestroyContext[size]; + for (size_t i = 0; i < size; i++) { + toDestroyContext[i] = mFunctors[i].get(); + } + mLock.unlock(); + for (size_t i = 0; i < size; i++) { + toDestroyContext[i]->destroyContext(); + } +} + +void WebViewFunctorManager::destroyFunctor(int functor) { + std::unique_ptr<WebViewFunctor> toRelease; + { + std::lock_guard _lock{mLock}; + for (auto iter = mFunctors.begin(); iter != mFunctors.end(); iter++) { + if ((*iter)->id() == functor) { + toRelease = std::move(*iter); + mFunctors.erase(iter); + break; + } + } + } +} + +sp<WebViewFunctor::Handle> WebViewFunctorManager::handleFor(int functor) { + std::lock_guard _lock{mLock}; + for (auto& iter : mActiveFunctors) { + if (iter->id() == functor) { + return iter; + } + } + return nullptr; +} + +} // namespace android::uirenderer
\ No newline at end of file |