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

Commit 02c160c8 authored by Nolan Scobie's avatar Nolan Scobie
Browse files

Split Ganesh-specific parts of SkiaVkRenderEngine into subclass

Similarly to Ia65306cc825b71fe0b89c7f8545ce1c71a81d86b, this will allow
for a Graphite-specific variant of SkiaVkRenderEngine.

waitFence and flushAndSubmit are kept on the *RenderEngine classes (as
opposed to the recently added SkiaGpuContext abstraction) because they
are specific to the intersection of both <Skia backend> x <GPU API>,
with 3 variants. Their logic is also RE-specific, and not suitable for
a Skia abstraction.

Misc. cleanup:
- Remove SkiaVkRenderEngine's flush() and mBackendContext declarations
  as they were undefined and unnecessary.
- Mark some local variables as const.
- Pass named constant to GrDirectContext::wait in
  GaneshVkRenderEngine::waitFence

Test: manual validation & existing tests (refactor)
Bug: b/293371537
Change-Id: I695a0554b20ca14cf475aeff1b92c4445c1af55b
parent ca050286
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ filegroup {
        "skia/AutoBackendTexture.cpp",
        "skia/Cache.cpp",
        "skia/ColorSpaces.cpp",
        "skia/GaneshVkRenderEngine.cpp",
        "skia/GLExtensions.cpp",
        "skia/SkiaRenderEngine.cpp",
        "skia/SkiaGLRenderEngine.cpp",
+84 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 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 "GaneshVkRenderEngine.h"

#undef LOG_TAG
#define LOG_TAG "RenderEngine"

#include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>

#include <log/log_main.h>
#include <sync/sync.h>

namespace android::renderengine::skia {

// Ganesh-specific function signature for fFinishedProc callback.
static void unref_semaphore(void* semaphore) {
    SkiaVkRenderEngine::DestroySemaphoreInfo* info =
            reinterpret_cast<SkiaVkRenderEngine::DestroySemaphoreInfo*>(semaphore);
    info->unref();
}

void GaneshVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) {
    if (fenceFd.get() < 0) return;

    const int dupedFd = dup(fenceFd.get());
    if (dupedFd < 0) {
        ALOGE("failed to create duplicate fence fd: %d", dupedFd);
        sync_wait(fenceFd.get(), -1);
        return;
    }

    base::unique_fd fenceDup(dupedFd);
    VkSemaphore waitSemaphore =
            getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
    GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(waitSemaphore);
    constexpr bool kDeleteAfterWait = true;
    context->grDirectContext()->wait(1, &beSemaphore, kDeleteAfterWait);
}

base::unique_fd GaneshVkRenderEngine::flushAndSubmit(SkiaGpuContext* context) {
    sk_sp<GrDirectContext> grContext = context->grDirectContext();
    VulkanInterface& vi = getVulkanInterface(isProtected());
    VkSemaphore semaphore = vi.createExportableSemaphore();

    GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);

    GrFlushInfo flushInfo;
    DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
    if (semaphore != VK_NULL_HANDLE) {
        destroySemaphoreInfo = new DestroySemaphoreInfo(vi, semaphore);
        flushInfo.fNumSemaphores = 1;
        flushInfo.fSignalSemaphores = &backendSemaphore;
        flushInfo.fFinishedProc = unref_semaphore;
        flushInfo.fFinishedContext = destroySemaphoreInfo;
    }
    GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
    grContext->submit(GrSyncCpu::kNo);
    int drawFenceFd = -1;
    if (semaphore != VK_NULL_HANDLE) {
        if (GrSemaphoresSubmitted::kYes == submitted) {
            drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
        }
        // Now that drawFenceFd has been created, we can delete our reference to this semaphore
        flushInfo.fFinishedProc(destroySemaphoreInfo);
    }
    base::unique_fd res(drawFenceFd);
    return res;
}

} // namespace android::renderengine::skia
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 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.
 */

#pragma once

#include "skia/SkiaVkRenderEngine.h"

