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 
WebViewFunctor_queryPlatformRenderMode()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 
WebViewFunctor_create(void * data,const WebViewFunctorCallbacks & prototype,RenderMode functorMode)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 
WebViewFunctor_release(int functor)55 void WebViewFunctor_release(int functor) {
56     WebViewFunctorManager::instance().releaseFunctor(functor);
57 }
58 
59 static std::atomic_int sNextId{1};
60 
WebViewFunctor(void * data,const WebViewFunctorCallbacks & callbacks,RenderMode functorMode)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 
~WebViewFunctor()69 WebViewFunctor::~WebViewFunctor() {
70     destroyContext();
71 
72     ATRACE_NAME("WebViewFunctor::onDestroy");
73     mCallbacks.onDestroyed(mFunctor, mData);
74 }
75 
sync(const WebViewSyncData & syncData) const76 void WebViewFunctor::sync(const WebViewSyncData& syncData) const {
77     ATRACE_NAME("WebViewFunctor::sync");
78     mCallbacks.onSync(mFunctor, mData, syncData);
79 }
80 
drawGl(const DrawGlInfo & drawInfo)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 
initVk(const VkFunctorInitParams & params)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 
drawVk(const VkFunctorDrawParams & params)99 void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) {
100     ATRACE_NAME("WebViewFunctor::drawVk");
101     mCallbacks.vk.draw(mFunctor, mData, params);
102 }
103 
postDrawVk()104 void WebViewFunctor::postDrawVk() {
105     ATRACE_NAME("WebViewFunctor::postDrawVk");
106     mCallbacks.vk.postDraw(mFunctor, mData);
107 }
108 
destroyContext()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 
instance()121 WebViewFunctorManager& WebViewFunctorManager::instance() {
122     static WebViewFunctorManager sInstance;
123     return sInstance;
124 }
125 
createFunctor(void * data,const WebViewFunctorCallbacks & callbacks,RenderMode functorMode)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 
releaseFunctor(int functor)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 
onContextDestroyed()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 
destroyFunctor(int functor)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 
handleFor(int functor)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