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