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