1 /*
2  * Copyright 2024 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 "GaneshVkRenderEngine.h"
18 
19 #undef LOG_TAG
20 #define LOG_TAG "RenderEngine"
21 
22 #include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
23 
24 #include <log/log_main.h>
25 #include <sync/sync.h>
26 #include <utils/Trace.h>
27 
28 namespace android::renderengine::skia {
29 
create(const RenderEngineCreationArgs & args)30 std::unique_ptr<GaneshVkRenderEngine> GaneshVkRenderEngine::create(
31         const RenderEngineCreationArgs& args) {
32     std::unique_ptr<GaneshVkRenderEngine> engine(new GaneshVkRenderEngine(args));
33     engine->ensureContextsCreated();
34 
35     if (getVulkanInterface(false).isInitialized()) {
36         ALOGD("GaneshVkRenderEngine::%s: successfully initialized GaneshVkRenderEngine", __func__);
37         return engine;
38     } else {
39         ALOGE("GaneshVkRenderEngine::%s: could not create GaneshVkRenderEngine. "
40               "Likely insufficient Vulkan support",
41               __func__);
42         return {};
43     }
44 }
45 
46 // Ganesh-specific function signature for fFinishedProc callback.
unref_semaphore(void * semaphore)47 static void unref_semaphore(void* semaphore) {
48     SkiaVkRenderEngine::DestroySemaphoreInfo* info =
49             reinterpret_cast<SkiaVkRenderEngine::DestroySemaphoreInfo*>(semaphore);
50     info->unref();
51 }
52 
createContext(VulkanInterface & vulkanInterface)53 std::unique_ptr<SkiaGpuContext> GaneshVkRenderEngine::createContext(
54         VulkanInterface& vulkanInterface) {
55     return SkiaGpuContext::MakeVulkan_Ganesh(vulkanInterface.getGaneshBackendContext(),
56                                              mSkSLCacheMonitor);
57 }
58 
waitFence(SkiaGpuContext * context,base::borrowed_fd fenceFd)59 void GaneshVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) {
60     if (fenceFd.get() < 0) return;
61 
62     const int dupedFd = dup(fenceFd.get());
63     if (dupedFd < 0) {
64         ALOGE("failed to create duplicate fence fd: %d", dupedFd);
65         sync_wait(fenceFd.get(), -1);
66         return;
67     }
68 
69     base::unique_fd fenceDup(dupedFd);
70     VkSemaphore waitSemaphore =
71             getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
72     GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(waitSemaphore);
73     constexpr bool kDeleteAfterWait = true;
74     context->grDirectContext()->wait(1, &beSemaphore, kDeleteAfterWait);
75 }
76 
flushAndSubmit(SkiaGpuContext * context,sk_sp<SkSurface> dstSurface)77 base::unique_fd GaneshVkRenderEngine::flushAndSubmit(SkiaGpuContext* context,
78                                                      sk_sp<SkSurface> dstSurface) {
79     sk_sp<GrDirectContext> grContext = context->grDirectContext();
80     {
81         ATRACE_NAME("flush surface");
82         // TODO: Investigate feasibility of combining this "surface flush" into the "context flush"
83         // below.
84         context->grDirectContext()->flush(dstSurface.get());
85     }
86 
87     VulkanInterface& vi = getVulkanInterface(isProtected());
88     VkSemaphore semaphore = vi.createExportableSemaphore();
89     GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);
90 
91     GrFlushInfo flushInfo;
92     DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
93     if (semaphore != VK_NULL_HANDLE) {
94         destroySemaphoreInfo = new DestroySemaphoreInfo(vi, semaphore);
95         flushInfo.fNumSemaphores = 1;
96         flushInfo.fSignalSemaphores = &backendSemaphore;
97         flushInfo.fFinishedProc = unref_semaphore;
98         flushInfo.fFinishedContext = destroySemaphoreInfo;
99     }
100     GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
101     grContext->submit(GrSyncCpu::kNo);
102     int drawFenceFd = -1;
103     if (semaphore != VK_NULL_HANDLE) {
104         if (GrSemaphoresSubmitted::kYes == submitted) {
105             drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
106         }
107         // Now that drawFenceFd has been created, we can delete our reference to this semaphore
108         flushInfo.fFinishedProc(destroySemaphoreInfo);
109     }
110     base::unique_fd res(drawFenceFd);
111     return res;
112 }
113 
114 } // namespace android::renderengine::skia
115