1 /*
2 * Copyright (C) 2011 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 "RenderControl.h"
18 
19 #include <inttypes.h>
20 #include <string.h>
21 
22 #include <atomic>
23 #include <limits>
24 #include <memory>
25 
26 #include "ChecksumCalculatorThreadInfo.h"
27 #include "FrameBuffer.h"
28 #include "GLESVersionDetector.h"
29 #include "OpenGLESDispatch/DispatchTables.h"
30 #include "OpenGLESDispatch/EGLDispatch.h"
31 #include "RenderThreadInfo.h"
32 #include "RenderThreadInfoGl.h"
33 #include "SyncThread.h"
34 #include "aemu/base/Tracing.h"
35 #include "host-common/logging.h"
36 #include "host-common/misc.h"
37 #include "host-common/opengl/misc.h"
38 #include "host-common/sync_device.h"
39 #include "compressedTextureFormats/AstcCpuDecompressor.h"
40 #include "vulkan/VkCommonOperations.h"
41 #include "vulkan/VkDecoderGlobalState.h"
42 
43 namespace gfxstream {
44 
45 using android::base::AutoLock;
46 using android::base::Lock;
47 using emugl::emugl_sync_device_exists;
48 using emugl::emugl_sync_register_trigger_wait;
49 using gl::EmulatedEglFenceSync;
50 using gl::GLES_DISPATCH_MAX_VERSION_2;
51 using gl::GLES_DISPATCH_MAX_VERSION_3_0;
52 using gl::GLES_DISPATCH_MAX_VERSION_3_1;
53 using gl::GLESApi;
54 using gl::GLESApi_CM;
55 using gl::GLESDispatchMaxVersion;
56 using gl::RenderThreadInfoGl;
57 
58 #define DEBUG 0
59 #define DEBUG_GRALLOC_SYNC 0
60 #define DEBUG_EGL_SYNC 0
61 
62 #define RENDERCONTROL_DPRINT(...)         \
63     do {                                  \
64         if (DEBUG) {                      \
65             fprintf(stderr, __VA_ARGS__); \
66         }                                 \
67     } while (0)
68 
69 #if DEBUG_GRALLOC_SYNC
70 #define GRSYNC_DPRINT RENDERCONTROL_DPRINT
71 #else
72 #define GRSYNC_DPRINT(...)
73 #endif
74 
75 #if DEBUG_EGL_SYNC
76 #define EGLSYNC_DPRINT RENDERCONTROL_DPRINT
77 #else
78 #define EGLSYNC_DPRINT(...)
79 #endif
80 
81 // GrallocSync is a class that helps to reflect the behavior of
82 // gralloc_lock/gralloc_unlock on the guest.
83 // If we don't use this, apps that use gralloc buffers (such as webcam)
84 // will have out-of-order frames,
85 // as GL calls from different threads in the guest
86 // are allowed to arrive at the host in any ordering.
87 class GrallocSync {
88 public:
GrallocSync()89     GrallocSync() {
90         // Having in-order webcam frames is nice, but not at the cost
91         // of potential deadlocks;
92         // we need to be careful of what situations in which
93         // we actually lock/unlock the gralloc color buffer.
94         //
95         // To avoid deadlock:
96         // we require rcColorBufferCacheFlush to be called
97         // whenever gralloc_lock is called on the guest,
98         // and we require rcUpdateWindowColorBuffer to be called
99         // whenever gralloc_unlock is called on the guest.
100         //
101         // Some versions of the system image optimize out
102         // the call to rcUpdateWindowColorBuffer in the case of zero
103         // width/height, but since we're using that as synchronization,
104         // that lack of calling can lead to a deadlock on the host
105         // in many situations
106         // (switching camera sides, exiting benchmark apps, etc).
107         // So, we put GrallocSync under the feature control.
108         mEnabled = FrameBuffer::getFB()->getFeatures().GrallocSync.enabled;
109 
110         // There are two potential tricky situations to handle:
111         // a. Multiple users of gralloc buffers that all want to
112         // call gralloc_lock. This is obeserved to happen on older APIs
113         // (<= 19).
114         // b. The pipe doesn't have to preserve ordering of the
115         // gralloc_lock and gralloc_unlock commands themselves.
116         //
117         // To handle a), notice the situation is one of one type of user
118         // needing multiple locks that needs to exclude concurrent use
119         // by another type of user. This maps well to a read/write lock,
120         // where gralloc_lock and gralloc_unlock users are readers
121         // and rcFlushWindowColorBuffer is the writer.
122         // From the perspective of the host preparing and posting
123         // buffers, these are indeed read/write operations.
124         //
125         // To handle b), we give up on locking when the state is observed
126         // to be bad. lockState tracks how many color buffer locks there are.
127         // If lockState < 0, it means we definitely have an unlock before lock
128         // sort of situation, and should give up.
129         lockState = 0;
130     }
131 
132     // lockColorBufferPrepare is designed to handle
133     // gralloc_lock/unlock requests, and uses the read lock.
134     // When rcFlushWindowColorBuffer is called (when frames are posted),
135     // we use the write lock (see GrallocSyncPostLock).
lockColorBufferPrepare()136     void lockColorBufferPrepare() {
137         int newLockState = ++lockState;
138         if (mEnabled && newLockState == 1) {
139             mGrallocColorBufferLock.lockRead();
140         } else if (mEnabled) {
141             GRSYNC_DPRINT("warning: recursive/multiple locks from guest!");
142         }
143     }
unlockColorBufferPrepare()144     void unlockColorBufferPrepare() {
145         int newLockState = --lockState;
146         if (mEnabled && newLockState == 0) mGrallocColorBufferLock.unlockRead();
147     }
148     android::base::ReadWriteLock mGrallocColorBufferLock;
149 private:
150     bool mEnabled;
151     std::atomic<int> lockState;
152     DISALLOW_COPY_ASSIGN_AND_MOVE(GrallocSync);
153 };
154 
155 class GrallocSyncPostLock : public android::base::AutoWriteLock {
156 public:
GrallocSyncPostLock(GrallocSync & grallocsync)157     GrallocSyncPostLock(GrallocSync& grallocsync) :
158         android::base::AutoWriteLock(grallocsync.mGrallocColorBufferLock) { }
159 };
160 
sGrallocSync()161 static GrallocSync* sGrallocSync() {
162     static GrallocSync* g = new GrallocSync;
163     return g;
164 }
165 
166 static const GLint rendererVersion = 1;
167 
168 // GLAsyncSwap version history:
169 // "ANDROID_EMU_NATIVE_SYNC": original version
170 // "ANDROIDEMU_native_sync_v2": +cleanup of sync objects
171 // "ANDROIDEMU_native_sync_v3": EGL_KHR_wait_sync
172 // "ANDROIDEMU_native_sync_v4": Correct eglGetSyncAttrib via rcIsSyncSignaled
173 // (We need all the different strings to not be prefixes of any other
174 // due to how they are checked for in the GL extensions on the guest)
175 static const char* kAsyncSwapStrV2 = "ANDROID_EMU_native_sync_v2";
176 static const char* kAsyncSwapStrV3 = "ANDROID_EMU_native_sync_v3";
177 static const char* kAsyncSwapStrV4 = "ANDROID_EMU_native_sync_v4";
178 
179 // DMA version history:
180 // "ANDROID_EMU_dma_v1": add dma device and rcUpdateColorBufferDMA and do
181 // yv12 conversion on the GPU
182 // "ANDROID_EMU_dma_v2": adds DMA support glMapBufferRange (and unmap)
183 static const char* kDma1Str = "ANDROID_EMU_dma_v1";
184 static const char* kDma2Str = "ANDROID_EMU_dma_v2";
185 static const char* kDirectMemStr = "ANDROID_EMU_direct_mem";
186 
187 // GLESDynamicVersion: up to 3.1 so far
188 static const char* kGLESDynamicVersion_2 = "ANDROID_EMU_gles_max_version_2";
189 static const char* kGLESDynamicVersion_3_0 = "ANDROID_EMU_gles_max_version_3_0";
190 static const char* kGLESDynamicVersion_3_1 = "ANDROID_EMU_gles_max_version_3_1";
191 
192 // HWComposer Host Composition
193 static const char* kHostCompositionV1 = "ANDROID_EMU_host_composition_v1";
194 static const char* kHostCompositionV2 = "ANDROID_EMU_host_composition_v2";
195 
196 // Vulkan
197 static const char* kVulkanFeatureStr = "ANDROID_EMU_vulkan";
198 static const char* kDeferredVulkanCommands = "ANDROID_EMU_deferred_vulkan_commands";
199 static const char* kVulkanNullOptionalStrings = "ANDROID_EMU_vulkan_null_optional_strings";
200 static const char* kVulkanCreateResourcesWithRequirements = "ANDROID_EMU_vulkan_create_resources_with_requirements";
201 
202 // treat YUV420_888 as NV21
203 static const char* kYUV420888toNV21 = "ANDROID_EMU_YUV420_888_to_NV21";
204 
205 // Cache YUV frame
206 static const char* kYUVCache = "ANDROID_EMU_YUV_Cache";
207 
208 // GL protocol v2
209 static const char* kAsyncUnmapBuffer = "ANDROID_EMU_async_unmap_buffer";
210 // Vulkan: Correct marshaling for ignored handles
211 static const char* kVulkanIgnoredHandles = "ANDROID_EMU_vulkan_ignored_handles";
212 
213 // virtio-gpu-next
214 static const char* kVirtioGpuNext = "ANDROID_EMU_virtio_gpu_next";
215 
216 // address space subdevices
217 static const char* kHasSharedSlotsHostMemoryAllocator = "ANDROID_EMU_has_shared_slots_host_memory_allocator";
218 
219 // vulkan free memory sync
220 static const char* kVulkanFreeMemorySync = "ANDROID_EMU_vulkan_free_memory_sync";
221 
222 // virtio-gpu native sync
223 static const char* kVirtioGpuNativeSync = "ANDROID_EMU_virtio_gpu_native_sync";
224 
225 // Struct defs for VK_KHR_shader_float16_int8
226 static const char* kVulkanShaderFloat16Int8 = "ANDROID_EMU_vulkan_shader_float16_int8";
227 
228 // Async queue submit
229 static const char* kVulkanAsyncQueueSubmit = "ANDROID_EMU_vulkan_async_queue_submit";
230 
231 // Host side tracing
232 static const char* kHostSideTracing = "ANDROID_EMU_host_side_tracing";
233 
234 // Some frame commands we can easily make async
235 // rcMakeCurrent
236 // rcCompose
237 // rcDestroySyncKHR
238 static const char* kAsyncFrameCommands = "ANDROID_EMU_async_frame_commands";
239 
240 // Queue submit with commands
241 static const char* kVulkanQueueSubmitWithCommands = "ANDROID_EMU_vulkan_queue_submit_with_commands";
242 
243 // Batched descriptor set update
244 static const char* kVulkanBatchedDescriptorSetUpdate = "ANDROID_EMU_vulkan_batched_descriptor_set_update";
245 
246 // Synchronized glBufferData call
247 static const char* kSyncBufferData = "ANDROID_EMU_sync_buffer_data";
248 
249 // Async vkQSRI
250 static const char* kVulkanAsyncQsri = "ANDROID_EMU_vulkan_async_qsri";
251 
252 // Read color buffer DMA
253 static const char* kReadColorBufferDma = "ANDROID_EMU_read_color_buffer_dma";
254 
255 // Multiple display configs
256 static const char* kHWCMultiConfigs= "ANDROID_EMU_hwc_multi_configs";
257 
258 static constexpr const uint64_t kInvalidPUID = std::numeric_limits<uint64_t>::max();
259 
260 static void rcTriggerWait(uint64_t glsync_ptr,
261                           uint64_t thread_ptr,
262                           uint64_t timeline);
263 
registerTriggerWait()264 void registerTriggerWait() {
265     emugl_sync_register_trigger_wait(rcTriggerWait);
266 }
267 
rcGetRendererVersion()268 static GLint rcGetRendererVersion()
269 {
270     registerTriggerWait();
271 
272     sGrallocSync();
273     return rendererVersion;
274 }
275 
rcGetEGLVersion(EGLint * major,EGLint * minor)276 static EGLint rcGetEGLVersion(EGLint* major, EGLint* minor)
277 {
278     FrameBuffer *fb = FrameBuffer::getFB();
279     if (!fb) {
280         return EGL_FALSE;
281     }
282     fb->getEmulationGl().getEglVersion(major, minor);
283 
284     return EGL_TRUE;
285 }
286 
rcQueryEGLString(EGLenum name,void * buffer,EGLint bufferSize)287 static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize)
288 {
289     FrameBuffer *fb = FrameBuffer::getFB();
290     if (!fb) {
291         return 0;
292     }
293 
294     const char* str = gl::s_egl.eglQueryString(fb->getDisplay(), name);
295     if (!str) {
296         return 0;
297     }
298 
299     std::string eglStr(str);
300     if ((fb->getMaxGLESVersion() >= GLES_DISPATCH_MAX_VERSION_3_0) &&
301         fb->getFeatures().GlesDynamicVersion.enabled &&
302         eglStr.find("EGL_KHR_create_context") == std::string::npos) {
303         eglStr += "EGL_KHR_create_context ";
304     }
305 
306     int len = eglStr.size() + 1;
307     if (!buffer || len > bufferSize) {
308         return -len;
309     }
310 
311     strcpy((char *)buffer, eglStr.c_str());
312     return len;
313 }
314 
shouldEnableAsyncSwap(const gfxstream::host::FeatureSet & features)315 static bool shouldEnableAsyncSwap(const gfxstream::host::FeatureSet& features) {
316     bool isPhone = true;
317     bool playStoreImage = features.PlayStoreImage.enabled;
318     return features.GlAsyncSwap.enabled &&
319            emugl_sync_device_exists() && (isPhone || playStoreImage) &&
320            sizeof(void*) == 8;
321 }
322 
shouldEnableVulkan(const gfxstream::host::FeatureSet & features)323 static bool shouldEnableVulkan(const gfxstream::host::FeatureSet& features) {
324     // TODO: Restrict further to devices supporting external memory.
325     return features.Vulkan.enabled && vk::getGlobalVkEmulation() &&
326            vk::VkDecoderGlobalState::get()->getHostFeatureSupport().supportsVulkan;
327 }
328 
shouldEnableDeferredVulkanCommands()329 static bool shouldEnableDeferredVulkanCommands() {
330     auto supportInfo = vk::VkDecoderGlobalState::get()->getHostFeatureSupport();
331     return supportInfo.supportsVulkan &&
332            supportInfo.useDeferredCommands;
333 }
334 
shouldEnableCreateResourcesWithRequirements()335 static bool shouldEnableCreateResourcesWithRequirements() {
336     auto supportInfo = vk::VkDecoderGlobalState::get()->getHostFeatureSupport();
337     return supportInfo.supportsVulkan &&
338            supportInfo.useCreateResourcesWithRequirements;
339 }
340 
shouldEnableVulkanShaderFloat16Int8(const gfxstream::host::FeatureSet & features)341 static bool shouldEnableVulkanShaderFloat16Int8(const gfxstream::host::FeatureSet& features) {
342     return shouldEnableVulkan(features) && features.VulkanShaderFloat16Int8.enabled;
343 }
344 
shouldEnableAsyncQueueSubmit(const gfxstream::host::FeatureSet & features)345 static bool shouldEnableAsyncQueueSubmit(const gfxstream::host::FeatureSet& features) {
346     return shouldEnableVulkan(features);
347 }
348 
shouldEnableVulkanAsyncQsri(const gfxstream::host::FeatureSet & features)349 static bool shouldEnableVulkanAsyncQsri(const gfxstream::host::FeatureSet& features) {
350     return shouldEnableVulkan(features) &&
351         (features.GlAsyncSwap.enabled ||
352          (features.VirtioGpuNativeSync.enabled &&
353           features.VirtioGpuFenceContexts.enabled));
354 }
355 
shouldEnableVsyncGatedSyncFences(const gfxstream::host::FeatureSet & features)356 static bool shouldEnableVsyncGatedSyncFences(const gfxstream::host::FeatureSet& features) {
357     return shouldEnableAsyncSwap(features);
358 }
359 
maxVersionToFeatureString(GLESDispatchMaxVersion version)360 const char* maxVersionToFeatureString(GLESDispatchMaxVersion version) {
361     switch (version) {
362         case GLES_DISPATCH_MAX_VERSION_2:
363             return kGLESDynamicVersion_2;
364         case GLES_DISPATCH_MAX_VERSION_3_0:
365             return kGLESDynamicVersion_3_0;
366         case GLES_DISPATCH_MAX_VERSION_3_1:
367             return kGLESDynamicVersion_3_1;
368         default:
369             return kGLESDynamicVersion_2;
370     }
371 }
372 
shouldEnableQueueSubmitWithCommands(const gfxstream::host::FeatureSet & features)373 static bool shouldEnableQueueSubmitWithCommands(const gfxstream::host::FeatureSet& features) {
374     return shouldEnableVulkan(features) && features.VulkanQueueSubmitWithCommands.enabled;
375 }
376 
shouldEnableBatchedDescriptorSetUpdate(const gfxstream::host::FeatureSet & features)377 static bool shouldEnableBatchedDescriptorSetUpdate(const gfxstream::host::FeatureSet& features) {
378     return shouldEnableVulkan(features) &&
379         shouldEnableQueueSubmitWithCommands(features) &&
380         features.VulkanBatchedDescriptorSetUpdate.enabled;
381 }
382 
383 // OpenGL ES 3.x support involves changing the GL_VERSION string, which is
384 // assumed to be formatted in the following way:
385 // "OpenGL ES-CM 1.m <vendor-info>" or
386 // "OpenGL ES M.m <vendor-info>"
387 // where M is the major version number and m is minor version number.  If the
388 // GL_VERSION string doesn't reflect the maximum available version of OpenGL
389 // ES, many apps will not be able to detect support.  We need to mess with the
390 // version string in the first place since the underlying backend (whether it
391 // is Translator, SwiftShader, ANGLE, et al) may not advertise a GL_VERSION
392 // string reflecting their maximum capabilities.
replaceESVersionString(const std::string & prev,const std::string & newver)393 std::string replaceESVersionString(const std::string& prev,
394                                    const std::string& newver) {
395 
396     // There is no need to fiddle with the string
397     // if we are in a ES 1.x context.
398     // Such contexts are considered as a special case that must
399     // be untouched.
400     if (prev.find("ES-CM") != std::string::npos) {
401         return prev;
402     }
403 
404     size_t esStart = prev.find("ES ");
405     size_t esEnd = prev.find(" ", esStart + 3);
406 
407     if (esStart == std::string::npos ||
408         esEnd == std::string::npos) {
409         // Account for out-of-spec version strings.
410         fprintf(stderr, "%s: Error: invalid OpenGL ES version string %s\n",
411                 __func__, prev.c_str());
412         return prev;
413     }
414 
415     std::string res = prev.substr(0, esStart + 3);
416     res += newver;
417     res += prev.substr(esEnd);
418 
419     return res;
420 }
421 
422 // If the GLES3 feature is disabled, we also want to splice out
423 // OpenGL extensions that should not appear in a GLES2 system.
removeExtension(std::string & currExts,const std::string & toRemove)424 void removeExtension(std::string& currExts, const std::string& toRemove) {
425     size_t pos = currExts.find(toRemove);
426 
427     if (pos != std::string::npos)
428         currExts.erase(pos, toRemove.length());
429 }
430 
rcGetGLString(EGLenum name,void * buffer,EGLint bufferSize)431 static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) {
432     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
433 
434     // whatever we end up returning,
435     // it will have a terminating \0,
436     // so account for it here.
437     std::string glStr;
438 
439     if (tInfo && tInfo->currContext.get()) {
440         const char *str = nullptr;
441         if (tInfo->currContext->clientVersion() > GLESApi_CM) {
442             str = (const char*)gl::s_gles2.glGetString(name);
443         }
444         else {
445             str = (const char*)gl::s_gles1.glGetString(name);
446         }
447         if (str) {
448             glStr += str;
449         }
450     }
451 
452     FrameBuffer* fb = FrameBuffer::getFB();
453 
454     const gfxstream::host::FeatureSet& features = fb->getFeatures();
455 
456     // We add the maximum supported GL protocol number into GL_EXTENSIONS
457 
458     // filter extensions by name to match guest-side support
459     GLESDispatchMaxVersion maxVersion = fb->getMaxGLESVersion();
460     if (name == GL_EXTENSIONS) {
461         glStr = gl::filterExtensionsBasedOnMaxVersion(features, maxVersion, glStr);
462     }
463 
464     bool isChecksumEnabled = features.GlPipeChecksum.enabled;
465     bool asyncSwapEnabled = shouldEnableAsyncSwap(features);
466     bool virtioGpuNativeSyncEnabled = features.VirtioGpuNativeSync.enabled;
467     bool dma1Enabled = features.GlDma.enabled;
468     bool dma2Enabled = features.GlDma2.enabled;
469     bool directMemEnabled = features.GlDirectMem.enabled;
470     bool hostCompositionEnabled = features.HostComposition.enabled;
471     bool vulkanEnabled = shouldEnableVulkan(features);
472     bool deferredVulkanCommandsEnabled =
473         shouldEnableVulkan(features) && shouldEnableDeferredVulkanCommands();
474     bool vulkanNullOptionalStringsEnabled =
475         shouldEnableVulkan(features) && features.VulkanNullOptionalStrings.enabled;
476     bool vulkanCreateResourceWithRequirementsEnabled =
477         shouldEnableVulkan(features) && shouldEnableCreateResourcesWithRequirements();
478     bool YUV420888toNV21Enabled = features.Yuv420888ToNv21.enabled;
479     bool YUVCacheEnabled = features.YuvCache.enabled;
480     bool AsyncUnmapBufferEnabled = features.AsyncComposeSupport.enabled;
481     bool vulkanIgnoredHandlesEnabled =
482         shouldEnableVulkan(features) && features.VulkanIgnoredHandles.enabled;
483     bool virtioGpuNextEnabled = features.VirtioGpuNext.enabled;
484     bool hasSharedSlotsHostMemoryAllocatorEnabled =
485         features.HasSharedSlotsHostMemoryAllocator.enabled;
486     bool vulkanFreeMemorySyncEnabled =
487         shouldEnableVulkan(features);
488     bool vulkanShaderFloat16Int8Enabled = shouldEnableVulkanShaderFloat16Int8(features);
489     bool vulkanAsyncQueueSubmitEnabled = shouldEnableAsyncQueueSubmit(features);
490     bool vulkanQueueSubmitWithCommands = shouldEnableQueueSubmitWithCommands(features);
491     bool vulkanBatchedDescriptorSetUpdate = shouldEnableBatchedDescriptorSetUpdate(features);
492     bool syncBufferDataEnabled = true;
493     bool vulkanAsyncQsri = shouldEnableVulkanAsyncQsri(features);
494     bool readColorBufferDma = directMemEnabled && hasSharedSlotsHostMemoryAllocatorEnabled;
495     bool hwcMultiConfigs = features.HwcMultiConfigs.enabled;
496 
497     if (isChecksumEnabled && name == GL_EXTENSIONS) {
498         glStr += ChecksumCalculatorThreadInfo::getMaxVersionString();
499         glStr += " ";
500     }
501 
502     if (asyncSwapEnabled && name == GL_EXTENSIONS) {
503         glStr += kAsyncSwapStrV2;
504         glStr += " "; // for compatibility with older system images
505         // Only enable EGL_KHR_wait_sync (and above) for host gpu.
506         if (emugl::getRenderer() == SELECTED_RENDERER_HOST) {
507             glStr += kAsyncSwapStrV3;
508             glStr += " ";
509             glStr += kAsyncSwapStrV4;
510             glStr += " ";
511         }
512     }
513 
514     if (dma1Enabled && name == GL_EXTENSIONS) {
515         glStr += kDma1Str;
516         glStr += " ";
517     }
518 
519     if (dma2Enabled && name == GL_EXTENSIONS) {
520         glStr += kDma2Str;
521         glStr += " ";
522     }
523 
524     if (directMemEnabled && name == GL_EXTENSIONS) {
525         glStr += kDirectMemStr;
526         glStr += " ";
527     }
528 
529     if (hostCompositionEnabled && name == GL_EXTENSIONS) {
530         glStr += kHostCompositionV1;
531         glStr += " ";
532     }
533 
534     if (hostCompositionEnabled && name == GL_EXTENSIONS) {
535         glStr += kHostCompositionV2;
536         glStr += " ";
537     }
538 
539     if (vulkanEnabled && name == GL_EXTENSIONS) {
540         glStr += kVulkanFeatureStr;
541         glStr += " ";
542     }
543 
544     if (deferredVulkanCommandsEnabled && name == GL_EXTENSIONS) {
545         glStr += kDeferredVulkanCommands;
546         glStr += " ";
547     }
548 
549     if (vulkanNullOptionalStringsEnabled && name == GL_EXTENSIONS) {
550         glStr += kVulkanNullOptionalStrings;
551         glStr += " ";
552     }
553 
554     if (vulkanCreateResourceWithRequirementsEnabled && name == GL_EXTENSIONS) {
555         glStr += kVulkanCreateResourcesWithRequirements;
556         glStr += " ";
557     }
558 
559     if (YUV420888toNV21Enabled && name == GL_EXTENSIONS) {
560         glStr += kYUV420888toNV21;
561         glStr += " ";
562     }
563 
564     if (YUVCacheEnabled && name == GL_EXTENSIONS) {
565         glStr += kYUVCache;
566         glStr += " ";
567     }
568 
569     if (AsyncUnmapBufferEnabled && name == GL_EXTENSIONS) {
570         glStr += kAsyncUnmapBuffer;
571         glStr += " ";
572     }
573 
574     if (vulkanIgnoredHandlesEnabled && name == GL_EXTENSIONS) {
575         glStr += kVulkanIgnoredHandles;
576         glStr += " ";
577     }
578 
579     if (virtioGpuNextEnabled && name == GL_EXTENSIONS) {
580         glStr += kVirtioGpuNext;
581         glStr += " ";
582     }
583 
584     if (hasSharedSlotsHostMemoryAllocatorEnabled && name == GL_EXTENSIONS) {
585         glStr += kHasSharedSlotsHostMemoryAllocator;
586         glStr += " ";
587     }
588 
589     if (vulkanFreeMemorySyncEnabled && name == GL_EXTENSIONS) {
590         glStr += kVulkanFreeMemorySync;
591         glStr += " ";
592     }
593 
594     if (vulkanShaderFloat16Int8Enabled && name == GL_EXTENSIONS) {
595         glStr += kVulkanShaderFloat16Int8;
596         glStr += " ";
597     }
598 
599     if (vulkanAsyncQueueSubmitEnabled && name == GL_EXTENSIONS) {
600         glStr += kVulkanAsyncQueueSubmit;
601         glStr += " ";
602     }
603 
604     if (vulkanQueueSubmitWithCommands && name == GL_EXTENSIONS) {
605         glStr += kVulkanQueueSubmitWithCommands;
606         glStr += " ";
607     }
608 
609     if (vulkanBatchedDescriptorSetUpdate && name == GL_EXTENSIONS) {
610         glStr += kVulkanBatchedDescriptorSetUpdate;
611         glStr += " ";
612     }
613 
614     if (virtioGpuNativeSyncEnabled && name == GL_EXTENSIONS) {
615         glStr += kVirtioGpuNativeSync;
616         glStr += " ";
617     }
618 
619     if (syncBufferDataEnabled && name == GL_EXTENSIONS) {
620         glStr += kSyncBufferData;
621         glStr += " ";
622     }
623 
624     if (vulkanAsyncQsri && name == GL_EXTENSIONS) {
625         glStr += kVulkanAsyncQsri;
626         glStr += " ";
627     }
628 
629     if (readColorBufferDma && name == GL_EXTENSIONS) {
630         glStr += kReadColorBufferDma;
631         glStr += " ";
632     }
633 
634     if (hwcMultiConfigs && name == GL_EXTENSIONS) {
635         glStr += kHWCMultiConfigs;
636         glStr += " ";
637     }
638 
639     if (name == GL_EXTENSIONS) {
640         GLESDispatchMaxVersion guestExtVer = GLES_DISPATCH_MAX_VERSION_2;
641         if (features.GlesDynamicVersion.enabled) {
642             // If the image is in ES 3 mode, add GL_OES_EGL_image_external_essl3 for better Skia support.
643             glStr += "GL_OES_EGL_image_external_essl3 ";
644             guestExtVer = maxVersion;
645         }
646 
647         // If we have a GLES3 implementation, add the corresponding
648         // GLESv2 extensions as well.
649         if (maxVersion > GLES_DISPATCH_MAX_VERSION_2) {
650             glStr += "GL_OES_vertex_array_object ";
651         }
652 
653         // ASTC LDR compressed texture support.
654         const std::string& glExtensions =
655             FrameBuffer::getFB()->hasEmulationGl()
656                 ? FrameBuffer::getFB()->getEmulationGl().getGlesExtensionsString()
657                 : "<no GL emulation>";
658         const bool hasNativeAstc =
659             glExtensions.find("GL_KHR_texture_compression_astc_ldr") != std::string::npos;
660         const bool hasAstcDecompressor = vk::AstcCpuDecompressor::get().available();
661         if (hasNativeAstc || hasAstcDecompressor) {
662             glStr += "GL_KHR_texture_compression_astc_ldr ";
663         } else {
664             RENDERCONTROL_DPRINT(
665                 "rcGetGLString: ASTC not supported. CPU decompressor? %d. GL extensions: %s",
666                 hasAstcDecompressor, glExtensions.c_str());
667         }
668 
669         // Host side tracing support.
670         glStr += kHostSideTracing;
671         glStr += " ";
672 
673         if (features.AsyncComposeSupport.enabled) {
674             // Async makecurrent support.
675             glStr += kAsyncFrameCommands;
676             glStr += " ";
677         }
678 
679         glStr += maxVersionToFeatureString(guestExtVer);
680         glStr += " ";
681     }
682 
683     if (name == GL_VERSION) {
684         if (features.GlesDynamicVersion.enabled) {
685             switch (maxVersion) {
686             // Underlying GLES implmentation's max version string
687             // is allowed to be higher than the version of the request
688             // for the context---it can create a higher version context,
689             // and return simply the max possible version overall.
690             case GLES_DISPATCH_MAX_VERSION_2:
691                 glStr = replaceESVersionString(glStr, "2.0");
692                 break;
693             case GLES_DISPATCH_MAX_VERSION_3_0:
694                 glStr = replaceESVersionString(glStr, "3.0");
695                 break;
696             case GLES_DISPATCH_MAX_VERSION_3_1:
697                 glStr = replaceESVersionString(glStr, "3.1");
698                 break;
699             default:
700                 break;
701             }
702         } else {
703             glStr = replaceESVersionString(glStr, "2.0");
704         }
705     }
706 
707     int nextBufferSize = glStr.size() + 1;
708 
709     if (!buffer || nextBufferSize > bufferSize) {
710         return -nextBufferSize;
711     }
712 
713     snprintf((char *)buffer, nextBufferSize, "%s", glStr.c_str());
714     return nextBufferSize;
715 }
716 
rcGetNumConfigs(uint32_t * p_numAttribs)717 static EGLint rcGetNumConfigs(uint32_t* p_numAttribs)
718 {
719     int numConfigs = 0, numAttribs = 0;
720 
721     FrameBuffer::getFB()->getConfigs()->getPackInfo(&numConfigs, &numAttribs);
722     if (p_numAttribs) {
723         *p_numAttribs = static_cast<uint32_t>(numAttribs);
724     }
725     return numConfigs;
726 }
727 
rcGetConfigs(uint32_t bufSize,GLuint * buffer)728 static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer)
729 {
730     GLuint bufferSize = (GLuint)bufSize;
731     return FrameBuffer::getFB()->getConfigs()->packConfigs(bufferSize, buffer);
732 }
733 
rcChooseConfig(EGLint * attribs,uint32_t attribs_size,uint32_t * configs,uint32_t configs_size)734 static EGLint rcChooseConfig(EGLint *attribs,
735                              uint32_t attribs_size,
736                              uint32_t *configs,
737                              uint32_t configs_size)
738 {
739     FrameBuffer *fb = FrameBuffer::getFB();
740     if (!fb) {
741         return 0;
742     }
743 
744     if (attribs_size == 0) {
745         if (configs && configs_size > 0) {
746             // Pick the first config
747             *configs = 0;
748             if (attribs) *attribs = EGL_NONE;
749         }
750     }
751 
752     return fb->getConfigs()->chooseConfig(
753             attribs, (EGLint*)configs, (EGLint)configs_size);
754 }
755 
rcGetFBParam(EGLint param)756 static EGLint rcGetFBParam(EGLint param)
757 {
758     FrameBuffer *fb = FrameBuffer::getFB();
759     if (!fb) {
760         return 0;
761     }
762     return fb->getDisplayConfigsParam(0, param);
763 }
764 
rcCreateContext(uint32_t config,uint32_t share,uint32_t glVersion)765 static uint32_t rcCreateContext(uint32_t config,
766                                 uint32_t share, uint32_t glVersion)
767 {
768     FrameBuffer *fb = FrameBuffer::getFB();
769     if (!fb) {
770         return 0;
771     }
772 
773     HandleType ret = fb->createEmulatedEglContext(config, share, (GLESApi)glVersion);
774     return ret;
775 }
776 
rcDestroyContext(uint32_t context)777 static void rcDestroyContext(uint32_t context)
778 {
779     FrameBuffer *fb = FrameBuffer::getFB();
780     if (!fb) {
781         return;
782     }
783 
784     fb->destroyEmulatedEglContext(context);
785 }
786 
rcCreateWindowSurface(uint32_t config,uint32_t width,uint32_t height)787 static uint32_t rcCreateWindowSurface(uint32_t config,
788                                       uint32_t width, uint32_t height)
789 {
790     FrameBuffer *fb = FrameBuffer::getFB();
791     if (!fb) {
792         return 0;
793     }
794 
795     return fb->createEmulatedEglWindowSurface(config, width, height);
796 }
797 
rcDestroyWindowSurface(uint32_t windowSurface)798 static void rcDestroyWindowSurface(uint32_t windowSurface)
799 {
800     FrameBuffer *fb = FrameBuffer::getFB();
801     if (!fb) {
802         return;
803     }
804 
805     fb->destroyEmulatedEglWindowSurface(windowSurface);
806 }
807 
rcCreateColorBuffer(uint32_t width,uint32_t height,GLenum internalFormat)808 static uint32_t rcCreateColorBuffer(uint32_t width,
809                                     uint32_t height, GLenum internalFormat)
810 {
811     FrameBuffer *fb = FrameBuffer::getFB();
812     if (!fb) {
813         return 0;
814     }
815 
816     return fb->createColorBuffer(width, height, internalFormat,
817                                  FRAMEWORK_FORMAT_GL_COMPATIBLE);
818 }
819 
rcCreateColorBufferDMA(uint32_t width,uint32_t height,GLenum internalFormat,int frameworkFormat)820 static uint32_t rcCreateColorBufferDMA(uint32_t width,
821                                        uint32_t height, GLenum internalFormat,
822                                        int frameworkFormat)
823 {
824     FrameBuffer *fb = FrameBuffer::getFB();
825     if (!fb) {
826         return 0;
827     }
828 
829     return fb->createColorBuffer(width, height, internalFormat,
830                                  (FrameworkFormat)frameworkFormat);
831 }
832 
rcOpenColorBuffer2(uint32_t colorbuffer)833 static int rcOpenColorBuffer2(uint32_t colorbuffer)
834 {
835     FrameBuffer *fb = FrameBuffer::getFB();
836     if (!fb) {
837         return -1;
838     }
839     return fb->openColorBuffer( colorbuffer );
840 }
841 
rcOpenColorBuffer(uint32_t colorbuffer)842 static void rcOpenColorBuffer(uint32_t colorbuffer)
843 {
844     (void) rcOpenColorBuffer2(colorbuffer);
845 }
846 
rcCloseColorBuffer(uint32_t colorbuffer)847 static void rcCloseColorBuffer(uint32_t colorbuffer)
848 {
849     FrameBuffer *fb = FrameBuffer::getFB();
850     if (!fb) {
851         return;
852     }
853     fb->closeColorBuffer( colorbuffer );
854 }
855 
rcFlushWindowColorBuffer(uint32_t windowSurface)856 static int rcFlushWindowColorBuffer(uint32_t windowSurface)
857 {
858     GRSYNC_DPRINT("waiting for gralloc cb lock");
859     GrallocSyncPostLock lock(*sGrallocSync());
860     GRSYNC_DPRINT("lock gralloc cb lock {");
861 
862     FrameBuffer *fb = FrameBuffer::getFB();
863     if (!fb) {
864         GRSYNC_DPRINT("unlock gralloc cb lock");
865         return -1;
866     }
867 
868     HandleType colorBufferHandle = fb->getEmulatedEglWindowSurfaceColorBufferHandle(windowSurface);
869 
870     if (!fb->flushEmulatedEglWindowSurfaceColorBuffer(windowSurface)) {
871         GRSYNC_DPRINT("unlock gralloc cb lock }");
872         return -1;
873     }
874 
875     // Make the GL updates visible to other backings if necessary.
876     fb->flushColorBufferFromGl(colorBufferHandle);
877 
878     GRSYNC_DPRINT("unlock gralloc cb lock }");
879 
880     return 0;
881 }
882 
883 // Note that even though this calls rcFlushWindowColorBuffer,
884 // the "Async" part is in the return type, which is void
885 // versus return type int for rcFlushWindowColorBuffer.
886 //
887 // The different return type, even while calling the same
888 // functions internally, will end up making the encoder
889 // and decoder use a different protocol. This is because
890 // the encoder generally obeys the following conventions:
891 //
892 // - The encoder will immediately send and wait for a command
893 //   result if the return type is not void.
894 // - The encoder will cache the command in a buffer and send
895 //   at a convenient time if the return type is void.
896 //
897 // It can also be expensive performance-wise to trigger
898 // sending traffic back to the guest. Generally, the more we avoid
899 // encoding commands that perform two-way traffic, the better.
900 //
901 // Hence, |rcFlushWindowColorBufferAsync| will avoid extra traffic;
902 // with return type void,
903 // the guest will not wait until this function returns,
904 // nor will it immediately send the command,
905 // resulting in more asynchronous behavior.
rcFlushWindowColorBufferAsync(uint32_t windowSurface)906 static void rcFlushWindowColorBufferAsync(uint32_t windowSurface)
907 {
908     rcFlushWindowColorBuffer(windowSurface);
909 }
910 
rcSetWindowColorBuffer(uint32_t windowSurface,uint32_t colorBuffer)911 static void rcSetWindowColorBuffer(uint32_t windowSurface,
912                                    uint32_t colorBuffer)
913 {
914     FrameBuffer *fb = FrameBuffer::getFB();
915     if (!fb) {
916         return;
917     }
918     fb->setEmulatedEglWindowSurfaceColorBuffer(windowSurface, colorBuffer);
919 }
920 
rcMakeCurrent(uint32_t context,uint32_t drawSurf,uint32_t readSurf)921 static EGLint rcMakeCurrent(uint32_t context,
922                             uint32_t drawSurf, uint32_t readSurf)
923 {
924     FrameBuffer *fb = FrameBuffer::getFB();
925     if (!fb) {
926         return EGL_FALSE;
927     }
928 
929     bool ret = fb->bindContext(context, drawSurf, readSurf);
930 
931     return (ret ? EGL_TRUE : EGL_FALSE);
932 }
933 
rcFBPost(uint32_t colorBuffer)934 static void rcFBPost(uint32_t colorBuffer)
935 {
936     FrameBuffer *fb = FrameBuffer::getFB();
937     if (!fb) {
938         return;
939     }
940 
941     fb->post(colorBuffer);
942 }
943 
rcFBSetSwapInterval(EGLint interval)944 static void rcFBSetSwapInterval(EGLint interval)
945 {
946    // XXX: TBD - should be implemented
947 }
948 
rcBindTexture(uint32_t colorBuffer)949 static void rcBindTexture(uint32_t colorBuffer)
950 {
951     FrameBuffer *fb = FrameBuffer::getFB();
952     if (!fb) {
953         return;
954     }
955 
956     // Update for GL use if necessary.
957     fb->invalidateColorBufferForGl(colorBuffer);
958 
959     fb->bindColorBufferToTexture(colorBuffer);
960 }
961 
rcBindRenderbuffer(uint32_t colorBuffer)962 static void rcBindRenderbuffer(uint32_t colorBuffer)
963 {
964     FrameBuffer *fb = FrameBuffer::getFB();
965     if (!fb) {
966         return;
967     }
968 
969     // Update for GL use if necessary.
970     fb->invalidateColorBufferForGl(colorBuffer);
971 
972     fb->bindColorBufferToRenderbuffer(colorBuffer);
973 }
974 
rcColorBufferCacheFlush(uint32_t colorBuffer,EGLint postCount,int forRead)975 static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer,
976                                       EGLint postCount, int forRead)
977 {
978     // gralloc_lock() on the guest calls rcColorBufferCacheFlush
979     GRSYNC_DPRINT("waiting for gralloc cb lock");
980     sGrallocSync()->lockColorBufferPrepare();
981     GRSYNC_DPRINT("lock gralloc cb lock {");
982     return 0;
983 }
984 
rcReadColorBuffer(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,GLenum format,GLenum type,void * pixels)985 static void rcReadColorBuffer(uint32_t colorBuffer,
986                               GLint x, GLint y,
987                               GLint width, GLint height,
988                               GLenum format, GLenum type, void* pixels)
989 {
990     FrameBuffer *fb = FrameBuffer::getFB();
991     if (!fb) {
992         return;
993     }
994 
995     fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
996 }
997 
rcUpdateColorBuffer(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,GLenum format,GLenum type,void * pixels)998 static int rcUpdateColorBuffer(uint32_t colorBuffer,
999                                GLint x, GLint y,
1000                                GLint width, GLint height,
1001                                GLenum format, GLenum type, void* pixels)
1002 {
1003     FrameBuffer *fb = FrameBuffer::getFB();
1004 
1005     if (!fb) {
1006         GRSYNC_DPRINT("unlock gralloc cb lock");
1007         sGrallocSync()->unlockColorBufferPrepare();
1008         return -1;
1009     }
1010 
1011     fb->updateColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
1012 
1013     GRSYNC_DPRINT("unlock gralloc cb lock");
1014     sGrallocSync()->unlockColorBufferPrepare();
1015 
1016     return 0;
1017 }
1018 
rcUpdateColorBufferDMA(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,GLenum format,GLenum type,void * pixels,uint32_t pixels_size)1019 static int rcUpdateColorBufferDMA(uint32_t colorBuffer,
1020                                   GLint x, GLint y,
1021                                   GLint width, GLint height,
1022                                   GLenum format, GLenum type,
1023                                   void* pixels, uint32_t pixels_size)
1024 {
1025     FrameBuffer *fb = FrameBuffer::getFB();
1026 
1027     if (!fb) {
1028         GRSYNC_DPRINT("unlock gralloc cb lock");
1029         sGrallocSync()->unlockColorBufferPrepare();
1030         return -1;
1031     }
1032 
1033     fb->updateColorBuffer(colorBuffer, x, y, width, height,
1034                           format, type, pixels);
1035 
1036     GRSYNC_DPRINT("unlock gralloc cb lock");
1037     sGrallocSync()->unlockColorBufferPrepare();
1038 
1039     return 0;
1040 }
1041 
rcCreateClientImage(uint32_t context,EGLenum target,GLuint buffer)1042 static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buffer)
1043 {
1044     FrameBuffer *fb = FrameBuffer::getFB();
1045     if (!fb) {
1046         return 0;
1047     }
1048 
1049     return fb->createEmulatedEglImage(context, target, buffer);
1050 }
1051 
rcDestroyClientImage(uint32_t image)1052 static int rcDestroyClientImage(uint32_t image)
1053 {
1054     FrameBuffer *fb = FrameBuffer::getFB();
1055     if (!fb) {
1056         return 0;
1057     }
1058 
1059     return fb->destroyEmulatedEglImage(image);
1060 }
1061 
rcSelectChecksumHelper(uint32_t protocol,uint32_t reserved)1062 static void rcSelectChecksumHelper(uint32_t protocol, uint32_t reserved) {
1063     ChecksumCalculatorThreadInfo::setVersion(protocol);
1064 }
1065 
1066 // |rcTriggerWait| is called from the goldfish sync
1067 // kernel driver whenever a native fence fd is created.
1068 // We will then need to use the host to find out
1069 // when to signal that native fence fd. We use
1070 // SyncThread for that.
rcTriggerWait(uint64_t eglsync_ptr,uint64_t thread_ptr,uint64_t timeline)1071 static void rcTriggerWait(uint64_t eglsync_ptr,
1072                           uint64_t thread_ptr,
1073                           uint64_t timeline) {
1074     if (thread_ptr == 1) {
1075         // Is vulkan sync fd;
1076         // just signal right away for now
1077         EGLSYNC_DPRINT("vkFence=0x%llx timeline=0x%llx", eglsync_ptr,
1078                        thread_ptr, timeline);
1079         SyncThread::get()->triggerWaitVk(reinterpret_cast<VkFence>(eglsync_ptr),
1080                                          timeline);
1081     } else if (thread_ptr == 2) {
1082         EGLSYNC_DPRINT("vkFence=0x%llx timeline=0x%llx", eglsync_ptr,
1083                        thread_ptr, timeline);
1084         SyncThread::get()->triggerWaitVkQsri(reinterpret_cast<VkImage>(eglsync_ptr), timeline);
1085     } else {
1086         EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(eglsync_ptr);
1087         FrameBuffer *fb = FrameBuffer::getFB();
1088         if (fb && fenceSync && fenceSync->isCompositionFence()) {
1089             fb->scheduleVsyncTask([eglsync_ptr, fenceSync, timeline](uint64_t) {
1090                 EGLSYNC_DPRINT(
1091                     "vsync: eglsync=0x%llx fenceSync=%p thread_ptr=0x%llx "
1092                     "timeline=0x%llx",
1093                     eglsync_ptr, fenceSync, thread_ptr, timeline);
1094                 SyncThread::get()->triggerWait(fenceSync, timeline);
1095             });
1096         } else {
1097             EGLSYNC_DPRINT(
1098                     "eglsync=0x%llx fenceSync=%p thread_ptr=0x%llx "
1099                     "timeline=0x%llx",
1100                     eglsync_ptr, fenceSync, thread_ptr, timeline);
1101             SyncThread::get()->triggerWait(fenceSync, timeline);
1102         }
1103     }
1104 }
1105 
1106 // |rcCreateSyncKHR| implements the guest's |eglCreateSyncKHR| by calling the
1107 // host's implementation of |eglCreateSyncKHR|. A SyncThread is also notified
1108 // for purposes of signaling any native fence fd's that get created in the
1109 // guest off the sync object created here.
rcCreateSyncKHR(EGLenum type,EGLint * attribs,uint32_t num_attribs,int destroyWhenSignaled,uint64_t * outSync,uint64_t * outSyncThread)1110 static void rcCreateSyncKHR(EGLenum type,
1111                             EGLint* attribs,
1112                             uint32_t num_attribs,
1113                             int destroyWhenSignaled,
1114                             uint64_t* outSync,
1115                             uint64_t* outSyncThread) {
1116     // Usually we expect rcTriggerWait to be registered
1117     // at the beginning in rcGetRendererVersion, called
1118     // on init for all contexts.
1119     // But if we are loading from snapshot, that's not
1120     // guaranteed, and we need to make sure
1121     // rcTriggerWait is registered.
1122     emugl_sync_register_trigger_wait(rcTriggerWait);
1123 
1124     FrameBuffer* fb = FrameBuffer::getFB();
1125 
1126     fb->createEmulatedEglFenceSync(type,
1127                                    destroyWhenSignaled,
1128                                    outSync,
1129                                    outSyncThread);
1130 
1131     RenderThreadInfo* tInfo = RenderThreadInfo::get();
1132     if (tInfo && outSync && shouldEnableVsyncGatedSyncFences(fb->getFeatures())) {
1133         auto fenceSync = reinterpret_cast<EmulatedEglFenceSync*>(outSync);
1134         fenceSync->setIsCompositionFence(tInfo->m_isCompositionThread);
1135     }
1136 }
1137 
1138 // |rcClientWaitSyncKHR| implements |eglClientWaitSyncKHR|
1139 // on the guest through using the host's existing
1140 // |eglClientWaitSyncKHR| implementation, which is done
1141 // through the EmulatedEglFenceSync object.
rcClientWaitSyncKHR(uint64_t handle,EGLint flags,uint64_t timeout)1142 static EGLint rcClientWaitSyncKHR(uint64_t handle,
1143                                   EGLint flags,
1144                                   uint64_t timeout) {
1145     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
1146     if (!tInfo) {
1147         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1148             << "Render thread GL not available.";
1149     }
1150 
1151     FrameBuffer *fb = FrameBuffer::getFB();
1152 
1153     EGLSYNC_DPRINT("handle=0x%lx flags=0x%x timeout=%" PRIu64,
1154                 handle, flags, timeout);
1155 
1156     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1157 
1158     if (!fenceSync) {
1159         EGLSYNC_DPRINT("fenceSync null, return condition satisfied");
1160         return EGL_CONDITION_SATISFIED_KHR;
1161     }
1162 
1163     // Sometimes a gralloc-buffer-only thread is doing stuff with sync.
1164     // This happens all the time with YouTube videos in the browser.
1165     // In this case, create a context on the host just for syncing.
1166     if (!tInfo->currContext) {
1167         uint32_t gralloc_sync_cxt, gralloc_sync_surf;
1168         fb->createTrivialContext(0, // There is no context to share.
1169                                  &gralloc_sync_cxt,
1170                                  &gralloc_sync_surf);
1171         fb->bindContext(gralloc_sync_cxt,
1172                         gralloc_sync_surf,
1173                         gralloc_sync_surf);
1174         // This context is then cleaned up when the render thread exits.
1175     }
1176 
1177     return fenceSync->wait(timeout);
1178 }
1179 
rcWaitSyncKHR(uint64_t handle,EGLint flags)1180 static void rcWaitSyncKHR(uint64_t handle,
1181                                   EGLint flags) {
1182     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
1183     if (!tInfo) {
1184         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1185             << "Render thread GL not available.";
1186     }
1187 
1188     FrameBuffer *fb = FrameBuffer::getFB();
1189 
1190     EGLSYNC_DPRINT("handle=0x%lx flags=0x%x", handle, flags);
1191 
1192     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1193 
1194     if (!fenceSync) { return; }
1195 
1196     // Sometimes a gralloc-buffer-only thread is doing stuff with sync.
1197     // This happens all the time with YouTube videos in the browser.
1198     // In this case, create a context on the host just for syncing.
1199     if (!tInfo->currContext) {
1200         uint32_t gralloc_sync_cxt, gralloc_sync_surf;
1201         fb->createTrivialContext(0, // There is no context to share.
1202                                  &gralloc_sync_cxt,
1203                                  &gralloc_sync_surf);
1204         fb->bindContext(gralloc_sync_cxt,
1205                         gralloc_sync_surf,
1206                         gralloc_sync_surf);
1207         // This context is then cleaned up when the render thread exits.
1208     }
1209 
1210     fenceSync->waitAsync();
1211 }
1212 
rcDestroySyncKHR(uint64_t handle)1213 static int rcDestroySyncKHR(uint64_t handle) {
1214     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1215     if (!fenceSync) return 0;
1216     fenceSync->decRef();
1217     return 0;
1218 }
1219 
rcSetPuid(uint64_t puid)1220 static void rcSetPuid(uint64_t puid) {
1221     if (puid == kInvalidPUID) {
1222         // The host process pipe implementation (GLProcessPipe) has been updated
1223         // to not generate a unique pipe id when running with virtio gpu and
1224         // instead send -1 to the guest. Ignore those requests as the PUID will
1225         // instead be the virtio gpu context id.
1226         return;
1227     }
1228 
1229     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1230     tInfo->m_puid = puid;
1231 }
1232 
rcCompose(uint32_t bufferSize,void * buffer)1233 static int rcCompose(uint32_t bufferSize, void* buffer) {
1234     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1235     if (tInfo) tInfo->m_isCompositionThread = true;
1236 
1237     FrameBuffer *fb = FrameBuffer::getFB();
1238     if (!fb) {
1239         return -1;
1240     }
1241     return fb->compose(bufferSize, buffer, true);
1242 }
1243 
rcComposeWithoutPost(uint32_t bufferSize,void * buffer)1244 static int rcComposeWithoutPost(uint32_t bufferSize, void* buffer) {
1245     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1246     if (tInfo) tInfo->m_isCompositionThread = true;
1247 
1248     FrameBuffer *fb = FrameBuffer::getFB();
1249     if (!fb) {
1250         return -1;
1251     }
1252     return fb->compose(bufferSize, buffer, false);
1253 }
1254 
rcCreateDisplay(uint32_t * displayId)1255 static int rcCreateDisplay(uint32_t* displayId) {
1256     FrameBuffer *fb = FrameBuffer::getFB();
1257     if (!fb) {
1258         return -1;
1259     }
1260 
1261     // Assume this API call always allocates a new displayId
1262     *displayId = FrameBuffer::s_invalidIdMultiDisplay;
1263     return fb->createDisplay(displayId);
1264 }
1265 
rcCreateDisplayById(uint32_t displayId)1266 static int rcCreateDisplayById(uint32_t displayId) {
1267     FrameBuffer *fb = FrameBuffer::getFB();
1268     if (!fb) {
1269         return -1;
1270     }
1271 
1272     return fb->createDisplay(displayId);
1273 }
1274 
rcDestroyDisplay(uint32_t displayId)1275 static int rcDestroyDisplay(uint32_t displayId) {
1276     FrameBuffer *fb = FrameBuffer::getFB();
1277     if (!fb) {
1278         return -1;
1279     }
1280 
1281     return fb->destroyDisplay(displayId);
1282 }
1283 
rcSetDisplayColorBuffer(uint32_t displayId,uint32_t colorBuffer)1284 static int rcSetDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer) {
1285     FrameBuffer *fb = FrameBuffer::getFB();
1286     if (!fb) {
1287         return -1;
1288     }
1289 
1290     return fb->setDisplayColorBuffer(displayId, colorBuffer);
1291 }
1292 
rcGetDisplayColorBuffer(uint32_t displayId,uint32_t * colorBuffer)1293 static int rcGetDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer) {
1294     FrameBuffer *fb = FrameBuffer::getFB();
1295     if (!fb) {
1296         return -1;
1297     }
1298 
1299     return fb->getDisplayColorBuffer(displayId, colorBuffer);
1300 }
1301 
rcGetColorBufferDisplay(uint32_t colorBuffer,uint32_t * displayId)1302 static int rcGetColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId) {
1303     FrameBuffer *fb = FrameBuffer::getFB();
1304     if (!fb) {
1305         return -1;
1306     }
1307 
1308     return fb->getColorBufferDisplay(colorBuffer, displayId);
1309 }
1310 
rcGetDisplayPose(uint32_t displayId,int32_t * x,int32_t * y,uint32_t * w,uint32_t * h)1311 static int rcGetDisplayPose(uint32_t displayId,
1312                             int32_t* x,
1313                             int32_t* y,
1314                             uint32_t* w,
1315                             uint32_t* h) {
1316     FrameBuffer *fb = FrameBuffer::getFB();
1317     if (!fb) {
1318         return -1;
1319     }
1320 
1321     return fb->getDisplayPose(displayId, x, y, w, h);
1322 }
1323 
rcSetDisplayPose(uint32_t displayId,int32_t x,int32_t y,uint32_t w,uint32_t h)1324 static int rcSetDisplayPose(uint32_t displayId,
1325                             int32_t x,
1326                             int32_t y,
1327                             uint32_t w,
1328                             uint32_t h) {
1329     FrameBuffer *fb = FrameBuffer::getFB();
1330     if (!fb) {
1331         return -1;
1332     }
1333 
1334     return fb->setDisplayPose(displayId, x, y, w, h);
1335 }
1336 
rcSetDisplayPoseDpi(uint32_t displayId,int32_t x,int32_t y,uint32_t w,uint32_t h,uint32_t dpi)1337 static int rcSetDisplayPoseDpi(uint32_t displayId,
1338                                int32_t x,
1339                                int32_t y,
1340                                uint32_t w,
1341                                uint32_t h,
1342                                uint32_t dpi) {
1343     FrameBuffer *fb = FrameBuffer::getFB();
1344     if (!fb) {
1345         return -1;
1346     }
1347 
1348     return fb->setDisplayPose(displayId, x, y, w, h, dpi);
1349 }
1350 
rcReadColorBufferYUV(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,void * pixels,uint32_t pixels_size)1351 static void rcReadColorBufferYUV(uint32_t colorBuffer,
1352                                 GLint x, GLint y,
1353                                 GLint width, GLint height,
1354                                 void* pixels, uint32_t pixels_size)
1355 {
1356     FrameBuffer *fb = FrameBuffer::getFB();
1357     if (!fb) {
1358         return;
1359     }
1360 
1361     fb->readColorBufferYUV(colorBuffer, x, y, width, height, pixels, pixels_size);
1362 }
1363 
rcIsSyncSignaled(uint64_t handle)1364 static int rcIsSyncSignaled(uint64_t handle) {
1365     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1366     if (!fenceSync) return 1; // assume destroyed => signaled
1367     return fenceSync->isSignaled() ? 1 : 0;
1368 }
1369 
rcCreateColorBufferWithHandle(uint32_t width,uint32_t height,GLenum internalFormat,uint32_t handle)1370 static void rcCreateColorBufferWithHandle(
1371     uint32_t width, uint32_t height, GLenum internalFormat, uint32_t handle)
1372 {
1373     FrameBuffer *fb = FrameBuffer::getFB();
1374 
1375     if (!fb) {
1376         return;
1377     }
1378 
1379     fb->createColorBufferWithHandle(
1380         width, height, internalFormat,
1381         FRAMEWORK_FORMAT_GL_COMPATIBLE, handle);
1382 }
1383 
rcCreateBuffer2(uint64_t size,uint32_t memoryProperty)1384 static uint32_t rcCreateBuffer2(uint64_t size, uint32_t memoryProperty) {
1385     FrameBuffer* fb = FrameBuffer::getFB();
1386     if (!fb) {
1387         return 0;
1388     }
1389 
1390     return fb->createBuffer(size, memoryProperty);
1391 }
1392 
rcCreateBuffer(uint32_t size)1393 static uint32_t rcCreateBuffer(uint32_t size) {
1394     return rcCreateBuffer2(size, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1395 }
1396 
rcCloseBuffer(uint32_t buffer)1397 static void rcCloseBuffer(uint32_t buffer) {
1398     FrameBuffer* fb = FrameBuffer::getFB();
1399     if (!fb) {
1400         return;
1401     }
1402     fb->closeBuffer(buffer);
1403 }
1404 
rcSetColorBufferVulkanMode2(uint32_t colorBuffer,uint32_t mode,uint32_t memoryProperty)1405 static int rcSetColorBufferVulkanMode2(uint32_t colorBuffer, uint32_t mode,
1406                                        uint32_t memoryProperty) {
1407 #define VULKAN_MODE_VULKAN_ONLY 1
1408 
1409     bool modeIsVulkanOnly = mode == VULKAN_MODE_VULKAN_ONLY;
1410 
1411     if (!vk::setColorBufferVulkanMode(colorBuffer, mode)) {
1412         fprintf(stderr,
1413                 "%s: error: failed to set Vulkan mode for colorBuffer 0x%x\n",
1414                 __func__, colorBuffer);
1415         return -1;
1416     }
1417 
1418     return 0;
1419 }
1420 
rcSetColorBufferVulkanMode(uint32_t colorBuffer,uint32_t mode)1421 static int rcSetColorBufferVulkanMode(uint32_t colorBuffer, uint32_t mode) {
1422     return rcSetColorBufferVulkanMode2(colorBuffer, mode,
1423                                        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1424 }
1425 
rcMapGpaToBufferHandle(uint32_t bufferHandle,uint64_t gpa)1426 static int32_t rcMapGpaToBufferHandle(uint32_t bufferHandle, uint64_t gpa) {
1427     int32_t result = vk::mapGpaToBufferHandle(bufferHandle, gpa);
1428     if (result < 0) {
1429         fprintf(stderr,
1430                 "%s: error: failed to map gpa %" PRIx64 " to buffer handle 0x%x: %d\n",
1431                 __func__, gpa, bufferHandle, result);
1432     }
1433     return result;
1434 }
1435 
rcMapGpaToBufferHandle2(uint32_t bufferHandle,uint64_t gpa,uint64_t size)1436 static int32_t rcMapGpaToBufferHandle2(uint32_t bufferHandle,
1437                                        uint64_t gpa,
1438                                        uint64_t size) {
1439     int32_t result = vk::mapGpaToBufferHandle(bufferHandle, gpa, size);
1440     if (result < 0) {
1441         fprintf(stderr,
1442                 "%s: error: failed to map gpa %" PRIx64 " to buffer handle 0x%x: %d\n",
1443                 __func__, gpa, bufferHandle, result);
1444     }
1445     return result;
1446 }
1447 
rcFlushWindowColorBufferAsyncWithFrameNumber(uint32_t windowSurface,uint32_t frameNumber)1448 static void rcFlushWindowColorBufferAsyncWithFrameNumber(uint32_t windowSurface, uint32_t frameNumber) {
1449     android::base::traceCounter("gfxstreamFrameNumber", (int64_t)frameNumber);
1450     rcFlushWindowColorBufferAsync(windowSurface);
1451 }
1452 
rcSetTracingForPuid(uint64_t puid,uint32_t enable,uint64_t time)1453 static void rcSetTracingForPuid(uint64_t puid, uint32_t enable, uint64_t time) {
1454     if (enable) {
1455         android::base::setGuestTime(time);
1456         android::base::enableTracing();
1457     } else {
1458         android::base::disableTracing();
1459     }
1460 }
1461 
rcMakeCurrentAsync(uint32_t context,uint32_t drawSurf,uint32_t readSurf)1462 static void rcMakeCurrentAsync(uint32_t context, uint32_t drawSurf, uint32_t readSurf) {
1463     AEMU_SCOPED_THRESHOLD_TRACE_CALL();
1464     FrameBuffer* fb = FrameBuffer::getFB();
1465     if (!fb) { return; }
1466 
1467     fb->bindContext(context, drawSurf, readSurf);
1468 }
1469 
rcComposeAsync(uint32_t bufferSize,void * buffer)1470 static void rcComposeAsync(uint32_t bufferSize, void* buffer) {
1471     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1472     if (tInfo) tInfo->m_isCompositionThread = true;
1473 
1474     FrameBuffer* fb = FrameBuffer::getFB();
1475     if (!fb) {
1476         return;
1477     }
1478     fb->compose(bufferSize, buffer, true);
1479 }
1480 
rcComposeAsyncWithoutPost(uint32_t bufferSize,void * buffer)1481 static void rcComposeAsyncWithoutPost(uint32_t bufferSize, void* buffer) {
1482     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1483     if (tInfo) tInfo->m_isCompositionThread = true;
1484 
1485     FrameBuffer *fb = FrameBuffer::getFB();
1486     if (!fb) {
1487         return;
1488     }
1489     fb->compose(bufferSize, buffer, false);
1490 }
1491 
rcDestroySyncKHRAsync(uint64_t handle)1492 static void rcDestroySyncKHRAsync(uint64_t handle) {
1493     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1494     if (!fenceSync) return;
1495     fenceSync->decRef();
1496 }
1497 
rcReadColorBufferDMA(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,GLenum format,GLenum type,void * pixels,uint32_t pixels_size)1498 static int rcReadColorBufferDMA(uint32_t colorBuffer,
1499                                 GLint x, GLint y,
1500                                 GLint width, GLint height,
1501                                 GLenum format, GLenum type, void* pixels, uint32_t pixels_size)
1502 {
1503     FrameBuffer *fb = FrameBuffer::getFB();
1504     if (!fb) {
1505         return -1;
1506     }
1507 
1508     fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
1509     return 0;
1510 }
1511 
rcGetFBDisplayConfigsCount()1512 static int rcGetFBDisplayConfigsCount() {
1513     FrameBuffer *fb = FrameBuffer::getFB();
1514     if (!fb) {
1515         return -1;
1516     }
1517     return fb->getDisplayConfigsCount();
1518 }
1519 
rcGetFBDisplayConfigsParam(int configId,GLint param)1520 static int rcGetFBDisplayConfigsParam(int configId, GLint param) {
1521     FrameBuffer *fb = FrameBuffer::getFB();
1522     if (!fb) {
1523         return -1;
1524     }
1525     return fb->getDisplayConfigsParam(configId, param);
1526 }
1527 
rcGetFBDisplayActiveConfig()1528 static int rcGetFBDisplayActiveConfig() {
1529     FrameBuffer *fb = FrameBuffer::getFB();
1530     if (!fb) {
1531         return -1;
1532     }
1533     return fb->getDisplayActiveConfig();
1534 }
1535 
rcSetProcessMetadata(char * key,RenderControlByte * valuePtr,uint32_t valueSize)1536 static void rcSetProcessMetadata(char* key, RenderControlByte* valuePtr, uint32_t valueSize) {
1537     RenderThreadInfo* tInfo = RenderThreadInfo::get();
1538     if (strcmp(key, "process_name") == 0) {
1539         // We know this is a c formatted string
1540         tInfo->m_processName = std::string((char*) valuePtr);
1541     }
1542 }
1543 
rcGetHostExtensionsString(uint32_t bufferSize,void * buffer)1544 static int rcGetHostExtensionsString(uint32_t bufferSize, void* buffer) {
1545     // TODO(b/233939967): split off host extensions from GL extensions.
1546     return rcGetGLString(GL_EXTENSIONS, buffer, bufferSize);
1547 }
1548 
initRenderControlContext(renderControl_decoder_context_t * dec)1549 void initRenderControlContext(renderControl_decoder_context_t *dec)
1550 {
1551     dec->rcGetRendererVersion = rcGetRendererVersion;
1552     dec->rcGetEGLVersion = rcGetEGLVersion;
1553     dec->rcQueryEGLString = rcQueryEGLString;
1554     dec->rcGetGLString = rcGetGLString;
1555     dec->rcGetNumConfigs = rcGetNumConfigs;
1556     dec->rcGetConfigs = rcGetConfigs;
1557     dec->rcChooseConfig = rcChooseConfig;
1558     dec->rcGetFBParam = rcGetFBParam;
1559     dec->rcCreateContext = rcCreateContext;
1560     dec->rcDestroyContext = rcDestroyContext;
1561     dec->rcCreateWindowSurface = rcCreateWindowSurface;
1562     dec->rcDestroyWindowSurface = rcDestroyWindowSurface;
1563     dec->rcCreateColorBuffer = rcCreateColorBuffer;
1564     dec->rcOpenColorBuffer = rcOpenColorBuffer;
1565     dec->rcCloseColorBuffer = rcCloseColorBuffer;
1566     dec->rcSetWindowColorBuffer = rcSetWindowColorBuffer;
1567     dec->rcFlushWindowColorBuffer = rcFlushWindowColorBuffer;
1568     dec->rcMakeCurrent = rcMakeCurrent;
1569     dec->rcFBPost = rcFBPost;
1570     dec->rcFBSetSwapInterval = rcFBSetSwapInterval;
1571     dec->rcBindTexture = rcBindTexture;
1572     dec->rcBindRenderbuffer = rcBindRenderbuffer;
1573     dec->rcColorBufferCacheFlush = rcColorBufferCacheFlush;
1574     dec->rcReadColorBuffer = rcReadColorBuffer;
1575     dec->rcUpdateColorBuffer = rcUpdateColorBuffer;
1576     dec->rcOpenColorBuffer2 = rcOpenColorBuffer2;
1577     dec->rcCreateClientImage = rcCreateClientImage;
1578     dec->rcDestroyClientImage = rcDestroyClientImage;
1579     dec->rcSelectChecksumHelper = rcSelectChecksumHelper;
1580     dec->rcCreateSyncKHR = rcCreateSyncKHR;
1581     dec->rcClientWaitSyncKHR = rcClientWaitSyncKHR;
1582     dec->rcFlushWindowColorBufferAsync = rcFlushWindowColorBufferAsync;
1583     dec->rcDestroySyncKHR = rcDestroySyncKHR;
1584     dec->rcSetPuid = rcSetPuid;
1585     dec->rcUpdateColorBufferDMA = rcUpdateColorBufferDMA;
1586     dec->rcCreateColorBufferDMA = rcCreateColorBufferDMA;
1587     dec->rcWaitSyncKHR = rcWaitSyncKHR;
1588     dec->rcCompose = rcCompose;
1589     dec->rcCreateDisplay = rcCreateDisplay;
1590     dec->rcDestroyDisplay = rcDestroyDisplay;
1591     dec->rcSetDisplayColorBuffer = rcSetDisplayColorBuffer;
1592     dec->rcGetDisplayColorBuffer = rcGetDisplayColorBuffer;
1593     dec->rcGetColorBufferDisplay = rcGetColorBufferDisplay;
1594     dec->rcGetDisplayPose = rcGetDisplayPose;
1595     dec->rcSetDisplayPose = rcSetDisplayPose;
1596     dec->rcSetColorBufferVulkanMode = rcSetColorBufferVulkanMode;
1597     dec->rcReadColorBufferYUV = rcReadColorBufferYUV;
1598     dec->rcIsSyncSignaled = rcIsSyncSignaled;
1599     dec->rcCreateColorBufferWithHandle = rcCreateColorBufferWithHandle;
1600     dec->rcCreateBuffer = rcCreateBuffer;
1601     dec->rcCreateBuffer2 = rcCreateBuffer2;
1602     dec->rcCloseBuffer = rcCloseBuffer;
1603     dec->rcSetColorBufferVulkanMode2 = rcSetColorBufferVulkanMode2;
1604     dec->rcMapGpaToBufferHandle = rcMapGpaToBufferHandle;
1605     dec->rcMapGpaToBufferHandle2 = rcMapGpaToBufferHandle2;
1606     dec->rcFlushWindowColorBufferAsyncWithFrameNumber = rcFlushWindowColorBufferAsyncWithFrameNumber;
1607     dec->rcSetTracingForPuid = rcSetTracingForPuid;
1608     dec->rcMakeCurrentAsync = rcMakeCurrentAsync;
1609     dec->rcComposeAsync = rcComposeAsync;
1610     dec->rcDestroySyncKHRAsync = rcDestroySyncKHRAsync;
1611     dec->rcComposeWithoutPost = rcComposeWithoutPost;
1612     dec->rcComposeAsyncWithoutPost = rcComposeAsyncWithoutPost;
1613     dec->rcCreateDisplayById = rcCreateDisplayById;
1614     dec->rcSetDisplayPoseDpi = rcSetDisplayPoseDpi;
1615     dec->rcReadColorBufferDMA = rcReadColorBufferDMA;
1616     dec->rcGetFBDisplayConfigsCount = rcGetFBDisplayConfigsCount;
1617     dec->rcGetFBDisplayConfigsParam = rcGetFBDisplayConfigsParam;
1618     dec->rcGetFBDisplayActiveConfig = rcGetFBDisplayActiveConfig;
1619     dec->rcSetProcessMetadata = rcSetProcessMetadata;
1620     dec->rcGetHostExtensionsString = rcGetHostExtensionsString;
1621 }
1622 
1623 }  // namespace gfxstream
1624