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" 18b1d38037SMarc-André Lureau #include "qemu/drm.h" 1938a55bddSCole Robinson #include "qemu/error-report.h" 2086c0522cSGerd Hoffmann #include "ui/console.h" 217ced9e9fSGerd Hoffmann #include "ui/egl-helpers.h" 227ced9e9fSGerd Hoffmann 237ced9e9fSGerd Hoffmann EGLDisplay *qemu_egl_display; 247ced9e9fSGerd Hoffmann EGLConfig qemu_egl_config; 2554d208ffSGerd Hoffmann DisplayGLMode qemu_egl_mode; 267ced9e9fSGerd Hoffmann 276fafc260SGerd Hoffmann /* ------------------------------------------------------------------ */ 286fafc260SGerd Hoffmann 2974083f9cSGerd Hoffmann static void egl_fb_delete_texture(egl_fb *fb) 3074083f9cSGerd Hoffmann { 3174083f9cSGerd Hoffmann if (!fb->delete_texture) { 3274083f9cSGerd Hoffmann return; 3374083f9cSGerd Hoffmann } 3474083f9cSGerd Hoffmann 3574083f9cSGerd Hoffmann glDeleteTextures(1, &fb->texture); 3674083f9cSGerd Hoffmann fb->delete_texture = false; 3774083f9cSGerd Hoffmann } 3874083f9cSGerd Hoffmann 396fafc260SGerd Hoffmann void egl_fb_destroy(egl_fb *fb) 406fafc260SGerd Hoffmann { 416fafc260SGerd Hoffmann if (!fb->framebuffer) { 426fafc260SGerd Hoffmann return; 436fafc260SGerd Hoffmann } 446fafc260SGerd Hoffmann 4574083f9cSGerd Hoffmann egl_fb_delete_texture(fb); 466fafc260SGerd Hoffmann glDeleteFramebuffers(1, &fb->framebuffer); 476fafc260SGerd Hoffmann 486fafc260SGerd Hoffmann fb->width = 0; 496fafc260SGerd Hoffmann fb->height = 0; 506fafc260SGerd Hoffmann fb->texture = 0; 516fafc260SGerd Hoffmann fb->framebuffer = 0; 526fafc260SGerd Hoffmann } 536fafc260SGerd Hoffmann 546fafc260SGerd Hoffmann void egl_fb_setup_default(egl_fb *fb, int width, int height) 556fafc260SGerd Hoffmann { 566fafc260SGerd Hoffmann fb->width = width; 576fafc260SGerd Hoffmann fb->height = height; 586fafc260SGerd Hoffmann fb->framebuffer = 0; /* default framebuffer */ 596fafc260SGerd Hoffmann } 606fafc260SGerd Hoffmann 6174083f9cSGerd Hoffmann void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, 6274083f9cSGerd Hoffmann GLuint texture, bool delete) 636fafc260SGerd Hoffmann { 6474083f9cSGerd Hoffmann egl_fb_delete_texture(fb); 6574083f9cSGerd Hoffmann 666fafc260SGerd Hoffmann fb->width = width; 676fafc260SGerd Hoffmann fb->height = height; 686fafc260SGerd Hoffmann fb->texture = texture; 6974083f9cSGerd Hoffmann fb->delete_texture = delete; 706fafc260SGerd Hoffmann if (!fb->framebuffer) { 716fafc260SGerd Hoffmann glGenFramebuffers(1, &fb->framebuffer); 726fafc260SGerd Hoffmann } 736fafc260SGerd Hoffmann 746fafc260SGerd Hoffmann glBindFramebuffer(GL_FRAMEBUFFER_EXT, fb->framebuffer); 756fafc260SGerd Hoffmann glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 766fafc260SGerd Hoffmann GL_TEXTURE_2D, fb->texture, 0); 776fafc260SGerd Hoffmann } 786fafc260SGerd Hoffmann 7974083f9cSGerd Hoffmann void egl_fb_setup_new_tex(egl_fb *fb, int width, int height) 806fafc260SGerd Hoffmann { 816fafc260SGerd Hoffmann GLuint texture; 826fafc260SGerd Hoffmann 836fafc260SGerd Hoffmann glGenTextures(1, &texture); 846fafc260SGerd Hoffmann glBindTexture(GL_TEXTURE_2D, texture); 8541126214SGerd Hoffmann glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 866fafc260SGerd Hoffmann 0, GL_BGRA, GL_UNSIGNED_BYTE, 0); 876fafc260SGerd Hoffmann 8874083f9cSGerd Hoffmann egl_fb_setup_for_tex(fb, width, height, texture, true); 896fafc260SGerd Hoffmann } 906fafc260SGerd Hoffmann 916fafc260SGerd Hoffmann void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip) 926fafc260SGerd Hoffmann { 936fafc260SGerd Hoffmann GLuint y1, y2; 946fafc260SGerd Hoffmann 956fafc260SGerd Hoffmann glBindFramebuffer(GL_READ_FRAMEBUFFER, src->framebuffer); 966fafc260SGerd Hoffmann glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst->framebuffer); 976fafc260SGerd Hoffmann glViewport(0, 0, dst->width, dst->height); 986fafc260SGerd Hoffmann y1 = flip ? src->height : 0; 996fafc260SGerd Hoffmann y2 = flip ? 0 : src->height; 1006fafc260SGerd Hoffmann glBlitFramebuffer(0, y1, src->width, y2, 1016fafc260SGerd Hoffmann 0, 0, dst->width, dst->height, 1026fafc260SGerd Hoffmann GL_COLOR_BUFFER_BIT, GL_LINEAR); 1036fafc260SGerd Hoffmann } 1046fafc260SGerd Hoffmann 1056fafc260SGerd Hoffmann void egl_fb_read(void *dst, egl_fb *src) 1066fafc260SGerd Hoffmann { 1076fafc260SGerd Hoffmann glBindFramebuffer(GL_READ_FRAMEBUFFER, src->framebuffer); 1086fafc260SGerd Hoffmann glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); 1096fafc260SGerd Hoffmann glReadPixels(0, 0, src->width, src->height, 1106fafc260SGerd Hoffmann GL_BGRA, GL_UNSIGNED_BYTE, dst); 1116fafc260SGerd Hoffmann } 1126fafc260SGerd Hoffmann 1130eb50c27SGerd Hoffmann void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip) 1140eb50c27SGerd Hoffmann { 1150eb50c27SGerd Hoffmann glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer); 1160eb50c27SGerd Hoffmann glViewport(0, 0, dst->width, dst->height); 1170eb50c27SGerd Hoffmann glEnable(GL_TEXTURE_2D); 1180eb50c27SGerd Hoffmann glBindTexture(GL_TEXTURE_2D, src->texture); 1190eb50c27SGerd Hoffmann qemu_gl_run_texture_blit(gls, flip); 1200eb50c27SGerd Hoffmann } 1210eb50c27SGerd Hoffmann 1220eb50c27SGerd Hoffmann void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip, 123*051a0cdeSChen Zhang int x, int y, double scale_x, double scale_y) 1240eb50c27SGerd Hoffmann { 1250eb50c27SGerd Hoffmann glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer); 126*051a0cdeSChen Zhang int w = scale_x * src->width; 127*051a0cdeSChen Zhang int h = scale_y * src->height; 1280eb50c27SGerd Hoffmann if (flip) { 129*051a0cdeSChen Zhang glViewport(x, y, w, h); 1300eb50c27SGerd Hoffmann } else { 131*051a0cdeSChen Zhang glViewport(x, dst->height - h - y, w, h); 1320eb50c27SGerd Hoffmann } 1330eb50c27SGerd Hoffmann glEnable(GL_TEXTURE_2D); 1340eb50c27SGerd Hoffmann glBindTexture(GL_TEXTURE_2D, src->texture); 1350eb50c27SGerd Hoffmann glEnable(GL_BLEND); 1360eb50c27SGerd Hoffmann glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1370eb50c27SGerd Hoffmann qemu_gl_run_texture_blit(gls, flip); 1380eb50c27SGerd Hoffmann glDisable(GL_BLEND); 1390eb50c27SGerd Hoffmann } 1400eb50c27SGerd Hoffmann 1417ced9e9fSGerd Hoffmann /* ---------------------------------------------------------------------- */ 1427ced9e9fSGerd Hoffmann 1431e316598SGerd Hoffmann #ifdef CONFIG_OPENGL_DMABUF 1441e316598SGerd Hoffmann 1451e316598SGerd Hoffmann int qemu_egl_rn_fd; 1461e316598SGerd Hoffmann struct gbm_device *qemu_egl_rn_gbm_dev; 1471e316598SGerd Hoffmann EGLContext qemu_egl_rn_ctx; 1481e316598SGerd Hoffmann 14954d208ffSGerd Hoffmann int egl_rendernode_init(const char *rendernode, DisplayGLMode mode) 1501e316598SGerd Hoffmann { 1511e316598SGerd Hoffmann qemu_egl_rn_fd = -1; 152151c8e60SGerd Hoffmann int rc; 1531e316598SGerd Hoffmann 154b1d38037SMarc-André Lureau qemu_egl_rn_fd = qemu_drm_rendernode_open(rendernode); 1551e316598SGerd Hoffmann if (qemu_egl_rn_fd == -1) { 15638a55bddSCole Robinson error_report("egl: no drm render node available"); 1571e316598SGerd Hoffmann goto err; 1581e316598SGerd Hoffmann } 1591e316598SGerd Hoffmann 1601e316598SGerd Hoffmann qemu_egl_rn_gbm_dev = gbm_create_device(qemu_egl_rn_fd); 1611e316598SGerd Hoffmann if (!qemu_egl_rn_gbm_dev) { 16238a55bddSCole Robinson error_report("egl: gbm_create_device failed"); 1631e316598SGerd Hoffmann goto err; 1641e316598SGerd Hoffmann } 1651e316598SGerd Hoffmann 16654d208ffSGerd Hoffmann rc = qemu_egl_init_dpy_mesa((EGLNativeDisplayType)qemu_egl_rn_gbm_dev, 16754d208ffSGerd Hoffmann mode); 168151c8e60SGerd Hoffmann if (rc != 0) { 169151c8e60SGerd Hoffmann /* qemu_egl_init_dpy_mesa reports error */ 170151c8e60SGerd Hoffmann goto err; 171151c8e60SGerd Hoffmann } 1721e316598SGerd Hoffmann 1731e316598SGerd Hoffmann if (!epoxy_has_egl_extension(qemu_egl_display, 1741e316598SGerd Hoffmann "EGL_KHR_surfaceless_context")) { 17538a55bddSCole Robinson error_report("egl: EGL_KHR_surfaceless_context not supported"); 1761e316598SGerd Hoffmann goto err; 1771e316598SGerd Hoffmann } 1781e316598SGerd Hoffmann if (!epoxy_has_egl_extension(qemu_egl_display, 1791e316598SGerd Hoffmann "EGL_MESA_image_dma_buf_export")) { 18038a55bddSCole Robinson error_report("egl: EGL_MESA_image_dma_buf_export not supported"); 1811e316598SGerd Hoffmann goto err; 1821e316598SGerd Hoffmann } 1831e316598SGerd Hoffmann 1841e316598SGerd Hoffmann qemu_egl_rn_ctx = qemu_egl_init_ctx(); 1851e316598SGerd Hoffmann if (!qemu_egl_rn_ctx) { 18638a55bddSCole Robinson error_report("egl: egl_init_ctx failed"); 1871e316598SGerd Hoffmann goto err; 1881e316598SGerd Hoffmann } 1891e316598SGerd Hoffmann 1901e316598SGerd Hoffmann return 0; 1911e316598SGerd Hoffmann 1921e316598SGerd Hoffmann err: 1931e316598SGerd Hoffmann if (qemu_egl_rn_gbm_dev) { 1941e316598SGerd Hoffmann gbm_device_destroy(qemu_egl_rn_gbm_dev); 1951e316598SGerd Hoffmann } 1961e316598SGerd Hoffmann if (qemu_egl_rn_fd != -1) { 1971e316598SGerd Hoffmann close(qemu_egl_rn_fd); 1981e316598SGerd Hoffmann } 1991e316598SGerd Hoffmann 2001e316598SGerd Hoffmann return -1; 2011e316598SGerd Hoffmann } 2021e316598SGerd Hoffmann 2031e316598SGerd Hoffmann int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc) 2041e316598SGerd Hoffmann { 2051e316598SGerd Hoffmann EGLImageKHR image; 2061e316598SGerd Hoffmann EGLint num_planes, fd; 2071e316598SGerd Hoffmann 2081e316598SGerd Hoffmann image = eglCreateImageKHR(qemu_egl_display, eglGetCurrentContext(), 2091e316598SGerd Hoffmann EGL_GL_TEXTURE_2D_KHR, 2101e316598SGerd Hoffmann (EGLClientBuffer)(unsigned long)tex_id, 2111e316598SGerd Hoffmann NULL); 2121e316598SGerd Hoffmann if (!image) { 2131e316598SGerd Hoffmann return -1; 2141e316598SGerd Hoffmann } 2151e316598SGerd Hoffmann 2161e316598SGerd Hoffmann eglExportDMABUFImageQueryMESA(qemu_egl_display, image, fourcc, 2171e316598SGerd Hoffmann &num_planes, NULL); 2181e316598SGerd Hoffmann if (num_planes != 1) { 2191e316598SGerd Hoffmann eglDestroyImageKHR(qemu_egl_display, image); 2201e316598SGerd Hoffmann return -1; 2211e316598SGerd Hoffmann } 2221e316598SGerd Hoffmann eglExportDMABUFImageMESA(qemu_egl_display, image, &fd, stride, NULL); 2231e316598SGerd Hoffmann eglDestroyImageKHR(qemu_egl_display, image); 2241e316598SGerd Hoffmann 2251e316598SGerd Hoffmann return fd; 2261e316598SGerd Hoffmann } 2271e316598SGerd Hoffmann 22886c0522cSGerd Hoffmann void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) 22986c0522cSGerd Hoffmann { 23086c0522cSGerd Hoffmann EGLImageKHR image = EGL_NO_IMAGE_KHR; 23186c0522cSGerd Hoffmann EGLint attrs[] = { 23286c0522cSGerd Hoffmann EGL_DMA_BUF_PLANE0_FD_EXT, dmabuf->fd, 23386c0522cSGerd Hoffmann EGL_DMA_BUF_PLANE0_PITCH_EXT, dmabuf->stride, 23486c0522cSGerd Hoffmann EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, 23586c0522cSGerd Hoffmann EGL_WIDTH, dmabuf->width, 23686c0522cSGerd Hoffmann EGL_HEIGHT, dmabuf->height, 23786c0522cSGerd Hoffmann EGL_LINUX_DRM_FOURCC_EXT, dmabuf->fourcc, 23886c0522cSGerd Hoffmann EGL_NONE, /* end of list */ 23986c0522cSGerd Hoffmann }; 24086c0522cSGerd Hoffmann 24186c0522cSGerd Hoffmann if (dmabuf->texture != 0) { 24286c0522cSGerd Hoffmann return; 24386c0522cSGerd Hoffmann } 24486c0522cSGerd Hoffmann 24586c0522cSGerd Hoffmann image = eglCreateImageKHR(qemu_egl_display, 24686c0522cSGerd Hoffmann EGL_NO_CONTEXT, 24786c0522cSGerd Hoffmann EGL_LINUX_DMA_BUF_EXT, 24886c0522cSGerd Hoffmann NULL, attrs); 24986c0522cSGerd Hoffmann if (image == EGL_NO_IMAGE_KHR) { 25086c0522cSGerd Hoffmann error_report("eglCreateImageKHR failed"); 25186c0522cSGerd Hoffmann return; 25286c0522cSGerd Hoffmann } 25386c0522cSGerd Hoffmann 25486c0522cSGerd Hoffmann glGenTextures(1, &dmabuf->texture); 25586c0522cSGerd Hoffmann glBindTexture(GL_TEXTURE_2D, dmabuf->texture); 25686c0522cSGerd Hoffmann glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 25786c0522cSGerd Hoffmann glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 25886c0522cSGerd Hoffmann 25986c0522cSGerd Hoffmann glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); 26086c0522cSGerd Hoffmann eglDestroyImageKHR(qemu_egl_display, image); 26186c0522cSGerd Hoffmann } 26286c0522cSGerd Hoffmann 26386c0522cSGerd Hoffmann void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) 26486c0522cSGerd Hoffmann { 26586c0522cSGerd Hoffmann if (dmabuf->texture == 0) { 26686c0522cSGerd Hoffmann return; 26786c0522cSGerd Hoffmann } 26886c0522cSGerd Hoffmann 26986c0522cSGerd Hoffmann glDeleteTextures(1, &dmabuf->texture); 27086c0522cSGerd Hoffmann dmabuf->texture = 0; 27186c0522cSGerd Hoffmann } 27286c0522cSGerd Hoffmann 2731e316598SGerd Hoffmann #endif /* CONFIG_OPENGL_DMABUF */ 2741e316598SGerd Hoffmann 2751e316598SGerd Hoffmann /* ---------------------------------------------------------------------- */ 2761e316598SGerd Hoffmann 277fbd57c75SAlexander Kanavin EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, EGLNativeWindowType win) 2787ced9e9fSGerd Hoffmann { 2797ced9e9fSGerd Hoffmann EGLSurface esurface; 2807ced9e9fSGerd Hoffmann EGLBoolean b; 2817ced9e9fSGerd Hoffmann 2827ced9e9fSGerd Hoffmann esurface = eglCreateWindowSurface(qemu_egl_display, 2837ced9e9fSGerd Hoffmann qemu_egl_config, 284fbd57c75SAlexander Kanavin win, NULL); 2857ced9e9fSGerd Hoffmann if (esurface == EGL_NO_SURFACE) { 28638a55bddSCole Robinson error_report("egl: eglCreateWindowSurface failed"); 2877ced9e9fSGerd Hoffmann return NULL; 2887ced9e9fSGerd Hoffmann } 2897ced9e9fSGerd Hoffmann 2907ced9e9fSGerd Hoffmann b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx); 2917ced9e9fSGerd Hoffmann if (b == EGL_FALSE) { 29238a55bddSCole Robinson error_report("egl: eglMakeCurrent failed"); 2937ced9e9fSGerd Hoffmann return NULL; 2947ced9e9fSGerd Hoffmann } 2957ced9e9fSGerd Hoffmann 2967ced9e9fSGerd Hoffmann return esurface; 2977ced9e9fSGerd Hoffmann } 2987ced9e9fSGerd Hoffmann 2997ced9e9fSGerd Hoffmann /* ---------------------------------------------------------------------- */ 3007ced9e9fSGerd Hoffmann 3018bce03e3SGerd Hoffmann /* 3028bce03e3SGerd Hoffmann * Taken from glamor_egl.h from the Xorg xserver, which is MIT licensed 3038bce03e3SGerd Hoffmann * 3048bce03e3SGerd Hoffmann * Create an EGLDisplay from a native display type. This is a little quirky 3058bce03e3SGerd Hoffmann * for a few reasons. 3068bce03e3SGerd Hoffmann * 3078bce03e3SGerd Hoffmann * 1: GetPlatformDisplayEXT and GetPlatformDisplay are the API you want to 3088bce03e3SGerd Hoffmann * use, but have different function signatures in the third argument; this 3098bce03e3SGerd Hoffmann * happens not to matter for us, at the moment, but it means epoxy won't alias 3108bce03e3SGerd Hoffmann * them together. 3118bce03e3SGerd Hoffmann * 3128bce03e3SGerd Hoffmann * 2: epoxy 1.3 and earlier don't understand EGL client extensions, which 3138bce03e3SGerd Hoffmann * means you can't call "eglGetPlatformDisplayEXT" directly, as the resolver 3148bce03e3SGerd Hoffmann * will crash. 3158bce03e3SGerd Hoffmann * 3168bce03e3SGerd Hoffmann * 3: You can't tell whether you have EGL 1.5 at this point, because 3178bce03e3SGerd Hoffmann * eglQueryString(EGL_VERSION) is a property of the display, which we don't 3188bce03e3SGerd Hoffmann * have yet. So you have to query for extensions no matter what. Fortunately 3198bce03e3SGerd Hoffmann * epoxy_has_egl_extension _does_ let you query for client extensions, so 3208bce03e3SGerd Hoffmann * we don't have to write our own extension string parsing. 3218bce03e3SGerd Hoffmann * 3228bce03e3SGerd Hoffmann * 4. There is no EGL_KHR_platform_base to complement the EXT one, thus one 3238bce03e3SGerd Hoffmann * needs to know EGL 1.5 is supported in order to use the eglGetPlatformDisplay 3248bce03e3SGerd Hoffmann * function pointer. 3258bce03e3SGerd Hoffmann * We can workaround this (circular dependency) by probing for the EGL 1.5 3268bce03e3SGerd Hoffmann * platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem 3278bce03e3SGerd Hoffmann * like mesa will be able to advertise these (even though it can do EGL 1.5). 3288bce03e3SGerd Hoffmann */ 329e1913dbbSGerd Hoffmann static EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native, 330e1913dbbSGerd Hoffmann EGLenum platform) 3318bce03e3SGerd Hoffmann { 3328bce03e3SGerd Hoffmann EGLDisplay dpy = EGL_NO_DISPLAY; 3338bce03e3SGerd Hoffmann 3348bce03e3SGerd Hoffmann /* In practise any EGL 1.5 implementation would support the EXT extension */ 3358bce03e3SGerd Hoffmann if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) { 3368bce03e3SGerd Hoffmann PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT = 3378bce03e3SGerd Hoffmann (void *) eglGetProcAddress("eglGetPlatformDisplayEXT"); 338e1913dbbSGerd Hoffmann if (getPlatformDisplayEXT && platform != 0) { 339e1913dbbSGerd Hoffmann dpy = getPlatformDisplayEXT(platform, native, NULL); 3408bce03e3SGerd Hoffmann } 3418bce03e3SGerd Hoffmann } 3428bce03e3SGerd Hoffmann 3438bce03e3SGerd Hoffmann if (dpy == EGL_NO_DISPLAY) { 3448bce03e3SGerd Hoffmann /* fallback */ 3458bce03e3SGerd Hoffmann dpy = eglGetDisplay(native); 3468bce03e3SGerd Hoffmann } 3478bce03e3SGerd Hoffmann return dpy; 3488bce03e3SGerd Hoffmann } 3498bce03e3SGerd Hoffmann 350e1913dbbSGerd Hoffmann static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, 35154d208ffSGerd Hoffmann EGLenum platform, 35254d208ffSGerd Hoffmann DisplayGLMode mode) 3537ced9e9fSGerd Hoffmann { 35454d208ffSGerd Hoffmann static const EGLint conf_att_core[] = { 3557ced9e9fSGerd Hoffmann EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 3567ced9e9fSGerd Hoffmann EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, 3577ced9e9fSGerd Hoffmann EGL_RED_SIZE, 5, 3587ced9e9fSGerd Hoffmann EGL_GREEN_SIZE, 5, 3597ced9e9fSGerd Hoffmann EGL_BLUE_SIZE, 5, 3607ced9e9fSGerd Hoffmann EGL_ALPHA_SIZE, 0, 3617ced9e9fSGerd Hoffmann EGL_NONE, 3627ced9e9fSGerd Hoffmann }; 36354d208ffSGerd Hoffmann static const EGLint conf_att_gles[] = { 36454d208ffSGerd Hoffmann EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 36554d208ffSGerd Hoffmann EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 36654d208ffSGerd Hoffmann EGL_RED_SIZE, 5, 36754d208ffSGerd Hoffmann EGL_GREEN_SIZE, 5, 36854d208ffSGerd Hoffmann EGL_BLUE_SIZE, 5, 36954d208ffSGerd Hoffmann EGL_ALPHA_SIZE, 0, 37054d208ffSGerd Hoffmann EGL_NONE, 37154d208ffSGerd Hoffmann }; 3727ced9e9fSGerd Hoffmann EGLint major, minor; 3737ced9e9fSGerd Hoffmann EGLBoolean b; 3747ced9e9fSGerd Hoffmann EGLint n; 37554d208ffSGerd Hoffmann bool gles = (mode == DISPLAYGL_MODE_ES); 3767ced9e9fSGerd Hoffmann 377e1913dbbSGerd Hoffmann qemu_egl_display = qemu_egl_get_display(dpy, platform); 3787ced9e9fSGerd Hoffmann if (qemu_egl_display == EGL_NO_DISPLAY) { 37938a55bddSCole Robinson error_report("egl: eglGetDisplay failed"); 3807ced9e9fSGerd Hoffmann return -1; 3817ced9e9fSGerd Hoffmann } 3827ced9e9fSGerd Hoffmann 3837ced9e9fSGerd Hoffmann b = eglInitialize(qemu_egl_display, &major, &minor); 3847ced9e9fSGerd Hoffmann if (b == EGL_FALSE) { 38538a55bddSCole Robinson error_report("egl: eglInitialize failed"); 3867ced9e9fSGerd Hoffmann return -1; 3877ced9e9fSGerd Hoffmann } 3887ced9e9fSGerd Hoffmann 38954d208ffSGerd Hoffmann b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API); 3907ced9e9fSGerd Hoffmann if (b == EGL_FALSE) { 39154d208ffSGerd Hoffmann error_report("egl: eglBindAPI failed (%s mode)", 39254d208ffSGerd Hoffmann gles ? "gles" : "core"); 3937ced9e9fSGerd Hoffmann return -1; 3947ced9e9fSGerd Hoffmann } 3957ced9e9fSGerd Hoffmann 39654d208ffSGerd Hoffmann b = eglChooseConfig(qemu_egl_display, 39754d208ffSGerd Hoffmann gles ? conf_att_gles : conf_att_core, 3987ced9e9fSGerd Hoffmann &qemu_egl_config, 1, &n); 3997ced9e9fSGerd Hoffmann if (b == EGL_FALSE || n != 1) { 40054d208ffSGerd Hoffmann error_report("egl: eglChooseConfig failed (%s mode)", 40154d208ffSGerd Hoffmann gles ? "gles" : "core"); 4027ced9e9fSGerd Hoffmann return -1; 4037ced9e9fSGerd Hoffmann } 40454d208ffSGerd Hoffmann 40554d208ffSGerd Hoffmann qemu_egl_mode = gles ? DISPLAYGL_MODE_ES : DISPLAYGL_MODE_CORE; 4067ced9e9fSGerd Hoffmann return 0; 4077ced9e9fSGerd Hoffmann } 4087ced9e9fSGerd Hoffmann 40954d208ffSGerd Hoffmann int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy, DisplayGLMode mode) 410e1913dbbSGerd Hoffmann { 411e1913dbbSGerd Hoffmann #ifdef EGL_KHR_platform_x11 41254d208ffSGerd Hoffmann return qemu_egl_init_dpy(dpy, EGL_PLATFORM_X11_KHR, mode); 413e1913dbbSGerd Hoffmann #else 41454d208ffSGerd Hoffmann return qemu_egl_init_dpy(dpy, 0, mode); 415e1913dbbSGerd Hoffmann #endif 416e1913dbbSGerd Hoffmann } 417e1913dbbSGerd Hoffmann 41854d208ffSGerd Hoffmann int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, DisplayGLMode mode) 419e1913dbbSGerd Hoffmann { 420e1913dbbSGerd Hoffmann #ifdef EGL_MESA_platform_gbm 42154d208ffSGerd Hoffmann return qemu_egl_init_dpy(dpy, EGL_PLATFORM_GBM_MESA, mode); 422e1913dbbSGerd Hoffmann #else 42354d208ffSGerd Hoffmann return qemu_egl_init_dpy(dpy, 0, mode); 424e1913dbbSGerd Hoffmann #endif 425e1913dbbSGerd Hoffmann } 426e1913dbbSGerd Hoffmann 4277ced9e9fSGerd Hoffmann EGLContext qemu_egl_init_ctx(void) 4287ced9e9fSGerd Hoffmann { 42954d208ffSGerd Hoffmann static const EGLint ctx_att_core[] = { 430bc8c946fSGerd Hoffmann EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, 4317ced9e9fSGerd Hoffmann EGL_NONE 4327ced9e9fSGerd Hoffmann }; 43354d208ffSGerd Hoffmann static const EGLint ctx_att_gles[] = { 43454d208ffSGerd Hoffmann EGL_CONTEXT_CLIENT_VERSION, 2, 43554d208ffSGerd Hoffmann EGL_NONE 43654d208ffSGerd Hoffmann }; 43754d208ffSGerd Hoffmann bool gles = (qemu_egl_mode == DISPLAYGL_MODE_ES); 4387ced9e9fSGerd Hoffmann EGLContext ectx; 4397ced9e9fSGerd Hoffmann EGLBoolean b; 4407ced9e9fSGerd Hoffmann 4417ced9e9fSGerd Hoffmann ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT, 44254d208ffSGerd Hoffmann gles ? ctx_att_gles : ctx_att_core); 4437ced9e9fSGerd Hoffmann if (ectx == EGL_NO_CONTEXT) { 44438a55bddSCole Robinson error_report("egl: eglCreateContext failed"); 4457ced9e9fSGerd Hoffmann return NULL; 4467ced9e9fSGerd Hoffmann } 4477ced9e9fSGerd Hoffmann 4487ced9e9fSGerd Hoffmann b = eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, ectx); 4497ced9e9fSGerd Hoffmann if (b == EGL_FALSE) { 45038a55bddSCole Robinson error_report("egl: eglMakeCurrent failed"); 4517ced9e9fSGerd Hoffmann return NULL; 4527ced9e9fSGerd Hoffmann } 4537ced9e9fSGerd Hoffmann 4547ced9e9fSGerd Hoffmann return ectx; 4557ced9e9fSGerd Hoffmann } 456