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