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/CanvasContext.h"
22 #include "renderthread/RenderThread.h"
23
24 #include <log/log.h>
25 #include <utils/Trace.h>
26 #include <atomic>
27
28 namespace android::uirenderer {
29
30 namespace {
31 class ScopedCurrentFunctor {
32 public:
ScopedCurrentFunctor(WebViewFunctor * functor)33 ScopedCurrentFunctor(WebViewFunctor* functor) {
34 ALOG_ASSERT(!sCurrentFunctor);
35 ALOG_ASSERT(functor);
36 sCurrentFunctor = functor;
37 }
~ScopedCurrentFunctor()38 ~ScopedCurrentFunctor() {
39 ALOG_ASSERT(sCurrentFunctor);
40 sCurrentFunctor = nullptr;
41 }
42
getSurfaceControl()43 static ASurfaceControl* getSurfaceControl() {
44 ALOG_ASSERT(sCurrentFunctor);
45 return sCurrentFunctor->getSurfaceControl();
46 }
mergeTransaction(ASurfaceTransaction * transaction)47 static void mergeTransaction(ASurfaceTransaction* transaction) {
48 ALOG_ASSERT(sCurrentFunctor);
49 sCurrentFunctor->mergeTransaction(transaction);
50 }
51
52 private:
53 static WebViewFunctor* sCurrentFunctor;
54 };
55
56 WebViewFunctor* ScopedCurrentFunctor::sCurrentFunctor = nullptr;
57 } // namespace
58
WebViewFunctor_queryPlatformRenderMode()59 RenderMode WebViewFunctor_queryPlatformRenderMode() {
60 auto pipelineType = Properties::getRenderPipelineType();
61 switch (pipelineType) {
62 case RenderPipelineType::SkiaGL:
63 return RenderMode::OpenGL_ES;
64 case RenderPipelineType::SkiaVulkan:
65 return RenderMode::Vulkan;
66 default:
67 LOG_ALWAYS_FATAL("Unknown render pipeline type: %d", (int)pipelineType);
68 }
69 }
70
WebViewFunctor_create(void * data,const WebViewFunctorCallbacks & prototype,RenderMode functorMode)71 int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype,
72 RenderMode functorMode) {
73 if (functorMode != RenderMode::OpenGL_ES && functorMode != RenderMode::Vulkan) {
74 ALOGW("Unknown rendermode %d", (int)functorMode);
75 return -1;
76 }
77 if (functorMode == RenderMode::Vulkan &&
78 WebViewFunctor_queryPlatformRenderMode() != RenderMode::Vulkan) {
79 ALOGW("Unable to map from GLES platform to a vulkan functor");
80 return -1;
81 }
82 return WebViewFunctorManager::instance().createFunctor(data, prototype, functorMode);
83 }
84
WebViewFunctor_release(int functor)85 void WebViewFunctor_release(int functor) {
86 WebViewFunctorManager::instance().releaseFunctor(functor);
87 }
88
89 static std::atomic_int sNextId{1};
90
WebViewFunctor(void * data,const WebViewFunctorCallbacks & callbacks,RenderMode functorMode)91 WebViewFunctor::WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks,
92 RenderMode functorMode)
93 : mData(data) {
94 mFunctor = sNextId++;
95 mCallbacks = callbacks;
96 mMode = functorMode;
97 }
98
~WebViewFunctor()99 WebViewFunctor::~WebViewFunctor() {
100 destroyContext();
101
102 ATRACE_NAME("WebViewFunctor::onDestroy");
103 if (mSurfaceControl) {
104 removeOverlays();
105 }
106 mCallbacks.onDestroyed(mFunctor, mData);
107 }
108
sync(const WebViewSyncData & syncData) const109 void WebViewFunctor::sync(const WebViewSyncData& syncData) const {
110 ATRACE_NAME("WebViewFunctor::sync");
111 mCallbacks.onSync(mFunctor, mData, syncData);
112 }
113
onRemovedFromTree()114 void WebViewFunctor::onRemovedFromTree() {
115 ATRACE_NAME("WebViewFunctor::onRemovedFromTree");
116 if (mSurfaceControl) {
117 removeOverlays();
118 }
119 }
120
prepareRootSurfaceControl()121 bool WebViewFunctor::prepareRootSurfaceControl() {
122 if (!Properties::enableWebViewOverlays) return false;
123
124 renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext();
125 if (!activeContext) return false;
126
127 ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl();
128 if (!rootSurfaceControl) return false;
129
130 int32_t rgid = activeContext->getSurfaceControlGenerationId();
131 if (mParentSurfaceControlGenerationId != rgid) {
132 reparentSurfaceControl(rootSurfaceControl);
133 mParentSurfaceControlGenerationId = rgid;
134 }
135
136 return true;
137 }
138
drawGl(const DrawGlInfo & drawInfo)139 void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) {
140 ATRACE_NAME("WebViewFunctor::drawGl");
141 if (!mHasContext) {
142 mHasContext = true;
143 }
144 ScopedCurrentFunctor currentFunctor(this);
145
146 WebViewOverlayData overlayParams = {
147 .overlaysMode = OverlaysMode::Disabled,
148 .getSurfaceControl = currentFunctor.getSurfaceControl,
149 .mergeTransaction = currentFunctor.mergeTransaction,
150 };
151
152 if (!drawInfo.isLayer && prepareRootSurfaceControl()) {
153 overlayParams.overlaysMode = OverlaysMode::Enabled;
154 }
155
156 mCallbacks.gles.draw(mFunctor, mData, drawInfo, overlayParams);
157 }
158
initVk(const VkFunctorInitParams & params)159 void WebViewFunctor::initVk(const VkFunctorInitParams& params) {
160 ATRACE_NAME("WebViewFunctor::initVk");
161 if (!mHasContext) {
162 mHasContext = true;
163 } else {
164 return;
165 }
166 mCallbacks.vk.initialize(mFunctor, mData, params);
167 }
168
drawVk(const VkFunctorDrawParams & params)169 void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) {
170 ATRACE_NAME("WebViewFunctor::drawVk");
171 ScopedCurrentFunctor currentFunctor(this);
172
173 WebViewOverlayData overlayParams = {
174 .overlaysMode = OverlaysMode::Disabled,
175 .getSurfaceControl = currentFunctor.getSurfaceControl,
176 .mergeTransaction = currentFunctor.mergeTransaction,
177 };
178
179 if (!params.is_layer && prepareRootSurfaceControl()) {
180 overlayParams.overlaysMode = OverlaysMode::Enabled;
181 }
182
183 mCallbacks.vk.draw(mFunctor, mData, params, overlayParams);
184 }
185
postDrawVk()186 void WebViewFunctor::postDrawVk() {
187 ATRACE_NAME("WebViewFunctor::postDrawVk");
188 mCallbacks.vk.postDraw(mFunctor, mData);
189 }
190
destroyContext()191 void WebViewFunctor::destroyContext() {
192 if (mHasContext) {
193 mHasContext = false;
194 ATRACE_NAME("WebViewFunctor::onContextDestroyed");
195 mCallbacks.onContextDestroyed(mFunctor, mData);
196
197 // grContext may be null in unit tests.
198 auto* grContext = renderthread::RenderThread::getInstance().getGrContext();
199 if (grContext) grContext->resetContext();
200 }
201 }
202
removeOverlays()203 void WebViewFunctor::removeOverlays() {
204 ScopedCurrentFunctor currentFunctor(this);
205 mCallbacks.removeOverlays(mFunctor, mData, currentFunctor.mergeTransaction);
206 if (mSurfaceControl) {
207 reparentSurfaceControl(nullptr);
208 auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
209 funcs.releaseFunc(mSurfaceControl);
210 mSurfaceControl = nullptr;
211 }
212 }
213
getSurfaceControl()214 ASurfaceControl* WebViewFunctor::getSurfaceControl() {
215 ATRACE_NAME("WebViewFunctor::getSurfaceControl");
216 if (mSurfaceControl != nullptr) return mSurfaceControl;
217
218 renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext();
219 LOG_ALWAYS_FATAL_IF(activeContext == nullptr, "Null active canvas context!");
220
221 ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl();
222 LOG_ALWAYS_FATAL_IF(rootSurfaceControl == nullptr, "Null root surface control!");
223
224 auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
225 mParentSurfaceControlGenerationId = activeContext->getSurfaceControlGenerationId();
226 mSurfaceControl = funcs.createFunc(rootSurfaceControl, "Webview Overlay SurfaceControl");
227 ASurfaceTransaction* transaction = funcs.transactionCreateFunc();
228 activeContext->prepareSurfaceControlForWebview();
229 funcs.transactionSetZOrderFunc(transaction, mSurfaceControl, -1);
230 funcs.transactionSetVisibilityFunc(transaction, mSurfaceControl,
231 ASURFACE_TRANSACTION_VISIBILITY_SHOW);
232 funcs.transactionApplyFunc(transaction);
233 funcs.transactionDeleteFunc(transaction);
234 return mSurfaceControl;
235 }
236
mergeTransaction(ASurfaceTransaction * transaction)237 void WebViewFunctor::mergeTransaction(ASurfaceTransaction* transaction) {
238 ATRACE_NAME("WebViewFunctor::mergeTransaction");
239 if (transaction == nullptr) return;
240 bool done = false;
241 renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext();
242 // activeContext might be null when called from mCallbacks.removeOverlays()
243 if (activeContext != nullptr) {
244 done = activeContext->mergeTransaction(transaction, mSurfaceControl);
245 }
246 if (!done) {
247 auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
248 funcs.transactionApplyFunc(transaction);
249 }
250 }
251
reparentSurfaceControl(ASurfaceControl * parent)252 void WebViewFunctor::reparentSurfaceControl(ASurfaceControl* parent) {
253 ATRACE_NAME("WebViewFunctor::reparentSurfaceControl");
254 if (mSurfaceControl == nullptr) return;
255
256 auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
257 ASurfaceTransaction* transaction = funcs.transactionCreateFunc();
258 funcs.transactionReparentFunc(transaction, mSurfaceControl, parent);
259 mergeTransaction(transaction);
260 funcs.transactionDeleteFunc(transaction);
261 }
262
instance()263 WebViewFunctorManager& WebViewFunctorManager::instance() {
264 static WebViewFunctorManager sInstance;
265 return sInstance;
266 }
267
validateCallbacks(const WebViewFunctorCallbacks & callbacks)268 static void validateCallbacks(const WebViewFunctorCallbacks& callbacks) {
269 // TODO: Should we do a stack peek to see if this is really webview?
270 LOG_ALWAYS_FATAL_IF(callbacks.onSync == nullptr, "onSync is null");
271 LOG_ALWAYS_FATAL_IF(callbacks.onContextDestroyed == nullptr, "onContextDestroyed is null");
272 LOG_ALWAYS_FATAL_IF(callbacks.onDestroyed == nullptr, "onDestroyed is null");
273 LOG_ALWAYS_FATAL_IF(callbacks.removeOverlays == nullptr, "removeOverlays is null");
274 switch (auto mode = WebViewFunctor_queryPlatformRenderMode()) {
275 case RenderMode::OpenGL_ES:
276 LOG_ALWAYS_FATAL_IF(callbacks.gles.draw == nullptr, "gles.draw is null");
277 break;
278 case RenderMode::Vulkan:
279 LOG_ALWAYS_FATAL_IF(callbacks.vk.initialize == nullptr, "vk.initialize is null");
280 LOG_ALWAYS_FATAL_IF(callbacks.vk.draw == nullptr, "vk.draw is null");
281 LOG_ALWAYS_FATAL_IF(callbacks.vk.postDraw == nullptr, "vk.postDraw is null");
282 break;
283 default:
284 LOG_ALWAYS_FATAL("unknown platform mode? %d", (int)mode);
285 break;
286 }
287 }
288
createFunctor(void * data,const WebViewFunctorCallbacks & callbacks,RenderMode functorMode)289 int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks,
290 RenderMode functorMode) {
291 validateCallbacks(callbacks);
292 auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode);
293 int id = object->id();
294 auto handle = object->createHandle();
295 {
296 std::lock_guard _lock{mLock};
297 mActiveFunctors.push_back(std::move(handle));
298 mFunctors.push_back(std::move(object));
299 }
300 return id;
301 }
302
releaseFunctor(int functor)303 void WebViewFunctorManager::releaseFunctor(int functor) {
304 sp<WebViewFunctor::Handle> toRelease;
305 {
306 std::lock_guard _lock{mLock};
307 for (auto iter = mActiveFunctors.begin(); iter != mActiveFunctors.end(); iter++) {
308 if ((*iter)->id() == functor) {
309 toRelease = std::move(*iter);
310 mActiveFunctors.erase(iter);
311 break;
312 }
313 }
314 }
315 }
316
onContextDestroyed()317 void WebViewFunctorManager::onContextDestroyed() {
318 // WARNING: SKETCHY
319 // Because we know that we always remove from mFunctors on RenderThread, the same
320 // thread that always invokes onContextDestroyed, we know that the functor pointers
321 // will remain valid without the lock held.
322 // However, we won't block new functors from being added in the meantime.
323 mLock.lock();
324 const size_t size = mFunctors.size();
325 WebViewFunctor* toDestroyContext[size];
326 for (size_t i = 0; i < size; i++) {
327 toDestroyContext[i] = mFunctors[i].get();
328 }
329 mLock.unlock();
330 for (size_t i = 0; i < size; i++) {
331 toDestroyContext[i]->destroyContext();
332 }
333 }
334
destroyFunctor(int functor)335 void WebViewFunctorManager::destroyFunctor(int functor) {
336 std::unique_ptr<WebViewFunctor> toRelease;
337 {
338 std::lock_guard _lock{mLock};
339 for (auto iter = mFunctors.begin(); iter != mFunctors.end(); iter++) {
340 if ((*iter)->id() == functor) {
341 toRelease = std::move(*iter);
342 mFunctors.erase(iter);
343 break;
344 }
345 }
346 }
347 }
348
handleFor(int functor)349 sp<WebViewFunctor::Handle> WebViewFunctorManager::handleFor(int functor) {
350 std::lock_guard _lock{mLock};
351 for (auto& iter : mActiveFunctors) {
352 if (iter->id() == functor) {
353 return iter;
354 }
355 }
356 return nullptr;
357 }
358
359 } // namespace android::uirenderer
360