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