• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011-2015 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 "FrameBuffer.h"
18 
19 #include <stdio.h>
20 #include <string.h>
21 #include <time.h>
22 
23 #include <iomanip>
24 
25 #if defined(__linux__)
26 #include <sys/resource.h>
27 #endif
28 
29 #include "ContextHelper.h"
30 #include "Hwc2.h"
31 #include "NativeSubWindow.h"
32 #include "RenderThreadInfo.h"
33 #include "SyncThread.h"
34 #include "aemu/base/LayoutResolver.h"
35 #include "aemu/base/Metrics.h"
36 #include "aemu/base/SharedLibrary.h"
37 #include "aemu/base/Tracing.h"
38 #include "aemu/base/containers/Lookup.h"
39 #include "aemu/base/files/StreamSerializing.h"
40 #include "aemu/base/memory/MemoryTracker.h"
41 #include "aemu/base/synchronization/Lock.h"
42 #include "aemu/base/system/System.h"
43 
44 #if GFXSTREAM_ENABLE_HOST_GLES
45 #include "GLESVersionDetector.h"
46 #include "OpenGLESDispatch/DispatchTables.h"
47 #include "OpenGLESDispatch/EGLDispatch.h"
48 #include "PostWorkerGl.h"
49 #include "RenderControl.h"
50 #include "RenderThreadInfoGl.h"
51 #include "gl/YUVConverter.h"
52 #include "gl/gles2_dec/gles2_dec.h"
53 #include "gl/glestranslator/EGL/EglGlobalInfo.h"
54 #endif
55 #include "gfxstream/host/Tracing.h"
56 #include "host-common/GfxstreamFatalError.h"
57 #include "host-common/crash_reporter.h"
58 #include "host-common/feature_control.h"
59 #include "host-common/logging.h"
60 #include "host-common/misc.h"
61 #include "host-common/opengl/misc.h"
62 #include "host-common/emugl_vm_operations.h"
63 #include "host-common/vm_operations.h"
64 #include "render-utils/MediaNative.h"
65 #include "vulkan/DisplayVk.h"
66 #include "vulkan/PostWorkerVk.h"
67 #include "vulkan/VkCommonOperations.h"
68 #include "vulkan/VkDecoderGlobalState.h"
69 
70 namespace gfxstream {
71 
72 using android::base::AutoLock;
73 using android::base::MetricEventVulkanOutOfMemory;
74 using android::base::Stream;
75 using android::base::WorkerProcessingResult;
76 using emugl::ABORT_REASON_OTHER;
77 using emugl::CreateHealthMonitor;
78 using emugl::FatalError;
79 using emugl::GfxApiLogger;
80 using gfxstream::host::FeatureSet;
81 
82 #if GFXSTREAM_ENABLE_HOST_GLES
83 using gl::DisplaySurfaceGl;
84 using gl::EmulatedEglConfig;
85 using gl::EmulatedEglConfigList;
86 using gl::EmulatedEglContext;
87 using gl::EmulatedEglContextMap;
88 using gl::EmulatedEglContextPtr;
89 using gl::EmulatedEglFenceSync;
90 using gl::EmulatedEglWindowSurface;
91 using gl::EmulatedEglWindowSurfaceMap;
92 using gl::EmulatedEglWindowSurfacePtr;
93 using gl::EmulationGl;
94 using gl::GLES_DISPATCH_MAX_VERSION_2;
95 using gl::GLESApi;
96 using gl::GLESApi_2;
97 using gl::GLESApi_CM;
98 using gl::GLESDispatchMaxVersion;
99 using gl::RenderThreadInfoGl;
100 using gl::s_egl;
101 using gl::s_gles2;
102 using gl::TextureDraw;
103 using gl::YUVConverter;
104 using gl::YUVPlane;
105 #endif
106 
107 using vk::AstcEmulationMode;
108 using vk::VkEmulation;
109 
110 // static std::string getTimeStampString() {
111 //     const time_t timestamp = android::base::getUnixTimeUs();
112 //     const struct tm *timeinfo = localtime(&timestamp);
113 //     // Target format: 07-31 4:44:33
114 //     char b[64];
115 //     snprintf(
116 //         b,
117 //         sizeof(b) - 1,
118 //         "%02u-%02u %02u:%02u:%02u",
119 //         timeinfo->tm_mon + 1,
120 //         timeinfo->tm_mday,
121 //         timeinfo->tm_hour,
122 //         timeinfo->tm_min,
123 //         timeinfo->tm_sec);
124 //     return std::string(b);
125 // }
126 
127 // static unsigned int getUptimeMs() {
128 //     return android::base::getUptimeMs();
129 // }
130 
dumpPerfStats()131 static void dumpPerfStats() {
132     // auto usage = System::get()->getMemUsage();
133     // std::string memoryStats =
134     //     emugl::getMemoryTracker()
135     //             ? emugl::getMemoryTracker()->printUsage()
136     //             : "";
137     // auto cpuUsage = emugl::getCpuUsage();
138     // std::string lastStats =
139     //     cpuUsage ? cpuUsage->printUsage() : "";
140     // printf("%s Uptime: %u ms Resident memory: %f mb %s \n%s\n",
141     //     getTimeStampString().c_str(), getUptimeMs(),
142     //     (float)usage.resident / 1048576.0f, lastStats.c_str(),
143     //     memoryStats.c_str());
144 }
145 
146 class PerfStatThread : public android::base::Thread {
147 public:
PerfStatThread(bool * perfStatActive)148     PerfStatThread(bool* perfStatActive) :
149       Thread(), m_perfStatActive(perfStatActive) {}
150 
main()151     virtual intptr_t main() {
152       while (*m_perfStatActive) {
153         sleepMs(1000);
154         dumpPerfStats();
155       }
156       return 0;
157     }
158 
159 private:
160     bool* m_perfStatActive;
161 };
162 
163 FrameBuffer* FrameBuffer::s_theFrameBuffer = NULL;
164 HandleType FrameBuffer::s_nextHandle = 0;
165 
166 // A condition variable needed to wait for framebuffer initialization.
167 namespace {
168 struct InitializedGlobals {
169     android::base::Lock lock;
170     android::base::ConditionVariable condVar;
171 };
172 
postOnlyOnMainThread()173 bool postOnlyOnMainThread() {
174 #if defined(__APPLE__) && !defined(QEMU_NEXT)
175     return true;
176 #else
177     return false;
178 #endif
179 }
180 
181 }  // namespace
182 
183 // |sInitialized| caches the initialized framebuffer state - this way
184 // happy path doesn't need to lock the mutex.
185 static std::atomic<bool> sInitialized{false};
sGlobals()186 static InitializedGlobals* sGlobals() {
187     static InitializedGlobals* g = new InitializedGlobals;
188     return g;
189 }
190 
waitUntilInitialized()191 void FrameBuffer::waitUntilInitialized() {
192     if (sInitialized.load(std::memory_order_relaxed)) {
193         return;
194     }
195 
196 #if SNAPSHOT_PROFILE > 1
197     const auto startTime = android::base::getHighResTimeUs();
198 #endif
199     {
200         AutoLock l(sGlobals()->lock);
201         sGlobals()->condVar.wait(
202                 &l, [] { return sInitialized.load(std::memory_order_acquire); });
203     }
204 #if SNAPSHOT_PROFILE > 1
205     printf("Waited for FrameBuffer initialization for %.03f ms\n",
206            (android::base::getHighResTimeUs() - startTime) / 1000.0);
207 #endif
208 }
209 
MaybeIncreaseFileDescriptorSoftLimit()210 void MaybeIncreaseFileDescriptorSoftLimit() {
211 #if defined(__linux__)
212     // Cuttlefish with Gfxstream on Nvidia and SwiftShader often hits the default nofile
213     // soft limit (1024) when running large test suites.
214     struct rlimit nofileLimits = {
215         .rlim_cur = 0,
216         .rlim_max = 0,
217     };
218 
219     int ret = getrlimit(RLIMIT_NOFILE, &nofileLimits);
220     if (ret) {
221         ERR("Warning: failed to query nofile limits.");
222         return;
223     }
224 
225     const auto softLimit = nofileLimits.rlim_cur;
226     const auto hardLimit = nofileLimits.rlim_max;
227 
228     constexpr const rlim_t kDesiredNofileSoftLimit = 4096;
229 
230     if (softLimit < kDesiredNofileSoftLimit) {
231         if (softLimit == hardLimit) {
232             ERR("Warning: unable to raise nofile soft limit - already at hard limit.");
233             return;
234         }
235 
236         if (kDesiredNofileSoftLimit > hardLimit) {
237             ERR("Warning: unable to raise nofile soft limit to desired %d - hard limit is %d.",
238                 static_cast<int>(kDesiredNofileSoftLimit), static_cast<int>(hardLimit));
239         }
240 
241         const rlim_t requestedSoftLimit = std::min(kDesiredNofileSoftLimit, hardLimit);
242 
243         struct rlimit requestedNofileLimits = {
244             .rlim_cur = requestedSoftLimit,
245             .rlim_max = hardLimit,
246         };
247 
248         ret = setrlimit(RLIMIT_NOFILE, &requestedNofileLimits);
249         if (ret) {
250             ERR("Warning: failed to raise nofile soft limit to %d: %s (%d)",
251                 static_cast<int>(requestedSoftLimit), strerror(errno), errno);
252             return;
253         }
254 
255         INFO("Raised nofile soft limit to %d.", static_cast<int>(requestedSoftLimit));
256     } else {
257         INFO("Not raising nofile soft limit from %d.", static_cast<int>(softLimit));
258     }
259 #endif
260 }
261 
initialize(int width,int height,gfxstream::host::FeatureSet features,bool useSubWindow,bool egl2egl)262 bool FrameBuffer::initialize(int width, int height, gfxstream::host::FeatureSet features,
263                              bool useSubWindow, bool egl2egl) {
264     GL_LOG("FrameBuffer::initialize");
265 
266     if (s_theFrameBuffer != NULL) {
267         return true;
268     }
269 
270     MaybeIncreaseFileDescriptorSoftLimit();
271 
272     android::base::initializeTracing();
273     gfxstream::host::InitializeTracing();
274 
275     //
276     // allocate space for the FrameBuffer object
277     //
278     std::unique_ptr<FrameBuffer> fb(new FrameBuffer(width, height, features, useSubWindow));
279     if (!fb) {
280         GL_LOG("Failed to create fb");
281         ERR("Failed to create fb\n");
282         return false;
283     }
284 
285     GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_DEFAULT_CATEGORY, "FrameBuffer::Init()");
286 
287     std::unique_ptr<emugl::RenderDocWithMultipleVkInstances> renderDocMultipleVkInstances = nullptr;
288     if (!android::base::getEnvironmentVariable("ANDROID_EMU_RENDERDOC").empty()) {
289         SharedLibrary* renderdocLib = nullptr;
290 #ifdef _WIN32
291         renderdocLib = SharedLibrary::open(R"(C:\Program Files\RenderDoc\renderdoc.dll)");
292 #elif defined(__linux__)
293         renderdocLib = SharedLibrary::open("librenderdoc.so");
294 #endif
295         fb->m_renderDoc = emugl::RenderDoc::create(renderdocLib);
296         if (fb->m_renderDoc) {
297             INFO("RenderDoc integration enabled.");
298             renderDocMultipleVkInstances =
299                 std::make_unique<emugl::RenderDocWithMultipleVkInstances>(*fb->m_renderDoc);
300             if (!renderDocMultipleVkInstances) {
301                 ERR("Failed to initialize RenderDoc with multiple VkInstances. Can't capture any "
302                     "information from guest VkInstances with RenderDoc.");
303             }
304         }
305     }
306     // Initialize Vulkan emulation state
307     //
308     // Note: This must happen before any use of s_egl,
309     // or it's possible that the existing EGL display and contexts
310     // used by underlying EGL driver might become invalid,
311     // preventing new contexts from being created that share
312     // against those contexts.
313     vk::VulkanDispatch* vkDispatch = nullptr;
314     if (fb->m_features.Vulkan.enabled) {
315         vkDispatch = vk::vkDispatch(false /* not for testing */);
316 
317         gfxstream::host::BackendCallbacks callbacks{
318             .registerProcessCleanupCallback =
319                 [fb = fb.get()](void* key, std::function<void()> callback) {
320                     fb->registerProcessCleanupCallback(key, callback);
321                 },
322             .unregisterProcessCleanupCallback =
323                 [fb = fb.get()](void* key) { fb->unregisterProcessCleanupCallback(key); },
324             .invalidateColorBuffer =
325                 [fb = fb.get()](uint32_t colorBufferHandle) {
326                     fb->invalidateColorBufferForVk(colorBufferHandle);
327                 },
328             .flushColorBuffer =
329                 [fb = fb.get()](uint32_t colorBufferHandle) {
330                     fb->flushColorBufferFromVk(colorBufferHandle);
331                 },
332             .flushColorBufferFromBytes =
333                 [fb = fb.get()](uint32_t colorBufferHandle, const void* bytes, size_t bytesSize) {
334                     fb->flushColorBufferFromVkBytes(colorBufferHandle, bytes, bytesSize);
335                 },
336             .scheduleAsyncWork =
337                 [fb = fb.get()](std::function<void()> work, std::string description) {
338                     auto promise = std::make_shared<AutoCancelingPromise>();
339                     auto future = promise->GetFuture();
340                     SyncThread::get()->triggerGeneral(
341                         [promise = std::move(promise), work = std::move(work)]() mutable {
342                             work();
343                             promise->MarkComplete();
344                         },
345                         description);
346                     return future;
347                 },
348 #ifdef CONFIG_AEMU
349             .registerVulkanInstance =
350                 [fb = fb.get()](uint64_t id, const char* appName) {
351                     fb->registerVulkanInstance(id, appName);
352                 },
353             .unregisterVulkanInstance =
354                 [fb = fb.get()](uint64_t id) { fb->unregisterVulkanInstance(id); },
355 #endif
356         };
357         fb->m_emulationVk = vk::VkEmulation::create(vkDispatch, callbacks, fb->m_features);
358         if (fb->m_emulationVk) {
359             vk::VkDecoderGlobalState::initialize(fb->m_emulationVk.get());
360         } else {
361             ERR("Failed to initialize global Vulkan emulation. Disable the Vulkan support.");
362         }
363     }
364     if (fb->m_emulationVk) {
365         fb->m_vulkanEnabled = true;
366         if (fb->m_features.VulkanNativeSwapchain.enabled) {
367             fb->m_vkInstance = fb->m_emulationVk->getInstance();
368         }
369 
370         auto vulkanUuidOpt = fb->m_emulationVk->getDeviceUuid();
371         if (vulkanUuidOpt) {
372             fb->m_vulkanUUID = *vulkanUuidOpt;
373         } else {
374             WARN("Doesn't support id properties, no vulkan device UUID");
375         }
376     }
377 
378 #if GFXSTREAM_ENABLE_HOST_GLES
379     // Do not initialize GL emulation if the guest is using ANGLE.
380     if (!fb->m_features.GuestVulkanOnly.enabled) {
381         fb->m_emulationGl = EmulationGl::create(width, height, fb->m_features, useSubWindow, egl2egl);
382         if (!fb->m_emulationGl) {
383             ERR("Failed to initialize GL emulation.");
384             return false;
385         }
386     }
387 #endif
388 
389     fb->m_useVulkanComposition = fb->m_features.GuestVulkanOnly.enabled ||
390                                  fb->m_features.VulkanNativeSwapchain.enabled;
391 
392     vk::VkEmulation::Features vkEmulationFeatures = {
393         .glInteropSupported = false,  // Set later.
394         .deferredCommands =
395             android::base::getEnvironmentVariable("ANDROID_EMU_VK_DISABLE_DEFERRED_COMMANDS")
396                 .empty(),
397         .createResourceWithRequirements =
398             android::base::getEnvironmentVariable(
399                 "ANDROID_EMU_VK_DISABLE_USE_CREATE_RESOURCES_WITH_REQUIREMENTS")
400                 .empty(),
401         .useVulkanComposition = fb->m_useVulkanComposition,
402         .useVulkanNativeSwapchain = fb->m_features.VulkanNativeSwapchain.enabled,
403         .guestRenderDoc = std::move(renderDocMultipleVkInstances),
404         .astcLdrEmulationMode = AstcEmulationMode::Gpu,
405         .enableEtc2Emulation = true,
406         .enableYcbcrEmulation = false,
407         .guestVulkanOnly = fb->m_features.GuestVulkanOnly.enabled,
408         .useDedicatedAllocations = false,  // Set later.
409     };
410 
411     //
412     // Cache the GL strings so we don't have to think about threading or
413     // current-context when asked for them.
414     //
415     bool useVulkanGraphicsDiagInfo = fb->m_emulationVk &&
416                                      fb->m_features.VulkanNativeSwapchain.enabled &&
417                                      fb->m_features.GuestVulkanOnly.enabled;
418 
419     if (useVulkanGraphicsDiagInfo) {
420         fb->m_graphicsAdapterVendor = fb->m_emulationVk->getGpuVendor();
421         fb->m_graphicsAdapterName = fb->m_emulationVk->getGpuName();
422         fb->m_graphicsApiVersion = fb->m_emulationVk->getGpuVersionString();
423         fb->m_graphicsApiExtensions = fb->m_emulationVk->getInstanceExtensionsString();
424         fb->m_graphicsDeviceExtensions = fb->m_emulationVk->getDeviceExtensionsString();
425     } else if (fb->m_emulationGl) {
426 #if GFXSTREAM_ENABLE_HOST_GLES
427         fb->m_graphicsAdapterVendor = fb->m_emulationGl->getGlesVendor();
428         fb->m_graphicsAdapterName = fb->m_emulationGl->getGlesRenderer();
429         fb->m_graphicsApiVersion = fb->m_emulationGl->getGlesVersionString();
430         fb->m_graphicsApiExtensions = fb->m_emulationGl->getGlesExtensionsString();
431         fb->m_graphicsDeviceExtensions = "N/A";
432 #endif
433     } else {
434         fb->m_graphicsAdapterVendor = "N/A";
435         fb->m_graphicsAdapterName = "N/A";
436         fb->m_graphicsApiVersion = "N/A";
437         fb->m_graphicsApiExtensions = "N/A";
438         fb->m_graphicsDeviceExtensions = "N/A";
439     }
440 
441     // Attempt to get the device UUID of the gles and match with Vulkan. If
442     // they match, interop is possible. If they don't, then don't trust the
443     // result of interop query to egl and fall back to CPU copy, as we might
444     // have initialized Vulkan devices and GLES contexts from different
445     // physical devices.
446 
447     bool vulkanInteropSupported = true;
448     // First, if the VkEmulation instance doesn't support ext memory capabilities,
449     // it won't support uuids.
450     if (!fb->m_emulationVk || !fb->m_emulationVk->supportsPhysicalDeviceIDProperties()) {
451         vulkanInteropSupported = false;
452     }
453     if (!fb->m_emulationGl) {
454         vulkanInteropSupported = false;
455     } else {
456 #if GFXSTREAM_ENABLE_HOST_GLES
457         if (!fb->m_emulationGl->isGlesVulkanInteropSupported()) {
458             vulkanInteropSupported = false;
459         }
460         const auto& glesDeviceUuid = fb->m_emulationGl->getGlesDeviceUuid();
461         if (!glesDeviceUuid  || glesDeviceUuid != fb->m_vulkanUUID) {
462             vulkanInteropSupported = false;
463         }
464 #endif
465     }
466     // TODO: 0-copy gl interop on swiftshader vk
467     if (android::base::getEnvironmentVariable("ANDROID_EMU_VK_ICD") == "lavapipe"
468             || android::base::getEnvironmentVariable("ANDROID_EMU_VK_ICD") == "swiftshader") {
469         vulkanInteropSupported = false;
470         GL_LOG("vk icd software rendering, disable interop");
471     }
472 
473     fb->m_vulkanInteropSupported = vulkanInteropSupported;
474     GL_LOG("interop? %d", fb->m_vulkanInteropSupported);
475 
476 #if GFXSTREAM_ENABLE_HOST_GLES
477     if (vulkanInteropSupported && fb->m_emulationGl && fb->m_emulationGl->isMesa()) {
478         // Mesa currently expects dedicated allocations for external memory sharing
479         // between GL and VK. See b/265186355.
480         vkEmulationFeatures.useDedicatedAllocations = true;
481     }
482 #endif
483 
484     GL_LOG("glvk interop final: %d", fb->m_vulkanInteropSupported);
485     vkEmulationFeatures.glInteropSupported = fb->m_vulkanInteropSupported;
486     if (fb->m_emulationVk && fb->m_features.Vulkan.enabled) {
487         fb->m_emulationVk->initFeatures(std::move(vkEmulationFeatures));
488 
489         auto* display = fb->m_emulationVk->getDisplay();
490         if (display) {
491             fb->m_displayVk = display;
492             fb->m_displaySurfaceUsers.push_back(fb->m_displayVk);
493         }
494     }
495 
496     if (fb->m_emulationVk && fb->m_useVulkanComposition) {
497         fb->m_compositor = fb->m_emulationVk->getCompositor();
498         if (!fb->m_compositor) {
499             ERR("Failed to get CompositorVk from VkEmulation.");
500             return false;
501         }
502         GL_LOG("Performing composition using CompositorVk.");
503     } else {
504         GL_LOG("Performing composition using CompositorGl.");
505 #if GFXSTREAM_ENABLE_HOST_GLES
506         auto compositorGl = fb->m_emulationGl->getCompositor();
507         fb->m_compositor = compositorGl;
508 #endif
509     }
510 
511 #if GFXSTREAM_ENABLE_HOST_GLES
512     if (fb->m_emulationGl) {
513         auto displayGl = fb->m_emulationGl->getDisplay();
514         fb->m_displayGl = displayGl;
515         fb->m_displaySurfaceUsers.push_back(displayGl);
516     }
517 #endif
518 
519     INFO("Graphics Adapter Vendor %s", fb->m_graphicsAdapterVendor.c_str());
520     INFO("Graphics Adapter %s", fb->m_graphicsAdapterName.c_str());
521     INFO("Graphics API Version %s", fb->m_graphicsApiVersion.c_str());
522     INFO("Graphics API Extensions %s", fb->m_graphicsApiExtensions.c_str());
523     INFO("Graphics Device Extensions %s", fb->m_graphicsDeviceExtensions.c_str());
524 
525     if (fb->m_useVulkanComposition) {
526         fb->m_postWorker.reset(new PostWorkerVk(fb.get(), fb->m_compositor, fb->m_displayVk));
527     } else {
528         const bool shouldPostOnlyOnMainThread = postOnlyOnMainThread();
529 
530 #if GFXSTREAM_ENABLE_HOST_GLES
531         PostWorkerGl* postWorkerGl =
532             new PostWorkerGl(shouldPostOnlyOnMainThread, fb.get(), fb->m_compositor,
533                              fb->m_displayGl, fb->m_emulationGl.get());
534         fb->m_postWorker.reset(postWorkerGl);
535         fb->m_displaySurfaceUsers.push_back(postWorkerGl);
536 #endif
537     }
538 
539     // Start up the single sync thread. If we are using Vulkan native
540     // swapchain, then don't initialize SyncThread worker threads with EGL
541     // contexts.
542     SyncThread::initialize(
543         /* hasGL */ fb->m_emulationGl != nullptr, fb->getHealthMonitor());
544 
545     // Start the vsync thread
546     const uint64_t kOneSecondNs = 1000000000ULL;
547     fb->m_vsyncThread.reset(new VsyncThread((uint64_t)kOneSecondNs / (uint64_t)fb->m_vsyncHz));
548 
549     //
550     // Keep the singleton framebuffer pointer
551     //
552     s_theFrameBuffer = fb.release();
553     {
554         AutoLock lock(sGlobals()->lock);
555         sInitialized.store(true, std::memory_order_release);
556         sGlobals()->condVar.broadcastAndUnlock(&lock);
557     }
558 
559     // Nothing else to do - we're ready to rock!
560     return true;
561 }
562 
finalize()563 void FrameBuffer::finalize() {
564     FrameBuffer* fb = s_theFrameBuffer;
565     s_theFrameBuffer = nullptr;
566     if (fb) {
567         delete fb;
568     }
569 }
570 
FrameBuffer(int p_width,int p_height,gfxstream::host::FeatureSet features,bool useSubWindow)571 FrameBuffer::FrameBuffer(int p_width, int p_height, gfxstream::host::FeatureSet features, bool useSubWindow)
572     : m_features(features),
573       m_framebufferWidth(p_width),
574       m_framebufferHeight(p_height),
575       m_windowWidth(p_width),
576       m_windowHeight(p_height),
577       m_useSubWindow(useSubWindow),
578       m_fpsStats(getenv("SHOW_FPS_STATS") != nullptr),
579       m_perfStats(!android::base::getEnvironmentVariable("SHOW_PERF_STATS").empty()),
580       m_perfThread(new PerfStatThread(&m_perfStats)),
581       m_readbackThread(
582           [this](FrameBuffer::Readback&& readback) { return sendReadbackWorkerCmd(readback); }),
583       m_refCountPipeEnabled(features.RefCountPipe.enabled),
584       m_noDelayCloseColorBufferEnabled(features.NoDelayCloseColorBuffer.enabled ||
585                                        features.Minigbm.enabled),
__anon404b1a010d02(Post&& post) 586       m_postThread([this](Post&& post) { return postWorkerFunc(post); }),
587       m_logger(CreateMetricsLogger()),
588       m_healthMonitor(CreateHealthMonitor(*m_logger)) {
589     mDisplayActiveConfigId = 0;
590     mDisplayConfigs[0] = {p_width, p_height, 160, 160};
591     uint32_t displayId = 0;
592     if (createDisplay(&displayId) < 0) {
593         ERR( "Failed to create default display");
594     }
595 
596     setDisplayPose(displayId, 0, 0, getWidth(), getHeight(), 0);
597     m_perfThread->start();
598 }
599 
~FrameBuffer()600 FrameBuffer::~FrameBuffer() {
601     AutoLock fbLock(m_lock);
602 
603     m_perfStats = false;
604     m_perfThread->wait(NULL);
605 
606     m_postThread.enqueue({PostCmd::Exit});
607     m_postThread.join();
608     m_postWorker.reset();
609 
610     // Run other cleanup callbacks
611     // Avoid deadlock by first storing a separate list of callbacks
612     std::vector<std::function<void()>> callbacks;
613     for (auto procIte : m_procOwnedCleanupCallbacks)
614     {
615         for (auto it : procIte.second) {
616             callbacks.push_back(it.second);
617         }
618     }
619     m_procOwnedCleanupCallbacks.clear();
620 
621     fbLock.unlock();
622 
623     for (auto cb : callbacks) {
624         cb();
625     }
626 
627     fbLock.lock();
628 
629     if (m_useSubWindow) {
630         removeSubWindow_locked();
631     }
632 
633     m_readbackThread.enqueue({ReadbackCmd::Exit});
634     m_readbackThread.join();
635 
636     m_vsyncThread.reset();
637 
638     delete m_perfThread;
639 
640     SyncThread::destroy();
641 
642     sweepColorBuffersLocked();
643 
644     m_buffers.clear();
645     {
646         AutoLock lock(m_colorBufferMapLock);
647         m_colorbuffers.clear();
648     }
649     m_colorBufferDelayedCloseList.clear();
650 
651 #if GFXSTREAM_ENABLE_HOST_GLES
652     m_windows.clear();
653     m_contexts.clear();
654 
655     for (auto it : m_platformEglContexts) {
656         destroySharedTrivialContext(it.second.context, it.second.surface);
657     }
658 #endif
659 
660     if (m_emulationGl) {
661         m_emulationGl.reset();
662     }
663     if (m_emulationVk) {
664         m_emulationVk.reset();
665     }
666 
667     sInitialized.store(false, std::memory_order_relaxed);
668 }
669 
670 WorkerProcessingResult
sendReadbackWorkerCmd(const Readback & readback)671 FrameBuffer::sendReadbackWorkerCmd(const Readback& readback) {
672     ensureReadbackWorker();
673     switch (readback.cmd) {
674     case ReadbackCmd::Init:
675         m_readbackWorker->init();
676         return WorkerProcessingResult::Continue;
677     case ReadbackCmd::GetPixels:
678         m_readbackWorker->getPixels(readback.displayId, readback.pixelsOut, readback.bytes);
679         return WorkerProcessingResult::Continue;
680     case ReadbackCmd::AddRecordDisplay:
681         m_readbackWorker->initReadbackForDisplay(readback.displayId, readback.width, readback.height);
682         return WorkerProcessingResult::Continue;
683     case ReadbackCmd::DelRecordDisplay:
684         m_readbackWorker->deinitReadbackForDisplay(readback.displayId);
685         return WorkerProcessingResult::Continue;
686     case ReadbackCmd::Exit:
687         return WorkerProcessingResult::Stop;
688     }
689     return WorkerProcessingResult::Stop;
690 }
691 
postWorkerFunc(Post & post)692 WorkerProcessingResult FrameBuffer::postWorkerFunc(Post& post) {
693     auto annotations = std::make_unique<EventHangMetadata::HangAnnotations>();
694     if (m_healthMonitor)
695         annotations->insert(
696             {"Post command opcode", std::to_string(static_cast<uint64_t>(post.cmd))});
697     auto watchdog = WATCHDOG_BUILDER(m_healthMonitor.get(), "PostWorker main function")
698                         .setAnnotations(std::move(annotations))
699                         .build();
700     switch (post.cmd) {
701         case PostCmd::Post: {
702             // We wrap the callback like this to workaround a bug in the MS STL implementation.
703             auto packagePostCmdCallback =
704                 std::shared_ptr<Post::CompletionCallback>(std::move(post.completionCallback));
705             std::unique_ptr<Post::CompletionCallback> postCallback =
706                 std::make_unique<Post::CompletionCallback>(
707                     [packagePostCmdCallback](std::shared_future<void> waitForGpu) {
708                         SyncThread::get()->triggerGeneral(
709                             [composeCallback = std::move(packagePostCmdCallback), waitForGpu] {
710                                 (*composeCallback)(waitForGpu);
711                             },
712                             "Wait for post");
713                     });
714             m_postWorker->post(post.cb, std::move(postCallback));
715             decColorBufferRefCountNoDestroy(post.cbHandle);
716             break;
717         }
718         case PostCmd::Viewport:
719             m_postWorker->viewport(post.viewport.width,
720                                    post.viewport.height);
721             break;
722         case PostCmd::Compose: {
723             std::unique_ptr<FlatComposeRequest> composeRequest;
724             std::unique_ptr<Post::CompletionCallback> composeCallback;
725             if (post.composeVersion <= 1) {
726                 composeCallback = std::move(post.completionCallback);
727                 composeRequest = ToFlatComposeRequest((ComposeDevice*)post.composeBuffer.data());
728             } else {
729                 // std::shared_ptr(std::move(...)) is WA for MSFT STL implementation bug:
730                 // https://developercommunity.visualstudio.com/t/unable-to-move-stdpackaged-task-into-any-stl-conta/108672
731                 auto packageComposeCallback =
732                     std::shared_ptr<Post::CompletionCallback>(std::move(post.completionCallback));
733                 composeCallback = std::make_unique<Post::CompletionCallback>(
734                     [packageComposeCallback](
735                         std::shared_future<void> waitForGpu) {
736                         SyncThread::get()->triggerGeneral(
737                             [composeCallback = std::move(packageComposeCallback), waitForGpu] {
738                                 (*composeCallback)(waitForGpu);
739                             },
740                             "Wait for host composition");
741                     });
742                 composeRequest = ToFlatComposeRequest((ComposeDevice_v2*)post.composeBuffer.data());
743             }
744             m_postWorker->compose(std::move(composeRequest), std::move(composeCallback));
745             break;
746         }
747         case PostCmd::Clear:
748             m_postWorker->clear();
749             break;
750         case PostCmd::Screenshot:
751             m_postWorker->screenshot(
752                     post.screenshot.cb, post.screenshot.screenwidth,
753                     post.screenshot.screenheight, post.screenshot.format,
754                     post.screenshot.type, post.screenshot.rotation,
755                     post.screenshot.pixels, post.screenshot.rect);
756             decColorBufferRefCountNoDestroy(post.cbHandle);
757             break;
758         case PostCmd::Block:
759             m_postWorker->block(std::move(post.block->scheduledSignal),
760                                 std::move(post.block->continueSignal));
761             break;
762         case PostCmd::Exit:
763             m_postWorker->exit();
764             return WorkerProcessingResult::Stop;
765         default:
766             break;
767     }
768     return WorkerProcessingResult::Continue;
769 }
770 
sendPostWorkerCmd(Post post)771 std::future<void> FrameBuffer::sendPostWorkerCmd(Post post) {
772     bool expectedPostThreadStarted = false;
773     if (m_postThreadStarted.compare_exchange_strong(expectedPostThreadStarted, true)) {
774         m_postThread.start();
775     }
776 
777     bool shouldPostOnlyOnMainThread = postOnlyOnMainThread();
778     // If we want to run only in the main thread and we are actually running
779     // in the main thread already, don't use the PostWorker thread. Ideally,
780     // PostWorker should handle this and dispatch directly, but we'll need to
781     // transfer ownership of the thread to PostWorker.
782     // TODO(lfy): do that refactor
783     // For now, this fixes a screenshot issue on macOS.
784     std::future<void> res = std::async(std::launch::deferred, [] {});
785     res.wait();
786     if (shouldPostOnlyOnMainThread && (PostCmd::Screenshot == post.cmd) &&
787         emugl::get_emugl_window_operations().isRunningInUiThread()) {
788         post.cb->readToBytesScaled(post.screenshot.screenwidth, post.screenshot.screenheight,
789                                    post.screenshot.format, post.screenshot.type,
790                                    post.screenshot.rotation, post.screenshot.rect,
791                                    post.screenshot.pixels);
792     } else {
793         std::future<void> completeFuture =
794             m_postThread.enqueue(Post(std::move(post)));
795         if (!shouldPostOnlyOnMainThread ||
796             (PostCmd::Screenshot == post.cmd &&
797              !emugl::get_emugl_window_operations().isRunningInUiThread())) {
798             res = std::move(completeFuture);
799         }
800     }
801     return res;
802 }
803 
setPostCallback(Renderer::OnPostCallback onPost,void * onPostContext,uint32_t displayId,bool useBgraReadback)804 void FrameBuffer::setPostCallback(Renderer::OnPostCallback onPost, void* onPostContext,
805                                   uint32_t displayId, bool useBgraReadback) {
806     AutoLock lock(m_lock);
807     if (onPost) {
808         uint32_t w, h;
809         if (!emugl::get_emugl_multi_display_operations().getMultiDisplay(displayId,
810                                                                          nullptr,
811                                                                          nullptr,
812                                                                          &w, &h,
813                                                                          nullptr,
814                                                                          nullptr,
815                                                                          nullptr)) {
816             ERR("display %d not exist, cancelling OnPost callback", displayId);
817             return;
818         }
819         if (m_onPost.find(displayId) != m_onPost.end()) {
820             ERR("display %d already configured for recording", displayId);
821             return;
822         }
823         m_onPost[displayId].cb = onPost;
824         m_onPost[displayId].context = onPostContext;
825         m_onPost[displayId].displayId = displayId;
826         m_onPost[displayId].width = w;
827         m_onPost[displayId].height = h;
828         m_onPost[displayId].img = new unsigned char[4 * w * h];
829         m_onPost[displayId].readBgra = useBgraReadback;
830         bool expectedReadbackThreadStarted = false;
831         if (m_readbackThreadStarted.compare_exchange_strong(expectedReadbackThreadStarted, true)) {
832             m_readbackThread.start();
833             m_readbackThread.enqueue({ ReadbackCmd::Init });
834         }
835         std::future<void> completeFuture = m_readbackThread.enqueue(
836             {ReadbackCmd::AddRecordDisplay, displayId, nullptr, 0, w, h});
837         completeFuture.wait();
838     } else {
839         std::future<void> completeFuture = m_readbackThread.enqueue(
840             {ReadbackCmd::DelRecordDisplay, displayId});
841         completeFuture.wait();
842         m_onPost.erase(displayId);
843     }
844 }
845 
subWindowRepaint(void * param)846 static void subWindowRepaint(void* param) {
847     GL_LOG("call repost from subWindowRepaint callback");
848     auto fb = static_cast<FrameBuffer*>(param);
849     fb->repost();
850 }
851 
setupSubWindow(FBNativeWindowType p_window,int wx,int wy,int ww,int wh,int fbw,int fbh,float dpr,float zRot,bool deleteExisting,bool hideWindow)852 bool FrameBuffer::setupSubWindow(FBNativeWindowType p_window,
853                                  int wx,
854                                  int wy,
855                                  int ww,
856                                  int wh,
857                                  int fbw,
858                                  int fbh,
859                                  float dpr,
860                                  float zRot,
861                                  bool deleteExisting,
862                                  bool hideWindow) {
863     GL_LOG("Begin setupSubWindow");
864     if (!m_useSubWindow) {
865         ERR("%s: Cannot create native sub-window in this configuration\n",
866             __FUNCTION__);
867         return false;
868     }
869 
870     // Do a quick check before even taking the lock - maybe we don't need to
871     // do anything here.
872 
873     const bool shouldCreateSubWindow = !m_subWin || deleteExisting;
874 
875     // On Mac, since window coordinates are Y-up and not Y-down, the
876     // subwindow may not change dimensions, but because the main window
877     // did, the subwindow technically needs to be re-positioned. This
878     // can happen on rotation, so a change in Z-rotation can be checked
879     // for this case. However, this *should not* be done on Windows/Linux,
880     // because the functions used to resize a native window on those hosts
881     // will block if the shape doesn't actually change, freezing the
882     // emulator.
883     const bool shouldMoveSubWindow =
884         !shouldCreateSubWindow &&
885         !(m_x == wx && m_y == wy && m_windowWidth == ww && m_windowHeight == wh
886 #if defined(__APPLE__)
887           && m_zRot == zRot
888 #endif
889         );
890 
891     const bool redrawSubwindow =
892         shouldCreateSubWindow || shouldMoveSubWindow || m_zRot != zRot || m_dpr != dpr ||
893         m_windowContentFullWidth != fbw || m_windowContentFullHeight != fbh;
894     if (!shouldCreateSubWindow && !shouldMoveSubWindow && !redrawSubwindow) {
895         assert(sInitialized.load(std::memory_order_relaxed));
896         GL_LOG("Exit setupSubWindow (nothing to do)");
897 #if SNAPSHOT_PROFILE > 1
898         // printf("FrameBuffer::%s(): nothing to do at %lld ms\n", __func__,
899                // (long long)System::get()->getProcessTimes().wallClockMs);
900 #endif
901         return true;
902     }
903 
904 #if SNAPSHOT_PROFILE > 1
905     // printf("FrameBuffer::%s(%s): start at %lld ms\n", __func__,
906     //        deleteExisting ? "deleteExisting" : "keepExisting",
907     //        (long long)System::get()->getProcessTimes().wallClockMs);
908 #endif
909     class ScopedPromise {
910        public:
911         ~ScopedPromise() { mPromise.set_value(); }
912         std::future<void> getFuture() { return mPromise.get_future(); }
913         DISALLOW_COPY_ASSIGN_AND_MOVE(ScopedPromise);
914         static std::tuple<std::unique_ptr<ScopedPromise>, std::future<void>> create() {
915             auto scopedPromise = std::unique_ptr<ScopedPromise>(new ScopedPromise());
916             auto future = scopedPromise->mPromise.get_future();
917             return std::make_tuple(std::move(scopedPromise), std::move(future));
918         }
919 
920        private:
921         ScopedPromise() = default;
922         std::promise<void> mPromise;
923     };
924     std::unique_ptr<ScopedPromise> postWorkerContinueSignal;
925     std::future<void> postWorkerContinueSignalFuture;
926     std::tie(postWorkerContinueSignal, postWorkerContinueSignalFuture) = ScopedPromise::create();
927     {
928         auto watchdog =
929             WATCHDOG_BUILDER(m_healthMonitor.get(), "Wait for other tasks on PostWorker")
930                 .setTimeoutMs(6000)
931                 .build();
932         blockPostWorker(std::move(postWorkerContinueSignalFuture)).wait();
933     }
934     if (m_displayVk) {
935         auto watchdog = WATCHDOG_BUILDER(m_healthMonitor.get(), "Draining the VkQueue")
936                             .setTimeoutMs(6000)
937                             .build();
938         m_displayVk->drainQueues();
939     }
940     auto lockWatchdog =
941         WATCHDOG_BUILDER(m_healthMonitor.get(), "Wait for the FrameBuffer global lock").build();
942     auto lockWatchdogId = lockWatchdog->release();
943     AutoLock mutex(m_lock);
944     if (lockWatchdogId.has_value()) {
945         m_healthMonitor->stopMonitoringTask(lockWatchdogId.value());
946     }
947 
948 #if SNAPSHOT_PROFILE > 1
949     // printf("FrameBuffer::%s(): got lock at %lld ms\n", __func__,
950     //        (long long)System::get()->getProcessTimes().wallClockMs);
951 #endif
952 
953     if (deleteExisting) {
954         removeSubWindow_locked();
955     }
956 
957     bool success = false;
958 
959     // If the subwindow doesn't exist, create it with the appropriate dimensions
960     if (!m_subWin) {
961         // Create native subwindow for FB display output
962         m_x = wx;
963         m_y = wy;
964         m_windowWidth = ww;
965         m_windowHeight = wh;
966 
967         if (!hideWindow) {
968             m_subWin = createSubWindow(p_window, m_x, m_y, m_windowWidth, m_windowHeight, dpr,
969                                        subWindowRepaint, this, hideWindow);
970         }
971         if (m_subWin) {
972             m_nativeWindow = p_window;
973 
974             if (m_displayVk) {
975                 m_displaySurface = m_emulationVk->createDisplaySurface(
976                     m_subWin, m_windowWidth * dpr, m_windowHeight * dpr);
977             } else if (m_emulationGl) {
978 #if GFXSTREAM_ENABLE_HOST_GLES
979                 m_displaySurface = m_emulationGl->createWindowSurface(m_windowWidth * dpr,
980                                                                       m_windowHeight * dpr,
981                                                                       m_subWin);
982 #endif
983             } else {
984                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
985                     << "Unhandled window surface creation.";
986             }
987 
988             if (m_displaySurface) {
989                 // Some backends use a default display surface. Unbind from that before
990                 // binding the new display surface. which potentially needs to be unbound.
991                 for (auto* displaySurfaceUser : m_displaySurfaceUsers) {
992                     displaySurfaceUser->unbindFromSurface();
993                 }
994 
995                 // TODO: Make RenderDoc a DisplaySurfaceUser.
996                 if (m_displayVk) {
997                     if (m_renderDoc) {
998                         m_renderDoc->call(emugl::RenderDoc::kSetActiveWindow,
999                                           RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(m_vkInstance),
1000                                           reinterpret_cast<RENDERDOC_WindowHandle>(m_subWin));
1001                     }
1002                 }
1003 
1004                 m_px = 0;
1005                 m_py = 0;
1006                 for (auto* displaySurfaceUser : m_displaySurfaceUsers) {
1007                     displaySurfaceUser->bindToSurface(m_displaySurface.get());
1008                 }
1009                 success = true;
1010             } else {
1011                 // Display surface creation failed.
1012                 if (m_emulationGl) {
1013                     // NOTE: This can typically happen with software-only renderers like OSMesa.
1014                     destroySubWindow(m_subWin);
1015                     m_subWin = (EGLNativeWindowType)0;
1016                 } else {
1017                     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1018                         << "Failed to create DisplaySurface.";
1019                 }
1020             }
1021         }
1022     }
1023 
1024     auto watchdog = WATCHDOG_BUILDER(m_healthMonitor.get(), "Updating subwindow state").build();
1025     // At this point, if the subwindow doesn't exist, it is because it either
1026     // couldn't be created
1027     // in the first place or the EGLSurface couldn't be created.
1028     if (m_subWin) {
1029         if (!shouldMoveSubWindow) {
1030             // Ensure that at least viewport parameters are properly updated.
1031             success = true;
1032         } else {
1033             // Only attempt to update window geometry if anything has actually
1034             // changed.
1035             m_x = wx;
1036             m_y = wy;
1037             m_windowWidth = ww;
1038             m_windowHeight = wh;
1039 
1040             {
1041                 auto moveWatchdog =
1042                     WATCHDOG_BUILDER(m_healthMonitor.get(), "Moving subwindow").build();
1043                 success = moveSubWindow(m_nativeWindow, m_subWin, m_x, m_y, m_windowWidth,
1044                                         m_windowHeight, dpr);
1045             }
1046             m_displaySurface->updateSize(m_windowWidth * dpr, m_windowHeight * dpr);
1047         }
1048         // We are safe to unblock the PostWorker thread now, because we have completed all the
1049         // operations that could modify the state of the m_subWin. We need to unblock the PostWorker
1050         // here because we may need to send and wait for other tasks dispatched to the PostWorker
1051         // later, e.g. the viewport command or the post command issued later.
1052         postWorkerContinueSignal.reset();
1053 
1054         if (success && redrawSubwindow) {
1055             // Subwin creation or movement was successful,
1056             // update viewport and z rotation and draw
1057             // the last posted color buffer.
1058             m_dpr = dpr;
1059             m_zRot = zRot;
1060             if (m_displayVk == nullptr) {
1061                 Post postCmd;
1062                 postCmd.cmd = PostCmd::Viewport;
1063                 postCmd.viewport.width = fbw;
1064                 postCmd.viewport.height = fbh;
1065                 sendPostWorkerCmd(std::move(postCmd));
1066 
1067                 if (m_lastPostedColorBuffer) {
1068                     GL_LOG("setupSubwindow: draw last posted cb");
1069                     postImpl(m_lastPostedColorBuffer,
1070                         [](std::shared_future<void> waitForGpu) {}, false);
1071                 } else {
1072                     Post clearCmd;
1073                     clearCmd.cmd = PostCmd::Clear;
1074                     sendPostWorkerCmd(std::move(clearCmd));
1075                 }
1076             }
1077             m_windowContentFullWidth = fbw;
1078             m_windowContentFullHeight = fbh;
1079         }
1080     }
1081 
1082     mutex.unlock();
1083 
1084     // Nobody ever checks for the return code, so there will be no retries or
1085     // even aborted run; if we don't mark the framebuffer as initialized here
1086     // its users will hang forever; if we do mark it, they will crash - which
1087     // is a better outcome (crash report == bug fixed).
1088     AutoLock lock(sGlobals()->lock);
1089     sInitialized.store(true, std::memory_order_relaxed);
1090     sGlobals()->condVar.broadcastAndUnlock(&lock);
1091 
1092 #if SNAPSHOT_PROFILE > 1
1093     // printf("FrameBuffer::%s(): end at %lld ms\n", __func__,
1094     //        (long long)System::get()->getProcessTimes().wallClockMs);
1095 #endif
1096 
1097     GL_LOG("Exit setupSubWindow (successful setup)");
1098     return success;
1099 }
1100 
removeSubWindow()1101 bool FrameBuffer::removeSubWindow() {
1102     if (!m_useSubWindow) {
1103         ERR("Cannot remove native sub-window in this configuration");
1104         return false;
1105     }
1106     AutoLock lock(sGlobals()->lock);
1107     sInitialized.store(false, std::memory_order_relaxed);
1108     sGlobals()->condVar.broadcastAndUnlock(&lock);
1109 
1110     AutoLock mutex(m_lock);
1111     return removeSubWindow_locked();
1112 }
1113 
removeSubWindow_locked()1114 bool FrameBuffer::removeSubWindow_locked() {
1115     if (!m_useSubWindow) {
1116         ERR("Cannot remove native sub-window in this configuration");
1117         return false;
1118     }
1119     bool removed = false;
1120     if (m_subWin) {
1121         for (auto* displaySurfaceUser : m_displaySurfaceUsers) {
1122             displaySurfaceUser->unbindFromSurface();
1123         }
1124         m_displaySurface.reset();
1125 
1126         destroySubWindow(m_subWin);
1127 
1128         m_subWin = (EGLNativeWindowType)0;
1129         removed = true;
1130     }
1131     return removed;
1132 }
1133 
genHandle_locked()1134 HandleType FrameBuffer::genHandle_locked() {
1135     HandleType id;
1136     do {
1137         id = ++s_nextHandle;
1138     } while (id == 0 ||
1139 #if GFXSTREAM_ENABLE_HOST_GLES
1140              m_contexts.find(id) != m_contexts.end() || m_windows.find(id) != m_windows.end() ||
1141 #endif
1142              m_colorbuffers.find(id) != m_colorbuffers.end() ||
1143              m_buffers.find(id) != m_buffers.end());
1144 
1145     return id;
1146 }
1147 
isFormatSupported(GLenum format)1148 bool FrameBuffer::isFormatSupported(GLenum format) {
1149     bool supported = true;
1150     if (m_emulationGl) {
1151         supported &= m_emulationGl->isFormatSupported(format);
1152     }
1153     if (m_emulationVk) {
1154         supported &= m_emulationVk->isFormatSupported(format);
1155     }
1156     return supported;
1157 }
1158 
createColorBuffer(int p_width,int p_height,GLenum p_internalFormat,FrameworkFormat p_frameworkFormat)1159 HandleType FrameBuffer::createColorBuffer(int p_width,
1160                                           int p_height,
1161                                           GLenum p_internalFormat,
1162                                           FrameworkFormat p_frameworkFormat) {
1163 
1164     AutoLock mutex(m_lock);
1165     sweepColorBuffersLocked();
1166     AutoLock colorBufferMapLock(m_colorBufferMapLock);
1167 
1168     return createColorBufferWithResourceHandleLocked(p_width, p_height, p_internalFormat,
1169                                                      p_frameworkFormat, genHandle_locked());
1170 }
1171 
createColorBufferWithResourceHandle(int p_width,int p_height,GLenum p_internalFormat,FrameworkFormat p_frameworkFormat,HandleType handle,bool p_linear)1172 void FrameBuffer::createColorBufferWithResourceHandle(int p_width, int p_height,
1173                                                       GLenum p_internalFormat,
1174                                                       FrameworkFormat p_frameworkFormat,
1175                                                       HandleType handle, bool p_linear) {
1176     {
1177         AutoLock mutex(m_lock);
1178         sweepColorBuffersLocked();
1179 
1180         AutoLock colorBufferMapLock(m_colorBufferMapLock);
1181 
1182         // Check for handle collision
1183         if (m_colorbuffers.count(handle) != 0) {
1184             // emugl::emugl_crash_reporter(
1185             //     "FATAL: color buffer with handle %u already exists",
1186             //     handle);
1187             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER));
1188         }
1189 
1190         createColorBufferWithResourceHandleLocked(p_width, p_height, p_internalFormat,
1191                                                   p_frameworkFormat, handle, p_linear);
1192     }
1193 }
1194 
createColorBufferWithResourceHandleLocked(int p_width,int p_height,GLenum p_internalFormat,FrameworkFormat p_frameworkFormat,HandleType handle,bool p_linear)1195 HandleType FrameBuffer::createColorBufferWithResourceHandleLocked(int p_width, int p_height,
1196                                                                   GLenum p_internalFormat,
1197                                                                   FrameworkFormat p_frameworkFormat,
1198                                                                   HandleType handle,
1199                                                                   bool p_linear) {
1200     ColorBufferPtr cb = ColorBuffer::create(m_emulationGl.get(), m_emulationVk.get(), p_width,
1201                                             p_height, p_internalFormat, p_frameworkFormat, handle,
1202                                             nullptr /*stream*/, p_linear);
1203     if (cb.get() == nullptr) {
1204         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1205             << "Failed to create ColorBuffer:" << handle << " format:" << p_internalFormat
1206             << " framework-format:" << p_frameworkFormat << " width:" << p_width
1207             << " height:" << p_height;
1208     }
1209 
1210     assert(m_colorbuffers.count(handle) == 0);
1211     // When guest feature flag RefCountPipe is on, no reference counting is
1212     // needed. We only memoize the mapping from handle to ColorBuffer.
1213     // Explicitly set refcount to 1 to avoid the colorbuffer being added to
1214     // m_colorBufferDelayedCloseList in FrameBuffer::onLoad().
1215     if (m_refCountPipeEnabled) {
1216         m_colorbuffers.try_emplace(handle, ColorBufferRef{std::move(cb), 1, false, 0});
1217     } else {
1218         // Android master default api level is 1000
1219         int apiLevel = 1000;
1220         emugl::getAvdInfo(nullptr, &apiLevel);
1221         // pre-O and post-O use different color buffer memory management
1222         // logic
1223         if (apiLevel > 0 && apiLevel < 26) {
1224             m_colorbuffers.try_emplace(handle, ColorBufferRef{std::move(cb), 1, false, 0});
1225 
1226             RenderThreadInfo* tInfo = RenderThreadInfo::get();
1227             uint64_t puid = tInfo->m_puid;
1228             if (puid) {
1229                 m_procOwnedColorBuffers[puid].insert(handle);
1230             }
1231 
1232         } else {
1233             m_colorbuffers.try_emplace(handle, ColorBufferRef{std::move(cb), 0, false, 0});
1234         }
1235     }
1236 
1237     return handle;
1238 }
1239 
createBuffer(uint64_t p_size,uint32_t memoryProperty)1240 HandleType FrameBuffer::createBuffer(uint64_t p_size, uint32_t memoryProperty) {
1241     AutoLock mutex(m_lock);
1242     AutoLock colorBufferMapLock(m_colorBufferMapLock);
1243     return createBufferWithResourceHandleLocked(p_size, genHandle_locked(), memoryProperty);
1244 }
1245 
createBufferWithResourceHandle(uint64_t size,HandleType handle)1246 void FrameBuffer::createBufferWithResourceHandle(uint64_t size, HandleType handle) {
1247     AutoLock mutex(m_lock);
1248     AutoLock colorBufferMapLock(m_colorBufferMapLock);
1249 
1250     if (m_buffers.count(handle) != 0) {
1251         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1252             << "Buffer already exists with handle " << handle;
1253     }
1254 
1255     createBufferWithResourceHandleLocked(size, handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1256 }
1257 
createBufferWithResourceHandleLocked(int p_size,HandleType handle,uint32_t memoryProperty)1258 HandleType FrameBuffer::createBufferWithResourceHandleLocked(int p_size, HandleType handle,
1259                                                              uint32_t memoryProperty) {
1260     if (m_buffers.count(handle) != 0) {
1261         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1262             << "Buffer already exists with handle " << handle;
1263     }
1264 
1265     BufferPtr buffer(Buffer::create(m_emulationGl.get(), m_emulationVk.get(), p_size, handle));
1266     if (!buffer) {
1267         ERR("Create buffer failed.\n");
1268         return 0;
1269     }
1270 
1271     m_buffers[handle] = {std::move(buffer)};
1272 
1273     return handle;
1274 }
1275 
openColorBuffer(HandleType p_colorbuffer)1276 int FrameBuffer::openColorBuffer(HandleType p_colorbuffer) {
1277     // When guest feature flag RefCountPipe is on, no reference counting is
1278     // needed.
1279     if (m_refCountPipeEnabled) return 0;
1280 
1281     RenderThreadInfo* tInfo = RenderThreadInfo::get();
1282 
1283     AutoLock mutex(m_lock);
1284 
1285     ColorBufferMap::iterator c;
1286     {
1287         AutoLock colorBuffermapLock(m_colorBufferMapLock);
1288         c = m_colorbuffers.find(p_colorbuffer);
1289         if (c == m_colorbuffers.end()) {
1290             // bad colorbuffer handle
1291             ERR("FB: openColorBuffer cb handle %d not found", p_colorbuffer);
1292             return -1;
1293         }
1294         c->second.refcount++;
1295         markOpened(&c->second);
1296     }
1297 
1298     uint64_t puid = tInfo ? tInfo->m_puid : 0;
1299     if (puid) {
1300         m_procOwnedColorBuffers[puid].insert(p_colorbuffer);
1301     }
1302     return 0;
1303 }
1304 
closeColorBuffer(HandleType p_colorbuffer)1305 void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer) {
1306     // When guest feature flag RefCountPipe is on, no reference counting is
1307     // needed.
1308     if (m_refCountPipeEnabled) {
1309         return;
1310     }
1311 
1312     RenderThreadInfo* tInfo = RenderThreadInfo::get();
1313 
1314     std::vector<HandleType> toCleanup;
1315 
1316     AutoLock mutex(m_lock);
1317     uint64_t puid = tInfo ? tInfo->m_puid : 0;
1318     if (puid) {
1319         auto ite = m_procOwnedColorBuffers.find(puid);
1320         if (ite != m_procOwnedColorBuffers.end()) {
1321             const auto& cb = ite->second.find(p_colorbuffer);
1322             if (cb != ite->second.end()) {
1323                 ite->second.erase(cb);
1324                 if (closeColorBufferLocked(p_colorbuffer)) {
1325                     toCleanup.push_back(p_colorbuffer);
1326                 }
1327             }
1328         }
1329     } else {
1330         if (closeColorBufferLocked(p_colorbuffer)) {
1331             toCleanup.push_back(p_colorbuffer);
1332         }
1333     }
1334 }
1335 
closeBuffer(HandleType p_buffer)1336 void FrameBuffer::closeBuffer(HandleType p_buffer) {
1337     AutoLock mutex(m_lock);
1338 
1339     auto it = m_buffers.find(p_buffer);
1340     if (it == m_buffers.end()) {
1341         ERR("Failed to find Buffer:%d", p_buffer);
1342         return;
1343     }
1344 
1345     m_buffers.erase(it);
1346 }
1347 
closeColorBufferLocked(HandleType p_colorbuffer,bool forced)1348 bool FrameBuffer::closeColorBufferLocked(HandleType p_colorbuffer, bool forced) {
1349     // When guest feature flag RefCountPipe is on, no reference counting is
1350     // needed.
1351     if (m_refCountPipeEnabled) {
1352         return false;
1353     }
1354     bool deleted = false;
1355     {
1356         AutoLock colorBufferMapLock(m_colorBufferMapLock);
1357 
1358         if (m_noDelayCloseColorBufferEnabled) forced = true;
1359 
1360         ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
1361         if (c == m_colorbuffers.end()) {
1362             // This is harmless: it is normal for guest system to issue
1363             // closeColorBuffer command when the color buffer is already
1364             // garbage collected on the host. (we don't have a mechanism
1365             // to give guest a notice yet)
1366             return false;
1367         }
1368 
1369         // The guest can and will gralloc_alloc/gralloc_free and then
1370         // gralloc_register a buffer, due to API level (O+) or
1371         // timing issues.
1372         // So, we don't actually close the color buffer when refcount
1373         // reached zero, unless it has been opened at least once already.
1374         // Instead, put it on a 'delayed close' list to return to it later.
1375         if (--c->second.refcount == 0) {
1376             if (forced) {
1377                 eraseDelayedCloseColorBufferLocked(c->first, c->second.closedTs);
1378                 m_colorbuffers.erase(c);
1379                 deleted = true;
1380             } else {
1381                 c->second.closedTs = android::base::getUnixTimeUs();
1382                 m_colorBufferDelayedCloseList.push_back({c->second.closedTs, p_colorbuffer});
1383             }
1384         }
1385     }
1386 
1387     performDelayedColorBufferCloseLocked(false);
1388 
1389     return deleted;
1390 }
1391 
decColorBufferRefCountNoDestroy(HandleType p_colorbuffer)1392 void FrameBuffer::decColorBufferRefCountNoDestroy(HandleType p_colorbuffer) {
1393     AutoLock colorBufferMapLock(m_colorBufferMapLock);
1394 
1395     ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
1396     if (c == m_colorbuffers.end()) {
1397         return;
1398     }
1399 
1400     if (--c->second.refcount == 0) {
1401         c->second.closedTs = android::base::getUnixTimeUs();
1402         m_colorBufferDelayedCloseList.push_back({c->second.closedTs, p_colorbuffer});
1403     }
1404 }
1405 
performDelayedColorBufferCloseLocked(bool forced)1406 void FrameBuffer::performDelayedColorBufferCloseLocked(bool forced) {
1407     // Let's wait just long enough to make sure it's not because of instant
1408     // timestamp change (end of previous second -> beginning of a next one),
1409     // but not for long - this is a workaround for race conditions, and they
1410     // are quick.
1411     static constexpr uint64_t kColorBufferClosingDelayUs = 1000000LL;
1412 
1413     const auto now = android::base::getUnixTimeUs();
1414     auto it = m_colorBufferDelayedCloseList.begin();
1415     while (it != m_colorBufferDelayedCloseList.end() &&
1416            (forced ||
1417            it->ts + kColorBufferClosingDelayUs <= now)) {
1418         if (it->cbHandle != 0) {
1419             AutoLock colorBufferMapLock(m_colorBufferMapLock);
1420             const auto& cb = m_colorbuffers.find(it->cbHandle);
1421             if (cb != m_colorbuffers.end()) {
1422                 m_colorbuffers.erase(cb);
1423             }
1424         }
1425         ++it;
1426     }
1427     m_colorBufferDelayedCloseList.erase(
1428                 m_colorBufferDelayedCloseList.begin(), it);
1429 }
1430 
eraseDelayedCloseColorBufferLocked(HandleType cb,uint64_t ts)1431 void FrameBuffer::eraseDelayedCloseColorBufferLocked(
1432         HandleType cb, uint64_t ts)
1433 {
1434     // Find the first delayed buffer with a timestamp <= |ts|
1435     auto it = std::lower_bound(
1436                   m_colorBufferDelayedCloseList.begin(),
1437                   m_colorBufferDelayedCloseList.end(), ts,
1438                   [](const ColorBufferCloseInfo& ci, uint64_t ts) {
1439         return ci.ts < ts;
1440     });
1441     while (it != m_colorBufferDelayedCloseList.end() &&
1442            it->ts == ts) {
1443         // if this is the one we need - clear it out.
1444         if (it->cbHandle == cb) {
1445             it->cbHandle = 0;
1446             break;
1447         }
1448         ++it;
1449     }
1450 }
1451 
createGraphicsProcessResources(uint64_t puid)1452 void FrameBuffer::createGraphicsProcessResources(uint64_t puid) {
1453     bool inserted = false;
1454     {
1455         AutoLock mutex(m_procOwnedResourcesLock);
1456         inserted = m_procOwnedResources.try_emplace(puid, ProcessResources::create()).second;
1457     }
1458     if (!inserted) {
1459         WARN("Failed to create process resource for puid %" PRIu64 ".", puid);
1460     }
1461 }
1462 
removeGraphicsProcessResources(uint64_t puid)1463 std::unique_ptr<ProcessResources> FrameBuffer::removeGraphicsProcessResources(uint64_t puid) {
1464     std::unordered_map<uint64_t, std::unique_ptr<ProcessResources>>::node_type node;
1465     {
1466         AutoLock mutex(m_procOwnedResourcesLock);
1467         node = m_procOwnedResources.extract(puid);
1468     }
1469     if (node.empty()) {
1470         WARN("Failed to find process resource for puid %" PRIu64 ".", puid);
1471         return nullptr;
1472     }
1473     std::unique_ptr<ProcessResources> res = std::move(node.mapped());
1474     return res;
1475 }
1476 
cleanupProcGLObjects(uint64_t puid)1477 void FrameBuffer::cleanupProcGLObjects(uint64_t puid) {
1478     bool renderThreadWithThisPuidExists = false;
1479 
1480     do {
1481         renderThreadWithThisPuidExists = false;
1482         RenderThreadInfo::forAllRenderThreadInfos(
1483             [puid, &renderThreadWithThisPuidExists](RenderThreadInfo* i) {
1484             if (i->m_puid == puid) {
1485                 renderThreadWithThisPuidExists = true;
1486             }
1487         });
1488         android::base::sleepUs(10000);
1489     } while (renderThreadWithThisPuidExists);
1490 
1491 
1492     AutoLock mutex(m_lock);
1493 
1494     cleanupProcGLObjects_locked(puid);
1495 
1496     // Run other cleanup callbacks
1497     // Avoid deadlock by first storing a separate list of callbacks
1498     std::vector<std::function<void()>> callbacks;
1499 
1500     {
1501         auto procIte = m_procOwnedCleanupCallbacks.find(puid);
1502         if (procIte != m_procOwnedCleanupCallbacks.end()) {
1503             for (auto it : procIte->second) {
1504                 callbacks.push_back(it.second);
1505             }
1506             m_procOwnedCleanupCallbacks.erase(procIte);
1507         }
1508     }
1509 
1510     mutex.unlock();
1511 
1512     for (auto cb : callbacks) {
1513         cb();
1514     }
1515 }
1516 
cleanupProcGLObjects_locked(uint64_t puid,bool forced)1517 std::vector<HandleType> FrameBuffer::cleanupProcGLObjects_locked(uint64_t puid, bool forced) {
1518     std::vector<HandleType> colorBuffersToCleanup;
1519     {
1520         std::unique_ptr<RecursiveScopedContextBind> bind = nullptr;
1521 #if GFXSTREAM_ENABLE_HOST_GLES
1522         if (m_emulationGl) {
1523             bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
1524         }
1525         // Clean up window surfaces
1526         if (m_emulationGl) {
1527             auto procIte = m_procOwnedEmulatedEglWindowSurfaces.find(puid);
1528             if (procIte != m_procOwnedEmulatedEglWindowSurfaces.end()) {
1529                 for (auto whndl : procIte->second) {
1530                     auto w = m_windows.find(whndl);
1531                     // TODO(b/265186226): figure out if we are leaking?
1532                     if (w == m_windows.end()) {
1533                         continue;
1534                     }
1535                     if (!m_guestManagedColorBufferLifetime) {
1536                         if (m_refCountPipeEnabled) {
1537                             if (decColorBufferRefCountLocked(w->second.second)) {
1538                                 colorBuffersToCleanup.push_back(w->second.second);
1539                             }
1540                         } else {
1541                             if (closeColorBufferLocked(w->second.second, forced)) {
1542                                 colorBuffersToCleanup.push_back(w->second.second);
1543                             }
1544                         }
1545                     }
1546                     m_windows.erase(w);
1547                 }
1548                 m_procOwnedEmulatedEglWindowSurfaces.erase(procIte);
1549             }
1550         }
1551 #endif
1552 
1553         // Clean up color buffers.
1554         // A color buffer needs to be closed as many times as it is opened by
1555         // the guest process, to give the correct reference count.
1556         // (Note that a color buffer can be shared across guest processes.)
1557         {
1558             if (!m_guestManagedColorBufferLifetime) {
1559                 auto procIte = m_procOwnedColorBuffers.find(puid);
1560                 if (procIte != m_procOwnedColorBuffers.end()) {
1561                     for (auto cb : procIte->second) {
1562                         if (closeColorBufferLocked(cb, forced)) {
1563                             colorBuffersToCleanup.push_back(cb);
1564                         }
1565                     }
1566                     m_procOwnedColorBuffers.erase(procIte);
1567                 }
1568             }
1569         }
1570 
1571 #if GFXSTREAM_ENABLE_HOST_GLES
1572         // Clean up EGLImage handles
1573         if (m_emulationGl) {
1574             auto procImagesIt = m_procOwnedEmulatedEglImages.find(puid);
1575             if (procImagesIt != m_procOwnedEmulatedEglImages.end()) {
1576                 for (auto image : procImagesIt->second) {
1577                     m_images.erase(image);
1578                 }
1579                 m_procOwnedEmulatedEglImages.erase(procImagesIt);
1580             }
1581         }
1582 #endif
1583     }
1584 
1585 #if GFXSTREAM_ENABLE_HOST_GLES
1586     // Unbind before cleaning up contexts
1587     // Cleanup render contexts
1588     if (m_emulationGl) {
1589         auto procIte = m_procOwnedEmulatedEglContexts.find(puid);
1590         if (procIte != m_procOwnedEmulatedEglContexts.end()) {
1591             for (auto ctx : procIte->second) {
1592                 m_contexts.erase(ctx);
1593             }
1594             m_procOwnedEmulatedEglContexts.erase(procIte);
1595         }
1596     }
1597 #endif
1598 
1599     return colorBuffersToCleanup;
1600 }
1601 
markOpened(ColorBufferRef * cbRef)1602 void FrameBuffer::markOpened(ColorBufferRef* cbRef) {
1603     cbRef->opened = true;
1604     eraseDelayedCloseColorBufferLocked(cbRef->cb->getHndl(), cbRef->closedTs);
1605     cbRef->closedTs = 0;
1606 }
1607 
readBuffer(HandleType handle,uint64_t offset,uint64_t size,void * bytes)1608 void FrameBuffer::readBuffer(HandleType handle, uint64_t offset, uint64_t size, void* bytes) {
1609     AutoLock mutex(m_lock);
1610 
1611     BufferPtr buffer = findBuffer(handle);
1612     if (!buffer) {
1613         ERR("Failed to read buffer: buffer %d not found.", handle);
1614         return;
1615     }
1616 
1617     buffer->readToBytes(offset, size, bytes);
1618 }
1619 
readColorBuffer(HandleType p_colorbuffer,int x,int y,int width,int height,GLenum format,GLenum type,void * outPixels,uint64_t outPixelsSize)1620 void FrameBuffer::readColorBuffer(HandleType p_colorbuffer, int x, int y, int width, int height,
1621                                   GLenum format, GLenum type, void* outPixels, uint64_t outPixelsSize) {
1622     GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_DEFAULT_CATEGORY, "FrameBuffer::readColorBuffer()",
1623                           "ColorBuffer", p_colorbuffer);
1624 
1625     AutoLock mutex(m_lock);
1626 
1627     ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
1628     if (!colorBuffer) {
1629         // bad colorbuffer handle
1630         return;
1631     }
1632 
1633     colorBuffer->readToBytes(x, y, width, height, format, type, outPixels, outPixelsSize);
1634 }
1635 
readColorBufferYUV(HandleType p_colorbuffer,int x,int y,int width,int height,void * outPixels,uint32_t outPixelsSize)1636 void FrameBuffer::readColorBufferYUV(HandleType p_colorbuffer, int x, int y, int width, int height,
1637                                      void* outPixels, uint32_t outPixelsSize) {
1638     AutoLock mutex(m_lock);
1639 
1640     ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
1641     if (!colorBuffer) {
1642         // bad colorbuffer handle
1643         return;
1644     }
1645 
1646     colorBuffer->readYuvToBytes(x, y, width, height, outPixels, outPixelsSize);
1647 }
1648 
updateBuffer(HandleType p_buffer,uint64_t offset,uint64_t size,void * bytes)1649 bool FrameBuffer::updateBuffer(HandleType p_buffer, uint64_t offset, uint64_t size, void* bytes) {
1650     AutoLock mutex(m_lock);
1651 
1652     BufferPtr buffer = findBuffer(p_buffer);
1653     if (!buffer) {
1654         ERR("Failed to update buffer: buffer %d not found.", p_buffer);
1655         return false;
1656     }
1657 
1658     return buffer->updateFromBytes(offset, size, bytes);
1659 }
1660 
updateColorBuffer(HandleType p_colorbuffer,int x,int y,int width,int height,GLenum format,GLenum type,void * pixels)1661 bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer,
1662                                     int x,
1663                                     int y,
1664                                     int width,
1665                                     int height,
1666                                     GLenum format,
1667                                     GLenum type,
1668                                     void* pixels) {
1669     GFXSTREAM_TRACE_EVENT(GFXSTREAM_TRACE_DEFAULT_CATEGORY, "FrameBuffer::updateColorBuffer()",
1670                           "ColorBuffer", p_colorbuffer);
1671 
1672     if (width == 0 || height == 0) {
1673         return false;
1674     }
1675 
1676     AutoLock mutex(m_lock);
1677 
1678     ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
1679     if (!colorBuffer) {
1680         // bad colorbuffer handle
1681         return false;
1682     }
1683 
1684     colorBuffer->updateFromBytes(x, y, width, height, format, type, pixels);
1685 
1686     return true;
1687 }
1688 
updateColorBufferFromFrameworkFormat(HandleType p_colorbuffer,int x,int y,int width,int height,FrameworkFormat fwkFormat,GLenum format,GLenum type,void * pixels,void * metadata)1689 bool FrameBuffer::updateColorBufferFromFrameworkFormat(HandleType p_colorbuffer, int x, int y,
1690                                                        int width, int height,
1691                                                        FrameworkFormat fwkFormat, GLenum format,
1692                                                        GLenum type, void* pixels, void* metadata) {
1693     if (width == 0 || height == 0) {
1694         return false;
1695     }
1696 
1697     AutoLock mutex(m_lock);
1698 
1699     ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
1700     if (c == m_colorbuffers.end()) {
1701         // bad colorbuffer handle
1702         return false;
1703     }
1704 
1705     (*c).second.cb->updateFromBytes(x, y, width, height, fwkFormat, format, type, pixels, metadata);
1706     return true;
1707 }
1708 
getColorBufferInfo(HandleType p_colorbuffer,int * width,int * height,GLint * internalformat,FrameworkFormat * frameworkFormat)1709 bool FrameBuffer::getColorBufferInfo(
1710     HandleType p_colorbuffer, int* width, int* height, GLint* internalformat,
1711     FrameworkFormat* frameworkFormat) {
1712 
1713     AutoLock mutex(m_lock);
1714 
1715     ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
1716     if (!colorBuffer) {
1717         // bad colorbuffer handle
1718         return false;
1719     }
1720 
1721     *width = colorBuffer->getWidth();
1722     *height = colorBuffer->getHeight();
1723     *internalformat = colorBuffer->getFormat();
1724     if (frameworkFormat) {
1725         *frameworkFormat = colorBuffer->getFrameworkFormat();
1726     }
1727 
1728     return true;
1729 }
1730 
getBufferInfo(HandleType p_buffer,int * size)1731 bool FrameBuffer::getBufferInfo(HandleType p_buffer, int* size) {
1732     AutoLock mutex(m_lock);
1733 
1734     BufferMap::iterator c(m_buffers.find(p_buffer));
1735     if (c == m_buffers.end()) {
1736         // Bad buffer handle.
1737         return false;
1738     }
1739 
1740     auto buf = (*c).second.buffer;
1741     *size = buf->getSize();
1742     return true;
1743 }
1744 
post(HandleType p_colorbuffer,bool needLockAndBind)1745 bool FrameBuffer::post(HandleType p_colorbuffer, bool needLockAndBind) {
1746 #if GFXSTREAM_ENABLE_HOST_GLES
1747     if (m_features.GuestVulkanOnly.enabled) {
1748         flushColorBufferFromGl(p_colorbuffer);
1749     }
1750 #endif
1751 
1752     auto res = postImplSync(p_colorbuffer, needLockAndBind);
1753     if (res) setGuestPostedAFrame();
1754     return res;
1755 }
1756 
postWithCallback(HandleType p_colorbuffer,Post::CompletionCallback callback,bool needLockAndBind)1757 void FrameBuffer::postWithCallback(HandleType p_colorbuffer, Post::CompletionCallback callback,
1758                                    bool needLockAndBind) {
1759 #if GFXSTREAM_ENABLE_HOST_GLES
1760     if (m_features.GuestVulkanOnly.enabled) {
1761         flushColorBufferFromGl(p_colorbuffer);
1762     }
1763 #endif
1764 
1765     AsyncResult res = postImpl(p_colorbuffer, callback, needLockAndBind);
1766     if (res.Succeeded()) {
1767         setGuestPostedAFrame();
1768     }
1769 
1770     if (!res.CallbackScheduledOrFired()) {
1771         // If postImpl fails, we have not fired the callback. postWithCallback
1772         // should always ensure the callback fires.
1773         std::shared_future<void> callbackRes = std::async(std::launch::deferred, [] {});
1774         callback(callbackRes);
1775     }
1776 }
1777 
postImplSync(HandleType p_colorbuffer,bool needLockAndBind,bool repaint)1778 bool FrameBuffer::postImplSync(HandleType p_colorbuffer, bool needLockAndBind, bool repaint) {
1779     std::promise<void> promise;
1780     std::future<void> completeFuture = promise.get_future();
1781     auto posted = postImpl(
1782         p_colorbuffer,
1783         [&](std::shared_future<void> waitForGpu) {
1784             waitForGpu.wait();
1785             promise.set_value();
1786         },
1787         needLockAndBind, repaint);
1788     if (posted.CallbackScheduledOrFired()) {
1789         completeFuture.wait();
1790     }
1791 
1792     return posted.Succeeded();
1793 }
1794 
postImpl(HandleType p_colorbuffer,Post::CompletionCallback callback,bool needLockAndBind,bool repaint)1795 AsyncResult FrameBuffer::postImpl(HandleType p_colorbuffer, Post::CompletionCallback callback,
1796                                   bool needLockAndBind, bool repaint) {
1797     ColorBufferPtr colorBuffer = nullptr;
1798     {
1799         AutoLock colorBufferMapLock(m_colorBufferMapLock);
1800         ColorBufferMap::iterator c = m_colorbuffers.find(p_colorbuffer);
1801         if (c != m_colorbuffers.end()) {
1802             colorBuffer = c->second.cb;
1803             c->second.refcount++;
1804             markOpened(&c->second);
1805         }
1806     }
1807     if (!colorBuffer) {
1808         return AsyncResult::FAIL_AND_CALLBACK_NOT_SCHEDULED;
1809     }
1810 
1811     std::optional<AutoLock> lock;
1812 #if GFXSTREAM_ENABLE_HOST_GLES
1813     std::optional<RecursiveScopedContextBind> bind;
1814 #endif
1815     if (needLockAndBind) {
1816         lock.emplace(m_lock);
1817 #if GFXSTREAM_ENABLE_HOST_GLES
1818         if (m_emulationGl) {
1819             bind.emplace(getPbufferSurfaceContextHelper());
1820         }
1821 #endif
1822     }
1823     AsyncResult ret = AsyncResult::FAIL_AND_CALLBACK_NOT_SCHEDULED;
1824 
1825     m_lastPostedColorBuffer = p_colorbuffer;
1826 
1827     colorBuffer->touch();
1828     if (m_subWin) {
1829         Post postCmd;
1830         postCmd.cmd = PostCmd::Post;
1831         postCmd.cb = colorBuffer.get();
1832         postCmd.cbHandle = p_colorbuffer;
1833         postCmd.completionCallback = std::make_unique<Post::CompletionCallback>(callback);
1834         sendPostWorkerCmd(std::move(postCmd));
1835         ret = AsyncResult::OK_AND_CALLBACK_SCHEDULED;
1836     } else {
1837         // If there is no sub-window, don't display anything, the client will
1838         // rely on m_onPost to get the pixels instead.
1839         ret = AsyncResult::OK_AND_CALLBACK_NOT_SCHEDULED;
1840     }
1841 
1842     //
1843     // output FPS and performance usage statistics
1844     //
1845     if (m_fpsStats) {
1846         long long currTime = android::base::getHighResTimeUs() / 1000;
1847         m_statsNumFrames++;
1848         if (currTime - m_statsStartTime >= 1000) {
1849             if (m_fpsStats) {
1850                 float dt = (float)(currTime - m_statsStartTime) / 1000.0f;
1851                 printf("FPS: %5.3f \n", (float)m_statsNumFrames / dt);
1852                 m_statsNumFrames = 0;
1853             }
1854             m_statsStartTime = currTime;
1855         }
1856     }
1857 
1858     //
1859     // Send framebuffer (without FPS overlay) to callback
1860     //
1861     if (!m_onPost.empty()) {
1862         for (auto& iter : m_onPost) {
1863             ColorBufferPtr cb;
1864             if (iter.first == 0) {
1865                 cb = colorBuffer;
1866             } else {
1867                 uint32_t displayColorBufferHandle = 0;
1868                 if (getDisplayColorBuffer(iter.first, &displayColorBufferHandle) < 0) {
1869                     ERR("Failed to get color buffer for display %d, skip onPost", iter.first);
1870                     continue;
1871                 }
1872 
1873                 cb = findColorBuffer(displayColorBufferHandle);
1874                 if (!cb) {
1875                     ERR("Failed to find ColorBuffer %d, skip onPost", displayColorBufferHandle);
1876                     continue;
1877                 }
1878             }
1879 
1880             if (asyncReadbackSupported()) {
1881                 ensureReadbackWorker();
1882                 const auto status = m_readbackWorker->doNextReadback(
1883                     iter.first, cb.get(), iter.second.img, repaint, iter.second.readBgra);
1884                 if (status == ReadbackWorker::DoNextReadbackResult::OK_READY_FOR_READ) {
1885                     doPostCallback(iter.second.img, iter.first);
1886                 }
1887             } else {
1888     #if GFXSTREAM_ENABLE_HOST_GLES
1889                 cb->glOpReadback(iter.second.img, iter.second.readBgra);
1890     #endif
1891                 doPostCallback(iter.second.img, iter.first);
1892             }
1893         }
1894     }
1895 
1896     if (!m_subWin) {  // m_subWin is supposed to be false
1897         decColorBufferRefCountLocked(p_colorbuffer);
1898     }
1899 
1900     return ret;
1901 }
1902 
doPostCallback(void * pixels,uint32_t displayId)1903 void FrameBuffer::doPostCallback(void* pixels, uint32_t displayId) {
1904     const auto& iter = m_onPost.find(displayId);
1905     if (iter == m_onPost.end()) {
1906         ERR("Cannot find post callback function for display %d", displayId);
1907         return;
1908     }
1909     iter->second.cb(iter->second.context, displayId, iter->second.width, iter->second.height, -1,
1910                     GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char*)pixels);
1911 }
1912 
getPixels(void * pixels,uint32_t bytes,uint32_t displayId)1913 void FrameBuffer::getPixels(void* pixels, uint32_t bytes, uint32_t displayId) {
1914     const auto& iter = m_onPost.find(displayId);
1915     if (iter == m_onPost.end()) {
1916         ERR("Display %d not configured for recording yet", displayId);
1917         return;
1918     }
1919     std::future<void> completeFuture =
1920         m_readbackThread.enqueue({ReadbackCmd::GetPixels, displayId, pixels, bytes});
1921     completeFuture.wait();
1922 }
1923 
flushReadPipeline(int displayId)1924 void FrameBuffer::flushReadPipeline(int displayId) {
1925     const auto& iter = m_onPost.find(displayId);
1926     if (iter == m_onPost.end()) {
1927         ERR("Cannot find onPost pixels for display %d", displayId);
1928         return;
1929     }
1930 
1931     ensureReadbackWorker();
1932 
1933     const auto status = m_readbackWorker->flushPipeline(displayId);
1934     if (status == ReadbackWorker::FlushResult::OK_READY_FOR_READ) {
1935         doPostCallback(nullptr, displayId);
1936     }
1937 }
1938 
ensureReadbackWorker()1939 void FrameBuffer::ensureReadbackWorker() {
1940 #if GFXSTREAM_ENABLE_HOST_GLES
1941     if (!m_readbackWorker) {
1942         if (!m_emulationGl) {
1943             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
1944         }
1945         m_readbackWorker = m_emulationGl->getReadbackWorker();
1946     }
1947 #endif
1948 }
1949 
sFrameBuffer_ReadPixelsCallback(void * pixels,uint32_t bytes,uint32_t displayId)1950 static void sFrameBuffer_ReadPixelsCallback(void* pixels, uint32_t bytes, uint32_t displayId) {
1951     FrameBuffer::getFB()->getPixels(pixels, bytes, displayId);
1952 }
1953 
sFrameBuffer_FlushReadPixelPipeline(int displayId)1954 static void sFrameBuffer_FlushReadPixelPipeline(int displayId) {
1955     FrameBuffer::getFB()->flushReadPipeline(displayId);
1956 }
1957 
asyncReadbackSupported()1958 bool FrameBuffer::asyncReadbackSupported() {
1959 #if GFXSTREAM_ENABLE_HOST_GLES
1960     return m_emulationGl && m_emulationGl->isAsyncReadbackSupported();
1961 #else
1962     return false;
1963 #endif
1964 }
1965 
getReadPixelsCallback()1966 Renderer::ReadPixelsCallback FrameBuffer::getReadPixelsCallback() {
1967     return sFrameBuffer_ReadPixelsCallback;
1968 }
1969 
getFlushReadPixelPipeline()1970 Renderer::FlushReadPixelPipeline FrameBuffer::getFlushReadPixelPipeline() {
1971     return sFrameBuffer_FlushReadPixelPipeline;
1972 }
1973 
repost(bool needLockAndBind)1974 bool FrameBuffer::repost(bool needLockAndBind) {
1975     GL_LOG("Reposting framebuffer.");
1976     if (m_displayVk) {
1977         setGuestPostedAFrame();
1978         return true;
1979     }
1980     if (m_lastPostedColorBuffer && sInitialized.load(std::memory_order_relaxed)) {
1981         GL_LOG("Has last posted colorbuffer and is initialized; post.");
1982         auto res = postImplSync(m_lastPostedColorBuffer, needLockAndBind, true);
1983         if (res) setGuestPostedAFrame();
1984         return res;
1985     } else {
1986         GL_LOG("No repost: no last posted color buffer");
1987         if (!sInitialized.load(std::memory_order_relaxed)) {
1988             GL_LOG("No repost: initialization is not finished.");
1989         }
1990     }
1991     return false;
1992 }
1993 
1994 template <class Collection>
saveProcOwnedCollection(Stream * stream,const Collection & c)1995 static void saveProcOwnedCollection(Stream* stream, const Collection& c) {
1996     // Exclude empty handle lists from saving as they add no value but only
1997     // increase the snapshot size; keep the format compatible with
1998     // android::base::saveCollection() though.
1999     const int count = std::count_if(
2000         c.begin(), c.end(),
2001         [](const typename Collection::value_type& pair) { return !pair.second.empty(); });
2002     stream->putBe32(count);
2003     for (const auto& pair : c) {
2004         if (pair.second.empty()) {
2005             continue;
2006         }
2007         stream->putBe64(pair.first);
2008         saveCollection(stream, pair.second, [](Stream* s, HandleType h) { s->putBe32(h); });
2009     }
2010 }
2011 
2012 template <class Collection>
loadProcOwnedCollection(Stream * stream,Collection * c)2013 static void loadProcOwnedCollection(Stream* stream, Collection* c) {
2014     loadCollection(stream, c, [](Stream* stream) -> typename Collection::value_type {
2015         const int processId = stream->getBe64();
2016         typename Collection::mapped_type handles;
2017         loadCollection(stream, &handles, [](Stream* s) { return s->getBe32(); });
2018         return {processId, std::move(handles)};
2019     });
2020 }
2021 
getScreenshot(unsigned int nChannels,unsigned int * width,unsigned int * height,uint8_t * pixels,size_t * cPixels,int displayId,int desiredWidth,int desiredHeight,int desiredRotation,Rect rect)2022 int FrameBuffer::getScreenshot(unsigned int nChannels, unsigned int* width, unsigned int* height,
2023                                uint8_t* pixels, size_t* cPixels, int displayId, int desiredWidth,
2024                                int desiredHeight, int desiredRotation, Rect rect) {
2025 #ifdef CONFIG_AEMU
2026    if (emugl::shouldSkipDraw()) {
2027         *width = 0;
2028         *height = 0;
2029         *cPixels = 0;
2030         return -1;
2031     }
2032 #endif
2033 
2034     AutoLock mutex(m_lock);
2035     uint32_t w, h, cb, screenWidth, screenHeight;
2036     if (!emugl::get_emugl_multi_display_operations().getMultiDisplay(
2037             displayId, nullptr, nullptr, &w, &h, nullptr, nullptr, nullptr)) {
2038         ERR("Screenshot of invalid display %d", displayId);
2039         *width = 0;
2040         *height = 0;
2041         *cPixels = 0;
2042         return -1;
2043     }
2044     if (nChannels != 3 && nChannels != 4) {
2045         ERR("Screenshot only support 3(RGB) or 4(RGBA) channels");
2046         *width = 0;
2047         *height = 0;
2048         *cPixels = 0;
2049         return -1;
2050     }
2051     emugl::get_emugl_multi_display_operations().getDisplayColorBuffer(displayId, &cb);
2052     if (displayId == 0) {
2053         cb = m_lastPostedColorBuffer;
2054     }
2055     ColorBufferPtr colorBuffer = findColorBuffer(cb);
2056     if (!colorBuffer) {
2057         *width = 0;
2058         *height = 0;
2059         *cPixels = 0;
2060         return -1;
2061     }
2062 
2063     screenWidth = (desiredWidth == 0) ? w : desiredWidth;
2064     screenHeight = (desiredHeight == 0) ? h : desiredHeight;
2065 
2066     bool useSnipping = (rect.size.w != 0 && rect.size.h != 0);
2067     if (useSnipping) {
2068         if (desiredWidth == 0 || desiredHeight == 0) {
2069             ERR("Must provide non-zero desiredWidth and desireRectanlge "
2070                 "when using rectangle snipping");
2071             *width = 0;
2072             *height = 0;
2073             *cPixels = 0;
2074             return -1;
2075         }
2076         if ((rect.pos.x < 0 || rect.pos.y < 0) ||
2077             (desiredWidth < rect.pos.x + rect.size.w || desiredHeight < rect.pos.y + rect.size.h)) {
2078             return -1;
2079         }
2080     }
2081 
2082     if (useSnipping) {
2083         *width = rect.size.w;
2084         *height = rect.size.h;
2085     } else {
2086         *width = screenWidth;
2087         *height = screenHeight;
2088     }
2089 
2090     int needed =
2091         useSnipping ? (nChannels * rect.size.w * rect.size.h) : (nChannels * (*width) * (*height));
2092 
2093     if (*cPixels < (size_t)needed) {
2094         *cPixels = needed;
2095         return -2;
2096     }
2097     *cPixels = needed;
2098     if (desiredRotation == SKIN_ROTATION_90 || desiredRotation == SKIN_ROTATION_270) {
2099         std::swap(*width, *height);
2100         std::swap(screenWidth, screenHeight);
2101         std::swap(rect.size.w, rect.size.h);
2102     }
2103     // Transform the x, y coordinates given the rotation.
2104     // Assume (0, 0) represents the top left corner of the screen.
2105     if (useSnipping) {
2106         int x = 0, y = 0;
2107         switch (desiredRotation) {
2108             case SKIN_ROTATION_0:
2109                 x = rect.pos.x;
2110                 y = rect.pos.y;
2111                 break;
2112             case SKIN_ROTATION_90:
2113                 x = rect.pos.y;
2114                 y = rect.pos.x;
2115                 break;
2116             case SKIN_ROTATION_180:
2117                 x = screenWidth - rect.pos.x - rect.size.w;
2118                 y = rect.pos.y;
2119                 break;
2120             case SKIN_ROTATION_270:
2121                 x = rect.pos.y;
2122                 y = screenHeight - rect.pos.x - rect.size.h;
2123                 break;
2124         }
2125         rect.pos.x = x;
2126         rect.pos.y = y;
2127     }
2128 
2129     GLenum format = nChannels == 3 ? GL_RGB : GL_RGBA;
2130     Post scrCmd;
2131     scrCmd.cmd = PostCmd::Screenshot;
2132     scrCmd.screenshot.cb = colorBuffer.get();
2133     scrCmd.screenshot.screenwidth = screenWidth;
2134     scrCmd.screenshot.screenheight = screenHeight;
2135     scrCmd.screenshot.format = format;
2136     scrCmd.screenshot.type = GL_UNSIGNED_BYTE;
2137     scrCmd.screenshot.rotation = desiredRotation;
2138     scrCmd.screenshot.pixels = pixels;
2139     scrCmd.screenshot.rect = rect;
2140 
2141     std::future<void> completeFuture = sendPostWorkerCmd(std::move(scrCmd));
2142 
2143     mutex.unlock();
2144     completeFuture.wait();
2145     return 0;
2146 }
2147 
onLastColorBufferRef(uint32_t handle)2148 void FrameBuffer::onLastColorBufferRef(uint32_t handle) {
2149     if (!mOutstandingColorBufferDestroys.trySend((HandleType)handle)) {
2150         ERR("warning: too many outstanding "
2151             "color buffer destroys. leaking handle 0x%x",
2152             handle);
2153     }
2154 }
2155 
decColorBufferRefCountLocked(HandleType p_colorbuffer)2156 bool FrameBuffer::decColorBufferRefCountLocked(HandleType p_colorbuffer) {
2157     AutoLock colorBufferMapLock(m_colorBufferMapLock);
2158     const auto& it = m_colorbuffers.find(p_colorbuffer);
2159     if (it != m_colorbuffers.end()) {
2160         it->second.refcount -= 1;
2161         if (it->second.refcount == 0) {
2162             m_colorbuffers.erase(p_colorbuffer);
2163             return true;
2164         }
2165     }
2166     return false;
2167 }
2168 
compose(uint32_t bufferSize,void * buffer,bool needPost)2169 bool FrameBuffer::compose(uint32_t bufferSize, void* buffer, bool needPost) {
2170     std::promise<void> promise;
2171     std::future<void> completeFuture = promise.get_future();
2172     auto composeRes =
2173         composeWithCallback(bufferSize, buffer, [&](std::shared_future<void> waitForGpu) {
2174             waitForGpu.wait();
2175             promise.set_value();
2176         });
2177     if (!composeRes.Succeeded()) {
2178         return false;
2179     }
2180 
2181     if (composeRes.CallbackScheduledOrFired()) {
2182         completeFuture.wait();
2183     }
2184 
2185     const auto& multiDisplay = emugl::get_emugl_multi_display_operations();
2186     const bool is_pixel_fold = multiDisplay.isPixelFold();
2187     if (needPost) {
2188         // AEMU with -no-window mode uses this code path.
2189         ComposeDevice* composeDevice = (ComposeDevice*)buffer;
2190 
2191         switch (composeDevice->version) {
2192             case 1: {
2193                 post(composeDevice->targetHandle, true);
2194                 break;
2195             }
2196             case 2: {
2197                 ComposeDevice_v2* composeDeviceV2 = (ComposeDevice_v2*)buffer;
2198                 if (is_pixel_fold || composeDeviceV2->displayId == 0) {
2199                     post(composeDeviceV2->targetHandle, true);
2200                 }
2201                 break;
2202             }
2203             default: {
2204                 return false;
2205             }
2206         }
2207     }
2208     return true;
2209 }
2210 
composeWithCallback(uint32_t bufferSize,void * buffer,Post::CompletionCallback callback)2211 AsyncResult FrameBuffer::composeWithCallback(uint32_t bufferSize, void* buffer,
2212                                              Post::CompletionCallback callback) {
2213     ComposeDevice* p = (ComposeDevice*)buffer;
2214     AutoLock mutex(m_lock);
2215 
2216     switch (p->version) {
2217         case 1: {
2218             Post composeCmd;
2219             composeCmd.composeVersion = 1;
2220             composeCmd.composeBuffer.resize(bufferSize);
2221             memcpy(composeCmd.composeBuffer.data(), buffer, bufferSize);
2222             composeCmd.completionCallback = std::make_unique<Post::CompletionCallback>(callback);
2223             composeCmd.cmd = PostCmd::Compose;
2224             sendPostWorkerCmd(std::move(composeCmd));
2225             return AsyncResult::OK_AND_CALLBACK_SCHEDULED;
2226         }
2227 
2228         case 2: {
2229             // support for multi-display
2230             ComposeDevice_v2* p2 = (ComposeDevice_v2*)buffer;
2231             if (p2->displayId != 0) {
2232                 mutex.unlock();
2233                 setDisplayColorBuffer(p2->displayId, p2->targetHandle);
2234                 mutex.lock();
2235             }
2236             Post composeCmd;
2237             composeCmd.composeVersion = 2;
2238             composeCmd.composeBuffer.resize(bufferSize);
2239             memcpy(composeCmd.composeBuffer.data(), buffer, bufferSize);
2240             composeCmd.completionCallback = std::make_unique<Post::CompletionCallback>(callback);
2241             composeCmd.cmd = PostCmd::Compose;
2242             sendPostWorkerCmd(std::move(composeCmd));
2243             return AsyncResult::OK_AND_CALLBACK_SCHEDULED;
2244         }
2245 
2246         default:
2247             ERR("yet to handle composition device version: %d", p->version);
2248             return AsyncResult::FAIL_AND_CALLBACK_NOT_SCHEDULED;
2249     }
2250 }
2251 
onSave(Stream * stream,const android::snapshot::ITextureSaverPtr & textureSaver)2252 void FrameBuffer::onSave(Stream* stream, const android::snapshot::ITextureSaverPtr& textureSaver) {
2253     // Things we do not need to snapshot:
2254     //     m_eglSurface
2255     //     m_eglContext
2256     //     m_pbufSurface
2257     //     m_pbufContext
2258     //     m_prevContext
2259     //     m_prevReadSurf
2260     //     m_prevDrawSurf
2261     AutoLock mutex(m_lock);
2262 
2263     std::unique_ptr<RecursiveScopedContextBind> bind;
2264 #if GFXSTREAM_ENABLE_HOST_GLES
2265     if (m_emulationGl) {
2266         // Some snapshot commands try using GL.
2267         bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
2268         if (!bind->isOk()) {
2269             ERR("Failed to make context current for saving snapshot.");
2270         }
2271 
2272         // eglPreSaveContext labels all guest context textures to be saved
2273         // (textures created by the host are not saved!)
2274         // eglSaveAllImages labels all EGLImages (both host and guest) to be saved
2275         // and save all labeled textures and EGLImages.
2276         if (s_egl.eglPreSaveContext && s_egl.eglSaveAllImages) {
2277             for (const auto& ctx : m_contexts) {
2278                 s_egl.eglPreSaveContext(getDisplay(), ctx.second->getEGLContext(), stream);
2279             }
2280             s_egl.eglSaveAllImages(getDisplay(), stream, &textureSaver);
2281         }
2282     }
2283 #endif
2284 
2285     // Don't save subWindow's x/y/w/h here - those are related to the current
2286     // emulator UI state, not guest state that we're saving.
2287     stream->putBe32(m_framebufferWidth);
2288     stream->putBe32(m_framebufferHeight);
2289     stream->putFloat(m_dpr);
2290     stream->putBe32(mDisplayActiveConfigId);
2291     saveCollection(stream, mDisplayConfigs,
2292                    [](Stream* s, const std::map<int, DisplayConfig>::value_type& pair) {
2293                        s->putBe32(pair.first);
2294                        s->putBe32(pair.second.w);
2295                        s->putBe32(pair.second.h);
2296                        s->putBe32(pair.second.dpiX);
2297                        s->putBe32(pair.second.dpiY);
2298                    });
2299 
2300     stream->putBe32(m_useSubWindow);
2301     stream->putBe32(/*Obsolete m_eglContextInitialized =*/1);
2302 
2303     stream->putBe32(m_fpsStats);
2304     stream->putBe32(m_statsNumFrames);
2305     stream->putBe64(m_statsStartTime);
2306 
2307     // Save all contexts.
2308     // Note: some of the contexts might not be restored yet. In such situation
2309     // we skip reading from GPU (for non-texture objects) or force a restore in
2310     // previous eglPreSaveContext and eglSaveAllImages calls (for texture
2311     // objects).
2312     // TODO: skip reading from GPU even for texture objects.
2313 #if GFXSTREAM_ENABLE_HOST_GLES
2314     saveCollection(
2315         stream, m_contexts,
2316         [](Stream* s, const EmulatedEglContextMap::value_type& pair) { pair.second->onSave(s); });
2317 #endif
2318 
2319     // We don't need to save |m_colorBufferCloseTsMap| here - there's enough
2320     // information to reconstruct it when loading.
2321     uint64_t now = android::base::getUnixTimeUs();
2322 
2323     {
2324         AutoLock colorBufferMapLock(m_colorBufferMapLock);
2325         stream->putByte(m_guestManagedColorBufferLifetime);
2326         saveCollection(stream, m_colorbuffers,
2327                        [now](Stream* s, const ColorBufferMap::value_type& pair) {
2328                            pair.second.cb->onSave(s);
2329                            s->putBe32(pair.second.refcount);
2330                            s->putByte(pair.second.opened);
2331                            s->putBe32(std::max<uint64_t>(0, now - pair.second.closedTs));
2332                        });
2333     }
2334     stream->putBe32(m_lastPostedColorBuffer);
2335 #if GFXSTREAM_ENABLE_HOST_GLES
2336     saveCollection(stream, m_windows,
2337                    [](Stream* s, const EmulatedEglWindowSurfaceMap::value_type& pair) {
2338                        pair.second.first->onSave(s);
2339                        s->putBe32(pair.second.second);  // Color buffer handle.
2340                    });
2341 #endif
2342 
2343 #if GFXSTREAM_ENABLE_HOST_GLES
2344     saveProcOwnedCollection(stream, m_procOwnedEmulatedEglWindowSurfaces);
2345 #endif
2346     saveProcOwnedCollection(stream, m_procOwnedColorBuffers);
2347 #if GFXSTREAM_ENABLE_HOST_GLES
2348     saveProcOwnedCollection(stream, m_procOwnedEmulatedEglImages);
2349     saveProcOwnedCollection(stream, m_procOwnedEmulatedEglContexts);
2350 #endif
2351 
2352     // TODO(b/309858017): remove if when ready to bump snapshot version
2353     if (m_features.VulkanSnapshots.enabled) {
2354         AutoLock procResourceLock(m_procOwnedResourcesLock);
2355         stream->putBe64(m_procOwnedResources.size());
2356         for (const auto& element : m_procOwnedResources) {
2357             stream->putBe64(element.first);
2358             stream->putBe32(element.second->getSequenceNumberPtr()->load());
2359         }
2360     }
2361 
2362     // Save Vulkan state
2363     if (m_features.VulkanSnapshots.enabled && vk::VkDecoderGlobalState::get()) {
2364         vk::VkDecoderGlobalState::get()->save(stream);
2365     }
2366 
2367 #if GFXSTREAM_ENABLE_HOST_GLES
2368     if (m_emulationGl) {
2369         if (s_egl.eglPostSaveContext) {
2370             for (const auto& ctx : m_contexts) {
2371                 s_egl.eglPostSaveContext(getDisplay(), ctx.second->getEGLContext(), stream);
2372             }
2373             // We need to run the post save step for m_eglContext
2374             // to mark their texture handles dirty
2375             if (getContext() != EGL_NO_CONTEXT) {
2376                 s_egl.eglPostSaveContext(getDisplay(), getContext(), stream);
2377             }
2378         }
2379 
2380         EmulatedEglFenceSync::onSave(stream);
2381     }
2382 #endif
2383 }
2384 
onLoad(Stream * stream,const android::snapshot::ITextureLoaderPtr & textureLoader)2385 bool FrameBuffer::onLoad(Stream* stream,
2386                          const android::snapshot::ITextureLoaderPtr& textureLoader) {
2387     AutoLock lock(m_lock);
2388     // cleanups
2389     {
2390         sweepColorBuffersLocked();
2391 
2392         std::unique_ptr<RecursiveScopedContextBind> bind;
2393 #if GFXSTREAM_ENABLE_HOST_GLES
2394         if (m_emulationGl) {
2395             // Some snapshot commands try using GL.
2396             bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
2397             if (!bind->isOk()) {
2398                 ERR("Failed to make context current for loading snapshot.");
2399             }
2400         }
2401 #endif
2402 
2403         bool cleanupComplete = false;
2404         {
2405             AutoLock colorBufferMapLock(m_colorBufferMapLock);
2406             if (m_procOwnedCleanupCallbacks.empty() && m_procOwnedColorBuffers.empty() &&
2407 #if GFXSTREAM_ENABLE_HOST_GLES
2408                 m_procOwnedEmulatedEglContexts.empty() && m_procOwnedEmulatedEglImages.empty() &&
2409                 m_procOwnedEmulatedEglWindowSurfaces.empty() &&
2410 #endif
2411                 (
2412 #if GFXSTREAM_ENABLE_HOST_GLES
2413                     !m_contexts.empty() || !m_windows.empty() ||
2414 #endif
2415                     m_colorbuffers.size() > m_colorBufferDelayedCloseList.size())) {
2416                 // we are likely on a legacy system image, which does not have
2417                 // process owned objects. We need to force cleanup everything
2418 #if GFXSTREAM_ENABLE_HOST_GLES
2419                 m_contexts.clear();
2420                 m_windows.clear();
2421 #endif
2422                 m_colorbuffers.clear();
2423                 cleanupComplete = true;
2424             }
2425         }
2426         if (!cleanupComplete) {
2427             std::vector<HandleType> colorBuffersToCleanup;
2428 
2429 #if GFXSTREAM_ENABLE_HOST_GLES
2430             while (m_procOwnedEmulatedEglWindowSurfaces.size()) {
2431                 auto cleanupHandles = cleanupProcGLObjects_locked(
2432                     m_procOwnedEmulatedEglWindowSurfaces.begin()->first, true);
2433                 colorBuffersToCleanup.insert(colorBuffersToCleanup.end(), cleanupHandles.begin(),
2434                                              cleanupHandles.end());
2435             }
2436 #endif
2437             while (m_procOwnedColorBuffers.size()) {
2438                 auto cleanupHandles =
2439                     cleanupProcGLObjects_locked(m_procOwnedColorBuffers.begin()->first, true);
2440                 colorBuffersToCleanup.insert(colorBuffersToCleanup.end(), cleanupHandles.begin(),
2441                                              cleanupHandles.end());
2442             }
2443 #if GFXSTREAM_ENABLE_HOST_GLES
2444             while (m_procOwnedEmulatedEglImages.size()) {
2445                 auto cleanupHandles =
2446                     cleanupProcGLObjects_locked(m_procOwnedEmulatedEglImages.begin()->first, true);
2447                 colorBuffersToCleanup.insert(colorBuffersToCleanup.end(), cleanupHandles.begin(),
2448                                              cleanupHandles.end());
2449             }
2450             while (m_procOwnedEmulatedEglContexts.size()) {
2451                 auto cleanupHandles = cleanupProcGLObjects_locked(
2452                     m_procOwnedEmulatedEglContexts.begin()->first, true);
2453                 colorBuffersToCleanup.insert(colorBuffersToCleanup.end(), cleanupHandles.begin(),
2454                                              cleanupHandles.end());
2455             }
2456 #endif
2457 
2458             std::vector<std::function<void()>> cleanupCallbacks;
2459 
2460             while (m_procOwnedCleanupCallbacks.size()) {
2461                 auto it = m_procOwnedCleanupCallbacks.begin();
2462                 while (it != m_procOwnedCleanupCallbacks.end()) {
2463                     for (auto it2 : it->second) {
2464                         cleanupCallbacks.push_back(it2.second);
2465                     }
2466                     it = m_procOwnedCleanupCallbacks.erase(it);
2467                 }
2468             }
2469 
2470             {
2471                 AutoLock mutex(m_procOwnedResourcesLock);
2472                 m_procOwnedResources.clear();
2473             }
2474 
2475             performDelayedColorBufferCloseLocked(true);
2476 
2477             lock.unlock();
2478 
2479             for (auto cb : cleanupCallbacks) {
2480                 cb();
2481             }
2482 
2483             lock.lock();
2484             cleanupComplete = true;
2485         }
2486         m_colorBufferDelayedCloseList.clear();
2487 #if GFXSTREAM_ENABLE_HOST_GLES
2488         assert(m_contexts.empty());
2489         assert(m_windows.empty());
2490 #endif
2491         {
2492             AutoLock colorBufferMapLock(m_colorBufferMapLock);
2493             if (!m_colorbuffers.empty()) {
2494                 ERR("warning: on load, stale colorbuffers: %zu", m_colorbuffers.size());
2495                 m_colorbuffers.clear();
2496             }
2497             assert(m_colorbuffers.empty());
2498         }
2499 #ifdef SNAPSHOT_PROFILE
2500         uint64_t texTime = android::base::getUnixTimeUs();
2501 #endif
2502 #if GFXSTREAM_ENABLE_HOST_GLES
2503         if (m_emulationGl) {
2504             if (s_egl.eglLoadAllImages) {
2505                 s_egl.eglLoadAllImages(getDisplay(), stream, &textureLoader);
2506             }
2507         }
2508 #endif
2509 #ifdef SNAPSHOT_PROFILE
2510         printf("Texture load time: %lld ms\n",
2511                (long long)(android::base::getUnixTimeUs() - texTime) / 1000);
2512 #endif
2513     }
2514     // See comment about subwindow position in onSave().
2515     m_framebufferWidth = stream->getBe32();
2516     m_framebufferHeight = stream->getBe32();
2517     m_dpr = stream->getFloat();
2518     mDisplayActiveConfigId = stream->getBe32();
2519     loadCollection(stream, &mDisplayConfigs,
2520                    [](Stream* s) -> std::map<int, DisplayConfig>::value_type {
2521                        int idx = static_cast<int>(s->getBe32());
2522                        int w = static_cast<int>(s->getBe32());
2523                        int h = static_cast<int>(s->getBe32());
2524                        int dpiX = static_cast<int>(s->getBe32());
2525                        int dpiY = static_cast<int>(s->getBe32());
2526                        return {idx, {w, h, dpiX, dpiY}};
2527                    });
2528 
2529     // TODO: resize the window
2530     //
2531     m_useSubWindow = stream->getBe32();
2532     /*Obsolete m_eglContextInitialized =*/stream->getBe32();
2533 
2534     m_fpsStats = stream->getBe32();
2535     m_statsNumFrames = stream->getBe32();
2536     m_statsStartTime = stream->getBe64();
2537 
2538 #if GFXSTREAM_ENABLE_HOST_GLES
2539     loadCollection(
2540         stream, &m_contexts, [this](Stream* stream) -> EmulatedEglContextMap::value_type {
2541             if (!m_emulationGl) {
2542                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
2543             }
2544 
2545             auto context = m_emulationGl->loadEmulatedEglContext(stream);
2546             auto contextHandle = context ? context->getHndl() : 0;
2547             return {contextHandle, std::move(context)};
2548         });
2549     assert(!android::base::find(m_contexts, 0));
2550 #endif
2551 
2552     auto now = android::base::getUnixTimeUs();
2553     {
2554         AutoLock colorBufferMapLock(m_colorBufferMapLock);
2555         m_guestManagedColorBufferLifetime = stream->getByte();
2556         loadCollection(
2557             stream, &m_colorbuffers, [this, now](Stream* stream) -> ColorBufferMap::value_type {
2558                 ColorBufferPtr cb =
2559                     ColorBuffer::onLoad(m_emulationGl.get(), m_emulationVk.get(), stream);
2560                 const HandleType handle = cb->getHndl();
2561                 const unsigned refCount = stream->getBe32();
2562                 const bool opened = stream->getByte();
2563                 const uint64_t closedTs = now - stream->getBe32();
2564                 if (refCount == 0) {
2565                     m_colorBufferDelayedCloseList.push_back({closedTs, handle});
2566                 }
2567                 return {handle, ColorBufferRef{std::move(cb), refCount, opened, closedTs}};
2568             });
2569     }
2570     m_lastPostedColorBuffer = static_cast<HandleType>(stream->getBe32());
2571     GL_LOG("Got lasted posted color buffer from snapshot");
2572 
2573     {
2574         AutoLock colorBufferMapLock(m_colorBufferMapLock);
2575 #if GFXSTREAM_ENABLE_HOST_GLES
2576         loadCollection(
2577             stream, &m_windows, [this](Stream* stream) -> EmulatedEglWindowSurfaceMap::value_type {
2578                 if (!m_emulationGl) {
2579                     GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
2580                         << "GL/EGL emulation not enabled.";
2581                 }
2582 
2583                 auto window =
2584                     m_emulationGl->loadEmulatedEglWindowSurface(stream, m_colorbuffers, m_contexts);
2585 
2586                 HandleType handle = window->getHndl();
2587                 HandleType colorBufferHandle = stream->getBe32();
2588                 return {handle, {std::move(window), colorBufferHandle}};
2589             });
2590 #endif
2591     }
2592 
2593 #if GFXSTREAM_ENABLE_HOST_GLES
2594     loadProcOwnedCollection(stream, &m_procOwnedEmulatedEglWindowSurfaces);
2595 #endif
2596     loadProcOwnedCollection(stream, &m_procOwnedColorBuffers);
2597 #if GFXSTREAM_ENABLE_HOST_GLES
2598     loadProcOwnedCollection(stream, &m_procOwnedEmulatedEglImages);
2599     loadProcOwnedCollection(stream, &m_procOwnedEmulatedEglContexts);
2600 #endif
2601     // TODO(b/309858017): remove if when ready to bump snapshot version
2602     if (m_features.VulkanSnapshots.enabled) {
2603         size_t resourceCount = stream->getBe64();
2604         for (size_t i = 0; i < resourceCount; i++) {
2605             uint64_t puid = stream->getBe64();
2606             uint32_t sequenceNumber = stream->getBe32();
2607             std::unique_ptr<ProcessResources> processResources = ProcessResources::create();
2608             processResources->getSequenceNumberPtr()->store(sequenceNumber);
2609             {
2610                 AutoLock mutex(m_procOwnedResourcesLock);
2611                 m_procOwnedResources.emplace(puid, std::move(processResources));
2612             }
2613         }
2614     }
2615 
2616 #if GFXSTREAM_ENABLE_HOST_GLES
2617     if (m_emulationGl) {
2618         if (s_egl.eglPostLoadAllImages) {
2619             s_egl.eglPostLoadAllImages(getDisplay(), stream);
2620         }
2621     }
2622 
2623     registerTriggerWait();
2624 #endif
2625 
2626     {
2627         std::unique_ptr<RecursiveScopedContextBind> bind;
2628 #if GFXSTREAM_ENABLE_HOST_GLES
2629         if (m_emulationGl) {
2630             // Some snapshot commands try using GL.
2631             bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
2632             if (!bind->isOk()) {
2633                 ERR("Failed to make context current for loading snapshot.");
2634             }
2635         }
2636 #endif
2637 
2638         AutoLock colorBufferMapLock(m_colorBufferMapLock);
2639         for (auto& it : m_colorbuffers) {
2640             if (it.second.cb) {
2641                 it.second.cb->touch();
2642             }
2643         }
2644     }
2645 
2646     // Restore Vulkan state
2647     if (m_features.VulkanSnapshots.enabled && vk::VkDecoderGlobalState::get()) {
2648         lock.unlock();
2649         GfxApiLogger gfxLogger;
2650         vk::VkDecoderGlobalState::get()->load(stream, gfxLogger, m_healthMonitor.get());
2651         lock.lock();
2652     }
2653 
2654     repost(false);
2655 
2656 #if GFXSTREAM_ENABLE_HOST_GLES
2657     if (m_emulationGl) {
2658         EmulatedEglFenceSync::onLoad(stream);
2659     }
2660 #endif
2661 
2662     return true;
2663     // TODO: restore memory management
2664 }
2665 
lock()2666 void FrameBuffer::lock() { m_lock.lock(); }
2667 
unlock()2668 void FrameBuffer::unlock() { m_lock.unlock(); }
2669 
findColorBuffer(HandleType p_colorbuffer)2670 ColorBufferPtr FrameBuffer::findColorBuffer(HandleType p_colorbuffer) {
2671     AutoLock colorBufferMapLock(m_colorBufferMapLock);
2672     ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
2673     if (c == m_colorbuffers.end()) {
2674         return nullptr;
2675     } else {
2676         return c->second.cb;
2677     }
2678 }
2679 
findBuffer(HandleType p_buffer)2680 BufferPtr FrameBuffer::findBuffer(HandleType p_buffer) {
2681     AutoLock colorBufferMapLock(m_colorBufferMapLock);
2682     BufferMap::iterator b(m_buffers.find(p_buffer));
2683     if (b == m_buffers.end()) {
2684         return nullptr;
2685     } else {
2686         return b->second.buffer;
2687     }
2688 }
2689 
registerProcessCleanupCallback(void * key,std::function<void ()> cb)2690 void FrameBuffer::registerProcessCleanupCallback(void* key, std::function<void()> cb) {
2691     AutoLock mutex(m_lock);
2692     RenderThreadInfo* tInfo = RenderThreadInfo::get();
2693     if (!tInfo) return;
2694 
2695     auto& callbackMap = m_procOwnedCleanupCallbacks[tInfo->m_puid];
2696     if (!callbackMap.insert({key, std::move(cb)}).second) {
2697         ERR("%s: tried to override existing key %p ", __func__, key);
2698     }
2699 }
2700 
unregisterProcessCleanupCallback(void * key)2701 void FrameBuffer::unregisterProcessCleanupCallback(void* key) {
2702     AutoLock mutex(m_lock);
2703     RenderThreadInfo* tInfo = RenderThreadInfo::get();
2704     if (!tInfo) return;
2705 
2706     auto& callbackMap = m_procOwnedCleanupCallbacks[tInfo->m_puid];
2707     auto erasedCount = callbackMap.erase(key);
2708     if (erasedCount == 0) {
2709         ERR("%s: tried to erase nonexistent key %p "
2710             "associated with process %llu",
2711             __func__, key, (unsigned long long)(tInfo->m_puid));
2712     }
2713 }
2714 
getProcessResources(uint64_t puid)2715 const ProcessResources* FrameBuffer::getProcessResources(uint64_t puid) {
2716     {
2717         AutoLock mutex(m_procOwnedResourcesLock);
2718         auto i = m_procOwnedResources.find(puid);
2719         if (i != m_procOwnedResources.end()) {
2720             return i->second.get();
2721         }
2722     }
2723     ERR("Failed to find process owned resources for puid %" PRIu64 ".", puid);
2724     return nullptr;
2725 }
2726 
createDisplay(uint32_t * displayId)2727 int FrameBuffer::createDisplay(uint32_t* displayId) {
2728     return emugl::get_emugl_multi_display_operations().createDisplay(displayId);
2729 }
2730 
createDisplay(uint32_t displayId)2731 int FrameBuffer::createDisplay(uint32_t displayId) {
2732     return emugl::get_emugl_multi_display_operations().createDisplay(&displayId);
2733 }
2734 
destroyDisplay(uint32_t displayId)2735 int FrameBuffer::destroyDisplay(uint32_t displayId) {
2736     return emugl::get_emugl_multi_display_operations().destroyDisplay(displayId);
2737 }
2738 
setDisplayColorBuffer(uint32_t displayId,uint32_t colorBuffer)2739 int FrameBuffer::setDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer) {
2740     return emugl::get_emugl_multi_display_operations().setDisplayColorBuffer(displayId,
2741                                                                              colorBuffer);
2742 }
2743 
getDisplayColorBuffer(uint32_t displayId,uint32_t * colorBuffer)2744 int FrameBuffer::getDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer) {
2745     return emugl::get_emugl_multi_display_operations().getDisplayColorBuffer(displayId,
2746                                                                              colorBuffer);
2747 }
2748 
getColorBufferDisplay(uint32_t colorBuffer,uint32_t * displayId)2749 int FrameBuffer::getColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId) {
2750     return emugl::get_emugl_multi_display_operations().getColorBufferDisplay(colorBuffer,
2751                                                                              displayId);
2752 }
2753 
getDisplayPose(uint32_t displayId,int32_t * x,int32_t * y,uint32_t * w,uint32_t * h)2754 int FrameBuffer::getDisplayPose(uint32_t displayId, int32_t* x, int32_t* y, uint32_t* w,
2755                                 uint32_t* h) {
2756     return emugl::get_emugl_multi_display_operations().getDisplayPose(displayId, x, y, w, h);
2757 }
2758 
setDisplayPose(uint32_t displayId,int32_t x,int32_t y,uint32_t w,uint32_t h,uint32_t dpi)2759 int FrameBuffer::setDisplayPose(uint32_t displayId, int32_t x, int32_t y, uint32_t w, uint32_t h,
2760                                 uint32_t dpi) {
2761     return emugl::get_emugl_multi_display_operations().setDisplayPose(displayId, x, y, w, h, dpi);
2762 }
2763 
sweepColorBuffersLocked()2764 void FrameBuffer::sweepColorBuffersLocked() {
2765     HandleType handleToDestroy = 0;
2766     while (mOutstandingColorBufferDestroys.tryReceive(&handleToDestroy)) {
2767         decColorBufferRefCountLocked(handleToDestroy);
2768     }
2769 }
2770 
blockPostWorker(std::future<void> continueSignal)2771 std::future<void> FrameBuffer::blockPostWorker(std::future<void> continueSignal) {
2772     std::promise<void> scheduled;
2773     std::future<void> scheduledFuture = scheduled.get_future();
2774     Post postCmd = {
2775         .cmd = PostCmd::Block,
2776         .block = std::make_unique<Post::Block>(Post::Block{
2777             .scheduledSignal = std::move(scheduled),
2778             .continueSignal = std::move(continueSignal),
2779         }),
2780     };
2781     sendPostWorkerCmd(std::move(postCmd));
2782     return scheduledFuture;
2783 }
2784 
asyncWaitForGpuVulkanWithCb(uint64_t deviceHandle,uint64_t fenceHandle,FenceCompletionCallback cb)2785 void FrameBuffer::asyncWaitForGpuVulkanWithCb(uint64_t deviceHandle, uint64_t fenceHandle,
2786                                               FenceCompletionCallback cb) {
2787     (void)deviceHandle;
2788     SyncThread::get()->triggerWaitVkWithCompletionCallback((VkFence)fenceHandle, std::move(cb));
2789 }
2790 
asyncWaitForGpuVulkanQsriWithCb(uint64_t image,FenceCompletionCallback cb)2791 void FrameBuffer::asyncWaitForGpuVulkanQsriWithCb(uint64_t image, FenceCompletionCallback cb) {
2792     SyncThread::get()->triggerWaitVkQsriWithCompletionCallback((VkImage)image, std::move(cb));
2793 }
2794 
setGuestManagedColorBufferLifetime(bool guestManaged)2795 void FrameBuffer::setGuestManagedColorBufferLifetime(bool guestManaged) {
2796     m_guestManagedColorBufferLifetime = guestManaged;
2797 }
2798 
borrowColorBufferForComposition(uint32_t colorBufferHandle,bool colorBufferIsTarget)2799 std::unique_ptr<BorrowedImageInfo> FrameBuffer::borrowColorBufferForComposition(
2800     uint32_t colorBufferHandle, bool colorBufferIsTarget) {
2801     ColorBufferPtr colorBufferPtr = findColorBuffer(colorBufferHandle);
2802     if (!colorBufferPtr) {
2803         ERR("Failed to get borrowed image info for ColorBuffer:%d", colorBufferHandle);
2804         return nullptr;
2805     }
2806 
2807     if (m_useVulkanComposition) {
2808         invalidateColorBufferForVk(colorBufferHandle);
2809     } else {
2810 #if GFXSTREAM_ENABLE_HOST_GLES
2811         invalidateColorBufferForGl(colorBufferHandle);
2812 #endif
2813     }
2814 
2815     const auto api = m_useVulkanComposition ? ColorBuffer::UsedApi::kVk : ColorBuffer::UsedApi::kGl;
2816     return colorBufferPtr->borrowForComposition(api, colorBufferIsTarget);
2817 }
2818 
borrowColorBufferForDisplay(uint32_t colorBufferHandle)2819 std::unique_ptr<BorrowedImageInfo> FrameBuffer::borrowColorBufferForDisplay(
2820     uint32_t colorBufferHandle) {
2821     ColorBufferPtr colorBufferPtr = findColorBuffer(colorBufferHandle);
2822     if (!colorBufferPtr) {
2823         ERR("Failed to get borrowed image info for ColorBuffer:%d", colorBufferHandle);
2824         return nullptr;
2825     }
2826 
2827     if (m_useVulkanComposition) {
2828         invalidateColorBufferForVk(colorBufferHandle);
2829     } else {
2830 #if GFXSTREAM_ENABLE_HOST_GLES
2831         invalidateColorBufferForGl(colorBufferHandle);
2832 #else
2833         ERR("Failed to invalidate ColorBuffer:%d", colorBufferHandle);
2834 #endif
2835     }
2836 
2837     const auto api = m_useVulkanComposition ? ColorBuffer::UsedApi::kVk : ColorBuffer::UsedApi::kGl;
2838     return colorBufferPtr->borrowForDisplay(api);
2839 }
2840 
logVulkanDeviceLost()2841 void FrameBuffer::logVulkanDeviceLost() {
2842     if (!m_emulationVk) {
2843         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Device lost without VkEmulation?";
2844     }
2845     m_emulationVk->onVkDeviceLost();
2846 }
2847 
logVulkanOutOfMemory(VkResult result,const char * function,int line,std::optional<uint64_t> allocationSize)2848 void FrameBuffer::logVulkanOutOfMemory(VkResult result, const char* function, int line,
2849                                        std::optional<uint64_t> allocationSize) {
2850     m_logger->logMetricEvent(MetricEventVulkanOutOfMemory{
2851         .vkResultCode = result,
2852         .function = function,
2853         .line = std::make_optional(line),
2854         .allocationSize = allocationSize,
2855     });
2856 }
2857 
setVsyncHz(int vsyncHz)2858 void FrameBuffer::setVsyncHz(int vsyncHz) {
2859     const uint64_t kOneSecondNs = 1000000000ULL;
2860     m_vsyncHz = vsyncHz;
2861     if (m_vsyncThread) {
2862         m_vsyncThread->setPeriod(kOneSecondNs / (uint64_t)m_vsyncHz);
2863     }
2864 }
2865 
scheduleVsyncTask(VsyncThread::VsyncTask task)2866 void FrameBuffer::scheduleVsyncTask(VsyncThread::VsyncTask task) {
2867     if (!m_vsyncThread) {
2868         ERR("%s: warning: no vsync thread exists", __func__);
2869         task(0);
2870         return;
2871     }
2872 
2873     m_vsyncThread->schedule(task);
2874 }
2875 
setDisplayConfigs(int configId,int w,int h,int dpiX,int dpiY)2876 void FrameBuffer::setDisplayConfigs(int configId, int w, int h, int dpiX, int dpiY) {
2877     AutoLock mutex(m_lock);
2878     mDisplayConfigs[configId] = {w, h, dpiX, dpiY};
2879     INFO("Setting display: %d configuration to: %dx%d, dpi: %dx%d ", configId,
2880            w, h, dpiX, dpiY);
2881 }
2882 
setDisplayActiveConfig(int configId)2883 void FrameBuffer::setDisplayActiveConfig(int configId) {
2884     AutoLock mutex(m_lock);
2885     if (mDisplayConfigs.find(configId) == mDisplayConfigs.end()) {
2886         ERR("config %d not set", configId);
2887         return;
2888     }
2889     mDisplayActiveConfigId = configId;
2890     m_framebufferWidth = mDisplayConfigs[configId].w;
2891     m_framebufferHeight = mDisplayConfigs[configId].h;
2892     setDisplayPose(0, 0, 0, getWidth(), getHeight(), 0);
2893     INFO("setDisplayActiveConfig %d", configId);
2894 }
2895 
getDisplayConfigsCount()2896 int FrameBuffer::getDisplayConfigsCount() {
2897     AutoLock mutex(m_lock);
2898     return mDisplayConfigs.size();
2899 }
2900 
getDisplayConfigsParam(int configId,EGLint param)2901 int FrameBuffer::getDisplayConfigsParam(int configId, EGLint param) {
2902     AutoLock mutex(m_lock);
2903     if (mDisplayConfigs.find(configId) == mDisplayConfigs.end()) {
2904         return -1;
2905     }
2906     switch (param) {
2907         case FB_WIDTH:
2908             return mDisplayConfigs[configId].w;
2909         case FB_HEIGHT:
2910             return mDisplayConfigs[configId].h;
2911         case FB_XDPI:
2912             return mDisplayConfigs[configId].dpiX;
2913         case FB_YDPI:
2914             return mDisplayConfigs[configId].dpiY;
2915         case FB_FPS:
2916             return 60;
2917         case FB_MIN_SWAP_INTERVAL:
2918             return -1;
2919         case FB_MAX_SWAP_INTERVAL:
2920             return -1;
2921         default:
2922             return -1;
2923     }
2924 }
2925 
getDisplayActiveConfig()2926 int FrameBuffer::getDisplayActiveConfig() {
2927     AutoLock mutex(m_lock);
2928     return mDisplayActiveConfigId >= 0 ? mDisplayActiveConfigId : -1;
2929 }
2930 
flushColorBufferFromVk(HandleType colorBufferHandle)2931 bool FrameBuffer::flushColorBufferFromVk(HandleType colorBufferHandle) {
2932     AutoLock mutex(m_lock);
2933     auto colorBuffer = findColorBuffer(colorBufferHandle);
2934     if (!colorBuffer) {
2935         ERR("%s: Failed to find ColorBuffer:%d", __func__, colorBufferHandle);
2936         return false;
2937     }
2938     return colorBuffer->flushFromVk();
2939 }
2940 
flushColorBufferFromVkBytes(HandleType colorBufferHandle,const void * bytes,size_t bytesSize)2941 bool FrameBuffer::flushColorBufferFromVkBytes(HandleType colorBufferHandle, const void* bytes,
2942                                               size_t bytesSize) {
2943     AutoLock mutex(m_lock);
2944 
2945     auto colorBuffer = findColorBuffer(colorBufferHandle);
2946     if (!colorBuffer) {
2947         ERR("%s: Failed to find ColorBuffer:%d", __func__, colorBufferHandle);
2948         return false;
2949     }
2950     return colorBuffer->flushFromVkBytes(bytes, bytesSize);
2951 }
2952 
invalidateColorBufferForVk(HandleType colorBufferHandle)2953 bool FrameBuffer::invalidateColorBufferForVk(HandleType colorBufferHandle) {
2954     // It reads contents from GL, which requires a context lock.
2955     // Also we should not do this in PostWorkerGl, otherwise it will deadlock.
2956     //
2957     // b/283524158
2958     // b/273986739
2959     AutoLock mutex(m_lock);
2960     auto colorBuffer = findColorBuffer(colorBufferHandle);
2961     if (!colorBuffer) {
2962         VERBOSE("%s: Failed to find ColorBuffer:%d", __func__, colorBufferHandle);
2963         return false;
2964     }
2965     return colorBuffer->invalidateForVk();
2966 }
2967 
exportColorBuffer(HandleType colorBufferHandle)2968 std::optional<BlobDescriptorInfo> FrameBuffer::exportColorBuffer(HandleType colorBufferHandle) {
2969     AutoLock mutex(m_lock);
2970 
2971     ColorBufferPtr colorBuffer = findColorBuffer(colorBufferHandle);
2972     if (!colorBuffer) {
2973         return std::nullopt;
2974     }
2975 
2976     return colorBuffer->exportBlob();
2977 }
2978 
exportBuffer(HandleType bufferHandle)2979 std::optional<BlobDescriptorInfo> FrameBuffer::exportBuffer(HandleType bufferHandle) {
2980     AutoLock mutex(m_lock);
2981 
2982     BufferPtr buffer = findBuffer(bufferHandle);
2983     if (!buffer) {
2984         return std::nullopt;
2985     }
2986 
2987     return buffer->exportBlob();
2988 }
2989 
2990 #if GFXSTREAM_ENABLE_HOST_GLES
getEmulatedEglWindowSurfaceColorBufferHandle(HandleType p_surface)2991 HandleType FrameBuffer::getEmulatedEglWindowSurfaceColorBufferHandle(HandleType p_surface) {
2992     AutoLock mutex(m_lock);
2993 
2994     auto it = m_EmulatedEglWindowSurfaceToColorBuffer.find(p_surface);
2995     if (it == m_EmulatedEglWindowSurfaceToColorBuffer.end()) {
2996         return 0;
2997     }
2998 
2999     return it->second;
3000 }
3001 
3002 #ifdef CONFIG_AEMU
unregisterVulkanInstance(uint64_t id) const3003 void FrameBuffer::unregisterVulkanInstance(uint64_t id) const {
3004     get_emugl_vm_operations().vulkanInstanceUnregister(id);
3005 }
3006 
registerVulkanInstance(uint64_t id,const char * appName) const3007 void FrameBuffer::registerVulkanInstance(uint64_t id, const char* appName) const {
3008     auto* tInfo = RenderThreadInfo::get();
3009     std::string process_name;
3010     if (tInfo && tInfo->m_processName.has_value()) {
3011         process_name = tInfo->m_processName.value();
3012         // for deqp: com.drawelements.deqp:testercore
3013         // remove the ":testercore" for deqp
3014         auto position = process_name.find(":");
3015         if (position != std::string::npos) {
3016             process_name = process_name.substr(0, position);
3017         }
3018     } else if(appName) {
3019         process_name = std::string(appName);
3020     }
3021     get_emugl_vm_operations().vulkanInstanceRegister(id, process_name.c_str());
3022 }
3023 #endif
3024 
createTrivialContext(HandleType shared,HandleType * contextOut,HandleType * surfOut)3025 void FrameBuffer::createTrivialContext(HandleType shared, HandleType* contextOut,
3026                                        HandleType* surfOut) {
3027     assert(contextOut);
3028     assert(surfOut);
3029 
3030     *contextOut = createEmulatedEglContext(0, shared, GLESApi_2);
3031     // Zero size is formally allowed here, but SwiftShader doesn't like it and
3032     // fails.
3033     *surfOut = createEmulatedEglWindowSurface(0, 1, 1);
3034 }
3035 
createSharedTrivialContext(EGLContext * contextOut,EGLSurface * surfOut)3036 void FrameBuffer::createSharedTrivialContext(EGLContext* contextOut, EGLSurface* surfOut) {
3037     assert(contextOut);
3038     assert(surfOut);
3039 
3040     const EmulatedEglConfig* config = getConfigs()->get(0 /* p_config */);
3041     if (!config) return;
3042 
3043     int maj, min;
3044     emugl::getGlesVersion(&maj, &min);
3045 
3046     const EGLint contextAttribs[] = {EGL_CONTEXT_MAJOR_VERSION_KHR, maj,
3047                                      EGL_CONTEXT_MINOR_VERSION_KHR, min, EGL_NONE};
3048 
3049     *contextOut = s_egl.eglCreateContext(getDisplay(), config->getHostEglConfig(),
3050                                          getGlobalEGLContext(), contextAttribs);
3051 
3052     const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
3053 
3054     *surfOut = s_egl.eglCreatePbufferSurface(getDisplay(), config->getHostEglConfig(), pbufAttribs);
3055 }
3056 
destroySharedTrivialContext(EGLContext context,EGLSurface surface)3057 void FrameBuffer::destroySharedTrivialContext(EGLContext context, EGLSurface surface) {
3058     if (getDisplay() != EGL_NO_DISPLAY) {
3059         s_egl.eglDestroyContext(getDisplay(), context);
3060         s_egl.eglDestroySurface(getDisplay(), surface);
3061     }
3062 }
3063 
getConfigs() const3064 const EmulatedEglConfigList* FrameBuffer::getConfigs() const {
3065     if (!m_emulationGl) {
3066         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3067     }
3068 
3069     return &m_emulationGl->getEmulationEglConfigs();
3070 }
3071 
setEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface,HandleType p_colorbuffer)3072 bool FrameBuffer::setEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface,
3073                                                          HandleType p_colorbuffer) {
3074     AutoLock mutex(m_lock);
3075 
3076     EmulatedEglWindowSurfaceMap::iterator w(m_windows.find(p_surface));
3077     if (w == m_windows.end()) {
3078         // bad surface handle
3079         ERR("bad window surface handle %#x", p_surface);
3080         return false;
3081     }
3082 
3083     {
3084         AutoLock colorBufferMapLock(m_colorBufferMapLock);
3085         ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
3086         if (c == m_colorbuffers.end()) {
3087             ERR("bad color buffer handle %d", p_colorbuffer);
3088             // bad colorbuffer handle
3089             return false;
3090         }
3091 
3092         (*w).second.first->setColorBuffer((*c).second.cb);
3093         markOpened(&c->second);
3094         if (!m_guestManagedColorBufferLifetime) {
3095             c->second.refcount++;
3096         }
3097     }
3098     if (w->second.second) {
3099         if (!m_guestManagedColorBufferLifetime) {
3100             if (m_refCountPipeEnabled) {
3101                 decColorBufferRefCountLocked(w->second.second);
3102             } else {
3103                 closeColorBufferLocked(w->second.second);
3104             }
3105         }
3106     }
3107 
3108     (*w).second.second = p_colorbuffer;
3109 
3110     m_EmulatedEglWindowSurfaceToColorBuffer[p_surface] = p_colorbuffer;
3111 
3112     return true;
3113 }
3114 
createEmulatedEglContext(int config,HandleType shareContextHandle,GLESApi version)3115 HandleType FrameBuffer::createEmulatedEglContext(int config, HandleType shareContextHandle,
3116                                                  GLESApi version) {
3117     if (!m_emulationGl) {
3118         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation unavailable.";
3119     }
3120 
3121     AutoLock mutex(m_lock);
3122     android::base::AutoWriteLock contextLock(m_contextStructureLock);
3123     // Hold the ColorBuffer map lock so that the new handle won't collide with a ColorBuffer handle.
3124     AutoLock colorBufferMapLock(m_colorBufferMapLock);
3125 
3126     EmulatedEglContextPtr shareContext = nullptr;
3127     if (shareContextHandle != 0) {
3128         auto shareContextIt = m_contexts.find(shareContextHandle);
3129         if (shareContextIt == m_contexts.end()) {
3130             ERR("Failed to find share EmulatedEglContext:%d", shareContextHandle);
3131             return 0;
3132         }
3133         shareContext = shareContextIt->second;
3134     }
3135 
3136     HandleType contextHandle = genHandle_locked();
3137     auto context =
3138         m_emulationGl->createEmulatedEglContext(config, shareContext.get(), version, contextHandle);
3139     if (!context) {
3140         ERR("Failed to create EmulatedEglContext.");
3141         return 0;
3142     }
3143 
3144     m_contexts[contextHandle] = std::move(context);
3145 
3146     RenderThreadInfo* tinfo = RenderThreadInfo::get();
3147     uint64_t puid = tinfo->m_puid;
3148     // The new emulator manages render contexts per guest process.
3149     // Fall back to per-thread management if the system image does not
3150     // support it.
3151     if (puid) {
3152         m_procOwnedEmulatedEglContexts[puid].insert(contextHandle);
3153     } else {  // legacy path to manage context lifetime by threads
3154         if (!tinfo->m_glInfo) {
3155             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
3156         }
3157         tinfo->m_glInfo->m_contextSet.insert(contextHandle);
3158     }
3159 
3160     return contextHandle;
3161 }
3162 
destroyEmulatedEglContext(HandleType contextHandle)3163 void FrameBuffer::destroyEmulatedEglContext(HandleType contextHandle) {
3164     AutoLock mutex(m_lock);
3165     sweepColorBuffersLocked();
3166 
3167     android::base::AutoWriteLock contextLock(m_contextStructureLock);
3168     m_contexts.erase(contextHandle);
3169     RenderThreadInfo* tinfo = RenderThreadInfo::get();
3170     uint64_t puid = tinfo->m_puid;
3171     // The new emulator manages render contexts per guest process.
3172     // Fall back to per-thread management if the system image does not
3173     // support it.
3174     if (puid) {
3175         auto it = m_procOwnedEmulatedEglContexts.find(puid);
3176         if (it != m_procOwnedEmulatedEglContexts.end()) {
3177             it->second.erase(contextHandle);
3178         }
3179     } else {
3180         if (!tinfo->m_glInfo) {
3181             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
3182         }
3183         tinfo->m_glInfo->m_contextSet.erase(contextHandle);
3184     }
3185 }
3186 
createEmulatedEglWindowSurface(int p_config,int p_width,int p_height)3187 HandleType FrameBuffer::createEmulatedEglWindowSurface(int p_config, int p_width, int p_height) {
3188     if (!m_emulationGl) {
3189         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation unavailable.";
3190     }
3191 
3192     AutoLock mutex(m_lock);
3193     // Hold the ColorBuffer map lock so that the new handle won't collide with a ColorBuffer handle.
3194     AutoLock colorBufferMapLock(m_colorBufferMapLock);
3195 
3196     HandleType handle = genHandle_locked();
3197 
3198     auto window =
3199         m_emulationGl->createEmulatedEglWindowSurface(p_config, p_width, p_height, handle);
3200     if (!window) {
3201         ERR("Failed to create EmulatedEglWindowSurface.");
3202         return 0;
3203     }
3204 
3205     m_windows[handle] = {std::move(window), 0};
3206 
3207     RenderThreadInfo* info = RenderThreadInfo::get();
3208     if (!info->m_glInfo) {
3209         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "RRenderThreadInfoGl not available.";
3210     }
3211 
3212     uint64_t puid = info->m_puid;
3213     if (puid) {
3214         m_procOwnedEmulatedEglWindowSurfaces[puid].insert(handle);
3215     } else {  // legacy path to manage window surface lifetime by threads
3216         info->m_glInfo->m_windowSet.insert(handle);
3217     }
3218 
3219     return handle;
3220 }
3221 
destroyEmulatedEglWindowSurface(HandleType p_surface)3222 void FrameBuffer::destroyEmulatedEglWindowSurface(HandleType p_surface) {
3223     if (m_shuttingDown) {
3224         return;
3225     }
3226     AutoLock mutex(m_lock);
3227     destroyEmulatedEglWindowSurfaceLocked(p_surface);
3228 }
3229 
destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface)3230 std::vector<HandleType> FrameBuffer::destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface) {
3231     std::vector<HandleType> colorBuffersToCleanUp;
3232     const auto w = m_windows.find(p_surface);
3233     if (w != m_windows.end()) {
3234         RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
3235         if (!m_guestManagedColorBufferLifetime) {
3236             if (m_refCountPipeEnabled) {
3237                 if (decColorBufferRefCountLocked(w->second.second)) {
3238                     colorBuffersToCleanUp.push_back(w->second.second);
3239                 }
3240             } else {
3241                 if (closeColorBufferLocked(w->second.second)) {
3242                     colorBuffersToCleanUp.push_back(w->second.second);
3243                 }
3244             }
3245         }
3246         m_windows.erase(w);
3247         RenderThreadInfo* tinfo = RenderThreadInfo::get();
3248         uint64_t puid = tinfo->m_puid;
3249         if (puid) {
3250             auto ite = m_procOwnedEmulatedEglWindowSurfaces.find(puid);
3251             if (ite != m_procOwnedEmulatedEglWindowSurfaces.end()) {
3252                 ite->second.erase(p_surface);
3253             }
3254         } else {
3255             if (!tinfo->m_glInfo) {
3256                 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
3257                     << "Render thread GL not available.";
3258             }
3259             tinfo->m_glInfo->m_windowSet.erase(p_surface);
3260         }
3261     }
3262     return colorBuffersToCleanUp;
3263 }
3264 
createEmulatedEglFenceSync(EGLenum type,int destroyWhenSignaled,uint64_t * outSync,uint64_t * outSyncThread)3265 void FrameBuffer::createEmulatedEglFenceSync(EGLenum type, int destroyWhenSignaled,
3266                                              uint64_t* outSync, uint64_t* outSyncThread) {
3267     if (!m_emulationGl) {
3268         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not available.";
3269     }
3270 
3271     // TODO(b/233939967): move RenderThreadInfoGl usage to EmulationGl.
3272     RenderThreadInfoGl* const info = RenderThreadInfoGl::get();
3273     if (!info) {
3274         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "RenderThreadInfoGl not available.";
3275     }
3276     if (!info->currContext) {
3277         uint32_t syncContext;
3278         uint32_t syncSurface;
3279         createTrivialContext(0,  // There is no context to share.
3280                              &syncContext, &syncSurface);
3281         bindContext(syncContext, syncSurface, syncSurface);
3282         // This context is then cleaned up when the render thread exits.
3283     }
3284 
3285     auto sync = m_emulationGl->createEmulatedEglFenceSync(type, destroyWhenSignaled);
3286     if (!sync) {
3287         return;
3288     }
3289 
3290     if (outSync) {
3291         *outSync = (uint64_t)(uintptr_t)sync.release();
3292     }
3293     if (outSyncThread) {
3294         *outSyncThread = reinterpret_cast<uint64_t>(SyncThread::get());
3295     }
3296 }
3297 
drainGlRenderThreadResources()3298 void FrameBuffer::drainGlRenderThreadResources() {
3299     // If we're already exiting then snapshot should not contain
3300     // this thread information at all.
3301     if (isShuttingDown()) {
3302         return;
3303     }
3304 
3305     // Release references to the current thread's context/surfaces if any
3306     bindContext(0, 0, 0);
3307 
3308     drainGlRenderThreadSurfaces();
3309     drainGlRenderThreadContexts();
3310 
3311     if (!s_egl.eglReleaseThread()) {
3312         ERR("Error: RenderThread @%p failed to eglReleaseThread()", this);
3313     }
3314 }
3315 
drainGlRenderThreadContexts()3316 void FrameBuffer::drainGlRenderThreadContexts() {
3317     if (isShuttingDown()) {
3318         return;
3319     }
3320 
3321     RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
3322     if (!tinfo) {
3323         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
3324     }
3325 
3326     if (tinfo->m_contextSet.empty()) {
3327         return;
3328     }
3329 
3330     AutoLock mutex(m_lock);
3331     android::base::AutoWriteLock contextLock(m_contextStructureLock);
3332     for (const HandleType contextHandle : tinfo->m_contextSet) {
3333         m_contexts.erase(contextHandle);
3334     }
3335     tinfo->m_contextSet.clear();
3336 }
3337 
drainGlRenderThreadSurfaces()3338 void FrameBuffer::drainGlRenderThreadSurfaces() {
3339     if (isShuttingDown()) {
3340         return;
3341     }
3342 
3343     RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
3344     if (!tinfo) {
3345         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
3346     }
3347 
3348     if (tinfo->m_windowSet.empty()) {
3349         return;
3350     }
3351 
3352     std::vector<HandleType> colorBuffersToCleanup;
3353 
3354     AutoLock mutex(m_lock);
3355     RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
3356     for (const HandleType winHandle : tinfo->m_windowSet) {
3357         const auto winIt = m_windows.find(winHandle);
3358         if (winIt != m_windows.end()) {
3359             if (const HandleType oldColorBufferHandle = winIt->second.second) {
3360                 if (!m_guestManagedColorBufferLifetime) {
3361                     if (m_refCountPipeEnabled) {
3362                         if (decColorBufferRefCountLocked(oldColorBufferHandle)) {
3363                             colorBuffersToCleanup.push_back(oldColorBufferHandle);
3364                         }
3365                     } else {
3366                         if (closeColorBufferLocked(oldColorBufferHandle)) {
3367                             colorBuffersToCleanup.push_back(oldColorBufferHandle);
3368                         }
3369                     }
3370                 }
3371                 m_windows.erase(winIt);
3372             }
3373         }
3374     }
3375     tinfo->m_windowSet.clear();
3376 }
3377 
getEmulationGl()3378 EmulationGl& FrameBuffer::getEmulationGl() {
3379     if (!m_emulationGl) {
3380         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
3381     }
3382     return *m_emulationGl;
3383 }
3384 
getEmulationVk()3385 VkEmulation& FrameBuffer::getEmulationVk() {
3386     if (!m_emulationVk) {
3387         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
3388     }
3389     return *m_emulationVk;
3390 }
3391 
getDisplay() const3392 EGLDisplay FrameBuffer::getDisplay() const {
3393     if (!m_emulationGl) {
3394         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3395     }
3396     return m_emulationGl->mEglDisplay;
3397 }
3398 
getWindowSurface() const3399 EGLSurface FrameBuffer::getWindowSurface() const {
3400     if (!m_emulationGl) {
3401         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3402     }
3403 
3404     if (!m_emulationGl->mWindowSurface) {
3405         return EGL_NO_SURFACE;
3406     }
3407 
3408     const auto* displaySurfaceGl =
3409         reinterpret_cast<const DisplaySurfaceGl*>(m_emulationGl->mWindowSurface->getImpl());
3410 
3411     return displaySurfaceGl->getSurface();
3412 }
3413 
getContext() const3414 EGLContext FrameBuffer::getContext() const {
3415     if (!m_emulationGl) {
3416         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3417     }
3418     return m_emulationGl->mEglContext;
3419 }
3420 
getConfig() const3421 EGLContext FrameBuffer::getConfig() const {
3422     if (!m_emulationGl) {
3423         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3424     }
3425     return m_emulationGl->mEglConfig;
3426 }
3427 
getGlobalEGLContext() const3428 EGLContext FrameBuffer::getGlobalEGLContext() const {
3429     if (!m_emulationGl) {
3430         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3431     }
3432 
3433     if (!m_emulationGl->mPbufferSurface) {
3434         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
3435             << "FrameBuffer pbuffer surface not available.";
3436     }
3437 
3438     const auto* displaySurfaceGl =
3439         reinterpret_cast<const DisplaySurfaceGl*>(m_emulationGl->mPbufferSurface->getImpl());
3440 
3441     return displaySurfaceGl->getContextForShareContext();
3442 }
3443 
getContext_locked(HandleType p_context)3444 EmulatedEglContextPtr FrameBuffer::getContext_locked(HandleType p_context) {
3445     return android::base::findOrDefault(m_contexts, p_context);
3446 }
3447 
getWindowSurface_locked(HandleType p_windowsurface)3448 EmulatedEglWindowSurfacePtr FrameBuffer::getWindowSurface_locked(HandleType p_windowsurface) {
3449     return android::base::findOrDefault(m_windows, p_windowsurface).first;
3450 }
3451 
getTextureDraw() const3452 TextureDraw* FrameBuffer::getTextureDraw() const {
3453     if (!m_emulationGl) {
3454         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3455     }
3456 
3457     return m_emulationGl->mTextureDraw.get();
3458 }
3459 
isFastBlitSupported() const3460 bool FrameBuffer::isFastBlitSupported() const {
3461     if (!m_emulationGl) {
3462         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3463     }
3464 
3465     return m_emulationGl->isFastBlitSupported();
3466 }
3467 
disableFastBlitForTesting()3468 void FrameBuffer::disableFastBlitForTesting() {
3469     if (!m_emulationGl) {
3470         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3471     }
3472 
3473     m_emulationGl->disableFastBlitForTesting();
3474 }
3475 
createEmulatedEglImage(HandleType contextHandle,EGLenum target,GLuint buffer)3476 HandleType FrameBuffer::createEmulatedEglImage(HandleType contextHandle, EGLenum target,
3477                                                GLuint buffer) {
3478     if (!m_emulationGl) {
3479         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
3480     }
3481 
3482     AutoLock mutex(m_lock);
3483 
3484     EmulatedEglContext* context = nullptr;
3485     if (contextHandle) {
3486         android::base::AutoWriteLock contextLock(m_contextStructureLock);
3487 
3488         auto it = m_contexts.find(contextHandle);
3489         if (it == m_contexts.end()) {
3490             ERR("Failed to find EmulatedEglContext:%d", contextHandle);
3491             return false;
3492         }
3493 
3494         context = it->second.get();
3495     }
3496 
3497     auto image = m_emulationGl->createEmulatedEglImage(context, target,
3498                                                        reinterpret_cast<EGLClientBuffer>(buffer));
3499     if (!image) {
3500         ERR("Failed to create EmulatedEglImage");
3501         return false;
3502     }
3503 
3504     HandleType imageHandle = image->getHandle();
3505 
3506     m_images[imageHandle] = std::move(image);
3507 
3508     RenderThreadInfo* tInfo = RenderThreadInfo::get();
3509     uint64_t puid = tInfo->m_puid;
3510     if (puid) {
3511         m_procOwnedEmulatedEglImages[puid].insert(imageHandle);
3512     }
3513     return imageHandle;
3514 }
3515 
destroyEmulatedEglImage(HandleType imageHandle)3516 EGLBoolean FrameBuffer::destroyEmulatedEglImage(HandleType imageHandle) {
3517     if (!m_emulationGl) {
3518         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
3519     }
3520 
3521     AutoLock mutex(m_lock);
3522 
3523     auto imageIt = m_images.find(imageHandle);
3524     if (imageIt == m_images.end()) {
3525         ERR("Failed to find EmulatedEglImage:%d", imageHandle);
3526         return false;
3527     }
3528     auto& image = imageIt->second;
3529 
3530     EGLBoolean success = image->destroy();
3531     m_images.erase(imageIt);
3532 
3533     RenderThreadInfo* tInfo = RenderThreadInfo::get();
3534     uint64_t puid = tInfo->m_puid;
3535     if (puid) {
3536         m_procOwnedEmulatedEglImages[puid].erase(imageHandle);
3537         // We don't explicitly call m_procOwnedEmulatedEglImages.erase(puid) when the
3538         // size reaches 0, since it could go between zero and one many times in
3539         // the lifetime of a process. It will be cleaned up by
3540         // cleanupProcGLObjects(puid) when the process is dead.
3541     }
3542     return success;
3543 }
3544 
flushEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface)3545 bool FrameBuffer::flushEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface) {
3546     AutoLock mutex(m_lock);
3547 
3548     auto it = m_windows.find(p_surface);
3549     if (it == m_windows.end()) {
3550         ERR("FB::flushEmulatedEglWindowSurfaceColorBuffer: window handle %#x not found", p_surface);
3551         // bad surface handle
3552         return false;
3553     }
3554 
3555     EmulatedEglWindowSurface* surface = it->second.first.get();
3556     surface->flushColorBuffer();
3557 
3558     return true;
3559 }
3560 
getMaxGLESVersion()3561 GLESDispatchMaxVersion FrameBuffer::getMaxGLESVersion() {
3562     if (!m_emulationGl) {
3563         return GLES_DISPATCH_MAX_VERSION_2;
3564     }
3565     return m_emulationGl->getGlesMaxDispatchVersion();
3566 }
3567 
fillGLESUsages(android_studio::EmulatorGLESUsages * usages)3568 void FrameBuffer::fillGLESUsages(android_studio::EmulatorGLESUsages* usages) {
3569     if (s_egl.eglFillUsages) {
3570         s_egl.eglFillUsages(usages);
3571     }
3572 }
3573 
platformCreateSharedEglContext(void)3574 void* FrameBuffer::platformCreateSharedEglContext(void) {
3575     AutoLock lock(m_lock);
3576 
3577     EGLContext context = 0;
3578     EGLSurface surface = 0;
3579     createSharedTrivialContext(&context, &surface);
3580 
3581     void* underlyingContext = s_egl.eglGetNativeContextANDROID(getDisplay(), context);
3582     if (!underlyingContext) {
3583         ERR("Error: Underlying egl backend could not produce a native EGL context.");
3584         return nullptr;
3585     }
3586 
3587     m_platformEglContexts[underlyingContext] = {context, surface};
3588 
3589 #if defined(__QNX__)
3590     EGLDisplay currDisplay = eglGetCurrentDisplay();
3591     EGLSurface currRead = eglGetCurrentSurface(EGL_READ);
3592     EGLSurface currDraw = eglGetCurrentSurface(EGL_DRAW);
3593     EGLSurface currContext = eglGetCurrentContext();
3594     // Make this context current to ensure thread-state is initialized
3595     s_egl.eglMakeCurrent(getDisplay(), surface, surface, context);
3596     // Revert back to original state
3597     s_egl.eglMakeCurrent(currDisplay, currRead, currDraw, currContext);
3598 #endif
3599 
3600     return underlyingContext;
3601 }
3602 
platformDestroySharedEglContext(void * underlyingContext)3603 bool FrameBuffer::platformDestroySharedEglContext(void* underlyingContext) {
3604     AutoLock lock(m_lock);
3605 
3606     auto it = m_platformEglContexts.find(underlyingContext);
3607     if (it == m_platformEglContexts.end()) {
3608         ERR("Error: Could not find underlying egl context %p (perhaps already destroyed?)",
3609             underlyingContext);
3610         return false;
3611     }
3612 
3613     destroySharedTrivialContext(it->second.context, it->second.surface);
3614 
3615     m_platformEglContexts.erase(it);
3616 
3617     return true;
3618 }
3619 
flushColorBufferFromGl(HandleType colorBufferHandle)3620 bool FrameBuffer::flushColorBufferFromGl(HandleType colorBufferHandle) {
3621     auto colorBuffer = findColorBuffer(colorBufferHandle);
3622     if (!colorBuffer) {
3623         ERR("%s: Failed to find ColorBuffer:%d", __func__, colorBufferHandle);
3624         return false;
3625     }
3626     return colorBuffer->flushFromGl();
3627 }
3628 
invalidateColorBufferForGl(HandleType colorBufferHandle)3629 bool FrameBuffer::invalidateColorBufferForGl(HandleType colorBufferHandle) {
3630     auto colorBuffer = findColorBuffer(colorBufferHandle);
3631     if (!colorBuffer) {
3632         VERBOSE("%s: Failed to find ColorBuffer:%d", __func__, colorBufferHandle);
3633         return false;
3634     }
3635     return colorBuffer->invalidateForGl();
3636 }
3637 
getPbufferSurfaceContextHelper() const3638 ContextHelper* FrameBuffer::getPbufferSurfaceContextHelper() const {
3639     if (!m_emulationGl) {
3640         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3641     }
3642     if (!m_emulationGl->mPbufferSurface) {
3643         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
3644             << "EGL emulation pbuffer surface not available.";
3645     }
3646     const auto* displaySurfaceGl =
3647         reinterpret_cast<const DisplaySurfaceGl*>(m_emulationGl->mPbufferSurface->getImpl());
3648 
3649     return displaySurfaceGl->getContextHelper();
3650 }
3651 
bindColorBufferToTexture(HandleType p_colorbuffer)3652 bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) {
3653     AutoLock mutex(m_lock);
3654 
3655     ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
3656     if (!colorBuffer) {
3657         // bad colorbuffer handle
3658         return false;
3659     }
3660 
3661     return colorBuffer->glOpBindToTexture();
3662 }
3663 
bindColorBufferToTexture2(HandleType p_colorbuffer)3664 bool FrameBuffer::bindColorBufferToTexture2(HandleType p_colorbuffer) {
3665     // This is only called when using multi window display
3666     // It will deadlock when posting from main thread.
3667     std::unique_ptr<AutoLock> mutex;
3668     if (!postOnlyOnMainThread()) {
3669         mutex = std::make_unique<AutoLock>(m_lock);
3670     }
3671 
3672     ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
3673     if (!colorBuffer) {
3674         // bad colorbuffer handle
3675         return false;
3676     }
3677 
3678     return colorBuffer->glOpBindToTexture2();
3679 }
3680 
bindColorBufferToRenderbuffer(HandleType p_colorbuffer)3681 bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) {
3682     AutoLock mutex(m_lock);
3683 
3684     ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
3685     if (!colorBuffer) {
3686         // bad colorbuffer handle
3687         return false;
3688     }
3689 
3690     return colorBuffer->glOpBindToRenderbuffer();
3691 }
3692 
bindContext(HandleType p_context,HandleType p_drawSurface,HandleType p_readSurface)3693 bool FrameBuffer::bindContext(HandleType p_context, HandleType p_drawSurface,
3694                               HandleType p_readSurface) {
3695     if (m_shuttingDown) {
3696         return false;
3697     }
3698 
3699     AutoLock mutex(m_lock);
3700 
3701     EmulatedEglWindowSurfacePtr draw, read;
3702     EmulatedEglContextPtr ctx;
3703 
3704     //
3705     // if this is not an unbind operation - make sure all handles are good
3706     //
3707     if (p_context || p_drawSurface || p_readSurface) {
3708         ctx = getContext_locked(p_context);
3709         if (!ctx) return false;
3710         auto drawWindowIt = m_windows.find(p_drawSurface);
3711         if (drawWindowIt == m_windows.end()) {
3712             // bad surface handle
3713             return false;
3714         }
3715         draw = (*drawWindowIt).second.first;
3716 
3717         if (p_readSurface != p_drawSurface) {
3718             auto readWindowIt = m_windows.find(p_readSurface);
3719             if (readWindowIt == m_windows.end()) {
3720                 // bad surface handle
3721                 return false;
3722             }
3723             read = (*readWindowIt).second.first;
3724         } else {
3725             read = draw;
3726         }
3727     } else {
3728         // if unbind operation, sweep color buffers
3729         sweepColorBuffersLocked();
3730     }
3731 
3732     if (!s_egl.eglMakeCurrent(getDisplay(), draw ? draw->getEGLSurface() : EGL_NO_SURFACE,
3733                               read ? read->getEGLSurface() : EGL_NO_SURFACE,
3734                               ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT)) {
3735         ERR("eglMakeCurrent failed");
3736         return false;
3737     }
3738 
3739     //
3740     // Bind the surface(s) to the context
3741     //
3742     RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
3743     if (!tinfo) {
3744         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
3745     }
3746 
3747     EmulatedEglWindowSurfacePtr bindDraw, bindRead;
3748     if (draw.get() == NULL && read.get() == NULL) {
3749         // Unbind the current read and draw surfaces from the context
3750         bindDraw = tinfo->currDrawSurf;
3751         bindRead = tinfo->currReadSurf;
3752     } else {
3753         bindDraw = draw;
3754         bindRead = read;
3755     }
3756 
3757     if (bindDraw.get() != NULL && bindRead.get() != NULL) {
3758         if (bindDraw.get() != bindRead.get()) {
3759             bindDraw->bind(ctx, EmulatedEglWindowSurface::BIND_DRAW);
3760             bindRead->bind(ctx, EmulatedEglWindowSurface::BIND_READ);
3761         } else {
3762             bindDraw->bind(ctx, EmulatedEglWindowSurface::BIND_READDRAW);
3763         }
3764     }
3765 
3766     //
3767     // update thread info with current bound context
3768     //
3769     tinfo->currContext = ctx;
3770     tinfo->currDrawSurf = draw;
3771     tinfo->currReadSurf = read;
3772     if (ctx) {
3773         if (ctx->clientVersion() > GLESApi_CM)
3774             tinfo->m_gl2Dec.setContextData(&ctx->decoderContextData());
3775         else
3776             tinfo->m_glDec.setContextData(&ctx->decoderContextData());
3777     } else {
3778         tinfo->m_glDec.setContextData(NULL);
3779         tinfo->m_gl2Dec.setContextData(NULL);
3780     }
3781     return true;
3782 }
3783 
createYUVTextures(uint32_t type,uint32_t count,int width,int height,uint32_t * output)3784 void FrameBuffer::createYUVTextures(uint32_t type, uint32_t count, int width, int height,
3785                                     uint32_t* output) {
3786     FrameworkFormat format = static_cast<FrameworkFormat>(type);
3787     AutoLock mutex(m_lock);
3788     RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
3789     for (uint32_t i = 0; i < count; ++i) {
3790         if (format == FRAMEWORK_FORMAT_NV12) {
3791             YUVConverter::createYUVGLTex(GL_TEXTURE0, width, height, format, m_features.Yuv420888ToNv21.enabled,
3792                                          YUVPlane::Y, &output[2 * i]);
3793             YUVConverter::createYUVGLTex(GL_TEXTURE1, width / 2, height / 2, format, m_features.Yuv420888ToNv21.enabled, YUVPlane::UV,
3794                                          &output[2 * i + 1]);
3795         } else if (format == FRAMEWORK_FORMAT_YUV_420_888) {
3796             YUVConverter::createYUVGLTex(GL_TEXTURE0, width, height, format, m_features.Yuv420888ToNv21.enabled, YUVPlane::Y,
3797                                          &output[3 * i]);
3798             YUVConverter::createYUVGLTex(GL_TEXTURE1, width / 2, height / 2, format, m_features.Yuv420888ToNv21.enabled, YUVPlane::U,
3799                                          &output[3 * i + 1]);
3800             YUVConverter::createYUVGLTex(GL_TEXTURE2, width / 2, height / 2, format, m_features.Yuv420888ToNv21.enabled, YUVPlane::V,
3801                                          &output[3 * i + 2]);
3802         }
3803     }
3804 }
3805 
destroyYUVTextures(uint32_t type,uint32_t count,uint32_t * textures)3806 void FrameBuffer::destroyYUVTextures(uint32_t type, uint32_t count, uint32_t* textures) {
3807     AutoLock mutex(m_lock);
3808     RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
3809     if (type == FRAMEWORK_FORMAT_NV12) {
3810         s_gles2.glDeleteTextures(2 * count, textures);
3811     } else if (type == FRAMEWORK_FORMAT_YUV_420_888) {
3812         s_gles2.glDeleteTextures(3 * count, textures);
3813     }
3814 }
3815 
updateYUVTextures(uint32_t type,uint32_t * textures,void * privData,void * func)3816 void FrameBuffer::updateYUVTextures(uint32_t type, uint32_t* textures, void* privData, void* func) {
3817     AutoLock mutex(m_lock);
3818     RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
3819 
3820     yuv_updater_t updater = (yuv_updater_t)func;
3821     uint32_t gtextures[3] = {0, 0, 0};
3822 
3823     if (type == FRAMEWORK_FORMAT_NV12) {
3824         gtextures[0] = s_gles2.glGetGlobalTexName(textures[0]);
3825         gtextures[1] = s_gles2.glGetGlobalTexName(textures[1]);
3826     } else if (type == FRAMEWORK_FORMAT_YUV_420_888) {
3827         gtextures[0] = s_gles2.glGetGlobalTexName(textures[0]);
3828         gtextures[1] = s_gles2.glGetGlobalTexName(textures[1]);
3829         gtextures[2] = s_gles2.glGetGlobalTexName(textures[2]);
3830     }
3831 
3832 #ifdef __APPLE__
3833     EGLContext prevContext = s_egl.eglGetCurrentContext();
3834     auto mydisp = EglGlobalInfo::getInstance()->getDisplayFromDisplayType(EGL_DEFAULT_DISPLAY);
3835     void* nativecontext = mydisp->getLowLevelContext(prevContext);
3836     struct MediaNativeCallerData callerdata;
3837     callerdata.ctx = nativecontext;
3838     callerdata.converter = nsConvertVideoFrameToNV12Textures;
3839     void* pcallerdata = &callerdata;
3840 #else
3841     void* pcallerdata = nullptr;
3842 #endif
3843 
3844     updater(privData, type, gtextures, pcallerdata);
3845 }
3846 
swapTexturesAndUpdateColorBuffer(uint32_t p_colorbuffer,int x,int y,int width,int height,uint32_t format,uint32_t type,uint32_t texture_type,uint32_t * textures)3847 void FrameBuffer::swapTexturesAndUpdateColorBuffer(uint32_t p_colorbuffer, int x, int y, int width,
3848                                                    int height, uint32_t format, uint32_t type,
3849                                                    uint32_t texture_type, uint32_t* textures) {
3850     {
3851         AutoLock mutex(m_lock);
3852         ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
3853         if (!colorBuffer) {
3854             // bad colorbuffer handle
3855             return;
3856         }
3857         colorBuffer->glOpSwapYuvTexturesAndUpdate(
3858             format, type, static_cast<FrameworkFormat>(texture_type), textures);
3859     }
3860 }
3861 
readColorBufferContents(HandleType p_colorbuffer,size_t * numBytes,void * pixels)3862 bool FrameBuffer::readColorBufferContents(HandleType p_colorbuffer, size_t* numBytes,
3863                                           void* pixels) {
3864     AutoLock mutex(m_lock);
3865 
3866     ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
3867     if (!colorBuffer) {
3868         // bad colorbuffer handle
3869         return false;
3870     }
3871 
3872     return colorBuffer->glOpReadContents(numBytes, pixels);
3873 }
3874 
asyncWaitForGpuWithCb(uint64_t eglsync,FenceCompletionCallback cb)3875 void FrameBuffer::asyncWaitForGpuWithCb(uint64_t eglsync, FenceCompletionCallback cb) {
3876     EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(eglsync);
3877 
3878     if (!fenceSync) {
3879         ERR("err: fence sync 0x%llx not found", (unsigned long long)eglsync);
3880         return;
3881     }
3882 
3883     SyncThread::get()->triggerWaitWithCompletionCallback(fenceSync, std::move(cb));
3884 }
3885 
getGles2Dispatch()3886 const gl::GLESv2Dispatch* FrameBuffer::getGles2Dispatch() {
3887     if (!m_emulationGl) {
3888         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3889     }
3890 
3891     return m_emulationGl->getGles2Dispatch();
3892 }
3893 
getEglDispatch()3894 const gl::EGLDispatch* FrameBuffer::getEglDispatch() {
3895     if (!m_emulationGl) {
3896         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
3897     }
3898 
3899     return m_emulationGl->getEglDispatch();
3900 }
3901 
3902 #endif
3903 
3904 }  // namespace gfxstream
3905