Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 283bb468 authored by John Reck's avatar John Reck
Browse files

New WebViewFunctor API

Should function alongside existing functor API.

Bug: 120997728
Test: hwuiunit passes
Change-Id: I8f6143d0be1111431b55016f34de319f6b8c8910
parent 832c1733
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -168,6 +168,11 @@ static void android_view_DisplayListCanvas_drawCircleProps(jlong canvasPtr,
    canvas->drawCircle(xProp, yProp, radiusProp, paintProp);
}

static void android_view_DisplayListCanvas_drawWebViewFunctor(jlong canvasPtr, jint functor) {
    Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
    canvas->drawWebViewFunctor(functor);
}

// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
@@ -192,6 +197,7 @@ static JNINativeMethod gMethods[] = {
    { "nDrawTextureLayer",        "(JJ)V",      (void*) android_view_DisplayListCanvas_drawTextureLayer },
    { "nDrawCircle",              "(JJJJJ)V",   (void*) android_view_DisplayListCanvas_drawCircleProps },
    { "nDrawRoundRect",           "(JJJJJJJJ)V",(void*) android_view_DisplayListCanvas_drawRoundRectProps },
    { "nDrawWebViewFunctor",      "(JI)V",      (void*) android_view_DisplayListCanvas_drawWebViewFunctor },
};

int register_android_view_DisplayListCanvas(JNIEnv* env) {
+10 −0
Original line number Diff line number Diff line
@@ -189,6 +189,14 @@ public final class RecordingCanvas extends DisplayListCanvas {
        nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunctor, releasedCallback);
    }

    /**
     * Calls the provided functor that was created via WebViewFunctor_create()
     * @hide
     */
    public void drawWebViewFunctor(int functor) {
        nDrawWebViewFunctor(mNativeCanvasWrapper, functor);
    }

    ///////////////////////////////////////////////////////////////////////////
    // Display list
    ///////////////////////////////////////////////////////////////////////////
@@ -303,4 +311,6 @@ public final class RecordingCanvas extends DisplayListCanvas {
    @CriticalNative
    private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
            long propRight, long propBottom, long propRx, long propRy, long propPaint);
    @CriticalNative
    private static native void nDrawWebViewFunctor(long canvas, int functor);
}
+4 −0
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@ cc_defaults {
        "hwui_lto",
    ],

    cpp_std: "experimental",

    cflags: [
        "-DEGL_EGLEXT_PROTOTYPES",
        "-DGL_GLEXT_PROTOTYPES",
@@ -224,6 +226,7 @@ cc_defaults {
        "RenderProperties.cpp",
        "SkiaCanvas.cpp",
        "TreeInfo.cpp",
        "WebViewFunctorManager.cpp",
        "VectorDrawable.cpp",
        "protos/graphicsstats.proto",
    ],
@@ -328,6 +331,7 @@ cc_test {
        "tests/unit/TypefaceTests.cpp",
        "tests/unit/VectorDrawableTests.cpp",
        "tests/unit/VectorDrawableAtlasTests.cpp",
        "tests/unit/WebViewFunctorManagerTests.cpp",
    ],
}

+4 −1
Original line number Diff line number Diff line
@@ -288,7 +288,10 @@ void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) {
    mDisplayList = mStagingDisplayList;
    mStagingDisplayList = nullptr;
    if (mDisplayList) {
        mDisplayList->syncContents();
        WebViewSyncData syncData {
            .applyForceDark = info && !info->disableForceDark
        };
        mDisplayList->syncContents(syncData);
        handleForceDark(info);
    }
}
+167 −0
Original line number Diff line number Diff line
/*
 * 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
Loading