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 "compressedTextureFormats/AstcCpuDecompressor.h"
36 #include "gfxstream/host/Tracing.h"
37 #include "host-common/logging.h"
38 #include "host-common/misc.h"
39 #include "host-common/opengl/misc.h"
40 #include "host-common/sync_device.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 = FrameBuffer::getFB()->getFeatures().GrallocSync.enabled;
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         fb->getFeatures().GlesDynamicVersion.enabled &&
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(const gfxstream::host::FeatureSet & features)316 static bool shouldEnableAsyncSwap(const gfxstream::host::FeatureSet& features) {
317     bool isPhone = true;
318     bool playStoreImage = features.PlayStoreImage.enabled;
319     return features.GlAsyncSwap.enabled &&
320            emugl_sync_device_exists() && (isPhone || playStoreImage) &&
321            sizeof(void*) == 8;
322 }
323 
shouldEnableVulkan(const gfxstream::host::FeatureSet & features)324 static bool shouldEnableVulkan(const gfxstream::host::FeatureSet& features) {
325     // TODO: Restrict further to devices supporting external memory.
326     return features.Vulkan.enabled && vk::getGlobalVkEmulation() &&
327            vk::VkDecoderGlobalState::get()->getHostFeatureSupport().supportsVulkan;
328 }
329 
shouldEnableDeferredVulkanCommands()330 static bool shouldEnableDeferredVulkanCommands() {
331     auto supportInfo = vk::VkDecoderGlobalState::get()->getHostFeatureSupport();
332     return supportInfo.supportsVulkan &&
333            supportInfo.useDeferredCommands;
334 }
335 
shouldEnableCreateResourcesWithRequirements()336 static bool shouldEnableCreateResourcesWithRequirements() {
337     auto supportInfo = vk::VkDecoderGlobalState::get()->getHostFeatureSupport();
338     return supportInfo.supportsVulkan &&
339            supportInfo.useCreateResourcesWithRequirements;
340 }
341 
shouldEnableVulkanShaderFloat16Int8(const gfxstream::host::FeatureSet & features)342 static bool shouldEnableVulkanShaderFloat16Int8(const gfxstream::host::FeatureSet& features) {
343     return shouldEnableVulkan(features) && features.VulkanShaderFloat16Int8.enabled;
344 }
345 
shouldEnableAsyncQueueSubmit(const gfxstream::host::FeatureSet & features)346 static bool shouldEnableAsyncQueueSubmit(const gfxstream::host::FeatureSet& features) {
347     return shouldEnableVulkan(features);
348 }
349 
shouldEnableVulkanAsyncQsri(const gfxstream::host::FeatureSet & features)350 static bool shouldEnableVulkanAsyncQsri(const gfxstream::host::FeatureSet& features) {
351     return shouldEnableVulkan(features) &&
352         (features.GlAsyncSwap.enabled ||
353          (features.VirtioGpuNativeSync.enabled &&
354           features.VirtioGpuFenceContexts.enabled));
355 }
356 
shouldEnableVsyncGatedSyncFences(const gfxstream::host::FeatureSet & features)357 static bool shouldEnableVsyncGatedSyncFences(const gfxstream::host::FeatureSet& features) {
358     return shouldEnableAsyncSwap(features);
359 }
360 
maxVersionToFeatureString(GLESDispatchMaxVersion version)361 const char* maxVersionToFeatureString(GLESDispatchMaxVersion version) {
362     switch (version) {
363         case GLES_DISPATCH_MAX_VERSION_2:
364             return kGLESDynamicVersion_2;
365         case GLES_DISPATCH_MAX_VERSION_3_0:
366             return kGLESDynamicVersion_3_0;
367         case GLES_DISPATCH_MAX_VERSION_3_1:
368             return kGLESDynamicVersion_3_1;
369         default:
370             return kGLESDynamicVersion_2;
371     }
372 }
373 
shouldEnableQueueSubmitWithCommands(const gfxstream::host::FeatureSet & features)374 static bool shouldEnableQueueSubmitWithCommands(const gfxstream::host::FeatureSet& features) {
375     return shouldEnableVulkan(features) && features.VulkanQueueSubmitWithCommands.enabled;
376 }
377 
shouldEnableBatchedDescriptorSetUpdate(const gfxstream::host::FeatureSet & features)378 static bool shouldEnableBatchedDescriptorSetUpdate(const gfxstream::host::FeatureSet& features) {
379     return shouldEnableVulkan(features) &&
380         shouldEnableQueueSubmitWithCommands(features) &&
381         features.VulkanBatchedDescriptorSetUpdate.enabled;
382 }
383 
384 // OpenGL ES 3.x support involves changing the GL_VERSION string, which is
385 // assumed to be formatted in the following way:
386 // "OpenGL ES-CM 1.m <vendor-info>" or
387 // "OpenGL ES M.m <vendor-info>"
388 // where M is the major version number and m is minor version number.  If the
389 // GL_VERSION string doesn't reflect the maximum available version of OpenGL
390 // ES, many apps will not be able to detect support.  We need to mess with the
391 // version string in the first place since the underlying backend (whether it
392 // is Translator, SwiftShader, ANGLE, et al) may not advertise a GL_VERSION
393 // string reflecting their maximum capabilities.
replaceESVersionString(const std::string & prev,const std::string & newver)394 std::string replaceESVersionString(const std::string& prev,
395                                    const std::string& newver) {
396 
397     // There is no need to fiddle with the string
398     // if we are in a ES 1.x context.
399     // Such contexts are considered as a special case that must
400     // be untouched.
401     if (prev.find("ES-CM") != std::string::npos) {
402         return prev;
403     }
404 
405     size_t esStart = prev.find("ES ");
406     size_t esEnd = prev.find(" ", esStart + 3);
407 
408     if (esStart == std::string::npos ||
409         esEnd == std::string::npos) {
410         // Account for out-of-spec version strings.
411         ERR("%s: Error: unexpected OpenGL ES version string %s",
412                 __func__, prev.c_str());
413         return prev;
414     }
415 
416     std::string res = prev.substr(0, esStart + 3);
417     res += newver;
418     res += prev.substr(esEnd);
419 
420     return res;
421 }
422 
423 // If the GLES3 feature is disabled, we also want to splice out
424 // OpenGL extensions that should not appear in a GLES2 system.
removeExtension(std::string & currExts,const std::string & toRemove)425 void removeExtension(std::string& currExts, const std::string& toRemove) {
426     size_t pos = currExts.find(toRemove);
427 
428     if (pos != std::string::npos)
429         currExts.erase(pos, toRemove.length());
430 }
431 
rcGetGLString(EGLenum name,void * buffer,EGLint bufferSize)432 static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) {
433     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
434 
435     // whatever we end up returning,
436     // it will have a terminating \0,
437     // so account for it here.
438     std::string glStr;
439 
440     if (tInfo && tInfo->currContext.get()) {
441         const char *str = nullptr;
442         if (tInfo->currContext->clientVersion() > GLESApi_CM) {
443             str = (const char*)gl::s_gles2.glGetString(name);
444         }
445         else {
446             str = (const char*)gl::s_gles1.glGetString(name);
447         }
448         if (str) {
449             glStr += str;
450         }
451     }
452 
453     FrameBuffer* fb = FrameBuffer::getFB();
454 
455     const gfxstream::host::FeatureSet& features = fb->getFeatures();
456 
457     // We add the maximum supported GL protocol number into GL_EXTENSIONS
458 
459     // filter extensions by name to match guest-side support
460     GLESDispatchMaxVersion maxVersion = fb->getMaxGLESVersion();
461     if (name == GL_EXTENSIONS) {
462         glStr = gl::filterExtensionsBasedOnMaxVersion(features, maxVersion, glStr);
463     }
464 
465     bool isChecksumEnabled = features.GlPipeChecksum.enabled;
466     bool asyncSwapEnabled = shouldEnableAsyncSwap(features);
467     bool virtioGpuNativeSyncEnabled = features.VirtioGpuNativeSync.enabled;
468     bool dma1Enabled = features.GlDma.enabled;
469     bool dma2Enabled = features.GlDma2.enabled;
470     bool directMemEnabled = features.GlDirectMem.enabled;
471     bool hostCompositionEnabled = features.HostComposition.enabled;
472     bool vulkanEnabled = shouldEnableVulkan(features);
473     bool deferredVulkanCommandsEnabled =
474         shouldEnableVulkan(features) && shouldEnableDeferredVulkanCommands();
475     bool vulkanNullOptionalStringsEnabled =
476         shouldEnableVulkan(features) && features.VulkanNullOptionalStrings.enabled;
477     bool vulkanCreateResourceWithRequirementsEnabled =
478         shouldEnableVulkan(features) && shouldEnableCreateResourcesWithRequirements();
479     bool YUV420888toNV21Enabled = features.Yuv420888ToNv21.enabled;
480     bool YUVCacheEnabled = features.YuvCache.enabled;
481     bool AsyncUnmapBufferEnabled = features.AsyncComposeSupport.enabled;
482     bool vulkanIgnoredHandlesEnabled =
483         shouldEnableVulkan(features) && features.VulkanIgnoredHandles.enabled;
484     bool virtioGpuNextEnabled = features.VirtioGpuNext.enabled;
485     bool hasSharedSlotsHostMemoryAllocatorEnabled =
486         features.HasSharedSlotsHostMemoryAllocator.enabled;
487     bool vulkanFreeMemorySyncEnabled =
488         shouldEnableVulkan(features);
489     bool vulkanShaderFloat16Int8Enabled = shouldEnableVulkanShaderFloat16Int8(features);
490     bool vulkanAsyncQueueSubmitEnabled = shouldEnableAsyncQueueSubmit(features);
491     bool vulkanQueueSubmitWithCommands = shouldEnableQueueSubmitWithCommands(features);
492     bool vulkanBatchedDescriptorSetUpdate = shouldEnableBatchedDescriptorSetUpdate(features);
493     bool syncBufferDataEnabled = true;
494     bool vulkanAsyncQsri = shouldEnableVulkanAsyncQsri(features);
495     bool readColorBufferDma = directMemEnabled && hasSharedSlotsHostMemoryAllocatorEnabled;
496     bool hwcMultiConfigs = features.HwcMultiConfigs.enabled;
497 
498     if (isChecksumEnabled && name == GL_EXTENSIONS) {
499         glStr += ChecksumCalculatorThreadInfo::getMaxVersionString();
500         glStr += " ";
501     }
502 
503     if (asyncSwapEnabled && name == GL_EXTENSIONS) {
504         glStr += kAsyncSwapStrV2;
505         glStr += " "; // for compatibility with older system images
506         // Only enable EGL_KHR_wait_sync (and above) for host gpu.
507         if (emugl::getRenderer() == SELECTED_RENDERER_HOST) {
508             glStr += kAsyncSwapStrV3;
509             glStr += " ";
510             glStr += kAsyncSwapStrV4;
511             glStr += " ";
512         }
513     }
514 
515     if (dma1Enabled && name == GL_EXTENSIONS) {
516         glStr += kDma1Str;
517         glStr += " ";
518     }
519 
520     if (dma2Enabled && name == GL_EXTENSIONS) {
521         glStr += kDma2Str;
522         glStr += " ";
523     }
524 
525     if (directMemEnabled && name == GL_EXTENSIONS) {
526         glStr += kDirectMemStr;
527         glStr += " ";
528     }
529 
530     if (hostCompositionEnabled && name == GL_EXTENSIONS) {
531         glStr += kHostCompositionV1;
532         glStr += " ";
533     }
534 
535     if (hostCompositionEnabled && name == GL_EXTENSIONS) {
536         glStr += kHostCompositionV2;
537         glStr += " ";
538     }
539 
540     if (vulkanEnabled && name == GL_EXTENSIONS) {
541         glStr += kVulkanFeatureStr;
542         glStr += " ";
543     }
544 
545     if (deferredVulkanCommandsEnabled && name == GL_EXTENSIONS) {
546         glStr += kDeferredVulkanCommands;
547         glStr += " ";
548     }
549 
550     if (vulkanNullOptionalStringsEnabled && name == GL_EXTENSIONS) {
551         glStr += kVulkanNullOptionalStrings;
552         glStr += " ";
553     }
554 
555     if (vulkanCreateResourceWithRequirementsEnabled && name == GL_EXTENSIONS) {
556         glStr += kVulkanCreateResourcesWithRequirements;
557         glStr += " ";
558     }
559 
560     if (YUV420888toNV21Enabled && name == GL_EXTENSIONS) {
561         glStr += kYUV420888toNV21;
562         glStr += " ";
563     }
564 
565     if (YUVCacheEnabled && name == GL_EXTENSIONS) {
566         glStr += kYUVCache;
567         glStr += " ";
568     }
569 
570     if (AsyncUnmapBufferEnabled && name == GL_EXTENSIONS) {
571         glStr += kAsyncUnmapBuffer;
572         glStr += " ";
573     }
574 
575     if (vulkanIgnoredHandlesEnabled && name == GL_EXTENSIONS) {
576         glStr += kVulkanIgnoredHandles;
577         glStr += " ";
578     }
579 
580     if (virtioGpuNextEnabled && name == GL_EXTENSIONS) {
581         glStr += kVirtioGpuNext;
582         glStr += " ";
583     }
584 
585     if (hasSharedSlotsHostMemoryAllocatorEnabled && name == GL_EXTENSIONS) {
586         glStr += kHasSharedSlotsHostMemoryAllocator;
587         glStr += " ";
588     }
589 
590     if (vulkanFreeMemorySyncEnabled && name == GL_EXTENSIONS) {
591         glStr += kVulkanFreeMemorySync;
592         glStr += " ";
593     }
594 
595     if (vulkanShaderFloat16Int8Enabled && name == GL_EXTENSIONS) {
596         glStr += kVulkanShaderFloat16Int8;
597         glStr += " ";
598     }
599 
600     if (vulkanAsyncQueueSubmitEnabled && name == GL_EXTENSIONS) {
601         glStr += kVulkanAsyncQueueSubmit;
602         glStr += " ";
603     }
604 
605     if (vulkanQueueSubmitWithCommands && name == GL_EXTENSIONS) {
606         glStr += kVulkanQueueSubmitWithCommands;
607         glStr += " ";
608     }
609 
610     if (vulkanBatchedDescriptorSetUpdate && name == GL_EXTENSIONS) {
611         glStr += kVulkanBatchedDescriptorSetUpdate;
612         glStr += " ";
613     }
614 
615     if (virtioGpuNativeSyncEnabled && name == GL_EXTENSIONS) {
616         glStr += kVirtioGpuNativeSync;
617         glStr += " ";
618     }
619 
620     if (syncBufferDataEnabled && name == GL_EXTENSIONS) {
621         glStr += kSyncBufferData;
622         glStr += " ";
623     }
624 
625     if (vulkanAsyncQsri && name == GL_EXTENSIONS) {
626         glStr += kVulkanAsyncQsri;
627         glStr += " ";
628     }
629 
630     if (readColorBufferDma && name == GL_EXTENSIONS) {
631         glStr += kReadColorBufferDma;
632         glStr += " ";
633     }
634 
635     if (hwcMultiConfigs && name == GL_EXTENSIONS) {
636         glStr += kHWCMultiConfigs;
637         glStr += " ";
638     }
639 
640     if (name == GL_EXTENSIONS) {
641         GLESDispatchMaxVersion guestExtVer = GLES_DISPATCH_MAX_VERSION_2;
642         if (features.GlesDynamicVersion.enabled) {
643             // If the image is in ES 3 mode, add GL_OES_EGL_image_external_essl3 for better Skia support.
644             glStr += "GL_OES_EGL_image_external_essl3 ";
645             guestExtVer = maxVersion;
646         }
647 
648         // If we have a GLES3 implementation, add the corresponding
649         // GLESv2 extensions as well.
650         if (maxVersion > GLES_DISPATCH_MAX_VERSION_2) {
651             glStr += "GL_OES_vertex_array_object ";
652         }
653 
654         // ASTC LDR compressed texture support.
655         const std::string& glExtensions =
656             FrameBuffer::getFB()->hasEmulationGl()
657                 ? FrameBuffer::getFB()->getEmulationGl().getGlesExtensionsString()
658                 : "<no GL emulation>";
659         const bool hasNativeAstc =
660             glExtensions.find("GL_KHR_texture_compression_astc_ldr") != std::string::npos;
661         const bool hasAstcDecompressor = vk::AstcCpuDecompressor::get().available();
662         if (hasNativeAstc || hasAstcDecompressor) {
663             glStr += "GL_KHR_texture_compression_astc_ldr ";
664         } else {
665             RENDERCONTROL_DPRINT(
666                 "rcGetGLString: ASTC not supported. CPU decompressor? %d. GL extensions: %s",
667                 hasAstcDecompressor, glExtensions.c_str());
668         }
669 
670         // Host side tracing support.
671         glStr += kHostSideTracing;
672         glStr += " ";
673 
674         if (features.AsyncComposeSupport.enabled) {
675             // Async makecurrent support.
676             glStr += kAsyncFrameCommands;
677             glStr += " ";
678         }
679 
680         glStr += maxVersionToFeatureString(guestExtVer);
681         glStr += " ";
682     }
683 
684     if (name == GL_VERSION) {
685         if (features.GlesDynamicVersion.enabled) {
686             switch (maxVersion) {
687             // Underlying GLES implmentation's max version string
688             // is allowed to be higher than the version of the request
689             // for the context---it can create a higher version context,
690             // and return simply the max possible version overall.
691             case GLES_DISPATCH_MAX_VERSION_2:
692                 glStr = replaceESVersionString(glStr, "2.0");
693                 break;
694             case GLES_DISPATCH_MAX_VERSION_3_0:
695                 glStr = replaceESVersionString(glStr, "3.0");
696                 break;
697             case GLES_DISPATCH_MAX_VERSION_3_1:
698                 glStr = replaceESVersionString(glStr, "3.1");
699                 break;
700             default:
701                 break;
702             }
703         } else {
704             glStr = replaceESVersionString(glStr, "2.0");
705         }
706     }
707 
708     int nextBufferSize = glStr.size() + 1;
709 
710     if (!buffer || nextBufferSize > bufferSize) {
711         return -nextBufferSize;
712     }
713 
714     snprintf((char *)buffer, nextBufferSize, "%s", glStr.c_str());
715     return nextBufferSize;
716 }
717 
rcGetNumConfigs(uint32_t * p_numAttribs)718 static EGLint rcGetNumConfigs(uint32_t* p_numAttribs)
719 {
720     int numConfigs = 0, numAttribs = 0;
721 
722     FrameBuffer::getFB()->getConfigs()->getPackInfo(&numConfigs, &numAttribs);
723     if (p_numAttribs) {
724         *p_numAttribs = static_cast<uint32_t>(numAttribs);
725     }
726     return numConfigs;
727 }
728 
rcGetConfigs(uint32_t bufSize,GLuint * buffer)729 static EGLint rcGetConfigs(uint32_t bufSize, GLuint* buffer)
730 {
731     GLuint bufferSize = (GLuint)bufSize;
732     return FrameBuffer::getFB()->getConfigs()->packConfigs(bufferSize, buffer);
733 }
734 
rcChooseConfig(EGLint * attribs,uint32_t attribs_size,uint32_t * configs,uint32_t configs_size)735 static EGLint rcChooseConfig(EGLint *attribs,
736                              uint32_t attribs_size,
737                              uint32_t *configs,
738                              uint32_t configs_size)
739 {
740     FrameBuffer *fb = FrameBuffer::getFB();
741     if (!fb) {
742         return 0;
743     }
744 
745     if (attribs_size == 0) {
746         if (configs && configs_size > 0) {
747             // Pick the first config
748             *configs = 0;
749             if (attribs) *attribs = EGL_NONE;
750         }
751     }
752 
753     return fb->getConfigs()->chooseConfig(
754             attribs, (EGLint*)configs, (EGLint)configs_size);
755 }
756 
rcGetFBParam(EGLint param)757 static EGLint rcGetFBParam(EGLint param)
758 {
759     FrameBuffer *fb = FrameBuffer::getFB();
760     if (!fb) {
761         return 0;
762     }
763     return fb->getDisplayConfigsParam(0, param);
764 }
765 
rcCreateContext(uint32_t config,uint32_t share,uint32_t glVersion)766 static uint32_t rcCreateContext(uint32_t config,
767                                 uint32_t share, uint32_t glVersion)
768 {
769     FrameBuffer *fb = FrameBuffer::getFB();
770     if (!fb) {
771         return 0;
772     }
773 
774     HandleType ret = fb->createEmulatedEglContext(config, share, (GLESApi)glVersion);
775     return ret;
776 }
777 
rcDestroyContext(uint32_t context)778 static void rcDestroyContext(uint32_t context)
779 {
780     FrameBuffer *fb = FrameBuffer::getFB();
781     if (!fb) {
782         return;
783     }
784 
785     fb->destroyEmulatedEglContext(context);
786 }
787 
rcCreateWindowSurface(uint32_t config,uint32_t width,uint32_t height)788 static uint32_t rcCreateWindowSurface(uint32_t config,
789                                       uint32_t width, uint32_t height)
790 {
791     FrameBuffer *fb = FrameBuffer::getFB();
792     if (!fb) {
793         return 0;
794     }
795 
796     return fb->createEmulatedEglWindowSurface(config, width, height);
797 }
798 
rcDestroyWindowSurface(uint32_t windowSurface)799 static void rcDestroyWindowSurface(uint32_t windowSurface)
800 {
801     FrameBuffer *fb = FrameBuffer::getFB();
802     if (!fb) {
803         return;
804     }
805 
806     fb->destroyEmulatedEglWindowSurface(windowSurface);
807 }
808 
rcCreateColorBuffer(uint32_t width,uint32_t height,GLenum internalFormat)809 static uint32_t rcCreateColorBuffer(uint32_t width,
810                                     uint32_t height, GLenum internalFormat)
811 {
812     FrameBuffer *fb = FrameBuffer::getFB();
813     if (!fb) {
814         return 0;
815     }
816 
817     return fb->createColorBuffer(width, height, internalFormat,
818                                  FRAMEWORK_FORMAT_GL_COMPATIBLE);
819 }
820 
rcCreateColorBufferDMA(uint32_t width,uint32_t height,GLenum internalFormat,int frameworkFormat)821 static uint32_t rcCreateColorBufferDMA(uint32_t width,
822                                        uint32_t height, GLenum internalFormat,
823                                        int frameworkFormat)
824 {
825     FrameBuffer *fb = FrameBuffer::getFB();
826     if (!fb) {
827         return 0;
828     }
829 
830     return fb->createColorBuffer(width, height, internalFormat,
831                                  (FrameworkFormat)frameworkFormat);
832 }
833 
rcOpenColorBuffer2(uint32_t colorbuffer)834 static int rcOpenColorBuffer2(uint32_t colorbuffer)
835 {
836     FrameBuffer *fb = FrameBuffer::getFB();
837     if (!fb) {
838         return -1;
839     }
840     return fb->openColorBuffer( colorbuffer );
841 }
842 
rcOpenColorBuffer(uint32_t colorbuffer)843 static void rcOpenColorBuffer(uint32_t colorbuffer)
844 {
845     (void) rcOpenColorBuffer2(colorbuffer);
846 }
847 
rcCloseColorBuffer(uint32_t colorbuffer)848 static void rcCloseColorBuffer(uint32_t colorbuffer)
849 {
850     FrameBuffer *fb = FrameBuffer::getFB();
851     if (!fb) {
852         return;
853     }
854     fb->closeColorBuffer( colorbuffer );
855 }
856 
rcFlushWindowColorBuffer(uint32_t windowSurface)857 static int rcFlushWindowColorBuffer(uint32_t windowSurface)
858 {
859     GRSYNC_DPRINT("waiting for gralloc cb lock");
860     GrallocSyncPostLock lock(*sGrallocSync());
861     GRSYNC_DPRINT("lock gralloc cb lock {");
862 
863     FrameBuffer *fb = FrameBuffer::getFB();
864     if (!fb) {
865         GRSYNC_DPRINT("unlock gralloc cb lock");
866         return -1;
867     }
868 
869     HandleType colorBufferHandle = fb->getEmulatedEglWindowSurfaceColorBufferHandle(windowSurface);
870 
871     if (!fb->flushEmulatedEglWindowSurfaceColorBuffer(windowSurface)) {
872         GRSYNC_DPRINT("unlock gralloc cb lock }");
873         return -1;
874     }
875 
876     // Make the GL updates visible to other backings if necessary.
877     fb->flushColorBufferFromGl(colorBufferHandle);
878 
879     GRSYNC_DPRINT("unlock gralloc cb lock }");
880 
881     return 0;
882 }
883 
884 // Note that even though this calls rcFlushWindowColorBuffer,
885 // the "Async" part is in the return type, which is void
886 // versus return type int for rcFlushWindowColorBuffer.
887 //
888 // The different return type, even while calling the same
889 // functions internally, will end up making the encoder
890 // and decoder use a different protocol. This is because
891 // the encoder generally obeys the following conventions:
892 //
893 // - The encoder will immediately send and wait for a command
894 //   result if the return type is not void.
895 // - The encoder will cache the command in a buffer and send
896 //   at a convenient time if the return type is void.
897 //
898 // It can also be expensive performance-wise to trigger
899 // sending traffic back to the guest. Generally, the more we avoid
900 // encoding commands that perform two-way traffic, the better.
901 //
902 // Hence, |rcFlushWindowColorBufferAsync| will avoid extra traffic;
903 // with return type void,
904 // the guest will not wait until this function returns,
905 // nor will it immediately send the command,
906 // resulting in more asynchronous behavior.
rcFlushWindowColorBufferAsync(uint32_t windowSurface)907 static void rcFlushWindowColorBufferAsync(uint32_t windowSurface)
908 {
909     rcFlushWindowColorBuffer(windowSurface);
910 }
911 
rcSetWindowColorBuffer(uint32_t windowSurface,uint32_t colorBuffer)912 static void rcSetWindowColorBuffer(uint32_t windowSurface,
913                                    uint32_t colorBuffer)
914 {
915     FrameBuffer *fb = FrameBuffer::getFB();
916     if (!fb) {
917         return;
918     }
919     fb->setEmulatedEglWindowSurfaceColorBuffer(windowSurface, colorBuffer);
920 }
921 
rcMakeCurrent(uint32_t context,uint32_t drawSurf,uint32_t readSurf)922 static EGLint rcMakeCurrent(uint32_t context,
923                             uint32_t drawSurf, uint32_t readSurf)
924 {
925     FrameBuffer *fb = FrameBuffer::getFB();
926     if (!fb) {
927         return EGL_FALSE;
928     }
929 
930     bool ret = fb->bindContext(context, drawSurf, readSurf);
931 
932     return (ret ? EGL_TRUE : EGL_FALSE);
933 }
934 
rcFBPost(uint32_t colorBuffer)935 static void rcFBPost(uint32_t colorBuffer)
936 {
937     FrameBuffer *fb = FrameBuffer::getFB();
938     if (!fb) {
939         return;
940     }
941 
942     fb->post(colorBuffer);
943 }
944 
rcFBSetSwapInterval(EGLint interval)945 static void rcFBSetSwapInterval(EGLint interval)
946 {
947    // XXX: TBD - should be implemented
948 }
949 
rcBindTexture(uint32_t colorBuffer)950 static void rcBindTexture(uint32_t colorBuffer)
951 {
952     FrameBuffer *fb = FrameBuffer::getFB();
953     if (!fb) {
954         return;
955     }
956 
957     // Update for GL use if necessary.
958     fb->invalidateColorBufferForGl(colorBuffer);
959 
960     fb->bindColorBufferToTexture(colorBuffer);
961 }
962 
rcBindRenderbuffer(uint32_t colorBuffer)963 static void rcBindRenderbuffer(uint32_t colorBuffer)
964 {
965     FrameBuffer *fb = FrameBuffer::getFB();
966     if (!fb) {
967         return;
968     }
969 
970     // Update for GL use if necessary.
971     fb->invalidateColorBufferForGl(colorBuffer);
972 
973     fb->bindColorBufferToRenderbuffer(colorBuffer);
974 }
975 
rcColorBufferCacheFlush(uint32_t colorBuffer,EGLint postCount,int forRead)976 static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer,
977                                       EGLint postCount, int forRead)
978 {
979     // gralloc_lock() on the guest calls rcColorBufferCacheFlush
980     GRSYNC_DPRINT("waiting for gralloc cb lock");
981     sGrallocSync()->lockColorBufferPrepare();
982     GRSYNC_DPRINT("lock gralloc cb lock {");
983     return 0;
984 }
985 
rcReadColorBuffer(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,GLenum format,GLenum type,void * pixels)986 static void rcReadColorBuffer(uint32_t colorBuffer,
987                               GLint x, GLint y,
988                               GLint width, GLint height,
989                               GLenum format, GLenum type, void* pixels)
990 {
991     FrameBuffer *fb = FrameBuffer::getFB();
992     if (!fb) {
993         return;
994     }
995 
996     fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
997 }
998 
rcUpdateColorBuffer(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,GLenum format,GLenum type,void * pixels)999 static int rcUpdateColorBuffer(uint32_t colorBuffer,
1000                                GLint x, GLint y,
1001                                GLint width, GLint height,
1002                                GLenum format, GLenum type, void* pixels)
1003 {
1004     FrameBuffer *fb = FrameBuffer::getFB();
1005 
1006     if (!fb) {
1007         GRSYNC_DPRINT("unlock gralloc cb lock");
1008         sGrallocSync()->unlockColorBufferPrepare();
1009         return -1;
1010     }
1011 
1012     fb->updateColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
1013 
1014     GRSYNC_DPRINT("unlock gralloc cb lock");
1015     sGrallocSync()->unlockColorBufferPrepare();
1016 
1017     return 0;
1018 }
1019 
rcUpdateColorBufferDMA(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,GLenum format,GLenum type,void * pixels,uint32_t pixels_size)1020 static int rcUpdateColorBufferDMA(uint32_t colorBuffer,
1021                                   GLint x, GLint y,
1022                                   GLint width, GLint height,
1023                                   GLenum format, GLenum type,
1024                                   void* pixels, uint32_t pixels_size)
1025 {
1026     FrameBuffer *fb = FrameBuffer::getFB();
1027 
1028     if (!fb) {
1029         GRSYNC_DPRINT("unlock gralloc cb lock");
1030         sGrallocSync()->unlockColorBufferPrepare();
1031         return -1;
1032     }
1033 
1034     fb->updateColorBuffer(colorBuffer, x, y, width, height,
1035                           format, type, pixels);
1036 
1037     GRSYNC_DPRINT("unlock gralloc cb lock");
1038     sGrallocSync()->unlockColorBufferPrepare();
1039 
1040     return 0;
1041 }
1042 
rcCreateClientImage(uint32_t context,EGLenum target,GLuint buffer)1043 static uint32_t rcCreateClientImage(uint32_t context, EGLenum target, GLuint buffer)
1044 {
1045     FrameBuffer *fb = FrameBuffer::getFB();
1046     if (!fb) {
1047         return 0;
1048     }
1049 
1050     return fb->createEmulatedEglImage(context, target, buffer);
1051 }
1052 
rcDestroyClientImage(uint32_t image)1053 static int rcDestroyClientImage(uint32_t image)
1054 {
1055     FrameBuffer *fb = FrameBuffer::getFB();
1056     if (!fb) {
1057         return 0;
1058     }
1059 
1060     return fb->destroyEmulatedEglImage(image);
1061 }
1062 
rcSelectChecksumHelper(uint32_t protocol,uint32_t reserved)1063 static void rcSelectChecksumHelper(uint32_t protocol, uint32_t reserved) {
1064     ChecksumCalculatorThreadInfo::setVersion(protocol);
1065 }
1066 
1067 // |rcTriggerWait| is called from the goldfish sync
1068 // kernel driver whenever a native fence fd is created.
1069 // We will then need to use the host to find out
1070 // when to signal that native fence fd. We use
1071 // SyncThread for that.
rcTriggerWait(uint64_t eglsync_ptr,uint64_t thread_ptr,uint64_t timeline)1072 static void rcTriggerWait(uint64_t eglsync_ptr,
1073                           uint64_t thread_ptr,
1074                           uint64_t timeline) {
1075     if (thread_ptr == 1) {
1076         // Is vulkan sync fd;
1077         // just signal right away for now
1078         EGLSYNC_DPRINT("vkFence=0x%llx timeline=0x%llx", eglsync_ptr,
1079                        thread_ptr, timeline);
1080         SyncThread::get()->triggerWaitVk(reinterpret_cast<VkFence>(eglsync_ptr),
1081                                          timeline);
1082     } else if (thread_ptr == 2) {
1083         EGLSYNC_DPRINT("vkFence=0x%llx timeline=0x%llx", eglsync_ptr,
1084                        thread_ptr, timeline);
1085         SyncThread::get()->triggerWaitVkQsri(reinterpret_cast<VkImage>(eglsync_ptr), timeline);
1086     } else {
1087         EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(eglsync_ptr);
1088         FrameBuffer *fb = FrameBuffer::getFB();
1089         if (fb && fenceSync && fenceSync->isCompositionFence()) {
1090             fb->scheduleVsyncTask([eglsync_ptr, fenceSync, timeline](uint64_t) {
1091                 EGLSYNC_DPRINT(
1092                     "vsync: eglsync=0x%llx fenceSync=%p thread_ptr=0x%llx "
1093                     "timeline=0x%llx",
1094                     eglsync_ptr, fenceSync, thread_ptr, timeline);
1095                 SyncThread::get()->triggerWait(fenceSync, timeline);
1096             });
1097         } else {
1098             EGLSYNC_DPRINT(
1099                     "eglsync=0x%llx fenceSync=%p thread_ptr=0x%llx "
1100                     "timeline=0x%llx",
1101                     eglsync_ptr, fenceSync, thread_ptr, timeline);
1102             SyncThread::get()->triggerWait(fenceSync, timeline);
1103         }
1104     }
1105 }
1106 
1107 // |rcCreateSyncKHR| implements the guest's |eglCreateSyncKHR| by calling the
1108 // host's implementation of |eglCreateSyncKHR|. A SyncThread is also notified
1109 // for purposes of signaling any native fence fd's that get created in the
1110 // guest off the sync object created here.
rcCreateSyncKHR(EGLenum type,EGLint * attribs,uint32_t num_attribs,int destroyWhenSignaled,uint64_t * outSync,uint64_t * outSyncThread)1111 static void rcCreateSyncKHR(EGLenum type,
1112                             EGLint* attribs,
1113                             uint32_t num_attribs,
1114                             int destroyWhenSignaled,
1115                             uint64_t* outSync,
1116                             uint64_t* outSyncThread) {
1117     // Usually we expect rcTriggerWait to be registered
1118     // at the beginning in rcGetRendererVersion, called
1119     // on init for all contexts.
1120     // But if we are loading from snapshot, that's not
1121     // guaranteed, and we need to make sure
1122     // rcTriggerWait is registered.
1123     emugl_sync_register_trigger_wait(rcTriggerWait);
1124 
1125     FrameBuffer* fb = FrameBuffer::getFB();
1126 
1127     fb->createEmulatedEglFenceSync(type,
1128                                    destroyWhenSignaled,
1129                                    outSync,
1130                                    outSyncThread);
1131 
1132     RenderThreadInfo* tInfo = RenderThreadInfo::get();
1133     if (tInfo && outSync && shouldEnableVsyncGatedSyncFences(fb->getFeatures())) {
1134         auto fenceSync = reinterpret_cast<EmulatedEglFenceSync*>(outSync);
1135         fenceSync->setIsCompositionFence(tInfo->m_isCompositionThread);
1136     }
1137 }
1138 
1139 // |rcClientWaitSyncKHR| implements |eglClientWaitSyncKHR|
1140 // on the guest through using the host's existing
1141 // |eglClientWaitSyncKHR| implementation, which is done
1142 // through the EmulatedEglFenceSync object.
rcClientWaitSyncKHR(uint64_t handle,EGLint flags,uint64_t timeout)1143 static EGLint rcClientWaitSyncKHR(uint64_t handle,
1144                                   EGLint flags,
1145                                   uint64_t timeout) {
1146     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
1147     if (!tInfo) {
1148         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1149             << "Render thread GL not available.";
1150     }
1151 
1152     FrameBuffer *fb = FrameBuffer::getFB();
1153 
1154     EGLSYNC_DPRINT("handle=0x%lx flags=0x%x timeout=%" PRIu64,
1155                 handle, flags, timeout);
1156 
1157     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1158 
1159     if (!fenceSync) {
1160         EGLSYNC_DPRINT("fenceSync null, return condition satisfied");
1161         return EGL_CONDITION_SATISFIED_KHR;
1162     }
1163 
1164     // Sometimes a gralloc-buffer-only thread is doing stuff with sync.
1165     // This happens all the time with YouTube videos in the browser.
1166     // In this case, create a context on the host just for syncing.
1167     if (!tInfo->currContext) {
1168         uint32_t gralloc_sync_cxt, gralloc_sync_surf;
1169         fb->createTrivialContext(0, // There is no context to share.
1170                                  &gralloc_sync_cxt,
1171                                  &gralloc_sync_surf);
1172         fb->bindContext(gralloc_sync_cxt,
1173                         gralloc_sync_surf,
1174                         gralloc_sync_surf);
1175         // This context is then cleaned up when the render thread exits.
1176     }
1177 
1178     return fenceSync->wait(timeout);
1179 }
1180 
rcWaitSyncKHR(uint64_t handle,EGLint flags)1181 static void rcWaitSyncKHR(uint64_t handle,
1182                                   EGLint flags) {
1183     RenderThreadInfoGl* const tInfo = RenderThreadInfoGl::get();
1184     if (!tInfo) {
1185         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1186             << "Render thread GL not available.";
1187     }
1188 
1189     FrameBuffer *fb = FrameBuffer::getFB();
1190 
1191     EGLSYNC_DPRINT("handle=0x%lx flags=0x%x", handle, flags);
1192 
1193     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1194 
1195     if (!fenceSync) { return; }
1196 
1197     // Sometimes a gralloc-buffer-only thread is doing stuff with sync.
1198     // This happens all the time with YouTube videos in the browser.
1199     // In this case, create a context on the host just for syncing.
1200     if (!tInfo->currContext) {
1201         uint32_t gralloc_sync_cxt, gralloc_sync_surf;
1202         fb->createTrivialContext(0, // There is no context to share.
1203                                  &gralloc_sync_cxt,
1204                                  &gralloc_sync_surf);
1205         fb->bindContext(gralloc_sync_cxt,
1206                         gralloc_sync_surf,
1207                         gralloc_sync_surf);
1208         // This context is then cleaned up when the render thread exits.
1209     }
1210 
1211     fenceSync->waitAsync();
1212 }
1213 
rcDestroySyncKHR(uint64_t handle)1214 static int rcDestroySyncKHR(uint64_t handle) {
1215     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1216     if (!fenceSync) return 0;
1217     fenceSync->decRef();
1218     return 0;
1219 }
1220 
rcSetPuid(uint64_t puid)1221 static void rcSetPuid(uint64_t puid) {
1222     if (puid == kInvalidPUID) {
1223         // The host process pipe implementation (GLProcessPipe) has been updated
1224         // to not generate a unique pipe id when running with virtio gpu and
1225         // instead send -1 to the guest. Ignore those requests as the PUID will
1226         // instead be the virtio gpu context id.
1227         return;
1228     }
1229 
1230     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1231     tInfo->m_puid = puid;
1232 }
1233 
rcCompose(uint32_t bufferSize,void * buffer)1234 static int rcCompose(uint32_t bufferSize, void* buffer) {
1235     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1236     if (tInfo) tInfo->m_isCompositionThread = true;
1237 
1238     FrameBuffer *fb = FrameBuffer::getFB();
1239     if (!fb) {
1240         return -1;
1241     }
1242     return fb->compose(bufferSize, buffer, true);
1243 }
1244 
rcComposeWithoutPost(uint32_t bufferSize,void * buffer)1245 static int rcComposeWithoutPost(uint32_t bufferSize, void* buffer) {
1246     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1247     if (tInfo) tInfo->m_isCompositionThread = true;
1248 
1249     FrameBuffer *fb = FrameBuffer::getFB();
1250     if (!fb) {
1251         return -1;
1252     }
1253     return fb->compose(bufferSize, buffer, false);
1254 }
1255 
rcCreateDisplay(uint32_t * displayId)1256 static int rcCreateDisplay(uint32_t* displayId) {
1257     FrameBuffer *fb = FrameBuffer::getFB();
1258     if (!fb) {
1259         return -1;
1260     }
1261 
1262     // Assume this API call always allocates a new displayId
1263     *displayId = FrameBuffer::s_invalidIdMultiDisplay;
1264     return fb->createDisplay(displayId);
1265 }
1266 
rcCreateDisplayById(uint32_t displayId)1267 static int rcCreateDisplayById(uint32_t displayId) {
1268     FrameBuffer *fb = FrameBuffer::getFB();
1269     if (!fb) {
1270         return -1;
1271     }
1272 
1273     return fb->createDisplay(displayId);
1274 }
1275 
rcDestroyDisplay(uint32_t displayId)1276 static int rcDestroyDisplay(uint32_t displayId) {
1277     FrameBuffer *fb = FrameBuffer::getFB();
1278     if (!fb) {
1279         return -1;
1280     }
1281 
1282     return fb->destroyDisplay(displayId);
1283 }
1284 
rcSetDisplayColorBuffer(uint32_t displayId,uint32_t colorBuffer)1285 static int rcSetDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer) {
1286     FrameBuffer *fb = FrameBuffer::getFB();
1287     if (!fb) {
1288         return -1;
1289     }
1290 
1291     return fb->setDisplayColorBuffer(displayId, colorBuffer);
1292 }
1293 
rcGetDisplayColorBuffer(uint32_t displayId,uint32_t * colorBuffer)1294 static int rcGetDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer) {
1295     FrameBuffer *fb = FrameBuffer::getFB();
1296     if (!fb) {
1297         return -1;
1298     }
1299 
1300     return fb->getDisplayColorBuffer(displayId, colorBuffer);
1301 }
1302 
rcGetColorBufferDisplay(uint32_t colorBuffer,uint32_t * displayId)1303 static int rcGetColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId) {
1304     FrameBuffer *fb = FrameBuffer::getFB();
1305     if (!fb) {
1306         return -1;
1307     }
1308 
1309     return fb->getColorBufferDisplay(colorBuffer, displayId);
1310 }
1311 
rcGetDisplayPose(uint32_t displayId,int32_t * x,int32_t * y,uint32_t * w,uint32_t * h)1312 static int rcGetDisplayPose(uint32_t displayId,
1313                             int32_t* x,
1314                             int32_t* y,
1315                             uint32_t* w,
1316                             uint32_t* h) {
1317     FrameBuffer *fb = FrameBuffer::getFB();
1318     if (!fb) {
1319         return -1;
1320     }
1321 
1322     return fb->getDisplayPose(displayId, x, y, w, h);
1323 }
1324 
rcSetDisplayPose(uint32_t displayId,int32_t x,int32_t y,uint32_t w,uint32_t h)1325 static int rcSetDisplayPose(uint32_t displayId,
1326                             int32_t x,
1327                             int32_t y,
1328                             uint32_t w,
1329                             uint32_t h) {
1330     FrameBuffer *fb = FrameBuffer::getFB();
1331     if (!fb) {
1332         return -1;
1333     }
1334 
1335     return fb->setDisplayPose(displayId, x, y, w, h);
1336 }
1337 
rcSetDisplayPoseDpi(uint32_t displayId,int32_t x,int32_t y,uint32_t w,uint32_t h,uint32_t dpi)1338 static int rcSetDisplayPoseDpi(uint32_t displayId,
1339                                int32_t x,
1340                                int32_t y,
1341                                uint32_t w,
1342                                uint32_t h,
1343                                uint32_t dpi) {
1344     FrameBuffer *fb = FrameBuffer::getFB();
1345     if (!fb) {
1346         return -1;
1347     }
1348 
1349     return fb->setDisplayPose(displayId, x, y, w, h, dpi);
1350 }
1351 
rcReadColorBufferYUV(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,void * pixels,uint32_t pixels_size)1352 static void rcReadColorBufferYUV(uint32_t colorBuffer,
1353                                 GLint x, GLint y,
1354                                 GLint width, GLint height,
1355                                 void* pixels, uint32_t pixels_size)
1356 {
1357     FrameBuffer *fb = FrameBuffer::getFB();
1358     if (!fb) {
1359         return;
1360     }
1361 
1362     fb->readColorBufferYUV(colorBuffer, x, y, width, height, pixels, pixels_size);
1363 }
1364 
rcIsSyncSignaled(uint64_t handle)1365 static int rcIsSyncSignaled(uint64_t handle) {
1366     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1367     if (!fenceSync) return 1; // assume destroyed => signaled
1368     return fenceSync->isSignaled() ? 1 : 0;
1369 }
1370 
rcCreateColorBufferWithHandle(uint32_t width,uint32_t height,GLenum internalFormat,uint32_t handle)1371 static void rcCreateColorBufferWithHandle(
1372     uint32_t width, uint32_t height, GLenum internalFormat, uint32_t handle)
1373 {
1374     FrameBuffer *fb = FrameBuffer::getFB();
1375 
1376     if (!fb) {
1377         return;
1378     }
1379 
1380     fb->createColorBufferWithHandle(
1381         width, height, internalFormat,
1382         FRAMEWORK_FORMAT_GL_COMPATIBLE, handle);
1383 }
1384 
rcCreateBuffer2(uint64_t size,uint32_t memoryProperty)1385 static uint32_t rcCreateBuffer2(uint64_t size, uint32_t memoryProperty) {
1386     FrameBuffer* fb = FrameBuffer::getFB();
1387     if (!fb) {
1388         return 0;
1389     }
1390 
1391     return fb->createBuffer(size, memoryProperty);
1392 }
1393 
rcCreateBuffer(uint32_t size)1394 static uint32_t rcCreateBuffer(uint32_t size) {
1395     return rcCreateBuffer2(size, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1396 }
1397 
rcCloseBuffer(uint32_t buffer)1398 static void rcCloseBuffer(uint32_t buffer) {
1399     FrameBuffer* fb = FrameBuffer::getFB();
1400     if (!fb) {
1401         return;
1402     }
1403     fb->closeBuffer(buffer);
1404 }
1405 
rcSetColorBufferVulkanMode2(uint32_t colorBuffer,uint32_t mode,uint32_t memoryProperty)1406 static int rcSetColorBufferVulkanMode2(uint32_t colorBuffer, uint32_t mode,
1407                                        uint32_t memoryProperty) {
1408 #define VULKAN_MODE_VULKAN_ONLY 1
1409 
1410     bool modeIsVulkanOnly = mode == VULKAN_MODE_VULKAN_ONLY;
1411 
1412     if (!vk::setColorBufferVulkanMode(colorBuffer, mode)) {
1413         fprintf(stderr,
1414                 "%s: error: failed to set Vulkan mode for colorBuffer 0x%x\n",
1415                 __func__, colorBuffer);
1416         return -1;
1417     }
1418 
1419     return 0;
1420 }
1421 
rcSetColorBufferVulkanMode(uint32_t colorBuffer,uint32_t mode)1422 static int rcSetColorBufferVulkanMode(uint32_t colorBuffer, uint32_t mode) {
1423     return rcSetColorBufferVulkanMode2(colorBuffer, mode,
1424                                        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1425 }
1426 
rcMapGpaToBufferHandle(uint32_t bufferHandle,uint64_t gpa)1427 static int32_t rcMapGpaToBufferHandle(uint32_t bufferHandle, uint64_t gpa) {
1428     int32_t result = vk::mapGpaToBufferHandle(bufferHandle, gpa);
1429     if (result < 0) {
1430         fprintf(stderr,
1431                 "%s: error: failed to map gpa %" PRIx64 " to buffer handle 0x%x: %d\n",
1432                 __func__, gpa, bufferHandle, result);
1433     }
1434     return result;
1435 }
1436 
rcMapGpaToBufferHandle2(uint32_t bufferHandle,uint64_t gpa,uint64_t size)1437 static int32_t rcMapGpaToBufferHandle2(uint32_t bufferHandle,
1438                                        uint64_t gpa,
1439                                        uint64_t size) {
1440     int32_t result = vk::mapGpaToBufferHandle(bufferHandle, gpa, size);
1441     if (result < 0) {
1442         fprintf(stderr,
1443                 "%s: error: failed to map gpa %" PRIx64 " to buffer handle 0x%x: %d\n",
1444                 __func__, gpa, bufferHandle, result);
1445     }
1446     return result;
1447 }
1448 
rcFlushWindowColorBufferAsyncWithFrameNumber(uint32_t windowSurface,uint32_t frameNumber)1449 static void rcFlushWindowColorBufferAsyncWithFrameNumber(uint32_t windowSurface, uint32_t frameNumber) {
1450     android::base::traceCounter("gfxstreamFrameNumber", (int64_t)frameNumber);
1451     rcFlushWindowColorBufferAsync(windowSurface);
1452 }
1453 
rcSetTracingForPuid(uint64_t puid,uint32_t enable,uint64_t time)1454 static void rcSetTracingForPuid(uint64_t puid, uint32_t enable, uint64_t time) {
1455     if (enable) {
1456         android::base::setGuestTime(time);
1457         android::base::enableTracing();
1458     } else {
1459         android::base::disableTracing();
1460     }
1461 }
1462 
rcMakeCurrentAsync(uint32_t context,uint32_t drawSurf,uint32_t readSurf)1463 static void rcMakeCurrentAsync(uint32_t context, uint32_t drawSurf, uint32_t readSurf) {
1464     AEMU_SCOPED_THRESHOLD_TRACE_CALL();
1465     FrameBuffer* fb = FrameBuffer::getFB();
1466     if (!fb) { return; }
1467 
1468     fb->bindContext(context, drawSurf, readSurf);
1469 }
1470 
rcComposeAsync(uint32_t bufferSize,void * buffer)1471 static void rcComposeAsync(uint32_t bufferSize, void* buffer) {
1472     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1473     if (tInfo) tInfo->m_isCompositionThread = true;
1474 
1475     FrameBuffer* fb = FrameBuffer::getFB();
1476     if (!fb) {
1477         return;
1478     }
1479     fb->compose(bufferSize, buffer, true);
1480 }
1481 
rcComposeAsyncWithoutPost(uint32_t bufferSize,void * buffer)1482 static void rcComposeAsyncWithoutPost(uint32_t bufferSize, void* buffer) {
1483     RenderThreadInfo *tInfo = RenderThreadInfo::get();
1484     if (tInfo) tInfo->m_isCompositionThread = true;
1485 
1486     FrameBuffer *fb = FrameBuffer::getFB();
1487     if (!fb) {
1488         return;
1489     }
1490     fb->compose(bufferSize, buffer, false);
1491 }
1492 
rcDestroySyncKHRAsync(uint64_t handle)1493 static void rcDestroySyncKHRAsync(uint64_t handle) {
1494     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(handle);
1495     if (!fenceSync) return;
1496     fenceSync->decRef();
1497 }
1498 
rcReadColorBufferDMA(uint32_t colorBuffer,GLint x,GLint y,GLint width,GLint height,GLenum format,GLenum type,void * pixels,uint32_t pixels_size)1499 static int rcReadColorBufferDMA(uint32_t colorBuffer,
1500                                 GLint x, GLint y,
1501                                 GLint width, GLint height,
1502                                 GLenum format, GLenum type, void* pixels, uint32_t pixels_size)
1503 {
1504     FrameBuffer *fb = FrameBuffer::getFB();
1505     if (!fb) {
1506         return -1;
1507     }
1508 
1509     fb->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels, pixels_size);
1510     return 0;
1511 }
1512 
rcGetFBDisplayConfigsCount()1513 static int rcGetFBDisplayConfigsCount() {
1514     FrameBuffer *fb = FrameBuffer::getFB();
1515     if (!fb) {
1516         return -1;
1517     }
1518     return fb->getDisplayConfigsCount();
1519 }
1520 
rcGetFBDisplayConfigsParam(int configId,GLint param)1521 static int rcGetFBDisplayConfigsParam(int configId, GLint param) {
1522     FrameBuffer *fb = FrameBuffer::getFB();
1523     if (!fb) {
1524         return -1;
1525     }
1526     return fb->getDisplayConfigsParam(configId, param);
1527 }
1528 
rcGetFBDisplayActiveConfig()1529 static int rcGetFBDisplayActiveConfig() {
1530     FrameBuffer *fb = FrameBuffer::getFB();
1531     if (!fb) {
1532         return -1;
1533     }
1534     return fb->getDisplayActiveConfig();
1535 }
1536 
rcSetProcessMetadata(char * key,RenderControlByte * valuePtr,uint32_t valueSize)1537 static void rcSetProcessMetadata(char* key, RenderControlByte* valuePtr, uint32_t valueSize) {
1538     RenderThreadInfo* tInfo = RenderThreadInfo::get();
1539     if (strcmp(key, "process_name") == 0) {
1540         // We know this is a c formatted string
1541         tInfo->m_processName = std::string((char*) valuePtr);
1542 
1543         GFXSTREAM_TRACE_NAME_TRACK(GFXSTREAM_TRACE_TRACK_FOR_CURRENT_THREAD(),
1544                                    *tInfo->m_processName);
1545     }
1546 }
1547 
rcGetHostExtensionsString(uint32_t bufferSize,void * buffer)1548 static int rcGetHostExtensionsString(uint32_t bufferSize, void* buffer) {
1549     // TODO(b/233939967): split off host extensions from GL extensions.
1550     return rcGetGLString(GL_EXTENSIONS, buffer, bufferSize);
1551 }
1552 
initRenderControlContext(renderControl_decoder_context_t * dec)1553 void initRenderControlContext(renderControl_decoder_context_t *dec)
1554 {
1555     dec->rcGetRendererVersion = rcGetRendererVersion;
1556     dec->rcGetEGLVersion = rcGetEGLVersion;
1557     dec->rcQueryEGLString = rcQueryEGLString;
1558     dec->rcGetGLString = rcGetGLString;
1559     dec->rcGetNumConfigs = rcGetNumConfigs;
1560     dec->rcGetConfigs = rcGetConfigs;
1561     dec->rcChooseConfig = rcChooseConfig;
1562     dec->rcGetFBParam = rcGetFBParam;
1563     dec->rcCreateContext = rcCreateContext;
1564     dec->rcDestroyContext = rcDestroyContext;
1565     dec->rcCreateWindowSurface = rcCreateWindowSurface;
1566     dec->rcDestroyWindowSurface = rcDestroyWindowSurface;
1567     dec->rcCreateColorBuffer = rcCreateColorBuffer;
1568     dec->rcOpenColorBuffer = rcOpenColorBuffer;
1569     dec->rcCloseColorBuffer = rcCloseColorBuffer;
1570     dec->rcSetWindowColorBuffer = rcSetWindowColorBuffer;
1571     dec->rcFlushWindowColorBuffer = rcFlushWindowColorBuffer;
1572     dec->rcMakeCurrent = rcMakeCurrent;
1573     dec->rcFBPost = rcFBPost;
1574     dec->rcFBSetSwapInterval = rcFBSetSwapInterval;
1575     dec->rcBindTexture = rcBindTexture;
1576     dec->rcBindRenderbuffer = rcBindRenderbuffer;
1577     dec->rcColorBufferCacheFlush = rcColorBufferCacheFlush;
1578     dec->rcReadColorBuffer = rcReadColorBuffer;
1579     dec->rcUpdateColorBuffer = rcUpdateColorBuffer;
1580     dec->rcOpenColorBuffer2 = rcOpenColorBuffer2;
1581     dec->rcCreateClientImage = rcCreateClientImage;
1582     dec->rcDestroyClientImage = rcDestroyClientImage;
1583     dec->rcSelectChecksumHelper = rcSelectChecksumHelper;
1584     dec->rcCreateSyncKHR = rcCreateSyncKHR;
1585     dec->rcClientWaitSyncKHR = rcClientWaitSyncKHR;
1586     dec->rcFlushWindowColorBufferAsync = rcFlushWindowColorBufferAsync;
1587     dec->rcDestroySyncKHR = rcDestroySyncKHR;
1588     dec->rcSetPuid = rcSetPuid;
1589     dec->rcUpdateColorBufferDMA = rcUpdateColorBufferDMA;
1590     dec->rcCreateColorBufferDMA = rcCreateColorBufferDMA;
1591     dec->rcWaitSyncKHR = rcWaitSyncKHR;
1592     dec->rcCompose = rcCompose;
1593     dec->rcCreateDisplay = rcCreateDisplay;
1594     dec->rcDestroyDisplay = rcDestroyDisplay;
1595     dec->rcSetDisplayColorBuffer = rcSetDisplayColorBuffer;
1596     dec->rcGetDisplayColorBuffer = rcGetDisplayColorBuffer;
1597     dec->rcGetColorBufferDisplay = rcGetColorBufferDisplay;
1598     dec->rcGetDisplayPose = rcGetDisplayPose;
1599     dec->rcSetDisplayPose = rcSetDisplayPose;
1600     dec->rcSetColorBufferVulkanMode = rcSetColorBufferVulkanMode;
1601     dec->rcReadColorBufferYUV = rcReadColorBufferYUV;
1602     dec->rcIsSyncSignaled = rcIsSyncSignaled;
1603     dec->rcCreateColorBufferWithHandle = rcCreateColorBufferWithHandle;
1604     dec->rcCreateBuffer = rcCreateBuffer;
1605     dec->rcCreateBuffer2 = rcCreateBuffer2;
1606     dec->rcCloseBuffer = rcCloseBuffer;
1607     dec->rcSetColorBufferVulkanMode2 = rcSetColorBufferVulkanMode2;
1608     dec->rcMapGpaToBufferHandle = rcMapGpaToBufferHandle;
1609     dec->rcMapGpaToBufferHandle2 = rcMapGpaToBufferHandle2;
1610     dec->rcFlushWindowColorBufferAsyncWithFrameNumber = rcFlushWindowColorBufferAsyncWithFrameNumber;
1611     dec->rcSetTracingForPuid = rcSetTracingForPuid;
1612     dec->rcMakeCurrentAsync = rcMakeCurrentAsync;
1613     dec->rcComposeAsync = rcComposeAsync;
1614     dec->rcDestroySyncKHRAsync = rcDestroySyncKHRAsync;
1615     dec->rcComposeWithoutPost = rcComposeWithoutPost;
1616     dec->rcComposeAsyncWithoutPost = rcComposeAsyncWithoutPost;
1617     dec->rcCreateDisplayById = rcCreateDisplayById;
1618     dec->rcSetDisplayPoseDpi = rcSetDisplayPoseDpi;
1619     dec->rcReadColorBufferDMA = rcReadColorBufferDMA;
1620     dec->rcGetFBDisplayConfigsCount = rcGetFBDisplayConfigsCount;
1621     dec->rcGetFBDisplayConfigsParam = rcGetFBDisplayConfigsParam;
1622     dec->rcGetFBDisplayActiveConfig = rcGetFBDisplayActiveConfig;
1623     dec->rcSetProcessMetadata = rcSetProcessMetadata;
1624     dec->rcGetHostExtensionsString = rcGetHostExtensionsString;
1625 }
1626 
1627 }  // namespace gfxstream
1628