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
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 5cd0ce5..0defc7e 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -83,6 +83,7 @@
         "skia/AutoBackendTexture.cpp",
         "skia/Cache.cpp",
         "skia/ColorSpaces.cpp",
+        "skia/GaneshVkRenderEngine.cpp",
         "skia/GLExtensions.cpp",
         "skia/SkiaRenderEngine.cpp",
         "skia/SkiaGLRenderEngine.cpp",
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.cpp b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
new file mode 100644
index 0000000..e76a4c3
--- /dev/null
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.h b/libs/renderengine/skia/GaneshVkRenderEngine.h
new file mode 100644
index 0000000..90e2487
--- /dev/null
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.h
@@ -0,0 +1,34 @@
+/*
+ * 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
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index 9f892bd..a39adbe 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -94,6 +94,7 @@
 
     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; }
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index d854929..473fa0a 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -21,6 +21,7 @@
 
 #include "SkiaVkRenderEngine.h"
 
+#include "GaneshVkRenderEngine.h"
 #include "compat/SkiaGpuContext.h"
 
 #include <GrBackendSemaphore.h>
@@ -84,7 +85,8 @@
 
 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 @@
     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;
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.h b/libs/renderengine/skia/SkiaVkRenderEngine.h
index 28b7595..5fd911f 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.h
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.h
@@ -71,20 +71,21 @@
     };
 
 protected:
+    // Redeclare parent functions that Ganesh vs. Graphite subclasses must implement.
+    virtual void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override = 0;
+    virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context) override = 0;
+
+    SkiaVkRenderEngine(const RenderEngineCreationArgs& args);
+
     // Implementations of abstract SkiaRenderEngine functions specific to
-    // rendering backend
+    // Vulkan, but shareable between Ganesh and Graphite.
     SkiaRenderEngine::Contexts createContexts() override;
     bool supportsProtectedContentImpl() const override;
     bool useProtectedContextImpl(GrProtected isProtected) override;
-    void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
-    base::unique_fd flushAndSubmit(SkiaGpuContext* context) override;
     void appendBackendSpecificInfoToDump(std::string& result) override;
 
-private:
-    SkiaVkRenderEngine(const RenderEngineCreationArgs& args);
-    base::unique_fd flush();
-
-    GrVkBackendContext mBackendContext;
+    // TODO: b/300533018 - refactor this to be non-static
+    static VulkanInterface& getVulkanInterface(bool protectedContext);
 };
 
 } // namespace skia