xref: /aosp_15_r20/frameworks/native/libs/renderengine/skia/SkiaVkRenderEngine.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2022 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 // #define LOG_NDEBUG 0
18 #undef LOG_TAG
19 #define LOG_TAG "RenderEngine"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 
22 #include "SkiaVkRenderEngine.h"
23 
24 #include "GaneshVkRenderEngine.h"
25 #include "compat/SkiaGpuContext.h"
26 
27 #include <include/gpu/ganesh/GrBackendSemaphore.h>
28 #include <include/gpu/ganesh/GrContextOptions.h>
29 #include <include/gpu/ganesh/GrDirectContext.h>
30 #include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
31 #include <include/gpu/ganesh/vk/GrVkDirectContext.h>
32 #include <include/gpu/ganesh/vk/GrVkTypes.h>
33 
34 #include <android-base/stringprintf.h>
35 #include <common/trace.h>
36 #include <sync/sync.h>
37 
38 #include <memory>
39 #include <string>
40 
41 #include <vulkan/vulkan.h>
42 #include "log/log_main.h"
43 
44 namespace android {
45 namespace renderengine {
46 
47 static skia::VulkanInterface sVulkanInterface;
48 static skia::VulkanInterface sProtectedContentVulkanInterface;
49 
sSetupVulkanInterface()50 static void sSetupVulkanInterface() {
51     if (!sVulkanInterface.isInitialized()) {
52         sVulkanInterface.init(false /* no protected content */);
53         // We will have to abort if non-protected VkDevice creation fails (then nothing works).
54         LOG_ALWAYS_FATAL_IF(!sVulkanInterface.isInitialized(),
55                             "Could not initialize Vulkan RenderEngine!");
56     }
57     if (!sProtectedContentVulkanInterface.isInitialized()) {
58         sProtectedContentVulkanInterface.init(true /* protected content */);
59         if (!sProtectedContentVulkanInterface.isInitialized()) {
60             ALOGE("Could not initialize protected content Vulkan RenderEngine.");
61         }
62     }
63 }
64 
canSupport(GraphicsApi graphicsApi)65 bool RenderEngine::canSupport(GraphicsApi graphicsApi) {
66     switch (graphicsApi) {
67         case GraphicsApi::GL:
68             return true;
69         case GraphicsApi::VK: {
70             // Static local variables are initialized once, on first invocation of the function.
71             static const bool canSupportVulkan = []() {
72                 if (!sVulkanInterface.isInitialized()) {
73                     sVulkanInterface.init(false /* no protected content */);
74                     ALOGD("%s: initialized == %s.", __func__,
75                           sVulkanInterface.isInitialized() ? "true" : "false");
76                     if (!sVulkanInterface.isInitialized()) {
77                         sVulkanInterface.teardown();
78                         return false;
79                     }
80                 }
81                 return true;
82             }();
83             return canSupportVulkan;
84         }
85     }
86 }
87 
teardown(GraphicsApi graphicsApi)88 void RenderEngine::teardown(GraphicsApi graphicsApi) {
89     switch (graphicsApi) {
90         case GraphicsApi::GL:
91             break;
92         case GraphicsApi::VK: {
93             if (sVulkanInterface.isInitialized()) {
94                 sVulkanInterface.teardown();
95                 ALOGD("Tearing down the unprotected VulkanInterface.");
96             }
97             if (sProtectedContentVulkanInterface.isInitialized()) {
98                 sProtectedContentVulkanInterface.teardown();
99                 ALOGD("Tearing down the protected VulkanInterface.");
100             }
101             break;
102         }
103     }
104 }
105 
106 namespace skia {
107 
108 using base::StringAppendF;
109 
SkiaVkRenderEngine(const RenderEngineCreationArgs & args)110 SkiaVkRenderEngine::SkiaVkRenderEngine(const RenderEngineCreationArgs& args)
111       : SkiaRenderEngine(args.threaded, static_cast<PixelFormat>(args.pixelFormat),
112                          args.blurAlgorithm) {}
113 
~SkiaVkRenderEngine()114 SkiaVkRenderEngine::~SkiaVkRenderEngine() {
115     finishRenderingAndAbandonContexts();
116     // Teardown VulkanInterfaces after Skia contexts have been abandoned
117     teardown(GraphicsApi::VK);
118 }
119 
createContexts()120 SkiaRenderEngine::Contexts SkiaVkRenderEngine::createContexts() {
121     sSetupVulkanInterface();
122     // More work would need to be done in order to have multiple RenderEngine instances. In
123     // particular, they would not be able to share the same VulkanInterface(s).
124     LOG_ALWAYS_FATAL_IF(!sVulkanInterface.takeOwnership(),
125                         "SkiaVkRenderEngine couldn't take ownership of existing unprotected "
126                         "VulkanInterface! Only one SkiaVkRenderEngine instance may exist at a "
127                         "time.");
128     if (sProtectedContentVulkanInterface.isInitialized()) {
129         // takeOwnership fails on an uninitialized VulkanInterface, but protected content support is
130         // optional.
131         LOG_ALWAYS_FATAL_IF(!sProtectedContentVulkanInterface.takeOwnership(),
132                             "SkiaVkRenderEngine couldn't take ownership of existing protected "
133                             "VulkanInterface! Only one SkiaVkRenderEngine instance may exist at a "
134                             "time.");
135     }
136 
137     SkiaRenderEngine::Contexts contexts;
138     contexts.first = createContext(sVulkanInterface);
139     if (supportsProtectedContentImpl()) {
140         contexts.second = createContext(sProtectedContentVulkanInterface);
141     }
142 
143     return contexts;
144 }
145 
supportsProtectedContentImpl() const146 bool SkiaVkRenderEngine::supportsProtectedContentImpl() const {
147     return sProtectedContentVulkanInterface.isInitialized();
148 }
149 
useProtectedContextImpl(GrProtected)150 bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
151     return true;
152 }
153 
getVulkanInterface(bool protectedContext)154 VulkanInterface& SkiaVkRenderEngine::getVulkanInterface(bool protectedContext) {
155     if (protectedContext) {
156         return sProtectedContentVulkanInterface;
157     }
158     return sVulkanInterface;
159 }
160 
getContextPriority()161 int SkiaVkRenderEngine::getContextPriority() {
162     // EGL_CONTEXT_PRIORITY_REALTIME_NV
163     constexpr int kRealtimePriority = 0x3357;
164     if (getVulkanInterface(isProtected()).isRealtimePriority()) {
165         return kRealtimePriority;
166     } else {
167         return 0;
168     }
169 }
170 
appendBackendSpecificInfoToDump(std::string & result)171 void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
172     // Subclasses will prepend a backend-specific name / section header
173     StringAppendF(&result, "Vulkan device initialized: %d\n", sVulkanInterface.isInitialized());
174     StringAppendF(&result, "Vulkan protected device initialized: %d\n",
175                   sProtectedContentVulkanInterface.isInitialized());
176 
177     if (!sVulkanInterface.isInitialized()) {
178         return;
179     }
180 
181     StringAppendF(&result, "Instance extensions: [\n");
182     for (const auto& name : sVulkanInterface.getInstanceExtensionNames()) {
183         StringAppendF(&result, "  %s\n", name.c_str());
184     }
185     StringAppendF(&result, "]\n");
186 
187     StringAppendF(&result, "Device extensions: [\n");
188     for (const auto& name : sVulkanInterface.getDeviceExtensionNames()) {
189         StringAppendF(&result, "  %s\n", name.c_str());
190     }
191     StringAppendF(&result, "]\n");
192 }
193 
194 } // namespace skia
195 } // namespace renderengine
196 } // namespace android
197