namespace android::renderengine::skia {

class GaneshVkRenderEngine : public SkiaVkRenderEngine {
    friend std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
            const RenderEngineCreationArgs& args);

protected:
    GaneshVkRenderEngine(const RenderEngineCreationArgs& args) : SkiaVkRenderEngine(args) {}

    void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
    base::unique_fd flushAndSubmit(SkiaGpuContext* context) override;
};

} // namespace android::renderengine::skia
+1 −0
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ protected:

    size_t getMaxTextureSize() const override final;
    size_t getMaxViewportDims() const override final;
    // TODO: b/293371537 - Return reference instead of pointer? (Cleanup)
    SkiaGpuContext* getActiveContext();

    bool isProtected() const { return mInProtectedContext; }
+4 −55
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include "SkiaVkRenderEngine.h"

#include "GaneshVkRenderEngine.h"
#include "compat/SkiaGpuContext.h"

#include <GrBackendSemaphore.h>
@@ -84,7 +85,8 @@ using base::StringAppendF;

std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
        const RenderEngineCreationArgs& args) {
    std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args));
    // TODO: b/293371537 - Ganesh vs. Graphite subclass based on flag in RenderEngineCreationArgs
    std::unique_ptr<SkiaVkRenderEngine> engine(new GaneshVkRenderEngine(args));
    engine->ensureContextsCreated();

    if (sVulkanInterface.isInitialized()) {
@@ -129,66 +131,13 @@ bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
    return true;
}

static void unref_semaphore(void* semaphore) {
    SkiaVkRenderEngine::DestroySemaphoreInfo* info =
            reinterpret_cast<SkiaVkRenderEngine::DestroySemaphoreInfo*>(semaphore);
    info->unref();
}

static VulkanInterface& getVulkanInterface(bool protectedContext) {
VulkanInterface& SkiaVkRenderEngine::getVulkanInterface(bool protectedContext) {
    if (protectedContext) {
        return sProtectedContentVulkanInterface;
    }
    return sVulkanInterface;
}

void SkiaVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) {
    if (fenceFd.get() < 0) return;

    int dupedFd = dup(fenceFd.get());
    if (dupedFd < 0) {
        ALOGE("failed to create duplicate fence fd: %d", dupedFd);
        sync_wait(fenceFd.get(), -1);
        return;
    }

    base::unique_fd fenceDup(dupedFd);
    VkSemaphore waitSemaphore =
            getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
    GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(waitSemaphore);
    context->grDirectContext()->wait(1, &beSemaphore, true /* delete after wait */);
}

base::unique_fd SkiaVkRenderEngine::flushAndSubmit(SkiaGpuContext* context) {
    sk_sp<GrDirectContext> grContext = context->grDirectContext();
    VulkanInterface& vi = getVulkanInterface(isProtected());
    VkSemaphore semaphore = vi.createExportableSemaphore();

    GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);

    GrFlushInfo flushInfo;
    DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
    if (semaphore != VK_NULL_HANDLE) {
        destroySemaphoreInfo = new DestroySemaphoreInfo(vi, semaphore);
        flushInfo.fNumSemaphores = 1;
        flushInfo.fSignalSemaphores = &backendSemaphore;
        flushInfo.fFinishedProc = unref_semaphore;
        flushInfo.fFinishedContext = destroySemaphoreInfo;
    }
    GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
    grContext->submit(GrSyncCpu::kNo);
    int drawFenceFd = -1;
    if (semaphore != VK_NULL_HANDLE) {
        if (GrSemaphoresSubmitted::kYes == submitted) {
            drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
        }
        // Now that drawFenceFd has been created, we can delete our reference to this semaphore
        flushInfo.fFinishedProc(destroySemaphoreInfo);
    }
    base::unique_fd res(drawFenceFd);
    return res;
}

int SkiaVkRenderEngine::getContextPriority() {
    // EGL_CONTEXT_PRIORITY_REALTIME_NV
    constexpr int kRealtimePriority = 0x3357;
Loading