xref: /openbmc/qemu/ui/gtk-egl.c (revision 01782d6b294f95bcde334386f0aaac593cd28c0d)
197edf3bdSGerd Hoffmann /*
297edf3bdSGerd Hoffmann  * GTK UI -- egl opengl code.
397edf3bdSGerd Hoffmann  *
497edf3bdSGerd Hoffmann  * Note that gtk 3.16+ (released 2015-03-23) has a GtkGLArea widget,
597edf3bdSGerd Hoffmann  * which is GtkDrawingArea like widget with opengl rendering support.
697edf3bdSGerd Hoffmann  *
797edf3bdSGerd Hoffmann  * This code handles opengl support on older gtk versions, using egl
897edf3bdSGerd Hoffmann  * to get a opengl context for the X11 window.
997edf3bdSGerd Hoffmann  *
1097edf3bdSGerd Hoffmann  * This work is licensed under the terms of the GNU GPL, version 2 or later.
1197edf3bdSGerd Hoffmann  * See the COPYING file in the top-level directory.
1297edf3bdSGerd Hoffmann  */
1397edf3bdSGerd Hoffmann 
14e16f4c87SPeter Maydell #include "qemu/osdep.h"
1565b847d2SVivek Kasireddy #include "qemu/main-loop.h"
161d48c9fdSMarc-André Lureau #include "qemu/error-report.h"
1797edf3bdSGerd Hoffmann 
1897edf3bdSGerd Hoffmann #include "trace.h"
1997edf3bdSGerd Hoffmann 
2097edf3bdSGerd Hoffmann #include "ui/console.h"
2197edf3bdSGerd Hoffmann #include "ui/gtk.h"
2297edf3bdSGerd Hoffmann #include "ui/egl-helpers.h"
23f1bd3132SGerd Hoffmann #include "ui/shader.h"
2497edf3bdSGerd Hoffmann 
2597edf3bdSGerd Hoffmann #include "sysemu/sysemu.h"
2697edf3bdSGerd Hoffmann 
gtk_egl_set_scanout_mode(VirtualConsole * vc,bool scanout)274782aeb7SGerd Hoffmann static void gtk_egl_set_scanout_mode(VirtualConsole *vc, bool scanout)
284782aeb7SGerd Hoffmann {
294782aeb7SGerd Hoffmann     if (vc->gfx.scanout_mode == scanout) {
304782aeb7SGerd Hoffmann         return;
314782aeb7SGerd Hoffmann     }
324782aeb7SGerd Hoffmann 
334782aeb7SGerd Hoffmann     vc->gfx.scanout_mode = scanout;
344782aeb7SGerd Hoffmann     if (!vc->gfx.scanout_mode) {
3583b4b236SDongwon Kim         eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
3683b4b236SDongwon Kim                        vc->gfx.esurface, vc->gfx.ectx);
37a4f113fdSGerd Hoffmann         egl_fb_destroy(&vc->gfx.guest_fb);
384782aeb7SGerd Hoffmann         if (vc->gfx.surface) {
394782aeb7SGerd Hoffmann             surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
404782aeb7SGerd Hoffmann             surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds);
414782aeb7SGerd Hoffmann         }
424782aeb7SGerd Hoffmann     }
434782aeb7SGerd Hoffmann }
444782aeb7SGerd Hoffmann 
4597edf3bdSGerd Hoffmann /** DisplayState Callbacks (opengl version) **/
4697edf3bdSGerd Hoffmann 
gd_egl_init(VirtualConsole * vc)4797edf3bdSGerd Hoffmann void gd_egl_init(VirtualConsole *vc)
4897edf3bdSGerd Hoffmann {
4997edf3bdSGerd Hoffmann     GdkWindow *gdk_window = gtk_widget_get_window(vc->gfx.drawing_area);
5097edf3bdSGerd Hoffmann     if (!gdk_window) {
5197edf3bdSGerd Hoffmann         return;
5297edf3bdSGerd Hoffmann     }
5397edf3bdSGerd Hoffmann 
5497edf3bdSGerd Hoffmann     Window x11_window = gdk_x11_window_get_xid(gdk_window);
5597edf3bdSGerd Hoffmann     if (!x11_window) {
5697edf3bdSGerd Hoffmann         return;
5797edf3bdSGerd Hoffmann     }
5897edf3bdSGerd Hoffmann 
5997edf3bdSGerd Hoffmann     vc->gfx.ectx = qemu_egl_init_ctx();
60fbd57c75SAlexander Kanavin     vc->gfx.esurface = qemu_egl_init_surface_x11
61fbd57c75SAlexander Kanavin         (vc->gfx.ectx, (EGLNativeWindowType)x11_window);
6297edf3bdSGerd Hoffmann 
6397edf3bdSGerd Hoffmann     assert(vc->gfx.esurface);
6497edf3bdSGerd Hoffmann }
6597edf3bdSGerd Hoffmann 
gd_egl_draw(VirtualConsole * vc)6697edf3bdSGerd Hoffmann void gd_egl_draw(VirtualConsole *vc)
6797edf3bdSGerd Hoffmann {
6897edf3bdSGerd Hoffmann     GdkWindow *window;
6955f4b767SDongwon Kim #ifdef CONFIG_GBM
7055f4b767SDongwon Kim     QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
71*3dba3c0bSCédric Le Goater     int fence_fd;
7255f4b767SDongwon Kim #endif
7347fd6ab1SDongwon Kim     int ww, wh, ws;
7497edf3bdSGerd Hoffmann 
754782aeb7SGerd Hoffmann     if (!vc->gfx.gls) {
7697edf3bdSGerd Hoffmann         return;
7797edf3bdSGerd Hoffmann     }
7897edf3bdSGerd Hoffmann 
79f1aba960SGerd Hoffmann     window = gtk_widget_get_window(vc->gfx.drawing_area);
8047fd6ab1SDongwon Kim     ws = gdk_window_get_scale_factor(window);
8147fd6ab1SDongwon Kim     ww = gdk_window_get_width(window) * ws;
8247fd6ab1SDongwon Kim     wh = gdk_window_get_height(window) * ws;
83f1aba960SGerd Hoffmann 
844782aeb7SGerd Hoffmann     if (vc->gfx.scanout_mode) {
8555f4b767SDongwon Kim #ifdef CONFIG_GBM
8655f4b767SDongwon Kim         if (dmabuf) {
876779a307SDongwon Kim             if (!qemu_dmabuf_get_draw_submitted(dmabuf)) {
8855f4b767SDongwon Kim                 return;
8955f4b767SDongwon Kim             } else {
90fa642680SDongwon Kim                 qemu_dmabuf_set_draw_submitted(dmabuf, false);
9155f4b767SDongwon Kim             }
9255f4b767SDongwon Kim         }
9355f4b767SDongwon Kim #endif
944782aeb7SGerd Hoffmann         gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
95f1aba960SGerd Hoffmann 
96f8a951bbSErico Nunes         vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
97f8a951bbSErico Nunes         vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
9855f4b767SDongwon Kim 
9955f4b767SDongwon Kim         glFlush();
10055f4b767SDongwon Kim #ifdef CONFIG_GBM
10155f4b767SDongwon Kim         if (dmabuf) {
10255f4b767SDongwon Kim             egl_dmabuf_create_fence(dmabuf);
1036779a307SDongwon Kim             fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
1046779a307SDongwon Kim             if (fence_fd >= 0) {
1056779a307SDongwon Kim                 qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc);
10655f4b767SDongwon Kim                 return;
10755f4b767SDongwon Kim             }
10855f4b767SDongwon Kim             graphic_hw_gl_block(vc->gfx.dcl.con, false);
10955f4b767SDongwon Kim         }
11055f4b767SDongwon Kim #endif
1114782aeb7SGerd Hoffmann     } else {
1124782aeb7SGerd Hoffmann         if (!vc->gfx.ds) {
1134782aeb7SGerd Hoffmann             return;
1144782aeb7SGerd Hoffmann         }
11597edf3bdSGerd Hoffmann         eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
11697edf3bdSGerd Hoffmann                        vc->gfx.esurface, vc->gfx.ectx);
11797edf3bdSGerd Hoffmann 
11897edf3bdSGerd Hoffmann         surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh);
11997edf3bdSGerd Hoffmann         surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
12097edf3bdSGerd Hoffmann 
12197edf3bdSGerd Hoffmann         eglSwapBuffers(qemu_egl_display, vc->gfx.esurface);
122f1aba960SGerd Hoffmann 
123f1aba960SGerd Hoffmann         vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
124f1aba960SGerd Hoffmann         vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
1253cddb8b9SMarc-André Lureau 
1263cddb8b9SMarc-André Lureau         glFlush();
12755f4b767SDongwon Kim     }
1284782aeb7SGerd Hoffmann }
12997edf3bdSGerd Hoffmann 
gd_egl_update(DisplayChangeListener * dcl,int x,int y,int w,int h)13097edf3bdSGerd Hoffmann void gd_egl_update(DisplayChangeListener *dcl,
13197edf3bdSGerd Hoffmann                    int x, int y, int w, int h)
13297edf3bdSGerd Hoffmann {
13397edf3bdSGerd Hoffmann     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
13497edf3bdSGerd Hoffmann 
13597edf3bdSGerd Hoffmann     if (!vc->gfx.gls || !vc->gfx.ds) {
13697edf3bdSGerd Hoffmann         return;
13797edf3bdSGerd Hoffmann     }
13897edf3bdSGerd Hoffmann 
13997edf3bdSGerd Hoffmann     eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
14097edf3bdSGerd Hoffmann                    vc->gfx.esurface, vc->gfx.ectx);
14197edf3bdSGerd Hoffmann     surface_gl_update_texture(vc->gfx.gls, vc->gfx.ds, x, y, w, h);
14297edf3bdSGerd Hoffmann     vc->gfx.glupdates++;
14383b4b236SDongwon Kim     eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE,
14483b4b236SDongwon Kim                    EGL_NO_SURFACE, EGL_NO_CONTEXT);
14597edf3bdSGerd Hoffmann }
14697edf3bdSGerd Hoffmann 
gd_egl_refresh(DisplayChangeListener * dcl)14797edf3bdSGerd Hoffmann void gd_egl_refresh(DisplayChangeListener *dcl)
14897edf3bdSGerd Hoffmann {
14997edf3bdSGerd Hoffmann     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
15097edf3bdSGerd Hoffmann 
151aeffd071SAkihiko Odaki     gd_update_monitor_refresh_rate(
152aeffd071SAkihiko Odaki             vc, vc->window ? vc->window : vc->gfx.drawing_area);
153cab82424SNikola Pavlica 
1546779a307SDongwon Kim     if (vc->gfx.guest_fb.dmabuf &&
1556779a307SDongwon Kim         qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
15677bf3100SDongwon Kim         gd_egl_draw(vc);
1571be878ebSDongwon Kim         return;
1581be878ebSDongwon Kim     }
1591be878ebSDongwon Kim 
16097edf3bdSGerd Hoffmann     if (!vc->gfx.esurface) {
16197edf3bdSGerd Hoffmann         gd_egl_init(vc);
16297edf3bdSGerd Hoffmann         if (!vc->gfx.esurface) {
16397edf3bdSGerd Hoffmann             return;
16497edf3bdSGerd Hoffmann         }
16546e19e14SGerd Hoffmann         vc->gfx.gls = qemu_gl_init_shader();
16697edf3bdSGerd Hoffmann         if (vc->gfx.ds) {
16701eb4749SDongwon Kim             surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
16897edf3bdSGerd Hoffmann             surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds);
16997edf3bdSGerd Hoffmann         }
1708b4ed0daSPhilippe Mathieu-Daudé #ifdef CONFIG_GBM
1714872a023SDongwon Kim         if (vc->gfx.guest_fb.dmabuf) {
1724872a023SDongwon Kim             egl_dmabuf_release_texture(vc->gfx.guest_fb.dmabuf);
1734872a023SDongwon Kim             gd_egl_scanout_dmabuf(dcl, vc->gfx.guest_fb.dmabuf);
1744872a023SDongwon Kim         }
1758b4ed0daSPhilippe Mathieu-Daudé #endif
17697edf3bdSGerd Hoffmann     }
17797edf3bdSGerd Hoffmann 
17897edf3bdSGerd Hoffmann     graphic_hw_update(dcl->con);
17997edf3bdSGerd Hoffmann 
18097edf3bdSGerd Hoffmann     if (vc->gfx.glupdates) {
18197edf3bdSGerd Hoffmann         vc->gfx.glupdates = 0;
1824782aeb7SGerd Hoffmann         gtk_egl_set_scanout_mode(vc, false);
18397edf3bdSGerd Hoffmann         gd_egl_draw(vc);
18497edf3bdSGerd Hoffmann     }
18597edf3bdSGerd Hoffmann }
18697edf3bdSGerd Hoffmann 
gd_egl_switch(DisplayChangeListener * dcl,DisplaySurface * surface)18797edf3bdSGerd Hoffmann void gd_egl_switch(DisplayChangeListener *dcl,
18897edf3bdSGerd Hoffmann                    DisplaySurface *surface)
18997edf3bdSGerd Hoffmann {
19097edf3bdSGerd Hoffmann     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
19197edf3bdSGerd Hoffmann     bool resized = true;
19297edf3bdSGerd Hoffmann 
19397edf3bdSGerd Hoffmann     trace_gd_switch(vc->label, surface_width(surface), surface_height(surface));
19497edf3bdSGerd Hoffmann 
19597edf3bdSGerd Hoffmann     if (vc->gfx.ds &&
19697edf3bdSGerd Hoffmann         surface_width(vc->gfx.ds) == surface_width(surface) &&
19797edf3bdSGerd Hoffmann         surface_height(vc->gfx.ds) == surface_height(surface)) {
19897edf3bdSGerd Hoffmann         resized = false;
19997edf3bdSGerd Hoffmann     }
20001eb4749SDongwon Kim     eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
20101eb4749SDongwon Kim                    vc->gfx.esurface, vc->gfx.ectx);
20297edf3bdSGerd Hoffmann 
20397edf3bdSGerd Hoffmann     surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
20497edf3bdSGerd Hoffmann     vc->gfx.ds = surface;
20597edf3bdSGerd Hoffmann     if (vc->gfx.gls) {
20697edf3bdSGerd Hoffmann         surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds);
20797edf3bdSGerd Hoffmann     }
20897edf3bdSGerd Hoffmann 
20997edf3bdSGerd Hoffmann     if (resized) {
21097edf3bdSGerd Hoffmann         gd_update_windowsize(vc);
21197edf3bdSGerd Hoffmann     }
212604a8689SDongwon Kim 
213604a8689SDongwon Kim     eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
214604a8689SDongwon Kim                    EGL_NO_CONTEXT);
21597edf3bdSGerd Hoffmann }
21697edf3bdSGerd Hoffmann 
gd_egl_create_context(DisplayGLCtx * dgc,QEMUGLParams * params)2175e79d516SMarc-André Lureau QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc,
2184782aeb7SGerd Hoffmann                                     QEMUGLParams *params)
2194782aeb7SGerd Hoffmann {
2205e79d516SMarc-André Lureau     VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc);
2214782aeb7SGerd Hoffmann 
2224782aeb7SGerd Hoffmann     eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
2234782aeb7SGerd Hoffmann                    vc->gfx.esurface, vc->gfx.ectx);
2245e79d516SMarc-André Lureau     return qemu_egl_create_context(dgc, params);
2254782aeb7SGerd Hoffmann }
2264782aeb7SGerd Hoffmann 
gd_egl_scanout_disable(DisplayChangeListener * dcl)227543a7a16SGerd Hoffmann void gd_egl_scanout_disable(DisplayChangeListener *dcl)
228543a7a16SGerd Hoffmann {
229543a7a16SGerd Hoffmann     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
230543a7a16SGerd Hoffmann 
231543a7a16SGerd Hoffmann     vc->gfx.w = 0;
232543a7a16SGerd Hoffmann     vc->gfx.h = 0;
233543a7a16SGerd Hoffmann     gtk_egl_set_scanout_mode(vc, false);
234543a7a16SGerd Hoffmann }
235543a7a16SGerd Hoffmann 
gd_egl_scanout_texture(DisplayChangeListener * dcl,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,void * d3d_tex2d)236f4c36bdaSGerd Hoffmann void gd_egl_scanout_texture(DisplayChangeListener *dcl,
2374782aeb7SGerd Hoffmann                             uint32_t backing_id, bool backing_y_0_top,
2389d8256ebSMarc-André Lureau                             uint32_t backing_width, uint32_t backing_height,
2394782aeb7SGerd Hoffmann                             uint32_t x, uint32_t y,
240bf41ab61SMarc-André Lureau                             uint32_t w, uint32_t h,
241bf41ab61SMarc-André Lureau                             void *d3d_tex2d)
2424782aeb7SGerd Hoffmann {
2434782aeb7SGerd Hoffmann     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
2444782aeb7SGerd Hoffmann 
2454782aeb7SGerd Hoffmann     vc->gfx.x = x;
2464782aeb7SGerd Hoffmann     vc->gfx.y = y;
2474782aeb7SGerd Hoffmann     vc->gfx.w = w;
2484782aeb7SGerd Hoffmann     vc->gfx.h = h;
2494782aeb7SGerd Hoffmann     vc->gfx.y0_top = backing_y_0_top;
2504782aeb7SGerd Hoffmann 
2516f189a08SAntonio Caggiano     if (!vc->gfx.esurface) {
2526f189a08SAntonio Caggiano         gd_egl_init(vc);
2536f189a08SAntonio Caggiano         if (!vc->gfx.esurface) {
2546f189a08SAntonio Caggiano             return;
2556f189a08SAntonio Caggiano         }
25653a939f1SVolker Rümelin     }
2576f189a08SAntonio Caggiano 
2584782aeb7SGerd Hoffmann     eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
2594782aeb7SGerd Hoffmann                    vc->gfx.esurface, vc->gfx.ectx);
2604782aeb7SGerd Hoffmann 
26158ea90f8SDongwon Kim     gtk_egl_set_scanout_mode(vc, true);
26274083f9cSGerd Hoffmann     egl_fb_setup_for_tex(&vc->gfx.guest_fb, backing_width, backing_height,
26374083f9cSGerd Hoffmann                          backing_id, false);
2644782aeb7SGerd Hoffmann }
2654782aeb7SGerd Hoffmann 
gd_egl_scanout_dmabuf(DisplayChangeListener * dcl,QemuDmaBuf * dmabuf)26670763feaSGerd Hoffmann void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
26770763feaSGerd Hoffmann                            QemuDmaBuf *dmabuf)
26870763feaSGerd Hoffmann {
269bc6a3565SAkihiko Odaki #ifdef CONFIG_GBM
27065b847d2SVivek Kasireddy     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
2716779a307SDongwon Kim     uint32_t x, y, width, height, backing_width, backing_height, texture;
2726779a307SDongwon Kim     bool y0_top;
27365b847d2SVivek Kasireddy 
27401eb4749SDongwon Kim     eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
27501eb4749SDongwon Kim                    vc->gfx.esurface, vc->gfx.ectx);
27601eb4749SDongwon Kim 
27770763feaSGerd Hoffmann     egl_dmabuf_import_texture(dmabuf);
2786779a307SDongwon Kim     texture = qemu_dmabuf_get_texture(dmabuf);
2796779a307SDongwon Kim     if (!texture) {
28070763feaSGerd Hoffmann         return;
28170763feaSGerd Hoffmann     }
28270763feaSGerd Hoffmann 
2836779a307SDongwon Kim     x = qemu_dmabuf_get_x(dmabuf);
2846779a307SDongwon Kim     y = qemu_dmabuf_get_y(dmabuf);
2856779a307SDongwon Kim     width = qemu_dmabuf_get_width(dmabuf);
2866779a307SDongwon Kim     height = qemu_dmabuf_get_height(dmabuf);
2876779a307SDongwon Kim     backing_width = qemu_dmabuf_get_backing_width(dmabuf);
2886779a307SDongwon Kim     backing_height = qemu_dmabuf_get_backing_height(dmabuf);
2896779a307SDongwon Kim     y0_top = qemu_dmabuf_get_y0_top(dmabuf);
29065b847d2SVivek Kasireddy 
2916779a307SDongwon Kim     gd_egl_scanout_texture(dcl, texture, y0_top, backing_width, backing_height,
2926779a307SDongwon Kim                            x, y, width, height, NULL);
2936779a307SDongwon Kim 
2946779a307SDongwon Kim     if (qemu_dmabuf_get_allow_fences(dmabuf)) {
29565b847d2SVivek Kasireddy         vc->gfx.guest_fb.dmabuf = dmabuf;
29665b847d2SVivek Kasireddy     }
29770763feaSGerd Hoffmann #endif
29870763feaSGerd Hoffmann }
29970763feaSGerd Hoffmann 
gd_egl_cursor_dmabuf(DisplayChangeListener * dcl,QemuDmaBuf * dmabuf,bool have_hot,uint32_t hot_x,uint32_t hot_y)300f1bd3132SGerd Hoffmann void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl,
301f1bd3132SGerd Hoffmann                           QemuDmaBuf *dmabuf, bool have_hot,
302f1bd3132SGerd Hoffmann                           uint32_t hot_x, uint32_t hot_y)
303f1bd3132SGerd Hoffmann {
304bc6a3565SAkihiko Odaki #ifdef CONFIG_GBM
305f1bd3132SGerd Hoffmann     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
3066779a307SDongwon Kim     uint32_t backing_width, backing_height, texture;
307f1bd3132SGerd Hoffmann 
308f1bd3132SGerd Hoffmann     if (dmabuf) {
309f1bd3132SGerd Hoffmann         egl_dmabuf_import_texture(dmabuf);
3106779a307SDongwon Kim         texture = qemu_dmabuf_get_texture(dmabuf);
3116779a307SDongwon Kim         if (!texture) {
312f1bd3132SGerd Hoffmann             return;
313f1bd3132SGerd Hoffmann         }
3146779a307SDongwon Kim 
3156779a307SDongwon Kim         backing_width = qemu_dmabuf_get_backing_width(dmabuf);
3166779a307SDongwon Kim         backing_height = qemu_dmabuf_get_backing_height(dmabuf);
3176779a307SDongwon Kim         egl_fb_setup_for_tex(&vc->gfx.cursor_fb, backing_width, backing_height,
3186779a307SDongwon Kim                              texture, false);
319f1bd3132SGerd Hoffmann     } else {
320f1bd3132SGerd Hoffmann         egl_fb_destroy(&vc->gfx.cursor_fb);
321f1bd3132SGerd Hoffmann     }
322f1bd3132SGerd Hoffmann #endif
323f1bd3132SGerd Hoffmann }
324f1bd3132SGerd Hoffmann 
gd_egl_cursor_position(DisplayChangeListener * dcl,uint32_t pos_x,uint32_t pos_y)325f1bd3132SGerd Hoffmann void gd_egl_cursor_position(DisplayChangeListener *dcl,
326f1bd3132SGerd Hoffmann                             uint32_t pos_x, uint32_t pos_y)
327f1bd3132SGerd Hoffmann {
328f1bd3132SGerd Hoffmann     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
329f1bd3132SGerd Hoffmann 
330f1aba960SGerd Hoffmann     vc->gfx.cursor_x = pos_x * vc->gfx.scale_x;
331f1aba960SGerd Hoffmann     vc->gfx.cursor_y = pos_y * vc->gfx.scale_y;
332f1bd3132SGerd Hoffmann }
333f1bd3132SGerd Hoffmann 
gd_egl_scanout_flush(DisplayChangeListener * dcl,uint32_t x,uint32_t y,uint32_t w,uint32_t h)3344782aeb7SGerd Hoffmann void gd_egl_scanout_flush(DisplayChangeListener *dcl,
3354782aeb7SGerd Hoffmann                           uint32_t x, uint32_t y, uint32_t w, uint32_t h)
3364782aeb7SGerd Hoffmann {
3374782aeb7SGerd Hoffmann     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
3384782aeb7SGerd Hoffmann     GdkWindow *window;
33947fd6ab1SDongwon Kim     int ww, wh, ws;
3404782aeb7SGerd Hoffmann 
3414782aeb7SGerd Hoffmann     if (!vc->gfx.scanout_mode) {
3424782aeb7SGerd Hoffmann         return;
3434782aeb7SGerd Hoffmann     }
344a4f113fdSGerd Hoffmann     if (!vc->gfx.guest_fb.framebuffer) {
3454782aeb7SGerd Hoffmann         return;
3464782aeb7SGerd Hoffmann     }
3474782aeb7SGerd Hoffmann 
3484782aeb7SGerd Hoffmann     eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
3494782aeb7SGerd Hoffmann                    vc->gfx.esurface, vc->gfx.ectx);
3504782aeb7SGerd Hoffmann 
3514782aeb7SGerd Hoffmann     window = gtk_widget_get_window(vc->gfx.drawing_area);
35247fd6ab1SDongwon Kim     ws = gdk_window_get_scale_factor(window);
35347fd6ab1SDongwon Kim     ww = gdk_window_get_width(window) * ws;
35447fd6ab1SDongwon Kim     wh = gdk_window_get_height(window) * ws;
355a4f113fdSGerd Hoffmann     egl_fb_setup_default(&vc->gfx.win_fb, ww, wh);
356f1bd3132SGerd Hoffmann     if (vc->gfx.cursor_fb.texture) {
357f1bd3132SGerd Hoffmann         egl_texture_blit(vc->gfx.gls, &vc->gfx.win_fb, &vc->gfx.guest_fb,
358f1bd3132SGerd Hoffmann                          vc->gfx.y0_top);
359f1bd3132SGerd Hoffmann         egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, &vc->gfx.cursor_fb,
360f1bd3132SGerd Hoffmann                           vc->gfx.y0_top,
361051a0cdeSChen Zhang                           vc->gfx.cursor_x, vc->gfx.cursor_y,
362051a0cdeSChen Zhang                           vc->gfx.scale_x, vc->gfx.scale_y);
363f1bd3132SGerd Hoffmann     } else {
364a4f113fdSGerd Hoffmann         egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top);
365f1bd3132SGerd Hoffmann     }
3664782aeb7SGerd Hoffmann 
36765b847d2SVivek Kasireddy #ifdef CONFIG_GBM
36865b847d2SVivek Kasireddy     if (vc->gfx.guest_fb.dmabuf) {
36965b847d2SVivek Kasireddy         egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf);
37065b847d2SVivek Kasireddy     }
37165b847d2SVivek Kasireddy #endif
37265b847d2SVivek Kasireddy 
3734782aeb7SGerd Hoffmann     eglSwapBuffers(qemu_egl_display, vc->gfx.esurface);
3744782aeb7SGerd Hoffmann }
3754782aeb7SGerd Hoffmann 
gd_egl_flush(DisplayChangeListener * dcl,uint32_t x,uint32_t y,uint32_t w,uint32_t h)376ab971f8aSVivek Kasireddy void gd_egl_flush(DisplayChangeListener *dcl,
377ab971f8aSVivek Kasireddy                   uint32_t x, uint32_t y, uint32_t w, uint32_t h)
378ab971f8aSVivek Kasireddy {
379ab971f8aSVivek Kasireddy     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
380ab971f8aSVivek Kasireddy     GtkWidget *area = vc->gfx.drawing_area;
381ab971f8aSVivek Kasireddy 
3826779a307SDongwon Kim     if (vc->gfx.guest_fb.dmabuf &&
3836779a307SDongwon Kim         !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
384ab971f8aSVivek Kasireddy         graphic_hw_gl_block(vc->gfx.dcl.con, true);
385fa642680SDongwon Kim         qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
38692b58156SDongwon Kim         gtk_egl_set_scanout_mode(vc, true);
387ab971f8aSVivek Kasireddy         gtk_widget_queue_draw_area(area, x, y, w, h);
388ab971f8aSVivek Kasireddy         return;
389ab971f8aSVivek Kasireddy     }
390ab971f8aSVivek Kasireddy 
391ab971f8aSVivek Kasireddy     gd_egl_scanout_flush(&vc->gfx.dcl, x, y, w, h);
392ab971f8aSVivek Kasireddy }
393ab971f8aSVivek Kasireddy 
gtk_egl_init(DisplayGLMode mode)39454d208ffSGerd Hoffmann void gtk_egl_init(DisplayGLMode mode)
39597edf3bdSGerd Hoffmann {
39697edf3bdSGerd Hoffmann     GdkDisplay *gdk_display = gdk_display_get_default();
39797edf3bdSGerd Hoffmann     Display *x11_display = gdk_x11_display_get_xdisplay(gdk_display);
39897edf3bdSGerd Hoffmann 
39954d208ffSGerd Hoffmann     if (qemu_egl_init_dpy_x11(x11_display, mode) < 0) {
40097edf3bdSGerd Hoffmann         return;
40197edf3bdSGerd Hoffmann     }
40297edf3bdSGerd Hoffmann 
40397edf3bdSGerd Hoffmann     display_opengl = 1;
40497edf3bdSGerd Hoffmann }
4054782aeb7SGerd Hoffmann 
gd_egl_make_current(DisplayGLCtx * dgc,QEMUGLContext ctx)4065e79d516SMarc-André Lureau int gd_egl_make_current(DisplayGLCtx *dgc,
4074782aeb7SGerd Hoffmann                         QEMUGLContext ctx)
4084782aeb7SGerd Hoffmann {
4095e79d516SMarc-André Lureau     VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc);
4104782aeb7SGerd Hoffmann 
4111d48c9fdSMarc-André Lureau     if (!eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
4121d48c9fdSMarc-André Lureau                         vc->gfx.esurface, ctx)) {
4131d48c9fdSMarc-André Lureau         error_report("egl: eglMakeCurrent failed: %s", qemu_egl_get_error_string());
4141d48c9fdSMarc-André Lureau         return -1;
4151d48c9fdSMarc-André Lureau     }
4161d48c9fdSMarc-André Lureau 
4171d48c9fdSMarc-André Lureau     return 0;
4184782aeb7SGerd Hoffmann }
419