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