• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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