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