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