New WebViewFunctor API

Should function alongside existing functor API.

Bug: 120997728
Test: hwuiunit passes
Change-Id: I8f6143d0be1111431b55016f34de319f6b8c8910
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
new file mode 100644
index 0000000..20e77b4
--- /dev/null
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "WebViewFunctorManager.h"
+
+#include <private/hwui/WebViewFunctor.h>
+#include "Properties.h"
+
+#include <log/log.h>
+#include <utils/Trace.h>
+#include <atomic>
+
+namespace android::uirenderer {
+
+RenderMode WebViewFunctor_queryPlatformRenderMode() {
+    auto pipelineType = Properties::getRenderPipelineType();
+    switch (pipelineType) {
+        case RenderPipelineType::SkiaGL:
+            return RenderMode::OpenGL_ES;
+        case RenderPipelineType::SkiaVulkan:
+            return RenderMode::Vulkan;
+        default:
+            LOG_ALWAYS_FATAL("Unknown render pipeline type: %d", (int)pipelineType);
+    }
+}
+
+int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode functorMode) {
+    if (functorMode != RenderMode::OpenGL_ES && functorMode != RenderMode::Vulkan) {
+        ALOGW("Unknown rendermode %d", (int)functorMode);
+        return -1;
+    }
+    if (functorMode == RenderMode::Vulkan &&
+        WebViewFunctor_queryPlatformRenderMode() != RenderMode::Vulkan) {
+        ALOGW("Unable to map from GLES platform to a vulkan functor");
+        return -1;
+    }
+    return WebViewFunctorManager::instance().createFunctor(prototype, functorMode);
+}
+
+void WebViewFunctor_release(int functor) {
+    WebViewFunctorManager::instance().releaseFunctor(functor);
+}
+
+static std::atomic_int sNextId{1};
+
+WebViewFunctor::WebViewFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode) {
+    mFunctor = sNextId++;
+    mCallbacks = callbacks;
+    mMode = functorMode;
+}
+
+WebViewFunctor::~WebViewFunctor() {
+    destroyContext();
+
+    ATRACE_NAME("WebViewFunctor::onDestroy");
+    mCallbacks.onDestroyed(mFunctor);
+}
+
+void WebViewFunctor::sync(const WebViewSyncData& syncData) const {
+    ATRACE_NAME("WebViewFunctor::sync");
+    mCallbacks.onSync(mFunctor, syncData);
+}
+
+void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) {
+    ATRACE_NAME("WebViewFunctor::drawGl");
+    if (!mHasContext) {
+        mHasContext = true;
+    }
+    mCallbacks.gles.draw(mFunctor, drawInfo);
+}
+
+void WebViewFunctor::destroyContext() {
+    if (mHasContext) {
+        mHasContext = false;
+        ATRACE_NAME("WebViewFunctor::onContextDestroyed");
+        mCallbacks.onContextDestroyed(mFunctor);
+    }
+}
+
+WebViewFunctorManager& WebViewFunctorManager::instance() {
+    static WebViewFunctorManager sInstance;
+    return sInstance;
+}
+
+int WebViewFunctorManager::createFunctor(const WebViewFunctorCallbacks& callbacks,
+                                         RenderMode functorMode) {
+    auto object = std::make_unique<WebViewFunctor>(callbacks, functorMode);
+    int id = object->id();
+    auto handle = object->createHandle();
+    {
+        std::lock_guard _lock{mLock};
+        mActiveFunctors.push_back(std::move(handle));
+        mFunctors.push_back(std::move(object));
+    }
+    return id;
+}
+
+void WebViewFunctorManager::releaseFunctor(int functor) {
+    sp<WebViewFunctor::Handle> toRelease;
+    {
+        std::lock_guard _lock{mLock};
+        for (auto iter = mActiveFunctors.begin(); iter != mActiveFunctors.end(); iter++) {
+            if ((*iter)->id() == functor) {
+                toRelease = std::move(*iter);
+                mActiveFunctors.erase(iter);
+                break;
+            }
+        }
+    }
+}
+
+void WebViewFunctorManager::onContextDestroyed() {
+    // WARNING: SKETCHY
+    // Because we know that we always remove from mFunctors on RenderThread, the same
+    // thread that always invokes onContextDestroyed, we know that the functor pointers
+    // will remain valid without the lock held.
+    // However, we won't block new functors from being added in the meantime.
+    mLock.lock();
+    const size_t size = mFunctors.size();
+    WebViewFunctor* toDestroyContext[size];
+    for (size_t i = 0; i < size; i++) {
+        toDestroyContext[i] = mFunctors[i].get();
+    }
+    mLock.unlock();
+    for (size_t i = 0; i < size; i++) {
+        toDestroyContext[i]->destroyContext();
+    }
+}
+
+void WebViewFunctorManager::destroyFunctor(int functor) {
+    std::unique_ptr<WebViewFunctor> toRelease;
+    {
+        std::lock_guard _lock{mLock};
+        for (auto iter = mFunctors.begin(); iter != mFunctors.end(); iter++) {
+            if ((*iter)->id() == functor) {
+                toRelease = std::move(*iter);
+                mFunctors.erase(iter);
+                break;
+            }
+        }
+    }
+}
+
+sp<WebViewFunctor::Handle> WebViewFunctorManager::handleFor(int functor) {
+    std::lock_guard _lock{mLock};
+    for (auto& iter : mActiveFunctors) {
+        if (iter->id() == functor) {
+            return iter;
+        }
+    }
+    return nullptr;
+}
+
+}  // namespace android::uirenderer
\ No newline at end of file