Home | History | Annotate | Download | only in hwui
      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