1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "WebViewFunctorManager.h" 18 19 #include <private/hwui/WebViewFunctor.h> 20 #include "Properties.h" 21 #include "renderthread/RenderThread.h" 22 23 #include <log/log.h> 24 #include <utils/Trace.h> 25 #include <atomic> 26 27 namespace android::uirenderer { 28 29 RenderMode WebViewFunctor_queryPlatformRenderMode() { 30 auto pipelineType = Properties::getRenderPipelineType(); 31 switch (pipelineType) { 32 case RenderPipelineType::SkiaGL: 33 return RenderMode::OpenGL_ES; 34 case RenderPipelineType::SkiaVulkan: 35 return RenderMode::Vulkan; 36 default: 37 LOG_ALWAYS_FATAL("Unknown render pipeline type: %d", (int)pipelineType); 38 } 39 } 40 41 int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype, 42 RenderMode functorMode) { 43 if (functorMode != RenderMode::OpenGL_ES && functorMode != RenderMode::Vulkan) { 44 ALOGW("Unknown rendermode %d", (int)functorMode); 45 return -1; 46 } 47 if (functorMode == RenderMode::Vulkan && 48 WebViewFunctor_queryPlatformRenderMode() != RenderMode::Vulkan) { 49 ALOGW("Unable to map from GLES platform to a vulkan functor"); 50 return -1; 51 } 52 return WebViewFunctorManager::instance().createFunctor(data, prototype, functorMode); 53 } 54 55 void WebViewFunctor_release(int functor) { 56 WebViewFunctorManager::instance().releaseFunctor(functor); 57 } 58 59 static std::atomic_int sNextId{1}; 60 61 WebViewFunctor::WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks, 62 RenderMode functorMode) 63 : mData(data) { 64 mFunctor = sNextId++; 65 mCallbacks = callbacks; 66 mMode = functorMode; 67 } 68 69 WebViewFunctor::~WebViewFunctor() { 70 destroyContext(); 71 72 ATRACE_NAME("WebViewFunctor::onDestroy"); 73 mCallbacks.onDestroyed(mFunctor, mData); 74 } 75 76 void WebViewFunctor::sync(const WebViewSyncData& syncData) const { 77 ATRACE_NAME("WebViewFunctor::sync"); 78 mCallbacks.onSync(mFunctor, mData, syncData); 79 } 80 81 void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { 82 ATRACE_NAME("WebViewFunctor::drawGl"); 83 if (!mHasContext) { 84 mHasContext = true; 85 } 86 mCallbacks.gles.draw(mFunctor, mData, drawInfo); 87 } 88 89 void WebViewFunctor::initVk(const VkFunctorInitParams& params) { 90 ATRACE_NAME("WebViewFunctor::initVk"); 91 if (!mHasContext) { 92 mHasContext = true; 93 } else { 94 return; 95 } 96 mCallbacks.vk.initialize(mFunctor, mData, params); 97 } 98 99 void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) { 100 ATRACE_NAME("WebViewFunctor::drawVk"); 101 mCallbacks.vk.draw(mFunctor, mData, params); 102 } 103 104 void WebViewFunctor::postDrawVk() { 105 ATRACE_NAME("WebViewFunctor::postDrawVk"); 106 mCallbacks.vk.postDraw(mFunctor, mData); 107 } 108 109 void WebViewFunctor::destroyContext() { 110 if (mHasContext) { 111 mHasContext = false; 112 ATRACE_NAME("WebViewFunctor::onContextDestroyed"); 113 mCallbacks.onContextDestroyed(mFunctor, mData); 114 115 // grContext may be null in unit tests. 116 auto* grContext = renderthread::RenderThread::getInstance().getGrContext(); 117 if (grContext) grContext->resetContext(); 118 } 119 } 120 121 WebViewFunctorManager& WebViewFunctorManager::instance() { 122 static WebViewFunctorManager sInstance; 123 return sInstance; 124 } 125 126 int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks, 127 RenderMode functorMode) { 128 auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode); 129 int id = object->id(); 130 auto handle = object->createHandle(); 131 { 132 std::lock_guard _lock{mLock}; 133 mActiveFunctors.push_back(std::move(handle)); 134 mFunctors.push_back(std::move(object)); 135 } 136 return id; 137 } 138 139 void WebViewFunctorManager::releaseFunctor(int functor) { 140 sp<WebViewFunctor::Handle> toRelease; 141 { 142 std::lock_guard _lock{mLock}; 143 for (auto iter = mActiveFunctors.begin(); iter != mActiveFunctors.end(); iter++) { 144 if ((*iter)->id() == functor) { 145 toRelease = std::move(*iter); 146 mActiveFunctors.erase(iter); 147 break; 148 } 149 } 150 } 151 } 152 153 void WebViewFunctorManager::onContextDestroyed() { 154 // WARNING: SKETCHY 155 // Because we know that we always remove from mFunctors on RenderThread, the same 156 // thread that always invokes onContextDestroyed, we know that the functor pointers 157 // will remain valid without the lock held. 158 // However, we won't block new functors from being added in the meantime. 159 mLock.lock(); 160 const size_t size = mFunctors.size(); 161 WebViewFunctor* toDestroyContext[size]; 162 for (size_t i = 0; i < size; i++) { 163 toDestroyContext[i] = mFunctors[i].get(); 164 } 165 mLock.unlock(); 166 for (size_t i = 0; i < size; i++) { 167 toDestroyContext[i]->destroyContext(); 168 } 169 } 170 171 void WebViewFunctorManager::destroyFunctor(int functor) { 172 std::unique_ptr<WebViewFunctor> toRelease; 173 { 174 std::lock_guard _lock{mLock}; 175 for (auto iter = mFunctors.begin(); iter != mFunctors.end(); iter++) { 176 if ((*iter)->id() == functor) { 177 toRelease = std::move(*iter); 178 mFunctors.erase(iter); 179 break; 180 } 181 } 182 } 183 } 184 185 sp<WebViewFunctor::Handle> WebViewFunctorManager::handleFor(int functor) { 186 std::lock_guard _lock{mLock}; 187 for (auto& iter : mActiveFunctors) { 188 if (iter->id() == functor) { 189 return iter; 190 } 191 } 192 return nullptr; 193 } 194 195 } // namespace android::uirenderer 196