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(×tamp);
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