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) {
1496779a307SDongwon Kim x1 = qemu_dmabuf_get_x(src->dmabuf);
1506779a307SDongwon Kim y1 = qemu_dmabuf_get_y(src->dmabuf);
1516779a307SDongwon Kim w = qemu_dmabuf_get_width(src->dmabuf);
1526779a307SDongwon Kim h = qemu_dmabuf_get_height(src->dmabuf);
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;
3116779a307SDongwon Kim uint64_t modifier;
3126779a307SDongwon Kim uint32_t texture = qemu_dmabuf_get_texture(dmabuf);
31386c0522cSGerd Hoffmann
3146779a307SDongwon Kim if (texture != 0) {
31586c0522cSGerd Hoffmann return;
31686c0522cSGerd Hoffmann }
31786c0522cSGerd Hoffmann
31815ee0d9bSGerd Hoffmann attrs[i++] = EGL_WIDTH;
3196779a307SDongwon Kim attrs[i++] = qemu_dmabuf_get_backing_width(dmabuf);
32015ee0d9bSGerd Hoffmann attrs[i++] = EGL_HEIGHT;
3216779a307SDongwon Kim attrs[i++] = qemu_dmabuf_get_backing_height(dmabuf);
32215ee0d9bSGerd Hoffmann attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
3236779a307SDongwon Kim attrs[i++] = qemu_dmabuf_get_fourcc(dmabuf);
32415ee0d9bSGerd Hoffmann
32515ee0d9bSGerd Hoffmann attrs[i++] = EGL_DMA_BUF_PLANE0_FD_EXT;
3266779a307SDongwon Kim attrs[i++] = qemu_dmabuf_get_fd(dmabuf);
32715ee0d9bSGerd Hoffmann attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
3286779a307SDongwon Kim attrs[i++] = qemu_dmabuf_get_stride(dmabuf);
32915ee0d9bSGerd Hoffmann attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
33015ee0d9bSGerd Hoffmann attrs[i++] = 0;
33115ee0d9bSGerd Hoffmann #ifdef EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT
3326779a307SDongwon Kim modifier = qemu_dmabuf_get_modifier(dmabuf);
3336779a307SDongwon Kim if (modifier) {
33415ee0d9bSGerd Hoffmann attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
3356779a307SDongwon Kim attrs[i++] = (modifier >> 0) & 0xffffffff;
33615ee0d9bSGerd Hoffmann attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
3376779a307SDongwon Kim attrs[i++] = (modifier >> 32) & 0xffffffff;
33815ee0d9bSGerd Hoffmann }
33915ee0d9bSGerd Hoffmann #endif
34015ee0d9bSGerd Hoffmann attrs[i++] = EGL_NONE;
34115ee0d9bSGerd Hoffmann
34286c0522cSGerd Hoffmann image = eglCreateImageKHR(qemu_egl_display,
34386c0522cSGerd Hoffmann EGL_NO_CONTEXT,
34486c0522cSGerd Hoffmann EGL_LINUX_DMA_BUF_EXT,
34586c0522cSGerd Hoffmann NULL, attrs);
34686c0522cSGerd Hoffmann if (image == EGL_NO_IMAGE_KHR) {
34786c0522cSGerd Hoffmann error_report("eglCreateImageKHR failed");
34886c0522cSGerd Hoffmann return;
34986c0522cSGerd Hoffmann }
35086c0522cSGerd Hoffmann
351fa642680SDongwon Kim glGenTextures(1, &texture);
352fa642680SDongwon Kim qemu_dmabuf_set_texture(dmabuf, texture);
3536779a307SDongwon Kim glBindTexture(GL_TEXTURE_2D, texture);
35486c0522cSGerd Hoffmann glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
35586c0522cSGerd Hoffmann glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
35686c0522cSGerd Hoffmann
35786c0522cSGerd Hoffmann glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
35886c0522cSGerd Hoffmann eglDestroyImageKHR(qemu_egl_display, image);
35986c0522cSGerd Hoffmann }
36086c0522cSGerd Hoffmann
egl_dmabuf_release_texture(QemuDmaBuf * dmabuf)36186c0522cSGerd Hoffmann void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
36286c0522cSGerd Hoffmann {
3636779a307SDongwon Kim uint32_t texture;
3646779a307SDongwon Kim
3656779a307SDongwon Kim texture = qemu_dmabuf_get_texture(dmabuf);
3666779a307SDongwon Kim if (texture == 0) {
36786c0522cSGerd Hoffmann return;
36886c0522cSGerd Hoffmann }
36986c0522cSGerd Hoffmann
3706779a307SDongwon Kim glDeleteTextures(1, &texture);
371fa642680SDongwon Kim qemu_dmabuf_set_texture(dmabuf, 0);
37286c0522cSGerd Hoffmann }
37386c0522cSGerd Hoffmann
egl_dmabuf_create_sync(QemuDmaBuf * dmabuf)374121abaf3SVivek Kasireddy void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
375121abaf3SVivek Kasireddy {
376121abaf3SVivek Kasireddy EGLSyncKHR sync;
377121abaf3SVivek Kasireddy
378121abaf3SVivek Kasireddy if (epoxy_has_egl_extension(qemu_egl_display,
379121abaf3SVivek Kasireddy "EGL_KHR_fence_sync") &&
380121abaf3SVivek Kasireddy epoxy_has_egl_extension(qemu_egl_display,
381121abaf3SVivek Kasireddy "EGL_ANDROID_native_fence_sync")) {
382121abaf3SVivek Kasireddy sync = eglCreateSyncKHR(qemu_egl_display,
383121abaf3SVivek Kasireddy EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
384121abaf3SVivek Kasireddy if (sync != EGL_NO_SYNC_KHR) {
385fa642680SDongwon Kim qemu_dmabuf_set_sync(dmabuf, sync);
386121abaf3SVivek Kasireddy }
387121abaf3SVivek Kasireddy }
388121abaf3SVivek Kasireddy }
389121abaf3SVivek Kasireddy
egl_dmabuf_create_fence(QemuDmaBuf * dmabuf)390121abaf3SVivek Kasireddy void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
391121abaf3SVivek Kasireddy {
3926779a307SDongwon Kim void *sync = qemu_dmabuf_get_sync(dmabuf);
393fa642680SDongwon Kim int fence_fd;
3946779a307SDongwon Kim
3956779a307SDongwon Kim if (sync) {
396fa642680SDongwon Kim fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
3976779a307SDongwon Kim sync);
398fa642680SDongwon Kim qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
3996779a307SDongwon Kim eglDestroySyncKHR(qemu_egl_display, sync);
400fa642680SDongwon Kim qemu_dmabuf_set_sync(dmabuf, NULL);
401121abaf3SVivek Kasireddy }
402121abaf3SVivek Kasireddy }
403121abaf3SVivek Kasireddy
404bc6a3565SAkihiko Odaki #endif /* CONFIG_GBM */
4051e316598SGerd Hoffmann
4061e316598SGerd Hoffmann /* ---------------------------------------------------------------------- */
4071e316598SGerd Hoffmann
qemu_egl_init_surface_x11(EGLContext ectx,EGLNativeWindowType win)408fbd57c75SAlexander Kanavin EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, EGLNativeWindowType win)
4097ced9e9fSGerd Hoffmann {
4107ced9e9fSGerd Hoffmann EGLSurface esurface;
4117ced9e9fSGerd Hoffmann EGLBoolean b;
4127ced9e9fSGerd Hoffmann
4137ced9e9fSGerd Hoffmann esurface = eglCreateWindowSurface(qemu_egl_display,
4147ced9e9fSGerd Hoffmann qemu_egl_config,
415fbd57c75SAlexander Kanavin win, NULL);
4167ced9e9fSGerd Hoffmann if (esurface == EGL_NO_SURFACE) {
41738a55bddSCole Robinson error_report("egl: eglCreateWindowSurface failed");
4187ced9e9fSGerd Hoffmann return NULL;
4197ced9e9fSGerd Hoffmann }
4207ced9e9fSGerd Hoffmann
4217ced9e9fSGerd Hoffmann b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx);
4227ced9e9fSGerd Hoffmann if (b == EGL_FALSE) {
42338a55bddSCole Robinson error_report("egl: eglMakeCurrent failed");
4247ced9e9fSGerd Hoffmann return NULL;
4257ced9e9fSGerd Hoffmann }
4267ced9e9fSGerd Hoffmann
4277ced9e9fSGerd Hoffmann return esurface;
4287ced9e9fSGerd Hoffmann }
4297ced9e9fSGerd Hoffmann
4307ced9e9fSGerd Hoffmann /* ---------------------------------------------------------------------- */
4317ced9e9fSGerd Hoffmann
43239324b49SMarc-André Lureau #if defined(CONFIG_X11) || defined(CONFIG_GBM) || defined(WIN32)
433bc6a3565SAkihiko Odaki
4348bce03e3SGerd Hoffmann /*
4358bce03e3SGerd Hoffmann * Taken from glamor_egl.h from the Xorg xserver, which is MIT licensed
4368bce03e3SGerd Hoffmann *
4378bce03e3SGerd Hoffmann * Create an EGLDisplay from a native display type. This is a little quirky
4388bce03e3SGerd Hoffmann * for a few reasons.
4398bce03e3SGerd Hoffmann *
4408bce03e3SGerd Hoffmann * 1: GetPlatformDisplayEXT and GetPlatformDisplay are the API you want to
4418bce03e3SGerd Hoffmann * use, but have different function signatures in the third argument; this
4428bce03e3SGerd Hoffmann * happens not to matter for us, at the moment, but it means epoxy won't alias
4438bce03e3SGerd Hoffmann * them together.
4448bce03e3SGerd Hoffmann *
4458bce03e3SGerd Hoffmann * 2: epoxy 1.3 and earlier don't understand EGL client extensions, which
4468bce03e3SGerd Hoffmann * means you can't call "eglGetPlatformDisplayEXT" directly, as the resolver
4478bce03e3SGerd Hoffmann * will crash.
4488bce03e3SGerd Hoffmann *
4498bce03e3SGerd Hoffmann * 3: You can't tell whether you have EGL 1.5 at this point, because
4508bce03e3SGerd Hoffmann * eglQueryString(EGL_VERSION) is a property of the display, which we don't
4518bce03e3SGerd Hoffmann * have yet. So you have to query for extensions no matter what. Fortunately
4528bce03e3SGerd Hoffmann * epoxy_has_egl_extension _does_ let you query for client extensions, so
4538bce03e3SGerd Hoffmann * we don't have to write our own extension string parsing.
4548bce03e3SGerd Hoffmann *
4558bce03e3SGerd Hoffmann * 4. There is no EGL_KHR_platform_base to complement the EXT one, thus one
4568bce03e3SGerd Hoffmann * needs to know EGL 1.5 is supported in order to use the eglGetPlatformDisplay
4578bce03e3SGerd Hoffmann * function pointer.
4588bce03e3SGerd Hoffmann * We can workaround this (circular dependency) by probing for the EGL 1.5
4598bce03e3SGerd Hoffmann * platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem
4608bce03e3SGerd Hoffmann * like mesa will be able to advertise these (even though it can do EGL 1.5).
4618bce03e3SGerd Hoffmann */
qemu_egl_get_display(EGLNativeDisplayType native,EGLenum platform)462e1913dbbSGerd Hoffmann static EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native,
463e1913dbbSGerd Hoffmann EGLenum platform)
4648bce03e3SGerd Hoffmann {
4658bce03e3SGerd Hoffmann EGLDisplay dpy = EGL_NO_DISPLAY;
4668bce03e3SGerd Hoffmann
4678bce03e3SGerd Hoffmann /* In practise any EGL 1.5 implementation would support the EXT extension */
4688bce03e3SGerd Hoffmann if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) {
46972cbceadSMarc-André Lureau if (platform != 0) {
47072cbceadSMarc-André Lureau dpy = eglGetPlatformDisplayEXT(platform, native, NULL);
4718bce03e3SGerd Hoffmann }
4728bce03e3SGerd Hoffmann }
4738bce03e3SGerd Hoffmann
4748bce03e3SGerd Hoffmann if (dpy == EGL_NO_DISPLAY) {
4758bce03e3SGerd Hoffmann /* fallback */
4768bce03e3SGerd Hoffmann dpy = eglGetDisplay(native);
4778bce03e3SGerd Hoffmann }
4788bce03e3SGerd Hoffmann return dpy;
4798bce03e3SGerd Hoffmann }
4808bce03e3SGerd Hoffmann
qemu_egl_init_dpy(EGLNativeDisplayType dpy,EGLenum platform,DisplayGLMode mode)481e1913dbbSGerd Hoffmann static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
48254d208ffSGerd Hoffmann EGLenum platform,
48354d208ffSGerd Hoffmann DisplayGLMode mode)
4847ced9e9fSGerd Hoffmann {
48554d208ffSGerd Hoffmann static const EGLint conf_att_core[] = {
4867ced9e9fSGerd Hoffmann EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
4877ced9e9fSGerd Hoffmann EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
4887ced9e9fSGerd Hoffmann EGL_RED_SIZE, 5,
4897ced9e9fSGerd Hoffmann EGL_GREEN_SIZE, 5,
4907ced9e9fSGerd Hoffmann EGL_BLUE_SIZE, 5,
4917ced9e9fSGerd Hoffmann EGL_ALPHA_SIZE, 0,
4927ced9e9fSGerd Hoffmann EGL_NONE,
4937ced9e9fSGerd Hoffmann };
49454d208ffSGerd Hoffmann static const EGLint conf_att_gles[] = {
49554d208ffSGerd Hoffmann EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
49654d208ffSGerd Hoffmann EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
49754d208ffSGerd Hoffmann EGL_RED_SIZE, 5,
49854d208ffSGerd Hoffmann EGL_GREEN_SIZE, 5,
49954d208ffSGerd Hoffmann EGL_BLUE_SIZE, 5,
50054d208ffSGerd Hoffmann EGL_ALPHA_SIZE, 0,
50154d208ffSGerd Hoffmann EGL_NONE,
50254d208ffSGerd Hoffmann };
5037ced9e9fSGerd Hoffmann EGLint major, minor;
5047ced9e9fSGerd Hoffmann EGLBoolean b;
5057ced9e9fSGerd Hoffmann EGLint n;
506*154fd4d1SMarkus Armbruster bool gles = (mode == DISPLAY_GL_MODE_ES);
5077ced9e9fSGerd Hoffmann
508e1913dbbSGerd Hoffmann qemu_egl_display = qemu_egl_get_display(dpy, platform);
5097ced9e9fSGerd Hoffmann if (qemu_egl_display == EGL_NO_DISPLAY) {
510044ca4bfSMarc-André Lureau error_report("egl: eglGetDisplay failed: %s", qemu_egl_get_error_string());
5117ced9e9fSGerd Hoffmann return -1;
5127ced9e9fSGerd Hoffmann }
5137ced9e9fSGerd Hoffmann
5147ced9e9fSGerd Hoffmann b = eglInitialize(qemu_egl_display, &major, &minor);
5157ced9e9fSGerd Hoffmann if (b == EGL_FALSE) {
516044ca4bfSMarc-André Lureau error_report("egl: eglInitialize failed: %s", qemu_egl_get_error_string());
5177ced9e9fSGerd Hoffmann return -1;
5187ced9e9fSGerd Hoffmann }
5197ced9e9fSGerd Hoffmann
52054d208ffSGerd Hoffmann b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
5217ced9e9fSGerd Hoffmann if (b == EGL_FALSE) {
5221f086ef6SMarc-André Lureau error_report("egl: eglBindAPI failed (%s mode): %s",
523044ca4bfSMarc-André Lureau gles ? "gles" : "core", qemu_egl_get_error_string());
5247ced9e9fSGerd Hoffmann return -1;
5257ced9e9fSGerd Hoffmann }
5267ced9e9fSGerd Hoffmann
52754d208ffSGerd Hoffmann b = eglChooseConfig(qemu_egl_display,
52854d208ffSGerd Hoffmann gles ? conf_att_gles : conf_att_core,
5297ced9e9fSGerd Hoffmann &qemu_egl_config, 1, &n);
5307ced9e9fSGerd Hoffmann if (b == EGL_FALSE || n != 1) {
5311f086ef6SMarc-André Lureau error_report("egl: eglChooseConfig failed (%s mode): %s",
532044ca4bfSMarc-André Lureau gles ? "gles" : "core", qemu_egl_get_error_string());
5337ced9e9fSGerd Hoffmann return -1;
5347ced9e9fSGerd Hoffmann }
53554d208ffSGerd Hoffmann
536*154fd4d1SMarkus Armbruster qemu_egl_mode = gles ? DISPLAY_GL_MODE_ES : DISPLAY_GL_MODE_CORE;
5377ced9e9fSGerd Hoffmann return 0;
5387ced9e9fSGerd Hoffmann }
5397ced9e9fSGerd Hoffmann
54039324b49SMarc-André Lureau #endif
54139324b49SMarc-André Lureau
54239324b49SMarc-André Lureau #if defined(CONFIG_X11) || defined(CONFIG_GBM)
qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy,DisplayGLMode mode)54354d208ffSGerd Hoffmann int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy, DisplayGLMode mode)
544e1913dbbSGerd Hoffmann {
545e1913dbbSGerd Hoffmann #ifdef EGL_KHR_platform_x11
54654d208ffSGerd Hoffmann return qemu_egl_init_dpy(dpy, EGL_PLATFORM_X11_KHR, mode);
547e1913dbbSGerd Hoffmann #else
54854d208ffSGerd Hoffmann return qemu_egl_init_dpy(dpy, 0, mode);
549e1913dbbSGerd Hoffmann #endif
550e1913dbbSGerd Hoffmann }
551e1913dbbSGerd Hoffmann
qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy,DisplayGLMode mode)55254d208ffSGerd Hoffmann int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode)
553e1913dbbSGerd Hoffmann {
554e1913dbbSGerd Hoffmann #ifdef EGL_MESA_platform_gbm
55554d208ffSGerd Hoffmann return qemu_egl_init_dpy(dpy, EGL_PLATFORM_GBM_MESA, mode);
556e1913dbbSGerd Hoffmann #else
55754d208ffSGerd Hoffmann return qemu_egl_init_dpy(dpy, 0, mode);
558e1913dbbSGerd Hoffmann #endif
559e1913dbbSGerd Hoffmann }
56039324b49SMarc-André Lureau #endif
561e1913dbbSGerd Hoffmann
56239324b49SMarc-André Lureau
56339324b49SMarc-André Lureau #ifdef WIN32
qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy,DisplayGLMode mode)56439324b49SMarc-André Lureau int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode)
56539324b49SMarc-André Lureau {
566afe8e0b6SMarc-André Lureau /* prefer GL ES, as that's what ANGLE supports */
567*154fd4d1SMarkus Armbruster if (mode == DISPLAY_GL_MODE_ON) {
568*154fd4d1SMarkus Armbruster mode = DISPLAY_GL_MODE_ES;
569afe8e0b6SMarc-André Lureau }
57006c63a34SMarc-André Lureau
57106c63a34SMarc-André Lureau if (qemu_egl_init_dpy(dpy, 0, mode) < 0) {
57206c63a34SMarc-André Lureau return -1;
57306c63a34SMarc-André Lureau }
57406c63a34SMarc-André Lureau
57506c63a34SMarc-André Lureau #ifdef EGL_D3D11_DEVICE_ANGLE
57606c63a34SMarc-André Lureau if (epoxy_has_egl_extension(qemu_egl_display, "EGL_EXT_device_query")) {
57706c63a34SMarc-André Lureau EGLDeviceEXT device;
57806c63a34SMarc-André Lureau void *d3d11_device;
57906c63a34SMarc-André Lureau
58006c63a34SMarc-André Lureau if (!eglQueryDisplayAttribEXT(qemu_egl_display,
58106c63a34SMarc-André Lureau EGL_DEVICE_EXT,
58206c63a34SMarc-André Lureau (EGLAttrib *)&device)) {
58306c63a34SMarc-André Lureau return 0;
58406c63a34SMarc-André Lureau }
58506c63a34SMarc-André Lureau
58606c63a34SMarc-André Lureau if (!eglQueryDeviceAttribEXT(device,
58706c63a34SMarc-André Lureau EGL_D3D11_DEVICE_ANGLE,
58806c63a34SMarc-André Lureau (EGLAttrib *)&d3d11_device)) {
58906c63a34SMarc-André Lureau return 0;
59006c63a34SMarc-André Lureau }
59106c63a34SMarc-André Lureau
59206c63a34SMarc-André Lureau trace_egl_init_d3d11_device(device);
59306c63a34SMarc-André Lureau qemu_egl_angle_d3d = device != NULL;
59406c63a34SMarc-André Lureau }
59506c63a34SMarc-André Lureau #endif
59606c63a34SMarc-André Lureau
59706c63a34SMarc-André Lureau return 0;
59839324b49SMarc-André Lureau }
599bc6a3565SAkihiko Odaki #endif
600bc6a3565SAkihiko Odaki
qemu_egl_has_dmabuf(void)6010df5c72bSMarc-André Lureau bool qemu_egl_has_dmabuf(void)
6020df5c72bSMarc-André Lureau {
6030df5c72bSMarc-André Lureau if (qemu_egl_display == EGL_NO_DISPLAY) {
6040df5c72bSMarc-André Lureau return false;
6050df5c72bSMarc-André Lureau }
6060df5c72bSMarc-André Lureau
6070df5c72bSMarc-André Lureau return epoxy_has_egl_extension(qemu_egl_display,
6080df5c72bSMarc-André Lureau "EGL_EXT_image_dma_buf_import");
6090df5c72bSMarc-André Lureau }
6100df5c72bSMarc-André Lureau
qemu_egl_init_ctx(void)6117ced9e9fSGerd Hoffmann EGLContext qemu_egl_init_ctx(void)
6127ced9e9fSGerd Hoffmann {
61354d208ffSGerd Hoffmann static const EGLint ctx_att_core[] = {
614bc8c946fSGerd Hoffmann EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
6157ced9e9fSGerd Hoffmann EGL_NONE
6167ced9e9fSGerd Hoffmann };
61754d208ffSGerd Hoffmann static const EGLint ctx_att_gles[] = {
61854d208ffSGerd Hoffmann EGL_CONTEXT_CLIENT_VERSION, 2,
61954d208ffSGerd Hoffmann EGL_NONE
62054d208ffSGerd Hoffmann };
621*154fd4d1SMarkus Armbruster bool gles = (qemu_egl_mode == DISPLAY_GL_MODE_ES);
6227ced9e9fSGerd Hoffmann EGLContext ectx;
6237ced9e9fSGerd Hoffmann EGLBoolean b;
6247ced9e9fSGerd Hoffmann
6257ced9e9fSGerd Hoffmann ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT,
62654d208ffSGerd Hoffmann gles ? ctx_att_gles : ctx_att_core);
6277ced9e9fSGerd Hoffmann if (ectx == EGL_NO_CONTEXT) {
62838a55bddSCole Robinson error_report("egl: eglCreateContext failed");
6297ced9e9fSGerd Hoffmann return NULL;
6307ced9e9fSGerd Hoffmann }
6317ced9e9fSGerd Hoffmann
6327ced9e9fSGerd Hoffmann b = eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, ectx);
6337ced9e9fSGerd Hoffmann if (b == EGL_FALSE) {
63438a55bddSCole Robinson error_report("egl: eglMakeCurrent failed");
6357ced9e9fSGerd Hoffmann return NULL;
6367ced9e9fSGerd Hoffmann }
6377ced9e9fSGerd Hoffmann
6387ced9e9fSGerd Hoffmann return ectx;
6397ced9e9fSGerd Hoffmann }
6400e1be59eSMarc-André Lureau
egl_init(const char * rendernode,DisplayGLMode mode,Error ** errp)6410e1be59eSMarc-André Lureau bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp)
6420e1be59eSMarc-André Lureau {
6430e1be59eSMarc-André Lureau ERRP_GUARD();
6440e1be59eSMarc-André Lureau
645*154fd4d1SMarkus Armbruster if (mode == DISPLAY_GL_MODE_OFF) {
6460e1be59eSMarc-André Lureau error_setg(errp, "egl: turning off GL doesn't make sense");
6470e1be59eSMarc-André Lureau return false;
6480e1be59eSMarc-André Lureau }
6490e1be59eSMarc-André Lureau
65039324b49SMarc-André Lureau #ifdef WIN32
65139324b49SMarc-André Lureau if (qemu_egl_init_dpy_win32(EGL_DEFAULT_DISPLAY, mode) < 0) {
65239324b49SMarc-André Lureau error_setg(errp, "egl: init failed");
65339324b49SMarc-André Lureau return false;
65439324b49SMarc-André Lureau }
65539324b49SMarc-André Lureau qemu_egl_rn_ctx = qemu_egl_init_ctx();
65639324b49SMarc-André Lureau if (!qemu_egl_rn_ctx) {
65739324b49SMarc-André Lureau error_setg(errp, "egl: egl_init_ctx failed");
65839324b49SMarc-André Lureau return false;
65939324b49SMarc-André Lureau }
66039324b49SMarc-André Lureau #elif defined(CONFIG_GBM)
6610e1be59eSMarc-André Lureau if (egl_rendernode_init(rendernode, mode) < 0) {
6620e1be59eSMarc-André Lureau error_setg(errp, "egl: render node init failed");
6630e1be59eSMarc-André Lureau return false;
6640e1be59eSMarc-André Lureau }
66539324b49SMarc-André Lureau #endif
66639324b49SMarc-André Lureau
66739324b49SMarc-André Lureau if (!qemu_egl_rn_ctx) {
6680e1be59eSMarc-André Lureau error_setg(errp, "egl: not available on this platform");
6690e1be59eSMarc-André Lureau return false;
67039324b49SMarc-André Lureau }
67139324b49SMarc-André Lureau
67239324b49SMarc-André Lureau display_opengl = 1;
67339324b49SMarc-André Lureau return true;
6740e1be59eSMarc-André Lureau }
675