1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "ExtendedRenderControl.h"
15 
16 using gfxstream::guest::ChecksumCalculator;
17 
queryHostExtensions()18 const std::string& ExtendedRCEncoderContext::queryHostExtensions() {
19     if (!m_hostExtensions.empty()) {
20         return m_hostExtensions;
21     }
22 
23     // Extensions strings are usually quite long, preallocate enough here.
24     std::string extensionsBuffer(1023, '\0');
25 
26     // Returns the required size including the 0-terminator, so
27     // account it when passing/using the sizes.
28     int extensionSize =
29         this->rcGetHostExtensionsString(this, extensionsBuffer.size() + 1, &extensionsBuffer[0]);
30     if (extensionSize < 0) {
31         extensionsBuffer.resize(-extensionSize);
32         extensionSize =
33             this->rcGetHostExtensionsString(this, -extensionSize + 1, &extensionsBuffer[0]);
34     }
35 
36     if (extensionSize > 0) {
37         extensionsBuffer.resize(extensionSize - 1);
38         m_hostExtensions.swap(extensionsBuffer);
39     }
40 
41     return m_hostExtensions;
42 }
43 
queryAndSetHostCompositionImpl()44 void ExtendedRCEncoderContext::queryAndSetHostCompositionImpl() {
45     const std::string& hostExtensions = queryHostExtensions();
46     // make sure V2 is checked first before V1, as host may declare supporting both
47     if (hostExtensions.find(kHostCompositionV2) != std::string::npos) {
48         this->setHostComposition(HOST_COMPOSITION_V2);
49     } else if (hostExtensions.find(kHostCompositionV1) != std::string::npos) {
50         this->setHostComposition(HOST_COMPOSITION_V1);
51     } else {
52         this->setHostComposition(HOST_COMPOSITION_NONE);
53     }
54 }
55 
setChecksumHelper(ChecksumCalculator * calculator)56 void ExtendedRCEncoderContext::setChecksumHelper(ChecksumCalculator* calculator) {
57     const std::string& hostExtensions = queryHostExtensions();
58     // check the host supported version
59     uint32_t checksumVersion = 0;
60     const char* checksumPrefix = ChecksumCalculator::getMaxVersionStrPrefix();
61     const char* glProtocolStr = strstr(hostExtensions.c_str(), checksumPrefix);
62     if (glProtocolStr) {
63         uint32_t maxVersion = ChecksumCalculator::getMaxVersion();
64         sscanf(glProtocolStr + strlen(checksumPrefix), "%d", &checksumVersion);
65         if (maxVersion < checksumVersion) {
66             checksumVersion = maxVersion;
67         }
68         // The ordering of the following two commands matters!
69         // Must tell the host first before setting it in the guest
70         this->rcSelectChecksumHelper(this, checksumVersion, 0);
71         calculator->setVersion(checksumVersion);
72     }
73 }
74 
queryAndSetSyncImpl()75 void ExtendedRCEncoderContext::queryAndSetSyncImpl() {
76     const std::string& hostExtensions = queryHostExtensions();
77     if (hostExtensions.find(kRCNativeSyncV4) != std::string::npos) {
78         this->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V4);
79     } else if (hostExtensions.find(kRCNativeSyncV3) != std::string::npos) {
80         this->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V3);
81     } else if (hostExtensions.find(kRCNativeSyncV2) != std::string::npos) {
82         this->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V2);
83     } else {
84         this->setSyncImpl(SYNC_IMPL_NONE);
85     }
86 }
87 
queryAndSetDmaImpl()88 void ExtendedRCEncoderContext::queryAndSetDmaImpl() {
89     std::string hostExtensions = queryHostExtensions();
90     if (hostExtensions.find(kDmaExtStr_v1) != std::string::npos) {
91         this->setDmaImpl(DMA_IMPL_v1);
92     } else {
93         this->setDmaImpl(DMA_IMPL_NONE);
94     }
95 }
96 
queryAndSetGLESMaxVersion()97 void ExtendedRCEncoderContext::queryAndSetGLESMaxVersion() {
98     std::string hostExtensions = queryHostExtensions();
99     if (hostExtensions.find(kGLESMaxVersion_2) != std::string::npos) {
100         this->setGLESMaxVersion(GLES_MAX_VERSION_2);
101     } else if (hostExtensions.find(kGLESMaxVersion_3_0) != std::string::npos) {
102         this->setGLESMaxVersion(GLES_MAX_VERSION_3_0);
103     } else if (hostExtensions.find(kGLESMaxVersion_3_1) != std::string::npos) {
104         this->setGLESMaxVersion(GLES_MAX_VERSION_3_1);
105     } else if (hostExtensions.find(kGLESMaxVersion_3_2) != std::string::npos) {
106         this->setGLESMaxVersion(GLES_MAX_VERSION_3_2);
107     } else {
108         ALOGW("Unrecognized GLES max version string in extensions: %s", hostExtensions.c_str());
109         this->setGLESMaxVersion(GLES_MAX_VERSION_2);
110     }
111 }
112 
queryAndSetNoErrorState(bool & hostError)113 void ExtendedRCEncoderContext::queryAndSetNoErrorState(bool& hostError) {
114     std::string hostExtensions = queryHostExtensions();
115     if (hostExtensions.find(kGLESUseHostError) != std::string::npos) {
116         hostError = false;
117     }
118 }
119 
queryAndSetDirectMemSupport()120 void ExtendedRCEncoderContext::queryAndSetDirectMemSupport() {
121     std::string hostExtensions = queryHostExtensions();
122     if (hostExtensions.find(kGLDirectMem) != std::string::npos) {
123         this->featureInfo()->hasDirectMem = true;
124     }
125 }
126 
queryAndSetVulkanSupport()127 void ExtendedRCEncoderContext::queryAndSetVulkanSupport() {
128     std::string hostExtensions = queryHostExtensions();
129     if (hostExtensions.find(kVulkan) != std::string::npos) {
130         this->featureInfo()->hasVulkan = true;
131     }
132 }
133 
queryAndSetDeferredVulkanCommandsSupport()134 void ExtendedRCEncoderContext::queryAndSetDeferredVulkanCommandsSupport() {
135     std::string hostExtensions = queryHostExtensions();
136     if (hostExtensions.find(kDeferredVulkanCommands) != std::string::npos) {
137         this->featureInfo()->hasDeferredVulkanCommands = true;
138     }
139 }
140 
queryAndSetVulkanNullOptionalStringsSupport()141 void ExtendedRCEncoderContext::queryAndSetVulkanNullOptionalStringsSupport() {
142     std::string hostExtensions = queryHostExtensions();
143     if (hostExtensions.find(kVulkanNullOptionalStrings) != std::string::npos) {
144         this->featureInfo()->hasVulkanNullOptionalStrings = true;
145     }
146 }
147 
queryAndSetVulkanCreateResourcesWithRequirementsSupport()148 void ExtendedRCEncoderContext::queryAndSetVulkanCreateResourcesWithRequirementsSupport() {
149     std::string hostExtensions = queryHostExtensions();
150     if (hostExtensions.find(kVulkanCreateResourcesWithRequirements) != std::string::npos) {
151         this->featureInfo()->hasVulkanCreateResourcesWithRequirements = true;
152     }
153 }
154 
queryAndSetVulkanIgnoredHandles()155 void ExtendedRCEncoderContext::queryAndSetVulkanIgnoredHandles() {
156     std::string hostExtensions = queryHostExtensions();
157     if (hostExtensions.find(kVulkanIgnoredHandles) != std::string::npos) {
158         this->featureInfo()->hasVulkanIgnoredHandles = true;
159     }
160 }
161 
queryAndSetYUVCache()162 void ExtendedRCEncoderContext::queryAndSetYUVCache() {
163     std::string hostExtensions = queryHostExtensions();
164     if (hostExtensions.find(kYUVCache) != std::string::npos) {
165         this->featureInfo()->hasYUVCache = true;
166     }
167 }
168 
queryAndSetAsyncUnmapBuffer()169 void ExtendedRCEncoderContext::queryAndSetAsyncUnmapBuffer() {
170     std::string hostExtensions = queryHostExtensions();
171     if (hostExtensions.find(kAsyncUnmapBuffer) != std::string::npos) {
172         this->featureInfo()->hasAsyncUnmapBuffer = true;
173     }
174 }
175 
queryAndSetVirtioGpuNext()176 void ExtendedRCEncoderContext::queryAndSetVirtioGpuNext() {
177     std::string hostExtensions = queryHostExtensions();
178     if (hostExtensions.find(kVirtioGpuNext) != std::string::npos) {
179         this->featureInfo()->hasVirtioGpuNext = true;
180     }
181 }
182 
queryHasSharedSlotsHostMemoryAllocator()183 void ExtendedRCEncoderContext::queryHasSharedSlotsHostMemoryAllocator() {
184     const std::string& hostExtensions = queryHostExtensions();
185     if (hostExtensions.find(kHasSharedSlotsHostMemoryAllocator) != std::string::npos) {
186         this->featureInfo()->hasSharedSlotsHostMemoryAllocator = true;
187     }
188 }
189 
queryAndSetVulkanFreeMemorySync()190 void ExtendedRCEncoderContext::queryAndSetVulkanFreeMemorySync() {
191     const std::string& hostExtensions = queryHostExtensions();
192     if (hostExtensions.find(kVulkanFreeMemorySync) != std::string::npos) {
193         this->featureInfo()->hasVulkanFreeMemorySync = true;
194     }
195 }
196 
queryAndSetVirtioGpuNativeSync()197 void ExtendedRCEncoderContext::queryAndSetVirtioGpuNativeSync() {
198     std::string hostExtensions = queryHostExtensions();
199     if (hostExtensions.find(kVirtioGpuNativeSync) != std::string::npos) {
200         this->featureInfo()->hasVirtioGpuNativeSync = true;
201     }
202 }
203 
queryAndSetVulkanShaderFloat16Int8Support()204 void ExtendedRCEncoderContext::queryAndSetVulkanShaderFloat16Int8Support() {
205     std::string hostExtensions = queryHostExtensions();
206     if (hostExtensions.find(kVulkanShaderFloat16Int8) != std::string::npos) {
207         this->featureInfo()->hasVulkanShaderFloat16Int8 = true;
208     }
209 }
210 
queryAndSetVulkanAsyncQueueSubmitSupport()211 void ExtendedRCEncoderContext::queryAndSetVulkanAsyncQueueSubmitSupport() {
212     std::string hostExtensions = queryHostExtensions();
213     if (hostExtensions.find(kVulkanAsyncQueueSubmit) != std::string::npos) {
214         this->featureInfo()->hasVulkanAsyncQueueSubmit = true;
215     }
216 }
217 
queryAndSetHostSideTracingSupport()218 void ExtendedRCEncoderContext::queryAndSetHostSideTracingSupport() {
219     std::string hostExtensions = queryHostExtensions();
220     if (hostExtensions.find(kHostSideTracing) != std::string::npos) {
221         this->featureInfo()->hasHostSideTracing = true;
222     }
223 }
224 
queryAndSetAsyncFrameCommands()225 void ExtendedRCEncoderContext::queryAndSetAsyncFrameCommands() {
226     std::string hostExtensions = queryHostExtensions();
227     if (hostExtensions.find(kAsyncFrameCommands) != std::string::npos) {
228         this->featureInfo()->hasAsyncFrameCommands = true;
229     }
230 }
231 
queryAndSetVulkanQueueSubmitWithCommandsSupport()232 void ExtendedRCEncoderContext::queryAndSetVulkanQueueSubmitWithCommandsSupport() {
233     std::string hostExtensions = queryHostExtensions();
234     if (hostExtensions.find(kVulkanQueueSubmitWithCommands) != std::string::npos) {
235         this->featureInfo()->hasVulkanQueueSubmitWithCommands = true;
236     }
237 }
238 
queryAndSetVulkanBatchedDescriptorSetUpdateSupport()239 void ExtendedRCEncoderContext::queryAndSetVulkanBatchedDescriptorSetUpdateSupport() {
240     std::string hostExtensions = queryHostExtensions();
241     if (hostExtensions.find(kVulkanBatchedDescriptorSetUpdate) != std::string::npos) {
242         this->featureInfo()->hasVulkanBatchedDescriptorSetUpdate = true;
243     }
244 }
245 
queryAndSetSyncBufferData()246 void ExtendedRCEncoderContext::queryAndSetSyncBufferData() {
247     std::string hostExtensions = queryHostExtensions();
248     if (hostExtensions.find(kSyncBufferData) != std::string::npos) {
249         this->featureInfo()->hasSyncBufferData = true;
250     }
251 }
252 
queryAndSetVulkanAsyncQsri()253 void ExtendedRCEncoderContext::queryAndSetVulkanAsyncQsri() {
254     std::string hostExtensions = queryHostExtensions();
255     if (hostExtensions.find(kVulkanAsyncQsri) != std::string::npos) {
256         this->featureInfo()->hasVulkanAsyncQsri = true;
257     }
258 }
259 
queryAndSetReadColorBufferDma()260 void ExtendedRCEncoderContext::queryAndSetReadColorBufferDma() {
261     std::string hostExtensions = queryHostExtensions();
262     if (hostExtensions.find(kReadColorBufferDma) != std::string::npos) {
263         this->featureInfo()->hasReadColorBufferDma = true;
264     }
265 }
266 
queryAndSetHWCMultiConfigs()267 void ExtendedRCEncoderContext::queryAndSetHWCMultiConfigs() {
268     std::string hostExtensions = queryHostExtensions();
269     if (hostExtensions.find(kHWCMultiConfigs) != std::string::npos) {
270         this->featureInfo()->hasHWCMultiConfigs = true;
271     }
272 }
273 
queryAndSetVulkanAuxCommandBufferMemory()274 void ExtendedRCEncoderContext::queryAndSetVulkanAuxCommandBufferMemory() {
275     std::string hostExtensions = queryHostExtensions();
276     this->featureInfo()->hasVulkanAuxCommandMemory =
277         hostExtensions.find(kVulkanAuxCommandMemory) != std::string::npos;
278 }
279 
queryVersion()280 GLint ExtendedRCEncoderContext::queryVersion() {
281     GLint version = this->rcGetRendererVersion(this);
282     return version;
283 }
284 
setVulkanFeatureInfo(void * info)285 void ExtendedRCEncoderContext::setVulkanFeatureInfo(void* info) {
286     struct EmulatorGfxStreamVkFeatureInfo* featureInfo =
287         (struct EmulatorGfxStreamVkFeatureInfo*)info;
288 
289     featureInfo->hasDirectMem = this->featureInfo()->hasDirectMem;
290     featureInfo->hasVulkan = this->featureInfo()->hasVulkan;
291     featureInfo->hasDeferredVulkanCommands = this->featureInfo()->hasDeferredVulkanCommands;
292     featureInfo->hasVulkanNullOptionalStrings = this->featureInfo()->hasVulkanNullOptionalStrings;
293     featureInfo->hasVulkanCreateResourcesWithRequirements =
294         this->featureInfo()->hasVulkanCreateResourcesWithRequirements;
295     featureInfo->hasVulkanIgnoredHandles = this->featureInfo()->hasVulkanIgnoredHandles;
296     featureInfo->hasVirtioGpuNext = this->featureInfo()->hasVirtioGpuNext;
297     featureInfo->hasVulkanFreeMemorySync = this->featureInfo()->hasVulkanFreeMemorySync;
298     featureInfo->hasVirtioGpuNativeSync = this->featureInfo()->hasVirtioGpuNativeSync;
299     featureInfo->hasVulkanShaderFloat16Int8 = this->featureInfo()->hasVulkanShaderFloat16Int8;
300     featureInfo->hasVulkanAsyncQueueSubmit = this->featureInfo()->hasVulkanAsyncQueueSubmit;
301     featureInfo->hasVulkanQueueSubmitWithCommands =
302         this->featureInfo()->hasVulkanQueueSubmitWithCommands;
303     featureInfo->hasVulkanBatchedDescriptorSetUpdate =
304         this->featureInfo()->hasVulkanBatchedDescriptorSetUpdate;
305     featureInfo->hasVulkanAsyncQsri = this->featureInfo()->hasVulkanAsyncQsri;
306     featureInfo->hasVulkanAuxCommandMemory = this->featureInfo()->hasVulkanAuxCommandMemory;
307 }
308