xref: /qemu/ui/egl-helpers.c (revision 9ac06df8)
16250dff3SFrediano Ziglio /*
26250dff3SFrediano Ziglio  * Copyright (C) 2015-2016 Gerd Hoffmann <kraxel@redhat.com>
36250dff3SFrediano Ziglio  *
46250dff3SFrediano Ziglio  * This library is free software; you can redistribute it and/or
56250dff3SFrediano Ziglio  * modify it under the terms of the GNU Lesser General Public
66250dff3SFrediano Ziglio  * License as published by the Free Software Foundation; either
76250dff3SFrediano Ziglio  * version 2.1 of the License, or (at your option) any later version.
86250dff3SFrediano Ziglio  *
96250dff3SFrediano Ziglio  * This library is distributed in the hope that it will be useful,
106250dff3SFrediano Ziglio  * but WITHOUT ANY WARRANTY; without even the implied warranty of
116250dff3SFrediano Ziglio  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
126250dff3SFrediano Ziglio  * Lesser General Public License for more details.
136250dff3SFrediano Ziglio  *
146250dff3SFrediano Ziglio  * You should have received a copy of the GNU Lesser General Public
156250dff3SFrediano Ziglio  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
166250dff3SFrediano Ziglio  */
17e16f4c87SPeter Maydell #include "qemu/osdep.h"
1806c63a34SMarc-André Lureau 
19b1d38037SMarc-André Lureau #include "qemu/drm.h"
2038a55bddSCole Robinson #include "qemu/error-report.h"
2186c0522cSGerd Hoffmann #include "ui/console.h"
227ced9e9fSGerd Hoffmann #include "ui/egl-helpers.h"
230e1be59eSMarc-André Lureau #include "sysemu/sysemu.h"
240e1be59eSMarc-André Lureau #include "qapi/error.h"
2506c63a34SMarc-André Lureau #include "trace.h"
267ced9e9fSGerd Hoffmann 
277ced9e9fSGerd Hoffmann EGLDisplay *qemu_egl_display;
287ced9e9fSGerd Hoffmann EGLConfig qemu_egl_config;
2954d208ffSGerd Hoffmann DisplayGLMode qemu_egl_mode;
3006c63a34SMarc-André Lureau bool qemu_egl_angle_d3d;
317ced9e9fSGerd Hoffmann 
326fafc260SGerd Hoffmann /* ------------------------------------------------------------------ */
336fafc260SGerd Hoffmann 
qemu_egl_get_error_string(void)34044ca4bfSMarc-André Lureau const char *qemu_egl_get_error_string(void)
351f086ef6SMarc-André Lureau {
361f086ef6SMarc-André Lureau     EGLint error = eglGetError();
371f086ef6SMarc-André Lureau 
381f086ef6SMarc-André Lureau     switch (error) {
391f086ef6SMarc-André Lureau     case EGL_SUCCESS:
401f086ef6SMarc-André Lureau         return "EGL_SUCCESS";
411f086ef6SMarc-André Lureau     case EGL_NOT_INITIALIZED:
421f086ef6SMarc-André Lureau         return "EGL_NOT_INITIALIZED";
431f086ef6SMarc-André Lureau     case EGL_BAD_ACCESS:
441f086ef6SMarc-André Lureau         return "EGL_BAD_ACCESS";
451f086ef6SMarc-André Lureau     case EGL_BAD_ALLOC:
461f086ef6SMarc-André Lureau         return "EGL_BAD_ALLOC";
471f086ef6SMarc-André Lureau     case EGL_BAD_ATTRIBUTE:
481f086ef6SMarc-André Lureau         return "EGL_BAD_ATTRIBUTE";
491f086ef6SMarc-André Lureau     case EGL_BAD_CONTEXT:
501f086ef6SMarc-André Lureau         return "EGL_BAD_CONTEXT";
511f086ef6SMarc-André Lureau     case EGL_BAD_CONFIG:
521f086ef6SMarc-André Lureau         return "EGL_BAD_CONFIG";
531f086ef6SMarc-André Lureau     case EGL_BAD_CURRENT_SURFACE:
541f086ef6SMarc-André Lureau         return "EGL_BAD_CURRENT_SURFACE";
551f086ef6SMarc-André Lureau     case EGL_BAD_DISPLAY:
561f086ef6SMarc-André Lureau         return "EGL_BAD_DISPLAY";
571f086ef6SMarc-André Lureau     case EGL_BAD_SURFACE:
581f086ef6SMarc-André Lureau         return "EGL_BAD_SURFACE";
591f086ef6SMarc-André Lureau     case EGL_BAD_MATCH:
601f086ef6SMarc-André Lureau         return "EGL_BAD_MATCH";
611f086ef6SMarc-André Lureau     case EGL_BAD_PARAMETER:
621f086ef6SMarc-André Lureau         return "EGL_BAD_PARAMETER";
631f086ef6SMarc-André Lureau     case EGL_BAD_NATIVE_PIXMAP:
641f086ef6SMarc-André Lureau         return "EGL_BAD_NATIVE_PIXMAP";
651f086ef6SMarc-André Lureau     case EGL_BAD_NATIVE_WINDOW:
661f086ef6SMarc-André Lureau         return "EGL_BAD_NATIVE_WINDOW";
671f086ef6SMarc-André Lureau     case EGL_CONTEXT_LOST:
681f086ef6SMarc-André Lureau         return "EGL_CONTEXT_LOST";
691f086ef6SMarc-André Lureau     default:
701f086ef6SMarc-André Lureau         return "Unknown EGL error";
711f086ef6SMarc-André Lureau     }
721f086ef6SMarc-André Lureau }
731f086ef6SMarc-André Lureau 
egl_fb_delete_texture(egl_fb * fb)7474083f9cSGerd Hoffmann static void egl_fb_delete_texture(egl_fb *fb)
7574083f9cSGerd Hoffmann {
7674083f9cSGerd Hoffmann     if (!fb->delete_texture) {
7774083f9cSGerd Hoffmann         return;
7874083f9cSGerd Hoffmann     }
7974083f9cSGerd Hoffmann 
8074083f9cSGerd Hoffmann     glDeleteTextures(1, &fb->texture);
8174083f9cSGerd Hoffmann     fb->delete_texture = false;
8274083f9cSGerd Hoffmann }
8374083f9cSGerd Hoffmann 
egl_fb_destroy(egl_fb * fb)846fafc260SGerd Hoffmann void egl_fb_destroy(egl_fb *fb)
856fafc260SGerd Hoffmann {
866fafc260SGerd Hoffmann     if (!fb->framebuffer) {
876fafc260SGerd Hoffmann         return;
886fafc260SGerd Hoffmann     }
896fafc260SGerd Hoffmann 
9074083f9cSGerd Hoffmann     egl_fb_delete_texture(fb);
916fafc260SGerd Hoffmann     glDeleteFramebuffers(1, &fb->framebuffer);
926fafc260SGerd Hoffmann 
936fafc260SGerd Hoffmann     fb->width = 0;
946fafc260SGerd Hoffmann     fb->height = 0;
956fafc260SGerd Hoffmann     fb->texture = 0;
966fafc260SGerd Hoffmann     fb->framebuffer = 0;
976fafc260SGerd Hoffmann }
986fafc260SGerd Hoffmann 
egl_fb_setup_default(egl_fb * fb,int width,int height)996fafc260SGerd Hoffmann void egl_fb_setup_default(egl_fb *fb, int width, int height)
1006fafc260SGerd Hoffmann {
1016fafc260SGerd Hoffmann     fb->width = width;
1026fafc260SGerd Hoffmann     fb->height = height;
1036fafc260SGerd Hoffmann     fb->framebuffer = 0; /* default framebuffer */
1046fafc260SGerd Hoffmann }
1056fafc260SGerd Hoffmann 
egl_fb_setup_for_tex(egl_fb * fb,int width,int height,GLuint texture,bool delete)10674083f9cSGerd Hoffmann void egl_fb_setup_for_tex(egl_fb *fb, int width, int height,
10774083f9cSGerd Hoffmann                           GLuint texture, bool delete)
1086fafc260SGerd Hoffmann {
10974083f9cSGerd Hoffmann     egl_fb_delete_texture(fb);
11074083f9cSGerd Hoffmann 
1116fafc260SGerd Hoffmann     fb->width = width;
1126fafc260SGerd Hoffmann     fb->height = height;
1136fafc260SGerd Hoffmann     fb->texture = texture;
11474083f9cSGerd Hoffmann     fb->delete_texture = delete;
1156fafc260SGerd Hoffmann     if (!fb->framebuffer) {
1166fafc260SGerd Hoffmann         glGenFramebuffers(1, &fb->framebuffer);
1176fafc260SGerd Hoffmann     }
1186fafc260SGerd Hoffmann 
1196fafc260SGerd Hoffmann     glBindFramebuffer(GL_FRAMEBUFFER_EXT, fb->framebuffer);
1206fafc260SGerd Hoffmann     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
1216fafc260SGerd Hoffmann                               GL_TEXTURE_2D, fb->texture, 0);
1226fafc260SGerd Hoffmann }
1236fafc260SGerd Hoffmann 
egl_fb_setup_new_tex(egl_fb * fb,int width,int height)12474083f9cSGerd Hoffmann void egl_fb_setup_new_tex(egl_fb *fb, int width, int height)
1256fafc260SGerd Hoffmann {
1266fafc260SGerd Hoffmann     GLuint texture;
1276fafc260SGerd Hoffmann 
1286fafc260SGerd Hoffmann     glGenTextures(1, &texture);
1296fafc260SGerd Hoffmann     glBindTexture(GL_TEXTURE_2D, texture);
13041126214SGerd Hoffmann     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
1316fafc260SGerd Hoffmann                  0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1326fafc260SGerd Hoffmann 
13374083f9cSGerd Hoffmann     egl_fb_setup_for_tex(fb, width, height, texture, true);
1346fafc260SGerd Hoffmann }
1356fafc260SGerd Hoffmann 
egl_fb_blit(egl_fb * dst,egl_fb * src,bool flip)1366fafc260SGerd Hoffmann void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip)
1376fafc260SGerd Hoffmann {
1381350ff15SDongwon Kim     GLuint x1 = 0;
1391350ff15SDongwon Kim     GLuint y1 = 0;
1401350ff15SDongwon Kim     GLuint x2, y2;
1411350ff15SDongwon Kim     GLuint w = src->width;
1421350ff15SDongwon Kim     GLuint h = src->height;
1436fafc260SGerd Hoffmann 
1446fafc260SGerd Hoffmann     glBindFramebuffer(GL_READ_FRAMEBUFFER, src->framebuffer);
1456fafc260SGerd Hoffmann     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst->framebuffer);
1466fafc260SGerd Hoffmann     glViewport(0, 0, dst->width, dst->height);
1471350ff15SDongwon Kim 
1481350ff15SDongwon Kim     if (src->dmabuf) {
1491350ff15SDongwon Kim         x1 = src->dmabuf->x;
1501350ff15SDongwon Kim         y1 = src->dmabuf->y;
1519ac06df8SDongwon Kim         w = src->dmabuf->width;
1529ac06df8SDongwon Kim         h = src->dmabuf->height;
1531350ff15SDongwon Kim     }
1541350ff15SDongwon Kim 
1551350ff15SDongwon Kim     w = (x1 + w) > src->width ? src->width - x1 : w;
1561350ff15SDongwon Kim     h = (y1 + h) > src->height ? src->height - y1 : h;
1571350ff15SDongwon Kim 
1581350ff15SDongwon Kim     y2 = flip ? y1 : h + y1;
1591350ff15SDongwon Kim     y1 = flip ? h + y1 : y1;
1601350ff15SDongwon Kim     x2 = x1 + w;
1611350ff15SDongwon Kim 
1621350ff15SDongwon Kim     glBlitFramebuffer(x1, y1, x2, y2,
1636fafc260SGerd Hoffmann                       0, 0, dst->width, dst->height,
1646fafc260SGerd Hoffmann                       GL_COLOR_BUFFER_BIT, GL_LINEAR);
1656fafc260SGerd Hoffmann }
1666fafc260SGerd Hoffmann 
egl_fb_read(DisplaySurface * dst,egl_fb * src)167d2329237SGerd Hoffmann void egl_fb_read(DisplaySurface *dst, egl_fb *src)
1686fafc260SGerd Hoffmann {
1696fafc260SGerd Hoffmann     glBindFramebuffer(GL_READ_FRAMEBUFFER, src->framebuffer);
1706fafc260SGerd Hoffmann     glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
171d2329237SGerd Hoffmann     glReadPixels(0, 0, surface_width(dst), surface_height(dst),
172d2329237SGerd Hoffmann                  GL_BGRA, GL_UNSIGNED_BYTE, surface_data(dst));
1736fafc260SGerd Hoffmann }
1746fafc260SGerd Hoffmann 
egl_fb_read_rect(DisplaySurface * dst,egl_fb * src,int x,int y,int w,int h)175da9eb580SMarc-André Lureau void egl_fb_read_rect(DisplaySurface *dst, egl_fb *src, int x, int y, int w, int h)
176da9eb580SMarc-André Lureau {
177da9eb580SMarc-André Lureau     assert(surface_width(dst) == src->width);
178da9eb580SMarc-André Lureau     assert(surface_height(dst) == src->height);
179da9eb580SMarc-André Lureau     assert(surface_format(dst) == PIXMAN_x8r8g8b8);
180da9eb580SMarc-André Lureau 
181da9eb580SMarc-André Lureau     glBindFramebuffer(GL_READ_FRAMEBUFFER, src->framebuffer);
182da9eb580SMarc-André Lureau     glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
183da9eb580SMarc-André Lureau     glPixelStorei(GL_PACK_ROW_LENGTH, surface_stride(dst) / 4);
184da9eb580SMarc-André Lureau     glReadPixels(x, y, w, h,
185da9eb580SMarc-André Lureau                  GL_BGRA, GL_UNSIGNED_BYTE, surface_data(dst) + x * 4);
186da9eb580SMarc-André Lureau     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
187da9eb580SMarc-André Lureau }
188da9eb580SMarc-André Lureau 
egl_texture_blit(QemuGLShader * gls,egl_fb * dst,egl_fb * src,bool flip)1890eb50c27SGerd Hoffmann void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip)
1900eb50c27SGerd Hoffmann {
1910eb50c27SGerd Hoffmann     glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer);
1920eb50c27SGerd Hoffmann     glViewport(0, 0, dst->width, dst->height);
1930eb50c27SGerd Hoffmann     glEnable(GL_TEXTURE_2D);
1940eb50c27SGerd Hoffmann     glBindTexture(GL_TEXTURE_2D, src->texture);
1950eb50c27SGerd Hoffmann     qemu_gl_run_texture_blit(gls, flip);
1960eb50c27SGerd Hoffmann }
1970eb50c27SGerd Hoffmann 
egl_texture_blend(QemuGLShader * gls,egl_fb * dst,egl_fb * src,bool flip,int x,int y,double scale_x,double scale_y)1980eb50c27SGerd Hoffmann void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip,
199051a0cdeSChen Zhang                        int x, int y, double scale_x, double scale_y)
2000eb50c27SGerd Hoffmann {
2010eb50c27SGerd Hoffmann     glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer);
202051a0cdeSChen Zhang     int w = scale_x * src->width;
203051a0cdeSChen Zhang     int h = scale_y * src->height;
2040eb50c27SGerd Hoffmann     if (flip) {
205051a0cdeSChen Zhang         glViewport(x, y, w, h);
2060eb50c27SGerd Hoffmann     } else {
207051a0cdeSChen Zhang         glViewport(x, dst->height - h - y, w, h);
2080eb50c27SGerd Hoffmann     }
2090eb50c27SGerd Hoffmann     glEnable(GL_TEXTURE_2D);
2100eb50c27SGerd Hoffmann     glBindTexture(GL_TEXTURE_2D, src->texture);
2110eb50c27SGerd Hoffmann     glEnable(GL_BLEND);
2120eb50c27SGerd Hoffmann     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2130eb50c27SGerd Hoffmann     qemu_gl_run_texture_blit(gls, flip);
2140eb50c27SGerd Hoffmann     glDisable(GL_BLEND);
2150eb50c27SGerd Hoffmann }
2160eb50c27SGerd Hoffmann 
2177ced9e9fSGerd Hoffmann /* ---------------------------------------------------------------------- */
2187ced9e9fSGerd Hoffmann 
21939324b49SMarc-André Lureau EGLContext qemu_egl_rn_ctx;
22039324b49SMarc-André Lureau 
221bc6a3565SAkihiko Odaki #ifdef CONFIG_GBM
2221e316598SGerd Hoffmann 
2231e316598SGerd Hoffmann int qemu_egl_rn_fd;
2241e316598SGerd Hoffmann struct gbm_device *qemu_egl_rn_gbm_dev;
2251e316598SGerd Hoffmann 
egl_rendernode_init(const char * rendernode,DisplayGLMode mode)22654d208ffSGerd Hoffmann int egl_rendernode_init(const char *rendernode, DisplayGLMode mode)
2271e316598SGerd Hoffmann {
2281e316598SGerd Hoffmann     qemu_egl_rn_fd = -1;
229151c8e60SGerd Hoffmann     int rc;
2301e316598SGerd Hoffmann 
231b1d38037SMarc-André Lureau     qemu_egl_rn_fd = qemu_drm_rendernode_open(rendernode);
2321e316598SGerd Hoffmann     if (qemu_egl_rn_fd == -1) {
23338a55bddSCole Robinson         error_report("egl: no drm render node available");
2341e316598SGerd Hoffmann         goto err;
2351e316598SGerd Hoffmann     }
2361e316598SGerd Hoffmann 
2371e316598SGerd Hoffmann     qemu_egl_rn_gbm_dev = gbm_create_device(qemu_egl_rn_fd);
2381e316598SGerd Hoffmann     if (!qemu_egl_rn_gbm_dev) {
23938a55bddSCole Robinson         error_report("egl: gbm_create_device failed");
2401e316598SGerd Hoffmann         goto err;
2411e316598SGerd Hoffmann     }
2421e316598SGerd Hoffmann 
24354d208ffSGerd Hoffmann     rc = qemu_egl_init_dpy_mesa((EGLNativeDisplayType)qemu_egl_rn_gbm_dev,
24454d208ffSGerd Hoffmann                                 mode);
245151c8e60SGerd Hoffmann     if (rc != 0) {
246151c8e60SGerd Hoffmann         /* qemu_egl_init_dpy_mesa reports error */
247151c8e60SGerd Hoffmann         goto err;
248151c8e60SGerd Hoffmann     }
2491e316598SGerd Hoffmann 
2501e316598SGerd Hoffmann     if (!epoxy_has_egl_extension(qemu_egl_display,
2511e316598SGerd Hoffmann                                  "EGL_KHR_surfaceless_context")) {
25238a55bddSCole Robinson         error_report("egl: EGL_KHR_surfaceless_context not supported");
2531e316598SGerd Hoffmann         goto err;
2541e316598SGerd Hoffmann     }
2551e316598SGerd Hoffmann     if (!epoxy_has_egl_extension(qemu_egl_display,
2561e316598SGerd Hoffmann                                  "EGL_MESA_image_dma_buf_export")) {
25738a55bddSCole Robinson         error_report("egl: EGL_MESA_image_dma_buf_export not supported");
2581e316598SGerd Hoffmann         goto err;
2591e316598SGerd Hoffmann     }
2601e316598SGerd Hoffmann 
2611e316598SGerd Hoffmann     qemu_egl_rn_ctx = qemu_egl_init_ctx();
2621e316598SGerd Hoffmann     if (!qemu_egl_rn_ctx) {
26338a55bddSCole Robinson         error_report("egl: egl_init_ctx failed");
2641e316598SGerd Hoffmann         goto err;
2651e316598SGerd Hoffmann     }
2661e316598SGerd Hoffmann 
2671e316598SGerd Hoffmann     return 0;
2681e316598SGerd Hoffmann 
2691e316598SGerd Hoffmann err:
2701e316598SGerd Hoffmann     if (qemu_egl_rn_gbm_dev) {
2711e316598SGerd Hoffmann         gbm_device_destroy(qemu_egl_rn_gbm_dev);
2721e316598SGerd Hoffmann     }
2731e316598SGerd Hoffmann     if (qemu_egl_rn_fd != -1) {
2741e316598SGerd Hoffmann         close(qemu_egl_rn_fd);
2751e316598SGerd Hoffmann     }
2761e316598SGerd Hoffmann 
2771e316598SGerd Hoffmann     return -1;
2781e316598SGerd Hoffmann }
2791e316598SGerd Hoffmann 
egl_get_fd_for_texture(uint32_t tex_id,EGLint * stride,EGLint * fourcc,EGLuint64KHR * modifier)2805fc1fb62SGerd Hoffmann int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc,
2815fc1fb62SGerd Hoffmann                            EGLuint64KHR *modifier)
2821e316598SGerd Hoffmann {
2831e316598SGerd Hoffmann     EGLImageKHR image;
2841e316598SGerd Hoffmann     EGLint num_planes, fd;
2851e316598SGerd Hoffmann 
2861e316598SGerd Hoffmann     image = eglCreateImageKHR(qemu_egl_display, eglGetCurrentContext(),
2871e316598SGerd Hoffmann                               EGL_GL_TEXTURE_2D_KHR,
2881e316598SGerd Hoffmann                               (EGLClientBuffer)(unsigned long)tex_id,
2891e316598SGerd Hoffmann                               NULL);
2901e316598SGerd Hoffmann     if (!image) {
2911e316598SGerd Hoffmann         return -1;
2921e316598SGerd Hoffmann     }
2931e316598SGerd Hoffmann 
2941e316598SGerd Hoffmann     eglExportDMABUFImageQueryMESA(qemu_egl_display, image, fourcc,
2955fc1fb62SGerd Hoffmann                                   &num_planes, modifier);
2961e316598SGerd Hoffmann     if (num_planes != 1) {
2971e316598SGerd Hoffmann         eglDestroyImageKHR(qemu_egl_display, image);
2981e316598SGerd Hoffmann         return -1;
2991e316598SGerd Hoffmann     }
3001e316598SGerd Hoffmann     eglExportDMABUFImageMESA(qemu_egl_display, image, &fd, stride, NULL);
3011e316598SGerd Hoffmann     eglDestroyImageKHR(qemu_egl_display, image);
3021e316598SGerd Hoffmann 
3031e316598SGerd Hoffmann     return fd;
3041e316598SGerd Hoffmann }
3051e316598SGerd Hoffmann 
egl_dmabuf_import_texture(QemuDmaBuf * dmabuf)30686c0522cSGerd Hoffmann void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf)
30786c0522cSGerd Hoffmann {
30886c0522cSGerd Hoffmann     EGLImageKHR image = EGL_NO_IMAGE_KHR;
30915ee0d9bSGerd Hoffmann     EGLint attrs[64];
31015ee0d9bSGerd Hoffmann     int i = 0;
31186c0522cSGerd Hoffmann 
31286c0522cSGerd Hoffmann     if (dmabuf->texture != 0) {
31386c0522cSGerd Hoffmann         return;
31486c0522cSGerd Hoffmann     }
31586c0522cSGerd Hoffmann 
31615ee0d9bSGerd Hoffmann     attrs[i++] = EGL_WIDTH;
3179ac06df8SDongwon Kim     attrs[i++] = dmabuf->backing_width;
31815ee0d9bSGerd Hoffmann     attrs[i++] = EGL_HEIGHT;
3199ac06df8SDongwon Kim     attrs[i++] = dmabuf->backing_height;
32015ee0d9bSGerd Hoffmann     attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
32115ee0d9bSGerd Hoffmann     attrs[i++] = dmabuf->fourcc;
32215ee0d9bSGerd Hoffmann 
32315ee0d9bSGerd Hoffmann     attrs[i++] = EGL_DMA_BUF_PLANE0_FD_EXT;
32415ee0d9bSGerd Hoffmann     attrs[i++] = dmabuf->fd;
32515ee0d9bSGerd Hoffmann     attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
32615ee0d9bSGerd Hoffmann     attrs[i++] = dmabuf->stride;
32715ee0d9bSGerd Hoffmann     attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
32815ee0d9bSGerd Hoffmann     attrs[i++] = 0;
32915ee0d9bSGerd Hoffmann #ifdef EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT
33015ee0d9bSGerd Hoffmann     if (dmabuf->modifier) {
33115ee0d9bSGerd Hoffmann         attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
33215ee0d9bSGerd Hoffmann         attrs[i++] = (dmabuf->modifier >>  0) & 0xffffffff;
33315ee0d9bSGerd Hoffmann         attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
33415ee0d9bSGerd Hoffmann         attrs[i++] = (dmabuf->modifier >> 32) & 0xffffffff;
33515ee0d9bSGerd Hoffmann     }
33615ee0d9bSGerd Hoffmann #endif
33715ee0d9bSGerd Hoffmann     attrs[i++] = EGL_NONE;
33815ee0d9bSGerd Hoffmann 
33986c0522cSGerd Hoffmann     image = eglCreateImageKHR(qemu_egl_display,
34086c0522cSGerd Hoffmann                               EGL_NO_CONTEXT,
34186c0522cSGerd Hoffmann                               EGL_LINUX_DMA_BUF_EXT,
34286c0522cSGerd Hoffmann                               NULL, attrs);
34386c0522cSGerd Hoffmann     if (image == EGL_NO_IMAGE_KHR) {
34486c0522cSGerd Hoffmann         error_report("eglCreateImageKHR failed");
34586c0522cSGerd Hoffmann         return;
34686c0522cSGerd Hoffmann     }
34786c0522cSGerd Hoffmann 
34886c0522cSGerd Hoffmann     glGenTextures(1, &dmabuf->texture);
34986c0522cSGerd Hoffmann     glBindTexture(GL_TEXTURE_2D, dmabuf->texture);
35086c0522cSGerd Hoffmann     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
35186c0522cSGerd Hoffmann     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
35286c0522cSGerd Hoffmann 
35386c0522cSGerd Hoffmann     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
35486c0522cSGerd Hoffmann     eglDestroyImageKHR(qemu_egl_display, image);
35586c0522cSGerd Hoffmann }
35686c0522cSGerd Hoffmann 
egl_dmabuf_release_texture(QemuDmaBuf * dmabuf)35786c0522cSGerd Hoffmann void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
35886c0522cSGerd Hoffmann {
35986c0522cSGerd Hoffmann     if (dmabuf->texture == 0) {
36086c0522cSGerd Hoffmann         return;
36186c0522cSGerd Hoffmann     }
36286c0522cSGerd Hoffmann 
36386c0522cSGerd Hoffmann     glDeleteTextures(1, &dmabuf->texture);
36486c0522cSGerd Hoffmann     dmabuf->texture = 0;
36586c0522cSGerd Hoffmann }
36686c0522cSGerd Hoffmann 
egl_dmabuf_create_sync(QemuDmaBuf * dmabuf)367121abaf3SVivek Kasireddy void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
368121abaf3SVivek Kasireddy {
369121abaf3SVivek Kasireddy     EGLSyncKHR sync;
370121abaf3SVivek Kasireddy 
371121abaf3SVivek Kasireddy     if (epoxy_has_egl_extension(qemu_egl_display,
372121abaf3SVivek Kasireddy                                 "EGL_KHR_fence_sync") &&
373121abaf3SVivek Kasireddy         epoxy_has_egl_extension(qemu_egl_display,
374121abaf3SVivek Kasireddy                                 "EGL_ANDROID_native_fence_sync")) {
375121abaf3SVivek Kasireddy         sync = eglCreateSyncKHR(qemu_egl_display,
376121abaf3SVivek Kasireddy                                 EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
377121abaf3SVivek Kasireddy         if (sync != EGL_NO_SYNC_KHR) {
378121abaf3SVivek Kasireddy             dmabuf->sync = sync;
379121abaf3SVivek Kasireddy         }
380121abaf3SVivek Kasireddy     }
381121abaf3SVivek Kasireddy }
382121abaf3SVivek Kasireddy 
egl_dmabuf_create_fence(QemuDmaBuf * dmabuf)383121abaf3SVivek Kasireddy void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
384121abaf3SVivek Kasireddy {
385121abaf3SVivek Kasireddy     if (dmabuf->sync) {
386121abaf3SVivek Kasireddy         dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
387121abaf3SVivek Kasireddy                                                       dmabuf->sync);
388121abaf3SVivek Kasireddy         eglDestroySyncKHR(qemu_egl_display, dmabuf->sync);
389121abaf3SVivek Kasireddy         dmabuf->sync = NULL;
390121abaf3SVivek Kasireddy     }
391121abaf3SVivek Kasireddy }
392121abaf3SVivek Kasireddy 
393bc6a3565SAkihiko Odaki #endif /* CONFIG_GBM */
3941e316598SGerd Hoffmann 
3951e316598SGerd Hoffmann /* ---------------------------------------------------------------------- */
3961e316598SGerd Hoffmann 
qemu_egl_init_surface_x11(EGLContext ectx,EGLNativeWindowType win)397fbd57c75SAlexander Kanavin EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, EGLNativeWindowType win)
3987ced9e9fSGerd Hoffmann {
3997ced9e9fSGerd Hoffmann     EGLSurface esurface;
4007ced9e9fSGerd Hoffmann     EGLBoolean b;
4017ced9e9fSGerd Hoffmann 
4027ced9e9fSGerd Hoffmann     esurface = eglCreateWindowSurface(qemu_egl_display,
4037ced9e9fSGerd Hoffmann                                       qemu_egl_config,
404fbd57c75SAlexander Kanavin                                       win, NULL);
4057ced9e9fSGerd Hoffmann     if (esurface == EGL_NO_SURFACE) {
40638a55bddSCole Robinson         error_report("egl: eglCreateWindowSurface failed");
4077ced9e9fSGerd Hoffmann         return NULL;
4087ced9e9fSGerd Hoffmann     }
4097ced9e9fSGerd Hoffmann 
4107ced9e9fSGerd Hoffmann     b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx);
4117ced9e9fSGerd Hoffmann     if (b == EGL_FALSE) {
41238a55bddSCole Robinson         error_report("egl: eglMakeCurrent failed");
4137ced9e9fSGerd Hoffmann         return NULL;
4147ced9e9fSGerd Hoffmann     }
4157ced9e9fSGerd Hoffmann 
4167ced9e9fSGerd Hoffmann     return esurface;
4177ced9e9fSGerd Hoffmann }
4187ced9e9fSGerd Hoffmann 
4197ced9e9fSGerd Hoffmann /* ---------------------------------------------------------------------- */
4207ced9e9fSGerd Hoffmann 
42139324b49SMarc-André Lureau #if defined(CONFIG_X11) || defined(CONFIG_GBM) || defined(WIN32)
422bc6a3565SAkihiko Odaki 
4238bce03e3SGerd Hoffmann /*
4248bce03e3SGerd Hoffmann  * Taken from glamor_egl.h from the Xorg xserver, which is MIT licensed
4258bce03e3SGerd Hoffmann  *
4268bce03e3SGerd Hoffmann  * Create an EGLDisplay from a native display type. This is a little quirky
4278bce03e3SGerd Hoffmann  * for a few reasons.
4288bce03e3SGerd Hoffmann  *
4298bce03e3SGerd Hoffmann  * 1: GetPlatformDisplayEXT and GetPlatformDisplay are the API you want to
4308bce03e3SGerd Hoffmann  * use, but have different function signatures in the third argument; this
4318bce03e3SGerd Hoffmann  * happens not to matter for us, at the moment, but it means epoxy won't alias
4328bce03e3SGerd Hoffmann  * them together.
4338bce03e3SGerd Hoffmann  *
4348bce03e3SGerd Hoffmann  * 2: epoxy 1.3 and earlier don't understand EGL client extensions, which
4358bce03e3SGerd Hoffmann  * means you can't call "eglGetPlatformDisplayEXT" directly, as the resolver
4368bce03e3SGerd Hoffmann  * will crash.
4378bce03e3SGerd Hoffmann  *
4388bce03e3SGerd Hoffmann  * 3: You can't tell whether you have EGL 1.5 at this point, because
4398bce03e3SGerd Hoffmann  * eglQueryString(EGL_VERSION) is a property of the display, which we don't
4408bce03e3SGerd Hoffmann  * have yet. So you have to query for extensions no matter what. Fortunately
4418bce03e3SGerd Hoffmann  * epoxy_has_egl_extension _does_ let you query for client extensions, so
4428bce03e3SGerd Hoffmann  * we don't have to write our own extension string parsing.
4438bce03e3SGerd Hoffmann  *
4448bce03e3SGerd Hoffmann  * 4. There is no EGL_KHR_platform_base to complement the EXT one, thus one
4458bce03e3SGerd Hoffmann  * needs to know EGL 1.5 is supported in order to use the eglGetPlatformDisplay
4468bce03e3SGerd Hoffmann  * function pointer.
4478bce03e3SGerd Hoffmann  * We can workaround this (circular dependency) by probing for the EGL 1.5
4488bce03e3SGerd Hoffmann  * platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem
4498bce03e3SGerd Hoffmann  * like mesa will be able to advertise these (even though it can do EGL 1.5).
4508bce03e3SGerd Hoffmann  */
qemu_egl_get_display(EGLNativeDisplayType native,EGLenum platform)451e1913dbbSGerd Hoffmann static EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native,
452e1913dbbSGerd Hoffmann                                        EGLenum platform)
4538bce03e3SGerd Hoffmann {
4548bce03e3SGerd Hoffmann     EGLDisplay dpy = EGL_NO_DISPLAY;
4558bce03e3SGerd Hoffmann 
4568bce03e3SGerd Hoffmann     /* In practise any EGL 1.5 implementation would support the EXT extension */
4578bce03e3SGerd Hoffmann     if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) {
45872cbceadSMarc-André Lureau         if (platform != 0) {
45972cbceadSMarc-André Lureau             dpy = eglGetPlatformDisplayEXT(platform, native, NULL);
4608bce03e3SGerd Hoffmann         }
4618bce03e3SGerd Hoffmann     }
4628bce03e3SGerd Hoffmann 
4638bce03e3SGerd Hoffmann     if (dpy == EGL_NO_DISPLAY) {
4648bce03e3SGerd Hoffmann         /* fallback */
4658bce03e3SGerd Hoffmann         dpy = eglGetDisplay(native);
4668bce03e3SGerd Hoffmann     }
4678bce03e3SGerd Hoffmann     return dpy;
4688bce03e3SGerd Hoffmann }
4698bce03e3SGerd Hoffmann 
qemu_egl_init_dpy(EGLNativeDisplayType dpy,EGLenum platform,DisplayGLMode mode)470e1913dbbSGerd Hoffmann static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
47154d208ffSGerd Hoffmann                              EGLenum platform,
47254d208ffSGerd Hoffmann                              DisplayGLMode mode)
4737ced9e9fSGerd Hoffmann {
47454d208ffSGerd Hoffmann     static const EGLint conf_att_core[] = {
4757ced9e9fSGerd Hoffmann         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
4767ced9e9fSGerd Hoffmann         EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
4777ced9e9fSGerd Hoffmann         EGL_RED_SIZE,   5,
4787ced9e9fSGerd Hoffmann         EGL_GREEN_SIZE, 5,
4797ced9e9fSGerd Hoffmann         EGL_BLUE_SIZE,  5,
4807ced9e9fSGerd Hoffmann         EGL_ALPHA_SIZE, 0,
4817ced9e9fSGerd Hoffmann         EGL_NONE,
4827ced9e9fSGerd Hoffmann     };
48354d208ffSGerd Hoffmann     static const EGLint conf_att_gles[] = {
48454d208ffSGerd Hoffmann         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
48554d208ffSGerd Hoffmann         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
48654d208ffSGerd Hoffmann         EGL_RED_SIZE,   5,
48754d208ffSGerd Hoffmann         EGL_GREEN_SIZE, 5,
48854d208ffSGerd Hoffmann         EGL_BLUE_SIZE,  5,
48954d208ffSGerd Hoffmann         EGL_ALPHA_SIZE, 0,
49054d208ffSGerd Hoffmann         EGL_NONE,
49154d208ffSGerd Hoffmann     };
4927ced9e9fSGerd Hoffmann     EGLint major, minor;
4937ced9e9fSGerd Hoffmann     EGLBoolean b;
4947ced9e9fSGerd Hoffmann     EGLint n;
49554d208ffSGerd Hoffmann     bool gles = (mode == DISPLAYGL_MODE_ES);
4967ced9e9fSGerd Hoffmann 
497e1913dbbSGerd Hoffmann     qemu_egl_display = qemu_egl_get_display(dpy, platform);
4987ced9e9fSGerd Hoffmann     if (qemu_egl_display == EGL_NO_DISPLAY) {
499044ca4bfSMarc-André Lureau         error_report("egl: eglGetDisplay failed: %s", qemu_egl_get_error_string());
5007ced9e9fSGerd Hoffmann         return -1;
5017ced9e9fSGerd Hoffmann     }
5027ced9e9fSGerd Hoffmann 
5037ced9e9fSGerd Hoffmann     b = eglInitialize(qemu_egl_display, &major, &minor);
5047ced9e9fSGerd Hoffmann     if (b == EGL_FALSE) {
505044ca4bfSMarc-André Lureau         error_report("egl: eglInitialize failed: %s", qemu_egl_get_error_string());
5067ced9e9fSGerd Hoffmann         return -1;
5077ced9e9fSGerd Hoffmann     }
5087ced9e9fSGerd Hoffmann 
50954d208ffSGerd Hoffmann     b = eglBindAPI(gles ?  EGL_OPENGL_ES_API : EGL_OPENGL_API);
5107ced9e9fSGerd Hoffmann     if (b == EGL_FALSE) {
5111f086ef6SMarc-André Lureau         error_report("egl: eglBindAPI failed (%s mode): %s",
512044ca4bfSMarc-André Lureau                      gles ? "gles" : "core", qemu_egl_get_error_string());
5137ced9e9fSGerd Hoffmann         return -1;
5147ced9e9fSGerd Hoffmann     }
5157ced9e9fSGerd Hoffmann 
51654d208ffSGerd Hoffmann     b = eglChooseConfig(qemu_egl_display,
51754d208ffSGerd Hoffmann                         gles ? conf_att_gles : conf_att_core,
5187ced9e9fSGerd Hoffmann                         &qemu_egl_config, 1, &n);
5197ced9e9fSGerd Hoffmann     if (b == EGL_FALSE || n != 1) {
5201f086ef6SMarc-André Lureau         error_report("egl: eglChooseConfig failed (%s mode): %s",
521044ca4bfSMarc-André Lureau                      gles ? "gles" : "core", qemu_egl_get_error_string());
5227ced9e9fSGerd Hoffmann         return -1;
5237ced9e9fSGerd Hoffmann     }
52454d208ffSGerd Hoffmann 
52554d208ffSGerd Hoffmann     qemu_egl_mode = gles ? DISPLAYGL_MODE_ES : DISPLAYGL_MODE_CORE;
5267ced9e9fSGerd Hoffmann     return 0;
5277ced9e9fSGerd Hoffmann }
5287ced9e9fSGerd Hoffmann 
52939324b49SMarc-André Lureau #endif
53039324b49SMarc-André Lureau 
53139324b49SMarc-André Lureau #if defined(CONFIG_X11) || defined(CONFIG_GBM)
qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy,DisplayGLMode mode)53254d208ffSGerd Hoffmann int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy, DisplayGLMode mode)
533e1913dbbSGerd Hoffmann {
534e1913dbbSGerd Hoffmann #ifdef EGL_KHR_platform_x11
53554d208ffSGerd Hoffmann     return qemu_egl_init_dpy(dpy, EGL_PLATFORM_X11_KHR, mode);
536e1913dbbSGerd Hoffmann #else
53754d208ffSGerd Hoffmann     return qemu_egl_init_dpy(dpy, 0, mode);
538e1913dbbSGerd Hoffmann #endif
539e1913dbbSGerd Hoffmann }
540e1913dbbSGerd Hoffmann 
qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy,DisplayGLMode mode)54154d208ffSGerd Hoffmann int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode)
542e1913dbbSGerd Hoffmann {
543e1913dbbSGerd Hoffmann #ifdef EGL_MESA_platform_gbm
54454d208ffSGerd Hoffmann     return qemu_egl_init_dpy(dpy, EGL_PLATFORM_GBM_MESA, mode);
545e1913dbbSGerd Hoffmann #else
54654d208ffSGerd Hoffmann     return qemu_egl_init_dpy(dpy, 0, mode);
547e1913dbbSGerd Hoffmann #endif
548e1913dbbSGerd Hoffmann }
54939324b49SMarc-André Lureau #endif
550e1913dbbSGerd Hoffmann 
55139324b49SMarc-André Lureau 
55239324b49SMarc-André Lureau #ifdef WIN32
qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy,DisplayGLMode mode)55339324b49SMarc-André Lureau int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode)
55439324b49SMarc-André Lureau {
555afe8e0b6SMarc-André Lureau     /* prefer GL ES, as that's what ANGLE supports */
556afe8e0b6SMarc-André Lureau     if (mode == DISPLAYGL_MODE_ON) {
557afe8e0b6SMarc-André Lureau         mode = DISPLAYGL_MODE_ES;
558afe8e0b6SMarc-André Lureau     }
55906c63a34SMarc-André Lureau 
56006c63a34SMarc-André Lureau     if (qemu_egl_init_dpy(dpy, 0, mode) < 0) {
56106c63a34SMarc-André Lureau         return -1;
56206c63a34SMarc-André Lureau     }
56306c63a34SMarc-André Lureau 
56406c63a34SMarc-André Lureau #ifdef EGL_D3D11_DEVICE_ANGLE
56506c63a34SMarc-André Lureau     if (epoxy_has_egl_extension(qemu_egl_display, "EGL_EXT_device_query")) {
56606c63a34SMarc-André Lureau         EGLDeviceEXT device;
56706c63a34SMarc-André Lureau         void *d3d11_device;
56806c63a34SMarc-André Lureau 
56906c63a34SMarc-André Lureau         if (!eglQueryDisplayAttribEXT(qemu_egl_display,
57006c63a34SMarc-André Lureau                                       EGL_DEVICE_EXT,
57106c63a34SMarc-André Lureau                                       (EGLAttrib *)&device)) {
57206c63a34SMarc-André Lureau             return 0;
57306c63a34SMarc-André Lureau         }
57406c63a34SMarc-André Lureau 
57506c63a34SMarc-André Lureau         if (!eglQueryDeviceAttribEXT(device,
57606c63a34SMarc-André Lureau                                      EGL_D3D11_DEVICE_ANGLE,
57706c63a34SMarc-André Lureau                                      (EGLAttrib *)&d3d11_device)) {
57806c63a34SMarc-André Lureau             return 0;
57906c63a34SMarc-André Lureau         }
58006c63a34SMarc-André Lureau 
58106c63a34SMarc-André Lureau         trace_egl_init_d3d11_device(device);
58206c63a34SMarc-André Lureau         qemu_egl_angle_d3d = device != NULL;
58306c63a34SMarc-André Lureau     }
58406c63a34SMarc-André Lureau #endif
58506c63a34SMarc-André Lureau 
58606c63a34SMarc-André Lureau     return 0;
58739324b49SMarc-André Lureau }
588bc6a3565SAkihiko Odaki #endif
589bc6a3565SAkihiko Odaki 
qemu_egl_has_dmabuf(void)5900df5c72bSMarc-André Lureau bool qemu_egl_has_dmabuf(void)
5910df5c72bSMarc-André Lureau {
5920df5c72bSMarc-André Lureau     if (qemu_egl_display == EGL_NO_DISPLAY) {
5930df5c72bSMarc-André Lureau         return false;
5940df5c72bSMarc-André Lureau     }
5950df5c72bSMarc-André Lureau 
5960df5c72bSMarc-André Lureau     return epoxy_has_egl_extension(qemu_egl_display,
5970df5c72bSMarc-André Lureau                                    "EGL_EXT_image_dma_buf_import");
5980df5c72bSMarc-André Lureau }
5990df5c72bSMarc-André Lureau 
qemu_egl_init_ctx(void)6007ced9e9fSGerd Hoffmann EGLContext qemu_egl_init_ctx(void)
6017ced9e9fSGerd Hoffmann {
60254d208ffSGerd Hoffmann     static const EGLint ctx_att_core[] = {
603bc8c946fSGerd Hoffmann         EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
6047ced9e9fSGerd Hoffmann         EGL_NONE
6057ced9e9fSGerd Hoffmann     };
60654d208ffSGerd Hoffmann     static const EGLint ctx_att_gles[] = {
60754d208ffSGerd Hoffmann         EGL_CONTEXT_CLIENT_VERSION, 2,
60854d208ffSGerd Hoffmann         EGL_NONE
60954d208ffSGerd Hoffmann     };
61054d208ffSGerd Hoffmann     bool gles = (qemu_egl_mode == DISPLAYGL_MODE_ES);
6117ced9e9fSGerd Hoffmann     EGLContext ectx;
6127ced9e9fSGerd Hoffmann     EGLBoolean b;
6137ced9e9fSGerd Hoffmann 
6147ced9e9fSGerd Hoffmann     ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT,
61554d208ffSGerd Hoffmann                             gles ? ctx_att_gles : ctx_att_core);
6167ced9e9fSGerd Hoffmann     if (ectx == EGL_NO_CONTEXT) {
61738a55bddSCole Robinson         error_report("egl: eglCreateContext failed");
6187ced9e9fSGerd Hoffmann         return NULL;
6197ced9e9fSGerd Hoffmann     }
6207ced9e9fSGerd Hoffmann 
6217ced9e9fSGerd Hoffmann     b = eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, ectx);
6227ced9e9fSGerd Hoffmann     if (b == EGL_FALSE) {
62338a55bddSCole Robinson         error_report("egl: eglMakeCurrent failed");
6247ced9e9fSGerd Hoffmann         return NULL;
6257ced9e9fSGerd Hoffmann     }
6267ced9e9fSGerd Hoffmann 
6277ced9e9fSGerd Hoffmann     return ectx;
6287ced9e9fSGerd Hoffmann }
6290e1be59eSMarc-André Lureau 
egl_init(const char * rendernode,DisplayGLMode mode,Error ** errp)6300e1be59eSMarc-André Lureau bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp)
6310e1be59eSMarc-André Lureau {
6320e1be59eSMarc-André Lureau     ERRP_GUARD();
6330e1be59eSMarc-André Lureau 
6340e1be59eSMarc-André Lureau     if (mode == DISPLAYGL_MODE_OFF) {
6350e1be59eSMarc-André Lureau         error_setg(errp, "egl: turning off GL doesn't make sense");
6360e1be59eSMarc-André Lureau         return false;
6370e1be59eSMarc-André Lureau     }
6380e1be59eSMarc-André Lureau 
63939324b49SMarc-André Lureau #ifdef WIN32
64039324b49SMarc-André Lureau     if (qemu_egl_init_dpy_win32(EGL_DEFAULT_DISPLAY, mode) < 0) {
64139324b49SMarc-André Lureau         error_setg(errp, "egl: init failed");
64239324b49SMarc-André Lureau         return false;
64339324b49SMarc-André Lureau     }
64439324b49SMarc-André Lureau     qemu_egl_rn_ctx = qemu_egl_init_ctx();
64539324b49SMarc-André Lureau     if (!qemu_egl_rn_ctx) {
64639324b49SMarc-André Lureau         error_setg(errp, "egl: egl_init_ctx failed");
64739324b49SMarc-André Lureau         return false;
64839324b49SMarc-André Lureau     }
64939324b49SMarc-André Lureau #elif defined(CONFIG_GBM)
6500e1be59eSMarc-André Lureau     if (egl_rendernode_init(rendernode, mode) < 0) {
6510e1be59eSMarc-André Lureau         error_setg(errp, "egl: render node init failed");
6520e1be59eSMarc-André Lureau         return false;
6530e1be59eSMarc-André Lureau     }
65439324b49SMarc-André Lureau #endif
65539324b49SMarc-André Lureau 
65639324b49SMarc-André Lureau     if (!qemu_egl_rn_ctx) {
6570e1be59eSMarc-André Lureau         error_setg(errp, "egl: not available on this platform");
6580e1be59eSMarc-André Lureau         return false;
65939324b49SMarc-André Lureau     }
66039324b49SMarc-André Lureau 
66139324b49SMarc-André Lureau     display_opengl = 1;
66239324b49SMarc-André Lureau     return true;
6630e1be59eSMarc-André Lureau }
664