1 /*
2 * Copyright (C) 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 "HostConnection.h"
18 #include "ProcessPipe.h"
19 #include "ThreadInfo.h"
20
21 #if defined(__ANDROID__)
22 #include "android-base/properties.h"
23 #endif
24
25 using gfxstream::guest::ChecksumCalculator;
26 using gfxstream::guest::IOStream;
27
getDrawCallFlushIntervalFromProperty()28 static uint32_t getDrawCallFlushIntervalFromProperty() {
29 constexpr uint32_t kDefaultValue = 800;
30 uint32_t value = kDefaultValue;
31
32 #if defined(__ANDROID__)
33 value =
34 android::base::GetUintProperty("ro.boot.qemu.gltransport.drawFlushInterval", kDefaultValue);
35 #endif
36 return value;
37 }
38
glEncoder()39 GLEncoder* HostConnection::glEncoder() {
40 if (!m_glEnc) {
41 m_glEnc = std::make_unique<GLEncoder>(m_stream, checksumHelper());
42 DBG("HostConnection::glEncoder new encoder %p, tid %lu", m_glEnc, getCurrentThreadId());
43 m_glEnc->setContextAccessor(s_getGLContext);
44 }
45 return m_glEnc.get();
46 }
47
gl2Encoder()48 GL2Encoder* HostConnection::gl2Encoder() {
49 if (!m_gl2Enc) {
50 m_gl2Enc = std::make_unique<GL2Encoder>(m_stream, checksumHelper());
51 DBG("HostConnection::gl2Encoder new encoder %p, tid %lu", m_gl2Enc, getCurrentThreadId());
52 m_gl2Enc->setContextAccessor(s_getGL2Context);
53 m_gl2Enc->setNoHostError(m_noHostError);
54 m_gl2Enc->setDrawCallFlushInterval(getDrawCallFlushIntervalFromProperty());
55 m_gl2Enc->setHasAsyncUnmapBuffer(m_rcEnc->hasAsyncUnmapBuffer());
56 m_gl2Enc->setHasSyncBufferData(m_rcEnc->hasSyncBufferData());
57 }
58 return m_gl2Enc.get();
59 }
60
rcEncoder()61 ExtendedRCEncoderContext* HostConnection::rcEncoder() {
62 if (!m_rcEnc) {
63 m_rcEnc = std::make_unique<ExtendedRCEncoderContext>(m_stream, checksumHelper());
64
65 ExtendedRCEncoderContext* rcEnc = m_rcEnc.get();
66 setChecksumHelper(rcEnc);
67 queryAndSetSyncImpl(rcEnc);
68 queryAndSetGLESMaxVersion(rcEnc);
69 queryAndSetNoErrorState(rcEnc);
70 queryAndSetHostCompositionImpl(rcEnc);
71 queryAndSetDirectMemSupport(rcEnc);
72 queryAndSetVulkanSupport(rcEnc);
73 queryAndSetDeferredVulkanCommandsSupport(rcEnc);
74 queryAndSetVulkanNullOptionalStringsSupport(rcEnc);
75 queryAndSetVulkanCreateResourcesWithRequirementsSupport(rcEnc);
76 queryAndSetVulkanIgnoredHandles(rcEnc);
77 queryAndSetYUVCache(rcEnc);
78 queryAndSetAsyncUnmapBuffer(rcEnc);
79 queryAndSetVirtioGpuNext(rcEnc);
80 queryHasSharedSlotsHostMemoryAllocator(rcEnc);
81 queryAndSetVulkanFreeMemorySync(rcEnc);
82 queryAndSetVirtioGpuNativeSync(rcEnc);
83 queryAndSetVulkanShaderFloat16Int8Support(rcEnc);
84 queryAndSetVulkanAsyncQueueSubmitSupport(rcEnc);
85 queryAndSetHostSideTracingSupport(rcEnc);
86 queryAndSetAsyncFrameCommands(rcEnc);
87 queryAndSetVulkanQueueSubmitWithCommandsSupport(rcEnc);
88 queryAndSetVulkanBatchedDescriptorSetUpdateSupport(rcEnc);
89 queryAndSetSyncBufferData(rcEnc);
90 queryAndSetVulkanAsyncQsri(rcEnc);
91 queryAndSetReadColorBufferDma(rcEnc);
92 queryAndSetHWCMultiConfigs(rcEnc);
93 queryAndSetVulkanAuxCommandBufferMemory(rcEnc);
94 queryVersion(rcEnc);
95
96 rcEnc->rcSetPuid(rcEnc, getPuid());
97 }
98 return m_rcEnc.get();
99 }
100
s_getGLContext()101 gl_client_context_t* HostConnection::s_getGLContext() {
102 EGLThreadInfo* ti = getEGLThreadInfo();
103 if (ti->hostConn) {
104 return ti->hostConn->m_glEnc.get();
105 }
106 return NULL;
107 }
108
s_getGL2Context()109 gl2_client_context_t* HostConnection::s_getGL2Context() {
110 EGLThreadInfo* ti = getEGLThreadInfo();
111 if (ti->hostConn) {
112 return ti->hostConn->m_gl2Enc.get();
113 }
114 return NULL;
115 }
116
queryHostExtensions(ExtendedRCEncoderContext * rcEnc)117 const std::string& HostConnection::queryHostExtensions(ExtendedRCEncoderContext* rcEnc) {
118 if (!m_hostExtensions.empty()) {
119 return m_hostExtensions;
120 }
121
122 // Extensions strings are usually quite long, preallocate enough here.
123 std::string extensionsBuffer(1023, '\0');
124
125 // Returns the required size including the 0-terminator, so
126 // account it when passing/using the sizes.
127 int extensionSize =
128 rcEnc->rcGetHostExtensionsString(rcEnc, extensionsBuffer.size() + 1, &extensionsBuffer[0]);
129 if (extensionSize < 0) {
130 extensionsBuffer.resize(-extensionSize);
131 extensionSize =
132 rcEnc->rcGetHostExtensionsString(rcEnc, -extensionSize + 1, &extensionsBuffer[0]);
133 }
134
135 if (extensionSize > 0) {
136 extensionsBuffer.resize(extensionSize - 1);
137 m_hostExtensions.swap(extensionsBuffer);
138 }
139
140 return m_hostExtensions;
141 }
142
queryAndSetHostCompositionImpl(ExtendedRCEncoderContext * rcEnc)143 void HostConnection::queryAndSetHostCompositionImpl(ExtendedRCEncoderContext* rcEnc) {
144 const std::string& hostExtensions = queryHostExtensions(rcEnc);
145 ALOGV("HostComposition ext %s", hostExtensions.c_str());
146 // make sure V2 is checked first before V1, as host may declare supporting both
147 if (hostExtensions.find(kHostCompositionV2) != std::string::npos) {
148 rcEnc->setHostComposition(HOST_COMPOSITION_V2);
149 } else if (hostExtensions.find(kHostCompositionV1) != std::string::npos) {
150 rcEnc->setHostComposition(HOST_COMPOSITION_V1);
151 } else {
152 rcEnc->setHostComposition(HOST_COMPOSITION_NONE);
153 }
154 }
155
setChecksumHelper(ExtendedRCEncoderContext * rcEnc)156 void HostConnection::setChecksumHelper(ExtendedRCEncoderContext* rcEnc) {
157 const std::string& hostExtensions = queryHostExtensions(rcEnc);
158 // check the host supported version
159 uint32_t checksumVersion = 0;
160 const char* checksumPrefix = ChecksumCalculator::getMaxVersionStrPrefix();
161 const char* glProtocolStr = strstr(hostExtensions.c_str(), checksumPrefix);
162 if (glProtocolStr) {
163 uint32_t maxVersion = ChecksumCalculator::getMaxVersion();
164 sscanf(glProtocolStr + strlen(checksumPrefix), "%d", &checksumVersion);
165 if (maxVersion < checksumVersion) {
166 checksumVersion = maxVersion;
167 }
168 // The ordering of the following two commands matters!
169 // Must tell the host first before setting it in the guest
170 rcEnc->rcSelectChecksumHelper(rcEnc, checksumVersion, 0);
171 m_checksumHelper.setVersion(checksumVersion);
172 }
173 }
174
queryAndSetSyncImpl(ExtendedRCEncoderContext * rcEnc)175 void HostConnection::queryAndSetSyncImpl(ExtendedRCEncoderContext* rcEnc) {
176 const std::string& hostExtensions = queryHostExtensions(rcEnc);
177 if (hostExtensions.find(kRCNativeSyncV4) != std::string::npos) {
178 rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V4);
179 } else if (hostExtensions.find(kRCNativeSyncV3) != std::string::npos) {
180 rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V3);
181 } else if (hostExtensions.find(kRCNativeSyncV2) != std::string::npos) {
182 rcEnc->setSyncImpl(SYNC_IMPL_NATIVE_SYNC_V2);
183 } else {
184 rcEnc->setSyncImpl(SYNC_IMPL_NONE);
185 }
186 }
187
queryAndSetGLESMaxVersion(ExtendedRCEncoderContext * rcEnc)188 void HostConnection::queryAndSetGLESMaxVersion(ExtendedRCEncoderContext* rcEnc) {
189 std::string hostExtensions = queryHostExtensions(rcEnc);
190 if (hostExtensions.find(kGLESMaxVersion_2) != std::string::npos) {
191 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2);
192 } else if (hostExtensions.find(kGLESMaxVersion_3_0) != std::string::npos) {
193 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_0);
194 } else if (hostExtensions.find(kGLESMaxVersion_3_1) != std::string::npos) {
195 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_1);
196 } else if (hostExtensions.find(kGLESMaxVersion_3_2) != std::string::npos) {
197 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_3_2);
198 } else {
199 ALOGW("Unrecognized GLES max version string in extensions: %s", hostExtensions.c_str());
200 rcEnc->setGLESMaxVersion(GLES_MAX_VERSION_2);
201 }
202 }
203
queryAndSetNoErrorState(ExtendedRCEncoderContext * rcEnc)204 void HostConnection::queryAndSetNoErrorState(ExtendedRCEncoderContext* rcEnc) {
205 std::string hostExtensions = queryHostExtensions(rcEnc);
206 if (hostExtensions.find(kGLESUseHostError) != std::string::npos) {
207 m_noHostError = false;
208 }
209 }
210
queryAndSetDirectMemSupport(ExtendedRCEncoderContext * rcEnc)211 void HostConnection::queryAndSetDirectMemSupport(ExtendedRCEncoderContext* rcEnc) {
212 std::string hostExtensions = queryHostExtensions(rcEnc);
213 if (hostExtensions.find(kGLDirectMem) != std::string::npos) {
214 rcEnc->featureInfo()->hasDirectMem = true;
215 }
216 }
217
queryAndSetVulkanSupport(ExtendedRCEncoderContext * rcEnc)218 void HostConnection::queryAndSetVulkanSupport(ExtendedRCEncoderContext* rcEnc) {
219 std::string hostExtensions = queryHostExtensions(rcEnc);
220 if (hostExtensions.find(kVulkan) != std::string::npos) {
221 rcEnc->featureInfo()->hasVulkan = true;
222 }
223 }
224
queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext * rcEnc)225 void HostConnection::queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext* rcEnc) {
226 std::string hostExtensions = queryHostExtensions(rcEnc);
227 if (hostExtensions.find(kDeferredVulkanCommands) != std::string::npos) {
228 rcEnc->featureInfo()->hasDeferredVulkanCommands = true;
229 }
230 }
231
queryAndSetVulkanNullOptionalStringsSupport(ExtendedRCEncoderContext * rcEnc)232 void HostConnection::queryAndSetVulkanNullOptionalStringsSupport(ExtendedRCEncoderContext* rcEnc) {
233 std::string hostExtensions = queryHostExtensions(rcEnc);
234 if (hostExtensions.find(kVulkanNullOptionalStrings) != std::string::npos) {
235 rcEnc->featureInfo()->hasVulkanNullOptionalStrings = true;
236 }
237 }
238
queryAndSetVulkanCreateResourcesWithRequirementsSupport(ExtendedRCEncoderContext * rcEnc)239 void HostConnection::queryAndSetVulkanCreateResourcesWithRequirementsSupport(
240 ExtendedRCEncoderContext* rcEnc) {
241 std::string hostExtensions = queryHostExtensions(rcEnc);
242 if (hostExtensions.find(kVulkanCreateResourcesWithRequirements) != std::string::npos) {
243 rcEnc->featureInfo()->hasVulkanCreateResourcesWithRequirements = true;
244 }
245 }
246
queryAndSetVulkanIgnoredHandles(ExtendedRCEncoderContext * rcEnc)247 void HostConnection::queryAndSetVulkanIgnoredHandles(ExtendedRCEncoderContext* rcEnc) {
248 std::string hostExtensions = queryHostExtensions(rcEnc);
249 if (hostExtensions.find(kVulkanIgnoredHandles) != std::string::npos) {
250 rcEnc->featureInfo()->hasVulkanIgnoredHandles = true;
251 }
252 }
253
queryAndSetYUVCache(ExtendedRCEncoderContext * rcEnc)254 void HostConnection::queryAndSetYUVCache(ExtendedRCEncoderContext* rcEnc) {
255 std::string hostExtensions = queryHostExtensions(rcEnc);
256 if (hostExtensions.find(kYUVCache) != std::string::npos) {
257 rcEnc->featureInfo()->hasYUVCache = true;
258 }
259 }
260
queryAndSetAsyncUnmapBuffer(ExtendedRCEncoderContext * rcEnc)261 void HostConnection::queryAndSetAsyncUnmapBuffer(ExtendedRCEncoderContext* rcEnc) {
262 std::string hostExtensions = queryHostExtensions(rcEnc);
263 if (hostExtensions.find(kAsyncUnmapBuffer) != std::string::npos) {
264 rcEnc->featureInfo()->hasAsyncUnmapBuffer = true;
265 }
266 }
267
queryAndSetVirtioGpuNext(ExtendedRCEncoderContext * rcEnc)268 void HostConnection::queryAndSetVirtioGpuNext(ExtendedRCEncoderContext* rcEnc) {
269 std::string hostExtensions = queryHostExtensions(rcEnc);
270 if (hostExtensions.find(kVirtioGpuNext) != std::string::npos) {
271 rcEnc->featureInfo()->hasVirtioGpuNext = true;
272 }
273 }
274
queryHasSharedSlotsHostMemoryAllocator(ExtendedRCEncoderContext * rcEnc)275 void HostConnection::queryHasSharedSlotsHostMemoryAllocator(ExtendedRCEncoderContext* rcEnc) {
276 const std::string& hostExtensions = queryHostExtensions(rcEnc);
277 if (hostExtensions.find(kHasSharedSlotsHostMemoryAllocator) != std::string::npos) {
278 rcEnc->featureInfo()->hasSharedSlotsHostMemoryAllocator = true;
279 }
280 }
281
queryAndSetVulkanFreeMemorySync(ExtendedRCEncoderContext * rcEnc)282 void HostConnection::queryAndSetVulkanFreeMemorySync(ExtendedRCEncoderContext* rcEnc) {
283 const std::string& hostExtensions = queryHostExtensions(rcEnc);
284 if (hostExtensions.find(kVulkanFreeMemorySync) != std::string::npos) {
285 rcEnc->featureInfo()->hasVulkanFreeMemorySync = true;
286 }
287 }
288
queryAndSetVirtioGpuNativeSync(ExtendedRCEncoderContext * rcEnc)289 void HostConnection::queryAndSetVirtioGpuNativeSync(ExtendedRCEncoderContext* rcEnc) {
290 std::string hostExtensions = queryHostExtensions(rcEnc);
291 if (hostExtensions.find(kVirtioGpuNativeSync) != std::string::npos) {
292 rcEnc->featureInfo()->hasVirtioGpuNativeSync = true;
293 }
294 }
295
queryAndSetVulkanShaderFloat16Int8Support(ExtendedRCEncoderContext * rcEnc)296 void HostConnection::queryAndSetVulkanShaderFloat16Int8Support(ExtendedRCEncoderContext* rcEnc) {
297 std::string hostExtensions = queryHostExtensions(rcEnc);
298 if (hostExtensions.find(kVulkanShaderFloat16Int8) != std::string::npos) {
299 rcEnc->featureInfo()->hasVulkanShaderFloat16Int8 = true;
300 }
301 }
302
queryAndSetVulkanAsyncQueueSubmitSupport(ExtendedRCEncoderContext * rcEnc)303 void HostConnection::queryAndSetVulkanAsyncQueueSubmitSupport(ExtendedRCEncoderContext* rcEnc) {
304 std::string hostExtensions = queryHostExtensions(rcEnc);
305 if (hostExtensions.find(kVulkanAsyncQueueSubmit) != std::string::npos) {
306 rcEnc->featureInfo()->hasVulkanAsyncQueueSubmit = true;
307 }
308 }
309
queryAndSetHostSideTracingSupport(ExtendedRCEncoderContext * rcEnc)310 void HostConnection::queryAndSetHostSideTracingSupport(ExtendedRCEncoderContext* rcEnc) {
311 std::string hostExtensions = queryHostExtensions(rcEnc);
312 if (hostExtensions.find(kHostSideTracing) != std::string::npos) {
313 rcEnc->featureInfo()->hasHostSideTracing = true;
314 }
315 }
316
queryAndSetAsyncFrameCommands(ExtendedRCEncoderContext * rcEnc)317 void HostConnection::queryAndSetAsyncFrameCommands(ExtendedRCEncoderContext* rcEnc) {
318 std::string hostExtensions = queryHostExtensions(rcEnc);
319 if (hostExtensions.find(kAsyncFrameCommands) != std::string::npos) {
320 rcEnc->featureInfo()->hasAsyncFrameCommands = true;
321 }
322 }
323
queryAndSetVulkanQueueSubmitWithCommandsSupport(ExtendedRCEncoderContext * rcEnc)324 void HostConnection::queryAndSetVulkanQueueSubmitWithCommandsSupport(
325 ExtendedRCEncoderContext* rcEnc) {
326 std::string hostExtensions = queryHostExtensions(rcEnc);
327 if (hostExtensions.find(kVulkanQueueSubmitWithCommands) != std::string::npos) {
328 rcEnc->featureInfo()->hasVulkanQueueSubmitWithCommands = true;
329 }
330 }
331
queryAndSetVulkanBatchedDescriptorSetUpdateSupport(ExtendedRCEncoderContext * rcEnc)332 void HostConnection::queryAndSetVulkanBatchedDescriptorSetUpdateSupport(
333 ExtendedRCEncoderContext* rcEnc) {
334 std::string hostExtensions = queryHostExtensions(rcEnc);
335 if (hostExtensions.find(kVulkanBatchedDescriptorSetUpdate) != std::string::npos) {
336 rcEnc->featureInfo()->hasVulkanBatchedDescriptorSetUpdate = true;
337 }
338 }
339
queryAndSetSyncBufferData(ExtendedRCEncoderContext * rcEnc)340 void HostConnection::queryAndSetSyncBufferData(ExtendedRCEncoderContext* rcEnc) {
341 std::string hostExtensions = queryHostExtensions(rcEnc);
342 if (hostExtensions.find(kSyncBufferData) != std::string::npos) {
343 rcEnc->featureInfo()->hasSyncBufferData = true;
344 }
345 }
346
queryAndSetVulkanAsyncQsri(ExtendedRCEncoderContext * rcEnc)347 void HostConnection::queryAndSetVulkanAsyncQsri(ExtendedRCEncoderContext* rcEnc) {
348 std::string hostExtensions = queryHostExtensions(rcEnc);
349 if (hostExtensions.find(kVulkanAsyncQsri) != std::string::npos) {
350 rcEnc->featureInfo()->hasVulkanAsyncQsri = true;
351 }
352 }
353
queryAndSetReadColorBufferDma(ExtendedRCEncoderContext * rcEnc)354 void HostConnection::queryAndSetReadColorBufferDma(ExtendedRCEncoderContext* rcEnc) {
355 std::string hostExtensions = queryHostExtensions(rcEnc);
356 if (hostExtensions.find(kReadColorBufferDma) != std::string::npos) {
357 rcEnc->featureInfo()->hasReadColorBufferDma = true;
358 }
359 }
360
queryAndSetHWCMultiConfigs(ExtendedRCEncoderContext * rcEnc)361 void HostConnection::queryAndSetHWCMultiConfigs(ExtendedRCEncoderContext* rcEnc) {
362 std::string hostExtensions = queryHostExtensions(rcEnc);
363 if (hostExtensions.find(kHWCMultiConfigs) != std::string::npos) {
364 rcEnc->featureInfo()->hasHWCMultiConfigs = true;
365 }
366 }
367
queryAndSetVulkanAuxCommandBufferMemory(ExtendedRCEncoderContext * rcEnc)368 void HostConnection::queryAndSetVulkanAuxCommandBufferMemory(ExtendedRCEncoderContext* rcEnc) {
369 std::string hostExtensions = queryHostExtensions(rcEnc);
370 rcEnc->featureInfo()->hasVulkanAuxCommandMemory =
371 hostExtensions.find(kVulkanAuxCommandMemory) != std::string::npos;
372 }
373
queryVersion(ExtendedRCEncoderContext * rcEnc)374 GLint HostConnection::queryVersion(ExtendedRCEncoderContext* rcEnc) {
375 GLint version = m_rcEnc->rcGetRendererVersion(m_rcEnc.get());
376 return version;
377 }
378