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