• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "opengles.h"
16 
17 #include "base/GLObjectCounter.h"
18 #include "base/PathUtils.h"
19 #include "base/Stream.h"
20 #include "base/MemoryTracker.h"
21 #include "base/SharedLibrary.h"
22 #include "base/System.h"
23 #include "host-common/address_space_device.h"
24 #include "host-common/address_space_graphics.h"
25 #include "host-common/address_space_graphics_types.h"
26 #include "host-common/GoldfishDma.h"
27 #include "host-common/RefcountPipe.h"
28 #include "host-common/FeatureControl.h"
29 #include "host-common/globals.h"
30 #include "host-common/opengl/emugl_config.h"
31 #include "host-common/opengl/GLProcessPipe.h"
32 #include "host-common/opengl/logger.h"
33 #include "host-common/opengl/gpuinfo.h"
34 
35 #include "../stream-servers/render_api_functions.h"
36 #include "../stream-servers/OpenGLESDispatch/EGLDispatch.h"
37 #include "../stream-servers/OpenGLESDispatch/GLESv2Dispatch.h"
38 
39 #include <assert.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 
43 #define D(...)
44 #define DD(...)
45 #define E(...)
46 
47 // #define D(...) do { \
48 //     VERBOSE_PRINT(init,__VA_ARGS__); \
49 //     android_opengl_logger_write(__VA_ARGS__); \
50 // } while(0);
51 //
52 // #define DD(...) do { \
53 //     VERBOSE_PRINT(gles,__VA_ARGS__); \
54 //     android_opengl_logger_write(__VA_ARGS__); \
55 // } while(0);
56 //
57 // #define E(fmt,...) do { \
58 //     derror(fmt, ##__VA_ARGS__); \
59 //     android_opengl_logger_write(fmt "\n", ##__VA_ARGS__); \
60 // } while(0);
61 
62 using android::base::pj;
63 using android::base::SharedLibrary;
64 using android::emulation::asg::AddressSpaceGraphicsContext;
65 using android::emulation::asg::ConsumerInterface;
66 using android::emulation::asg::ConsumerCallbacks;
67 
68 /* Name of the GLES rendering library we're going to use */
69 #define RENDERER_LIB_NAME "libOpenglRender"
70 
71 /* Declared in "android/globals.h" */
72 int  android_gles_fast_pipes = 1;
73 
74 // Define the Render API function pointers.
75 #define FUNCTION_(ret, name, sig, params) \
76         inline ret (*name) sig = NULL;
77 LIST_RENDER_API_FUNCTIONS(FUNCTION_)
78 #undef FUNCTION_
79 
80 static bool sOpenglLoggerInitialized = false;
81 static bool sRendererUsesSubWindow = false;
82 static bool sEgl2egl = false;
83 static emugl::RenderLib* sRenderLib = nullptr;
84 static emugl::RendererPtr sRenderer = nullptr;
85 
86 static const EGLDispatch* sEgl = nullptr;
87 static const GLESv2Dispatch* sGlesv2 = nullptr;
88 
android_prepareOpenglesEmulation()89 int android_prepareOpenglesEmulation() {
90     android_init_opengl_logger();
91 
92     bool glFineLogging = android::base::getEnvironmentVariable("ANDROID_EMUGL_FINE_LOG") == "1";
93     bool glLogPrinting = android::base::getEnvironmentVariable("ANDROID_EMUGL_LOG_PRINT") == "1";
94 
95     AndroidOpenglLoggerFlags loggerFlags =
96         static_cast<AndroidOpenglLoggerFlags>(
97         (glFineLogging ? OPENGL_LOGGER_DO_FINE_LOGGING : 0) |
98         (glLogPrinting ? OPENGL_LOGGER_PRINT_TO_STDOUT : 0));
99 
100     android_opengl_logger_set_flags(loggerFlags);
101 
102     sOpenglLoggerInitialized = true;
103     sRendererUsesSubWindow = true;
104 
105     sEgl2egl = false;
106     if (android::base::getEnvironmentVariable("ANDROID_EGL_ON_EGL") == "1") {
107         sEgl2egl = true;
108     }
109 
110     return 0;
111 }
112 //
113 //     char* error = NULL;
114 //
115 //     if (sRenderLib != NULL)
116 //         return 0;
117 //
118 //     D("Initializing hardware OpenGLES emulation support");
119 //
120 //     SharedLibrary* rendererSo =
121 //         SharedLibrary::open(RENDERER_LIB_NAME);
122 //     if (rendererSo == NULL) {
123 //         E("Could not load OpenGLES emulation library [%s]: %s",
124 //                RENDERER_LIB_NAME, error);
125 //
126 //         E("Retrying in program directory/lib64...");
127 //
128 //         auto progDir = System::get()->getProgramDirectory();
129 //
130 //         auto retryLibPath =
131 //             pj(progDir, "lib64", RENDERER_LIB_NAME);
132 //
133 //         rendererSo = adynamicLibrary_open(retryLibPath.c_str(), &error);
134 //
135 //         if (rendererSo == nullptr) {
136 //             E("Could not load OpenGLES emulation library [%s]: %s (2nd try)",
137 //                    retryLibPath.c_str(), error);
138 //             return -1;
139 //         }
140 //     }
141 //
142 //     /* Resolve the functions */
143 //     if (initOpenglesEmulationFuncs(rendererSo) < 0) {
144 //         E("OpenGLES emulation library mismatch. Be sure to use the correct version!");
145 //         crashhandler_append_message_format(
146 //             "OpenGLES emulation library mismatch. Be sure to use the correct version!");
147 //         goto BAD_EXIT;
148 //     }
149 //
150 //     sRenderLib = initLibrary();
151 //     if (!sRenderLib) {
152 //         E("OpenGLES initialization failed!");
153 //         crashhandler_append_message_format("OpenGLES initialization failed!");
154 //         goto BAD_EXIT;
155 //     }
156 //
157 //     sRendererUsesSubWindow = true;
158 //     if (const char* env = getenv("ANDROID_GL_SOFTWARE_RENDERER")) {
159 //         if (env[0] != '\0' && env[0] != '0') {
160 //             sRendererUsesSubWindow = false;
161 //         }
162 //     }
163 //
164 //     sEgl2egl = false;
165 //     if (const char* env = getenv("ANDROID_EGL_ON_EGL")) {
166 //         if (env[0] != '\0' && env[0] == '1') {
167 //             sEgl2egl = true;
168 //         }
169 //     }
170 //
171 //     sEgl = (const EGLDispatch *)sRenderLib->getEGLDispatch();
172 //     sGlesv2 = (const GLESv2Dispatch *)sRenderLib->getGLESv2Dispatch();
173 //
174 //     return 0;
175 //
176 // BAD_EXIT:
177 //     E("OpenGLES emulation library could not be initialized!");
178 //     adynamicLibrary_close(rendererSo);
179 //     return -1;
180 //
181 
android_setOpenglesEmulation(void * renderLib,void * eglDispatch,void * glesv2Dispatch)182 int android_setOpenglesEmulation(void* renderLib, void* eglDispatch, void* glesv2Dispatch) {
183     sRenderLib = (emugl::RenderLib*)renderLib;
184     sEgl = (EGLDispatch*)eglDispatch;
185     sGlesv2 = (GLESv2Dispatch*)glesv2Dispatch;
186     sEgl2egl = false;
187     if (android::base::getEnvironmentVariable("ANDROID_EGL_ON_EGL") == "1") {
188         sEgl2egl = true;
189     }
190     return 0;
191 }
192 
android_initOpenglesEmulation()193 int android_initOpenglesEmulation() {
194     fprintf(stderr, "%s: Not meant to call android_initOpenglesEmulation in the new build\n", __func__);
195     abort();
196 }
197 
198 int
android_startOpenglesRenderer(int width,int height,bool guestPhoneApi,int guestApiLevel,const QAndroidVmOperations * vm_operations,const QAndroidEmulatorWindowAgent * window_agent,const QAndroidMultiDisplayAgent * multi_display_agent,int * glesMajorVersion_out,int * glesMinorVersion_out)199 android_startOpenglesRenderer(int width, int height, bool guestPhoneApi, int guestApiLevel,
200                               const QAndroidVmOperations *vm_operations,
201                               const QAndroidEmulatorWindowAgent *window_agent,
202                               const QAndroidMultiDisplayAgent *multi_display_agent,
203                               int* glesMajorVersion_out,
204                               int* glesMinorVersion_out)
205 {
206     if (!sRenderLib) {
207         D("Can't start OpenGLES renderer without support libraries");
208         return -1;
209     }
210 
211     if (!sEgl) {
212         D("Can't start OpenGLES renderer without EGL libraries");
213         return -1;
214     }
215 
216     if (!sGlesv2) {
217         D("Can't start OpenGLES renderer without GLES libraries");
218         return -1;
219     }
220 
221     if (sRenderer) {
222         return 0;
223     }
224 
225     const GpuInfoList& gpuList = globalGpuInfoList();
226     std::string gpuInfoAsString = gpuList.dump();
227     android_opengl_logger_write("%s: gpu info", __func__);
228     android_opengl_logger_write("%s", gpuInfoAsString.c_str());
229 
230     sRenderLib->setRenderer(emuglConfig_get_current_renderer());
231     sRenderLib->setAvdInfo(guestPhoneApi, guestApiLevel);
232     // sRenderLib->setCrashReporter(&crashhandler_die_format);
233     // sRenderLib->setFeatureController(&android::featurecontrol::isEnabled);
234     sRenderLib->setSyncDevice(goldfish_sync_create_timeline,
235             goldfish_sync_create_fence,
236             goldfish_sync_timeline_inc,
237             goldfish_sync_destroy_timeline,
238             goldfish_sync_register_trigger_wait,
239             goldfish_sync_device_exists);
240 
241     emugl_logger_struct logfuncs;
242     logfuncs.coarse = android_opengl_logger_write;
243     logfuncs.fine = android_opengl_cxt_logger_write;
244     sRenderLib->setLogger(logfuncs);
245     sRenderLib->setGLObjectCounter(android::base::GLObjectCounter::get());
246     emugl_dma_ops dma_ops;
247     dma_ops.get_host_addr = android_goldfish_dma_ops.get_host_addr;
248     dma_ops.unlock = android_goldfish_dma_ops.unlock;
249     sRenderLib->setDmaOps(dma_ops);
250     sRenderLib->setVmOps(*vm_operations);
251     sRenderLib->setAddressSpaceDeviceControlOps(get_address_space_device_control_ops());
252     sRenderLib->setWindowOps(*window_agent, *multi_display_agent);
253     // sRenderLib->setUsageTracker(android::base::CpuUsage::get(),
254     //                             android::base::MemoryTracker::get());
255 
256     sRenderer = sRenderLib->initRenderer(width, height, sRendererUsesSubWindow, sEgl2egl);
257 
258     // android::snapshot::Snapshotter::get().addOperationCallback(
259     //         [](android::snapshot::Snapshotter::Operation op,
260     //            android::snapshot::Snapshotter::Stage stage) {
261     //             sRenderer->snapshotOperationCallback(op, stage);
262     //         });
263 
264     android::emulation::registerOnLastRefCallback(
265             sRenderLib->getOnLastColorBufferRef());
266 
267     ConsumerInterface iface = {
268         // create
269         [](struct asg_context context,
270            android::base::Stream* loadStream,
271            ConsumerCallbacks callbacks) {
272            return sRenderer->addressSpaceGraphicsConsumerCreate(
273                context, loadStream, callbacks);
274         },
275         // destroy
276         [](void* consumer) {
277            sRenderer->addressSpaceGraphicsConsumerDestroy(consumer);
278         },
279         // pre save
280         [](void* consumer) {
281            sRenderer->addressSpaceGraphicsConsumerPreSave(consumer);
282         },
283         // global presave
284         []() {
285            sRenderer->pauseAllPreSave();
286         },
287         // save
288         [](void* consumer, android::base::Stream* stream) {
289            sRenderer->addressSpaceGraphicsConsumerSave(consumer, stream);
290         },
291         // global postsave
292         []() {
293            sRenderer->resumeAll();
294         },
295         // postSave
296         [](void* consumer) {
297            sRenderer->addressSpaceGraphicsConsumerPostSave(consumer);
298         },
299         // postLoad
300         [](void* consumer) {
301            sRenderer->addressSpaceGraphicsConsumerRegisterPostLoadRenderThread(consumer);
302         },
303         // global preload
304         []() {
305             // This wants to address that when using asg, pipe wants to clean
306             // up all render threads and wait for gl objects, but framebuffer
307             // notices that there is a render thread info that is still not
308             // cleaned up because these render threads come from asg.
309             android::opengl::forEachProcessPipeIdRunAndErase([](uint64_t id) {
310                 android_cleanupProcGLObjects(id);
311             });
312             android_waitForOpenglesProcessCleanup();
313         },
314     };
315     AddressSpaceGraphicsContext::setConsumer(iface);
316 
317     if (!sRenderer) {
318         D("Can't start OpenGLES renderer?");
319         return -1;
320     }
321 
322     // after initRenderer is a success, the maximum GLES API is calculated depending
323     // on feature control and host GPU support. Set the obtained GLES version here.
324     if (glesMajorVersion_out && glesMinorVersion_out)
325         sRenderLib->getGlesVersion(glesMajorVersion_out, glesMinorVersion_out);
326     return 0;
327 }
328 
329 bool
android_asyncReadbackSupported()330 android_asyncReadbackSupported() {
331     if (sRenderer) {
332         return sRenderer->asyncReadbackSupported();
333     } else {
334         D("tried to query async readback support "
335           "before renderer initialized. Likely guest rendering");
336         return false;
337     }
338 }
339 
340 void
android_setPostCallback(OnPostFunc onPost,void * onPostContext,bool useBgraReadback,uint32_t displayId)341 android_setPostCallback(OnPostFunc onPost, void* onPostContext, bool useBgraReadback, uint32_t displayId)
342 {
343     if (sRenderer) {
344         sRenderer->setPostCallback(onPost, onPostContext, useBgraReadback, displayId);
345     }
346 }
347 
android_getReadPixelsFunc()348 ReadPixelsFunc android_getReadPixelsFunc() {
349     if (sRenderer) {
350         return sRenderer->getReadPixelsCallback();
351     } else {
352         return nullptr;
353     }
354 }
355 
android_getFlushReadPixelPipeline()356 FlushReadPixelPipeline android_getFlushReadPixelPipeline() {
357     if (sRenderer) {
358         return sRenderer->getFlushReadPixelPipeline();
359     } else {
360         return nullptr;
361     }
362 }
363 
364 
strdupBaseString(const char * src)365 static char* strdupBaseString(const char* src) {
366     const char* begin = strchr(src, '(');
367     if (!begin) {
368         return strdup(src);
369     }
370 
371     const char* end = strrchr(begin + 1, ')');
372     if (!end) {
373         return strdup(src);
374     }
375 
376     // src is of the form:
377     // "foo (barzzzzzzzzzz)"
378     //       ^            ^
379     //       (b+1)        e
380     //     = 5            18
381     int len;
382     begin += 1;
383     len = end - begin;
384 
385     char* result;
386     result = (char*)malloc(len + 1);
387     memcpy(result, begin, len);
388     result[len] = '\0';
389     return result;
390 }
391 
android_getOpenglesHardwareStrings(char ** vendor,char ** renderer,char ** version)392 void android_getOpenglesHardwareStrings(char** vendor,
393                                         char** renderer,
394                                         char** version) {
395     assert(vendor != NULL && renderer != NULL && version != NULL);
396     assert(*vendor == NULL && *renderer == NULL && *version == NULL);
397     if (!sRenderer) {
398         D("Can't get OpenGL ES hardware strings when renderer not started");
399         return;
400     }
401 
402     const emugl::Renderer::HardwareStrings strings =
403             sRenderer->getHardwareStrings();
404     D("OpenGL Vendor=[%s]", strings.vendor.c_str());
405     D("OpenGL Renderer=[%s]", strings.renderer.c_str());
406     D("OpenGL Version=[%s]", strings.version.c_str());
407 
408     /* Special case for the default ES to GL translators: extract the strings
409      * of the underlying OpenGL implementation. */
410     if (strncmp(strings.vendor.c_str(), "Google", 6) == 0 &&
411             strncmp(strings.renderer.c_str(), "Android Emulator OpenGL ES Translator", 37) == 0) {
412         *vendor = strdupBaseString(strings.vendor.c_str());
413         *renderer = strdupBaseString(strings.renderer.c_str());
414         *version = strdupBaseString(strings.version.c_str());
415     } else {
416         *vendor = strdup(strings.vendor.c_str());
417         *renderer = strdup(strings.renderer.c_str());
418         *version = strdup(strings.version.c_str());
419     }
420 }
421 
android_getOpenglesVersion(int * maj,int * min)422 void android_getOpenglesVersion(int* maj, int* min) {
423     sRenderLib->getGlesVersion(maj, min);
424     fprintf(stderr, "%s: maj min %d %d\n", __func__, *maj, *min);
425 }
426 
427 void
android_stopOpenglesRenderer(bool wait)428 android_stopOpenglesRenderer(bool wait)
429 {
430     if (sRenderer) {
431         sRenderer->stop(wait);
432         if (wait) {
433             sRenderer.reset();
434             android_stop_opengl_logger();
435         }
436     }
437 }
438 
439 void
android_finishOpenglesRenderer()440 android_finishOpenglesRenderer()
441 {
442     if (sRenderer) {
443         sRenderer->finish();
444     }
445 }
446 
447 static emugl::RenderOpt sOpt;
448 static int sWidth, sHeight;
449 static int sNewWidth, sNewHeight;
450 
android_showOpenglesWindow(void * window,int wx,int wy,int ww,int wh,int fbw,int fbh,float dpr,float rotation,bool deleteExisting,bool hideWindow)451 int android_showOpenglesWindow(void* window,
452                                int wx,
453                                int wy,
454                                int ww,
455                                int wh,
456                                int fbw,
457                                int fbh,
458                                float dpr,
459                                float rotation,
460                                bool deleteExisting,
461                                bool hideWindow) {
462     if (!sRenderer) {
463         return -1;
464     }
465     FBNativeWindowType win = (FBNativeWindowType)(uintptr_t)window;
466     bool success = sRenderer->showOpenGLSubwindow(win, wx, wy, ww, wh, fbw, fbh,
467                                                   dpr, rotation, deleteExisting,
468                                                   hideWindow);
469     sNewWidth = ww * dpr;
470     sNewHeight = wh * dpr;
471     return success ? 0 : -1;
472 }
473 
474 void
android_setOpenglesTranslation(float px,float py)475 android_setOpenglesTranslation(float px, float py)
476 {
477     if (sRenderer) {
478         sRenderer->setOpenGLDisplayTranslation(px, py);
479     }
480 }
481 
482 void
android_setOpenglesScreenMask(int width,int height,const unsigned char * rgbaData)483 android_setOpenglesScreenMask(int width, int height, const unsigned char* rgbaData)
484 {
485     if (sRenderer) {
486         sRenderer->setScreenMask(width, height, rgbaData);
487     }
488 }
489 
490 int
android_hideOpenglesWindow(void)491 android_hideOpenglesWindow(void)
492 {
493     if (!sRenderer) {
494         return -1;
495     }
496     bool success = sRenderer->destroyOpenGLSubwindow();
497     return success ? 0 : -1;
498 }
499 
500 void
android_redrawOpenglesWindow(void)501 android_redrawOpenglesWindow(void)
502 {
503     if (sRenderer) {
504         sRenderer->repaintOpenGLDisplay();
505     }
506 }
507 
508 bool
android_hasGuestPostedAFrame(void)509 android_hasGuestPostedAFrame(void)
510 {
511     if (sRenderer) {
512         return sRenderer->hasGuestPostedAFrame();
513     }
514     return false;
515 }
516 
517 void
android_resetGuestPostedAFrame(void)518 android_resetGuestPostedAFrame(void)
519 {
520     if (sRenderer) {
521         sRenderer->resetGuestPostedAFrame();
522     }
523 }
524 
525 static ScreenshotFunc sScreenshotFunc = nullptr;
526 
android_registerScreenshotFunc(ScreenshotFunc f)527 void android_registerScreenshotFunc(ScreenshotFunc f)
528 {
529     sScreenshotFunc = f;
530 }
531 
android_screenShot(const char * dirname,uint32_t displayId)532 bool android_screenShot(const char* dirname, uint32_t displayId)
533 {
534     if (sScreenshotFunc) {
535         return sScreenshotFunc(dirname, displayId);
536     }
537     return false;
538 }
539 
android_getOpenglesRenderer()540 const emugl::RendererPtr& android_getOpenglesRenderer() {
541     return sRenderer;
542 }
543 
android_cleanupProcGLObjects(uint64_t puid)544 void android_cleanupProcGLObjects(uint64_t puid) {
545     if (sRenderer) {
546         sRenderer->cleanupProcGLObjects(puid);
547     }
548 }
549 
android_cleanupProcGLObjectsAndWaitFinished(uint64_t puid)550 void android_cleanupProcGLObjectsAndWaitFinished(uint64_t puid) {
551     if (sRenderer) {
552         sRenderer->cleanupProcGLObjects(puid);
553     }
554 }
555 
android_waitForOpenglesProcessCleanup()556 void android_waitForOpenglesProcessCleanup() {
557     if (sRenderer) {
558         sRenderer->waitForProcessCleanup();
559     }
560 }
561 
562 static void* sContext, * sRenderContext, * sSurface;
563 static EGLint s_gles_attr[5];
564 
565 extern void tinyepoxy_init(const GLESv2Dispatch* gles, int version);
566 
567 // static bool prepare_epoxy(void) {
568 //     if (!sRenderLib->getOpt(&sOpt)) {
569 //         return false;
570 //     }
571 //     int major, minor;
572 //     sRenderLib->getGlesVersion(&major, &minor);
573 //     EGLint attr[] = {
574 //         EGL_CONTEXT_CLIENT_VERSION, major,
575 //         EGL_CONTEXT_MINOR_VERSION_KHR, minor,
576 //         EGL_NONE
577 //     };
578 //     sContext = sEgl->eglCreateContext(sOpt.display, sOpt.config, EGL_NO_CONTEXT,
579 //                                       attr);
580 //     if (sContext == nullptr) {
581 //         return false;
582 //     }
583 //     sRenderContext = sEgl->eglCreateContext(sOpt.display, sOpt.config,
584 //                                             sContext, attr);
585 //     if (sRenderContext == nullptr) {
586 //         return false;
587 //     }
588 //     static constexpr EGLint surface_attr[] = {
589 //         EGL_WIDTH, 1,
590 //         EGL_HEIGHT, 1,
591 //         EGL_NONE
592 //     };
593 //     sSurface = sEgl->eglCreatePbufferSurface(sOpt.display, sOpt.config,
594 //                                              surface_attr);
595 //     if (sSurface == EGL_NO_SURFACE) {
596 //         return false;
597 //     }
598 //     static_assert(sizeof(attr) == sizeof(s_gles_attr), "Mismatch");
599 //     memcpy(s_gles_attr, attr, sizeof(s_gles_attr));
600 //     tinyepoxy_init(sGlesv2, major * 10 + minor);
601 //     return true;
602 // }
603 
604 struct DisplayChangeListener;
605 struct QEMUGLParams;
606 
android_gl_create_context(DisplayChangeListener * unuse1,QEMUGLParams * unuse2)607 void * android_gl_create_context(DisplayChangeListener * unuse1,
608                                  QEMUGLParams* unuse2) {
609     // static bool ok =  prepare_epoxy();
610     // if (!ok) {
611     //     return nullptr;
612     // }
613     sEgl->eglMakeCurrent(sOpt.display, sSurface, sSurface, sContext);
614     return sEgl->eglCreateContext(sOpt.display, sOpt.config, sContext, s_gles_attr);
615 }
616 
android_gl_destroy_context(DisplayChangeListener * unused,void * ctx)617 void android_gl_destroy_context(DisplayChangeListener* unused, void * ctx) {
618     sEgl->eglDestroyContext(sOpt.display, ctx);
619 }
620 
android_gl_make_context_current(DisplayChangeListener * unused,void * ctx)621 int android_gl_make_context_current(DisplayChangeListener* unused, void * ctx) {
622     return sEgl->eglMakeCurrent(sOpt.display, sSurface, sSurface, ctx);
623 }
624 
625 static GLuint s_tex_id, s_fbo_id;
626 static uint32_t s_gfx_h, s_gfx_w;
627 static bool s_y0_top;
628 
629 // ui/gtk-egl.c:gd_egl_scanout_texture as reference.
android_gl_scanout_texture(DisplayChangeListener * unuse,uint32_t backing_id,bool backing_y_0_top,uint32_t backing_width,uint32_t backing_height,uint32_t x,uint32_t y,uint32_t w,uint32_t h)630 void android_gl_scanout_texture(DisplayChangeListener* unuse,
631                                 uint32_t backing_id,
632                                 bool backing_y_0_top,
633                                 uint32_t backing_width,
634                                 uint32_t backing_height,
635                                 uint32_t x, uint32_t y,
636                                 uint32_t w, uint32_t h) {
637     s_tex_id = backing_id;
638     s_gfx_h = h;
639     s_gfx_w = w;
640     s_y0_top = backing_y_0_top;
641     if (sNewWidth != sWidth || sNewHeight != sHeight) {
642         sRenderLib->getOpt(&sOpt);
643         sWidth = sNewWidth;
644         sHeight = sNewHeight;
645     }
646     sEgl->eglMakeCurrent(sOpt.display, sOpt.surface, sOpt.surface,
647                          sRenderContext);
648     if (!s_fbo_id) {
649         sGlesv2->glGenFramebuffers(1, &s_fbo_id);
650     }
651     sGlesv2->glBindFramebuffer(GL_FRAMEBUFFER_EXT, s_fbo_id);
652     sGlesv2->glViewport(0, 0, h, w);
653     sGlesv2->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
654                                   GL_TEXTURE_2D, backing_id, 0);
655 }
656 
657 // ui/gtk-egl.c:gd_egl_scanout_flush as reference.
android_gl_scanout_flush(DisplayChangeListener * unuse,uint32_t x,uint32_t y,uint32_t w,uint32_t h)658 void android_gl_scanout_flush(DisplayChangeListener* unuse,
659                               uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
660     if (!s_fbo_id)  {
661         return;
662     }
663     sEgl->eglMakeCurrent(sOpt.display, sOpt.surface, sOpt.surface,
664                          sRenderContext);
665 
666     sGlesv2->glBindFramebuffer(GL_READ_FRAMEBUFFER, s_fbo_id);
667     sGlesv2->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
668 
669     int y1 = s_y0_top ? 0 : s_gfx_h;
670     int y2 = s_y0_top ? s_gfx_h : 0;
671 
672     sGlesv2->glViewport(0, 0, sWidth, sHeight);
673     sGlesv2->glBlitFramebuffer(0, y1, s_gfx_w, y2,
674                              0, 0, sWidth, sHeight,
675                              GL_COLOR_BUFFER_BIT, GL_NEAREST);
676     sEgl->eglSwapBuffers(sOpt.display, sOpt.surface);
677     sGlesv2->glBindFramebuffer(GL_FRAMEBUFFER_EXT, s_fbo_id);
678 }
679 
android_getVirtioGpuOps()680 struct AndroidVirtioGpuOps* android_getVirtioGpuOps() {
681     if (sRenderer) {
682         return sRenderer->getVirtioGpuOps();
683     }
684     return nullptr;
685 }
686 
android_getEGLDispatch()687 const void* android_getEGLDispatch() {
688     return sEgl;
689 }
690 
android_getGLESv2Dispatch()691 const void* android_getGLESv2Dispatch() {
692     return sGlesv2;
693 }
694