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