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