• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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