diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 9edf7632..25101a4b 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -11,7 +11,6 @@ #include #include #include "backend/drm/drm.h" -#include "glapi.h" bool init_drm_renderer(struct wlr_drm_backend *drm, struct wlr_drm_renderer *renderer, wlr_renderer_create_func_t create_renderer_func) { diff --git a/backend/headless/backend.c b/backend/headless/backend.c index c0fc6022..d6bb141a 100644 --- a/backend/headless/backend.c +++ b/backend/headless/backend.c @@ -6,7 +6,6 @@ #include #include #include "backend/headless.h" -#include "glapi.h" #include "util/signal.h" struct wlr_headless_backend *headless_backend_from_backend( diff --git a/backend/rdp/backend.c b/backend/rdp/backend.c index ef0fca85..c0b63921 100644 --- a/backend/rdp/backend.c +++ b/backend/rdp/backend.c @@ -6,7 +6,6 @@ #include #include #include "backend/rdp.h" -#include "glapi.h" #include "util/signal.h" struct wlr_rdp_backend *rdp_backend_from_backend( diff --git a/glgen.sh b/glgen.sh deleted file mode 100755 index 31af2812..00000000 --- a/glgen.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/sh - -# Generates a simple GL/EGL extension function loader. -# -# The input is a .txt file, with each function to load on its own line. -# If a line starts with a -, it is optional, and will not cause the loader -# to fail if it can't load the function. You'll need to check if that function -# is NULL before using it. - -if [ $# -ne 2 ]; then - exit 1 -fi - -SPEC=$1 -OUTDIR=$2 - -BASE=$(basename "$SPEC" .txt) -INCLUDE_GUARD=$(printf %s_%s_H "$OUTDIR" "$BASE" | tr -c [:alnum:] _ | tr [:lower:] [:upper:]) - -DECL="" -DEFN="" -LOADER="" - -DECL_FMT='extern %s %s;' -DEFN_FMT='%s %s;' -LOADER_FMT='%s = (%s)eglGetProcAddress("%s");' -CHECK_FMT='if (!%s) { - wlr_log(WLR_ERROR, "Unable to load %s"); - return false; -}' - -while read -r COMMAND; do - OPTIONAL=0 - FUNC_PTR_FMT='PFN%sPROC' - - case $COMMAND in - -*) - OPTIONAL=1 - ;; - esac - - case $COMMAND in - *WL) - FUNC_PTR_FMT='PFN%s' - ;; - esac - - COMMAND=${COMMAND#-} - FUNC_PTR=$(printf "$FUNC_PTR_FMT" "$COMMAND" | tr [:lower:] [:upper:]) - - DECL="$DECL$(printf "\n$DECL_FMT" "$FUNC_PTR" "$COMMAND")" - DEFN="$DEFN$(printf "\n$DEFN_FMT" "$FUNC_PTR" "$COMMAND")" - LOADER="$LOADER$(printf "\n$LOADER_FMT" "$COMMAND" "$FUNC_PTR" "$COMMAND")" - - if [ $OPTIONAL -eq 0 ]; then - LOADER="$LOADER$(printf "\n$CHECK_FMT" "$COMMAND" "$COMMAND")" - fi -done < "$SPEC" - -cat > "$OUTDIR/$BASE.h" << EOF -#ifndef $INCLUDE_GUARD -#define $INCLUDE_GUARD - -#include -#include - -#if !WLR_HAS_X11_BACKEND && !WLR_HAS_XWAYLAND -#ifndef MESA_EGL_NO_X11_HEADERS -#define MESA_EGL_NO_X11_HEADERS -#endif -#ifndef EGL_NO_X11 -#define EGL_NO_X11 -#endif -#endif - -#include -#include -#include -#include -#include - -bool load_$BASE(void); -$DECL - -#endif -EOF - -cat > "$OUTDIR/$BASE.c" << EOF -#include -#include "$BASE.h" -$DEFN - -bool load_$BASE(void) { - static bool done = false; - if (done) { - return true; - } -$LOADER - - done = true; - return true; -} -EOF diff --git a/include/render/gles2.h b/include/render/gles2.h index 7a629d69..817ec62d 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -14,6 +14,16 @@ #include #include +struct wlr_gles2_procs { + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; + PFNGLDEBUGMESSAGECALLBACKKHRPROC glDebugMessageCallbackKHR; + PFNGLDEBUGMESSAGECONTROLKHRPROC glDebugMessageControlKHR; + PFNGLPOPDEBUGGROUPKHRPROC glPopDebugGroupKHR; + PFNGLPUSHDEBUGGROUPKHRPROC glPushDebugGroupKHR; +}; + +extern struct wlr_gles2_procs gles2_procs; + struct wlr_gles2_pixel_format { enum wl_shm_format wl_format; GLint gl_format, gl_type; @@ -33,7 +43,6 @@ struct wlr_gles2_renderer { struct wlr_renderer wlr_renderer; struct wlr_egl *egl; - const char *exts_str; struct { bool read_format_bgra_ext; diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index efded0b6..2853f8ed 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -22,6 +22,8 @@ #include #include +// TODO: remove eglmesaext.h +#include #include #include #include @@ -34,8 +36,6 @@ struct wlr_egl { EGLConfig config; EGLContext context; - const char *exts_str; - struct { bool bind_wayland_display_wl; bool buffer_age_ext; @@ -43,10 +43,25 @@ struct wlr_egl { bool image_dma_buf_export_mesa; bool image_dmabuf_import_ext; bool image_dmabuf_import_modifiers_ext; - bool swap_buffers_with_damage_ext; - bool swap_buffers_with_damage_khr; + bool swap_buffers_with_damage; } exts; + struct { + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; + PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC eglCreatePlatformWindowSurfaceEXT; + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; + PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL; + PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL; + PFNEGLUNBINDWAYLANDDISPLAYWL eglUnbindWaylandDisplayWL; + PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC eglSwapBuffersWithDamage; // KHR or EXT + PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT; + PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT; + PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC eglExportDMABUFImageQueryMESA; + PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImageMESA; + PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR; + } procs; + struct wl_display *wl_display; struct wlr_drm_format_set dmabuf_formats; diff --git a/render/egl.c b/render/egl.c index cbd92cb9..14a7bf98 100644 --- a/render/egl.c +++ b/render/egl.c @@ -5,7 +5,6 @@ #include #include #include -#include "glapi.h" static bool egl_get_config(EGLDisplay disp, EGLint *attribs, EGLConfig *out, EGLint visual_id) { @@ -77,6 +76,15 @@ static bool check_egl_ext(const char *exts, const char *ext) { return false; } +static void load_egl_proc(void *proc_ptr, const char *name) { + void *proc = (void *)eglGetProcAddress(name); + if (proc == NULL) { + wlr_log(WLR_ERROR, "eglGetProcAddress(%s) failed", name); + abort(); + } + *(void **)proc_ptr = proc; +} + static int get_egl_dmabuf_formats(struct wlr_egl *egl, int **formats); static int get_egl_dmabuf_modifiers(struct wlr_egl *egl, int format, uint64_t **modifiers); @@ -125,11 +133,72 @@ out: bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, EGLint *config_attribs, EGLint visual_id) { - if (!load_glapi()) { + const char *exts_str = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (exts_str == NULL) { + wlr_log(WLR_ERROR, "Failed to query EGL extensions"); + return false; + } + + if (!check_egl_ext(exts_str, "EGL_EXT_platform_base")) { + wlr_log(WLR_ERROR, "EGL_EXT_platform_base not supported"); return false; } + load_egl_proc(&egl->procs.eglGetPlatformDisplayEXT, + "eglGetPlatformDisplayEXT"); + load_egl_proc(&egl->procs.eglCreatePlatformWindowSurfaceEXT, + "eglCreatePlatformWindowSurfaceEXT"); + + if (check_egl_ext(exts_str, "EGL_KHR_image_base")) { + egl->exts.image_base_khr = true; + load_egl_proc(&egl->procs.eglCreateImageKHR, "eglCreateImageKHR"); + load_egl_proc(&egl->procs.eglDestroyImageKHR, "eglDestroyImageKHR"); + } + + egl->exts.buffer_age_ext = + check_egl_ext(exts_str, "EGL_EXT_buffer_age"); + + if (check_egl_ext(exts_str, "EGL_KHR_swap_buffers_with_damage")) { + egl->exts.swap_buffers_with_damage = true; + load_egl_proc(&egl->procs.eglSwapBuffersWithDamage, + "eglSwapBuffersWithDamageKHR"); + } else if (check_egl_ext(exts_str, "EGL_EXT_swap_buffers_with_damage")) { + egl->exts.swap_buffers_with_damage = true; + load_egl_proc(&egl->procs.eglSwapBuffersWithDamage, + "eglSwapBuffersWithDamageEXT"); + } + + egl->exts.image_dmabuf_import_ext = + check_egl_ext(exts_str, "EGL_EXT_image_dma_buf_import"); + if (check_egl_ext(exts_str, "EGL_EXT_image_dma_buf_import_modifiers")) { + egl->exts.image_dmabuf_import_modifiers_ext = true; + load_egl_proc(&egl->procs.eglQueryDmaBufFormatsEXT, + "eglQueryDmaBufFormatsEXT"); + load_egl_proc(&egl->procs.eglQueryDmaBufModifiersEXT, + "eglQueryDmaBufModifiersEXT"); + } + + if (check_egl_ext(exts_str, "EGL_MESA_image_dma_buf_export")) { + egl->exts.image_dma_buf_export_mesa = true; + load_egl_proc(&egl->procs.eglExportDMABUFImageQueryMESA, + "eglExportDMABUFImageQueryMESA"); + load_egl_proc(&egl->procs.eglExportDMABUFImageMESA, + "eglExportDMABUFImageMESA"); + } + + if (check_egl_ext(exts_str, "EGL_WL_bind_wayland_display")) { + egl->exts.bind_wayland_display_wl = true; + load_egl_proc(&egl->procs.eglBindWaylandDisplayWL, + "eglBindWaylandDisplayWL"); + load_egl_proc(&egl->procs.eglUnbindWaylandDisplayWL, + "eglUnbindWaylandDisplayWL"); + load_egl_proc(&egl->procs.eglQueryWaylandBufferWL, + "eglQueryWaylandBufferWL"); + } + + if (check_egl_ext(exts_str, "EGL_KHR_debug")) { + load_egl_proc(&egl->procs.eglDebugMessageControlKHR, + "eglDebugMessageControlKHR"); - if (eglDebugMessageControlKHR) { static const EGLAttrib debug_attribs[] = { EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE, EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE, @@ -137,7 +206,7 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE, EGL_NONE, }; - eglDebugMessageControlKHR(egl_log, debug_attribs); + egl->procs.eglDebugMessageControlKHR(egl_log, debug_attribs); } if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) { @@ -147,9 +216,11 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, if (platform == EGL_PLATFORM_SURFACELESS_MESA) { assert(remote_display == NULL); - egl->display = eglGetPlatformDisplayEXT(platform, EGL_DEFAULT_DISPLAY, NULL); + egl->display = egl->procs.eglGetPlatformDisplayEXT(platform, + EGL_DEFAULT_DISPLAY, NULL); } else { - egl->display = eglGetPlatformDisplayEXT(platform, remote_display, NULL); + egl->display = egl->procs.eglGetPlatformDisplayEXT(platform, + remote_display, NULL); } if (egl->display == EGL_NO_DISPLAY) { wlr_log(WLR_ERROR, "Failed to create EGL display"); @@ -169,44 +240,14 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, goto error; } - egl->exts_str = eglQueryString(egl->display, EGL_EXTENSIONS); - wlr_log(WLR_INFO, "Using EGL %d.%d", (int)major, (int)minor); - wlr_log(WLR_INFO, "Supported EGL extensions: %s", egl->exts_str); + wlr_log(WLR_INFO, "Supported EGL extensions: %s", exts_str); wlr_log(WLR_INFO, "EGL vendor: %s", eglQueryString(egl->display, EGL_VENDOR)); - egl->exts.image_base_khr = - check_egl_ext(egl->exts_str, "EGL_KHR_image_base") - && eglCreateImageKHR && eglDestroyImageKHR; - - egl->exts.buffer_age_ext = - check_egl_ext(egl->exts_str, "EGL_EXT_buffer_age"); - egl->exts.swap_buffers_with_damage_ext = - (check_egl_ext(egl->exts_str, "EGL_EXT_swap_buffers_with_damage") && - eglSwapBuffersWithDamageEXT); - egl->exts.swap_buffers_with_damage_khr = - (check_egl_ext(egl->exts_str, "EGL_KHR_swap_buffers_with_damage") && - eglSwapBuffersWithDamageKHR); - - egl->exts.image_dmabuf_import_ext = - check_egl_ext(egl->exts_str, "EGL_EXT_image_dma_buf_import"); - egl->exts.image_dmabuf_import_modifiers_ext = - check_egl_ext(egl->exts_str, "EGL_EXT_image_dma_buf_import_modifiers") - && eglQueryDmaBufFormatsEXT && eglQueryDmaBufModifiersEXT; - - egl->exts.image_dma_buf_export_mesa = - check_egl_ext(egl->exts_str, "EGL_MESA_image_dma_buf_export") && - eglExportDMABUFImageQueryMESA && eglExportDMABUFImageMESA; - init_dmabuf_formats(egl); - egl->exts.bind_wayland_display_wl = - check_egl_ext(egl->exts_str, "EGL_WL_bind_wayland_display") - && eglBindWaylandDisplayWL && eglUnbindWaylandDisplayWL - && eglQueryWaylandBufferWL; - bool ext_context_priority = - check_egl_ext(egl->exts_str, "EGL_IMG_context_priority"); + check_egl_ext(exts_str, "EGL_IMG_context_priority"); size_t atti = 0; EGLint attribs[5]; @@ -272,7 +313,7 @@ void wlr_egl_finish(struct wlr_egl *egl) { eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (egl->wl_display) { assert(egl->exts.bind_wayland_display_wl); - eglUnbindWaylandDisplayWL(egl->display, egl->wl_display); + egl->procs.eglUnbindWaylandDisplayWL(egl->display, egl->wl_display); } eglDestroyContext(egl->display, egl->context); @@ -285,7 +326,7 @@ bool wlr_egl_bind_display(struct wlr_egl *egl, struct wl_display *local_display) return false; } - if (eglBindWaylandDisplayWL(egl->display, local_display)) { + if (egl->procs.eglBindWaylandDisplayWL(egl->display, local_display)) { egl->wl_display = local_display; return true; } @@ -300,13 +341,13 @@ bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImage image) { if (!image) { return true; } - return eglDestroyImageKHR(egl->display, image); + return egl->procs.eglDestroyImageKHR(egl->display, image); } EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window) { - assert(eglCreatePlatformWindowSurfaceEXT); - EGLSurface surf = eglCreatePlatformWindowSurfaceEXT(egl->display, - egl->config, window, NULL); + assert(egl->procs.eglCreatePlatformWindowSurfaceEXT); + EGLSurface surf = egl->procs.eglCreatePlatformWindowSurfaceEXT( + egl->display, egl->config, window, NULL); if (surf == EGL_NO_SURFACE) { wlr_log(WLR_ERROR, "Failed to create EGL surface"); return EGL_NO_SURFACE; @@ -355,8 +396,7 @@ bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface, } EGLBoolean ret; - if (damage != NULL && (egl->exts.swap_buffers_with_damage_ext || - egl->exts.swap_buffers_with_damage_khr)) { + if (damage != NULL && egl->exts.swap_buffers_with_damage) { EGLint width = 0, height = 0; eglQuerySurface(egl->display, surface, EGL_WIDTH, &width); eglQuerySurface(egl->display, surface, EGL_HEIGHT, &height); @@ -387,13 +427,8 @@ bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface, memset(egl_damage, 0, sizeof(egl_damage)); } - if (egl->exts.swap_buffers_with_damage_ext) { - ret = eglSwapBuffersWithDamageEXT(egl->display, surface, egl_damage, - nrects); - } else { - ret = eglSwapBuffersWithDamageKHR(egl->display, surface, egl_damage, - nrects); - } + ret = egl->procs.eglSwapBuffersWithDamage(egl->display, surface, + egl_damage, nrects); } else { ret = eglSwapBuffers(egl->display, surface); } @@ -412,16 +447,17 @@ EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl, return NULL; } - if (!eglQueryWaylandBufferWL(egl->display, data, EGL_TEXTURE_FORMAT, fmt)) { + if (!egl->procs.eglQueryWaylandBufferWL(egl->display, data, + EGL_TEXTURE_FORMAT, fmt)) { return NULL; } - eglQueryWaylandBufferWL(egl->display, data, EGL_WIDTH, width); - eglQueryWaylandBufferWL(egl->display, data, EGL_HEIGHT, height); + egl->procs.eglQueryWaylandBufferWL(egl->display, data, EGL_WIDTH, width); + egl->procs.eglQueryWaylandBufferWL(egl->display, data, EGL_HEIGHT, height); EGLint _inverted_y; - if (eglQueryWaylandBufferWL(egl->display, data, EGL_WAYLAND_Y_INVERTED_WL, - &_inverted_y)) { + if (egl->procs.eglQueryWaylandBufferWL(egl->display, data, + EGL_WAYLAND_Y_INVERTED_WL, &_inverted_y)) { *inverted_y = !!_inverted_y; } else { *inverted_y = false; @@ -431,8 +467,8 @@ EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl, EGL_WAYLAND_PLANE_WL, 0, EGL_NONE, }; - return eglCreateImageKHR(egl->display, egl->context, EGL_WAYLAND_BUFFER_WL, - data, attribs); + return egl->procs.eglCreateImageKHR(egl->display, egl->context, + EGL_WAYLAND_BUFFER_WL, data, attribs); } EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, @@ -517,7 +553,7 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, attribs[atti++] = EGL_NONE; assert(atti < sizeof(attribs)/sizeof(attribs[0])); - return eglCreateImageKHR(egl->display, EGL_NO_CONTEXT, + return egl->procs.eglCreateImageKHR(egl->display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); } @@ -551,7 +587,7 @@ static int get_egl_dmabuf_formats(struct wlr_egl *egl, int **formats) { } EGLint num; - if (!eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) { + if (!egl->procs.eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) { wlr_log(WLR_ERROR, "Failed to query number of dmabuf formats"); return -1; } @@ -562,7 +598,7 @@ static int get_egl_dmabuf_formats(struct wlr_egl *egl, int **formats) { return -1; } - if (!eglQueryDmaBufFormatsEXT(egl->display, num, *formats, &num)) { + if (!egl->procs.eglQueryDmaBufFormatsEXT(egl->display, num, *formats, &num)) { wlr_log(WLR_ERROR, "Failed to query dmabuf format"); free(*formats); return -1; @@ -582,7 +618,7 @@ static int get_egl_dmabuf_modifiers(struct wlr_egl *egl, int format, } EGLint num; - if (!eglQueryDmaBufModifiersEXT(egl->display, format, 0, + if (!egl->procs.eglQueryDmaBufModifiersEXT(egl->display, format, 0, NULL, NULL, &num)) { wlr_log(WLR_ERROR, "Failed to query dmabuf number of modifiers"); return -1; @@ -598,7 +634,7 @@ static int get_egl_dmabuf_modifiers(struct wlr_egl *egl, int format, return -1; } - if (!eglQueryDmaBufModifiersEXT(egl->display, format, num, + if (!egl->procs.eglQueryDmaBufModifiersEXT(egl->display, format, num, *modifiers, NULL, &num)) { wlr_log(WLR_ERROR, "Failed to query dmabuf modifiers"); free(*modifiers); @@ -621,7 +657,7 @@ bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image, } // Only one set of modifiers is returned for all planes - if (!eglExportDMABUFImageQueryMESA(egl->display, image, + if (!egl->procs.eglExportDMABUFImageQueryMESA(egl->display, image, (int *)&attribs->format, &attribs->n_planes, &attribs->modifier)) { return false; } @@ -631,7 +667,7 @@ bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image, return false; } - if (!eglExportDMABUFImageMESA(egl->display, image, attribs->fd, + if (!egl->procs.eglExportDMABUFImageMESA(egl->display, image, attribs->fd, (EGLint *)attribs->stride, (EGLint *)attribs->offset)) { return false; } diff --git a/render/glapi.txt b/render/glapi.txt deleted file mode 100644 index b1166f27..00000000 --- a/render/glapi.txt +++ /dev/null @@ -1,19 +0,0 @@ -eglGetPlatformDisplayEXT -eglCreatePlatformWindowSurfaceEXT --eglCreateImageKHR --eglDestroyImageKHR --eglQueryWaylandBufferWL --eglBindWaylandDisplayWL --eglUnbindWaylandDisplayWL --glEGLImageTargetTexture2DOES --eglSwapBuffersWithDamageEXT --eglSwapBuffersWithDamageKHR --eglQueryDmaBufFormatsEXT --eglQueryDmaBufModifiersEXT --eglExportDMABUFImageQueryMESA --eglExportDMABUFImageMESA --eglDebugMessageControlKHR --glDebugMessageCallbackKHR --glDebugMessageControlKHR --glPopDebugGroupKHR --glPushDebugGroupKHR diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 8bef5137..b5855d4e 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -11,9 +11,10 @@ #include #include #include -#include "glapi.h" #include "render/gles2.h" +struct wlr_gles2_procs gles2_procs = {0}; + static const struct wlr_renderer_impl renderer_impl; static struct wlr_gles2_renderer *gles2_get_renderer( @@ -219,13 +220,13 @@ static bool gles2_resource_is_wl_drm_buffer(struct wlr_renderer *wlr_renderer, struct wl_resource *resource) { struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - if (!eglQueryWaylandBufferWL) { + if (!renderer->egl->exts.bind_wayland_display_wl) { return false; } EGLint fmt; - return eglQueryWaylandBufferWL(renderer->egl->display, resource, - EGL_TEXTURE_FORMAT, &fmt); + return renderer->egl->procs.eglQueryWaylandBufferWL(renderer->egl->display, + resource, EGL_TEXTURE_FORMAT, &fmt); } static void gles2_wl_drm_buffer_get_size(struct wlr_renderer *wlr_renderer, @@ -233,12 +234,14 @@ static void gles2_wl_drm_buffer_get_size(struct wlr_renderer *wlr_renderer, struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - if (!eglQueryWaylandBufferWL) { + if (!renderer->egl->exts.bind_wayland_display_wl) { return; } - eglQueryWaylandBufferWL(renderer->egl->display, buffer, EGL_WIDTH, width); - eglQueryWaylandBufferWL(renderer->egl->display, buffer, EGL_HEIGHT, height); + renderer->egl->procs.eglQueryWaylandBufferWL(renderer->egl->display, + buffer, EGL_WIDTH, width); + renderer->egl->procs.eglQueryWaylandBufferWL(renderer->egl->display, + buffer, EGL_HEIGHT, height); } static const struct wlr_drm_format_set *gles2_get_dmabuf_formats( @@ -376,7 +379,7 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) { if (renderer->exts.debug_khr) { glDisable(GL_DEBUG_OUTPUT_KHR); - glDebugMessageCallbackKHR(NULL, NULL); + gles2_procs.glDebugMessageCallbackKHR(NULL, NULL); } free(renderer); @@ -405,19 +408,19 @@ static const struct wlr_renderer_impl renderer_impl = { }; void push_gles2_marker(const char *file, const char *func) { - if (!glPushDebugGroupKHR) { + if (!gles2_procs.glPushDebugGroupKHR) { return; } int len = snprintf(NULL, 0, "%s:%s", file, func) + 1; char str[len]; snprintf(str, len, "%s:%s", file, func); - glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, 1, -1, str); + gles2_procs.glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, 1, -1, str); } void pop_gles2_marker(void) { - if (glPopDebugGroupKHR) { - glPopDebugGroupKHR(); + if (gles2_procs.glPopDebugGroupKHR) { + gles2_procs.glPopDebugGroupKHR(); } } @@ -516,6 +519,15 @@ static bool check_gl_ext(const char *exts, const char *ext) { return false; } +static void load_gl_proc(void *proc_ptr, const char *name) { + void *proc = (void *)eglGetProcAddress(name); + if (proc == NULL) { + wlr_log(WLR_ERROR, "eglGetProcAddress(%s) failed", name); + abort(); + } + *(void **)proc_ptr = proc; +} + extern const GLchar quad_vertex_src[]; extern const GLchar quad_fragment_src[]; extern const GLchar ellipse_fragment_src[]; @@ -525,7 +537,9 @@ extern const GLchar tex_fragment_src_rgbx[]; extern const GLchar tex_fragment_src_external[]; struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { - if (!load_glapi()) { + const char *exts_str = (const char *)glGetString(GL_EXTENSIONS); + if (exts_str == NULL) { + wlr_log(WLR_ERROR, "Failed to get GL_EXTENSIONS"); return NULL; } @@ -542,37 +556,44 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { return NULL; } - renderer->exts_str = (const char *)glGetString(GL_EXTENSIONS); wlr_log(WLR_INFO, "Using %s", glGetString(GL_VERSION)); wlr_log(WLR_INFO, "GL vendor: %s", glGetString(GL_VENDOR)); wlr_log(WLR_INFO, "GL renderer: %s", glGetString(GL_RENDERER)); - wlr_log(WLR_INFO, "Supported GLES2 extensions: %s", renderer->exts_str); + wlr_log(WLR_INFO, "Supported GLES2 extensions: %s", exts_str); - if (!check_gl_ext(renderer->exts_str, "GL_EXT_texture_format_BGRA8888")) { + if (!check_gl_ext(exts_str, "GL_EXT_texture_format_BGRA8888")) { wlr_log(WLR_ERROR, "BGRA8888 format not supported by GLES2"); free(renderer); return NULL; } renderer->exts.read_format_bgra_ext = - check_gl_ext(renderer->exts_str, "GL_EXT_read_format_bgra"); - renderer->exts.debug_khr = - check_gl_ext(renderer->exts_str, "GL_KHR_debug") && - glDebugMessageCallbackKHR && glDebugMessageControlKHR; - renderer->exts.egl_image_external_oes = - check_gl_ext(renderer->exts_str, "GL_OES_EGL_image_external") && - glEGLImageTargetTexture2DOES; + check_gl_ext(exts_str, "GL_EXT_read_format_bgra"); + + if (check_gl_ext(exts_str, "GL_KHR_debug")) { + renderer->exts.debug_khr = true; + load_gl_proc(&gles2_procs.glDebugMessageCallbackKHR, + "glDebugMessageCallbackKHR"); + load_gl_proc(&gles2_procs.glDebugMessageControlKHR, + "glDebugMessageControlKHR"); + } + + if (check_gl_ext(exts_str, "GL_OES_EGL_image_external")) { + renderer->exts.egl_image_external_oes = true; + load_gl_proc(&gles2_procs.glEGLImageTargetTexture2DOES, + "glEGLImageTargetTexture2DOES"); + } if (renderer->exts.debug_khr) { glEnable(GL_DEBUG_OUTPUT_KHR); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); - glDebugMessageCallbackKHR(gles2_log, NULL); + gles2_procs.glDebugMessageCallbackKHR(gles2_log, NULL); // Silence unwanted message types - glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_POP_GROUP_KHR, - GL_DONT_CARE, 0, NULL, GL_FALSE); - glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_PUSH_GROUP_KHR, - GL_DONT_CARE, 0, NULL, GL_FALSE); + gles2_procs.glDebugMessageControlKHR(GL_DONT_CARE, + GL_DEBUG_TYPE_POP_GROUP_KHR, GL_DONT_CARE, 0, NULL, GL_FALSE); + gles2_procs.glDebugMessageControlKHR(GL_DONT_CARE, + GL_DEBUG_TYPE_PUSH_GROUP_KHR, GL_DONT_CARE, 0, NULL, GL_FALSE); } PUSH_GLES2_DEBUG; @@ -641,7 +662,7 @@ error: if (renderer->exts.debug_khr) { glDisable(GL_DEBUG_OUTPUT_KHR); - glDebugMessageCallbackKHR(NULL, NULL); + gles2_procs.glDebugMessageCallbackKHR(NULL, NULL); } free(renderer); diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 9ff88b35..7beb0672 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -11,7 +11,6 @@ #include #include #include -#include "glapi.h" #include "render/gles2.h" #include "util/signal.h" @@ -91,12 +90,12 @@ static bool gles2_texture_to_dmabuf(struct wlr_texture *wlr_texture, if (!texture->image) { assert(texture->target == GL_TEXTURE_2D); - if (!eglCreateImageKHR) { + if (!texture->egl->exts.image_base_khr) { return false; } - texture->image = eglCreateImageKHR(texture->egl->display, - texture->egl->context, EGL_GL_TEXTURE_2D_KHR, + texture->image = texture->egl->procs.eglCreateImageKHR( + texture->egl->display, texture->egl->context, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(uintptr_t)texture->tex, NULL); if (texture->image == EGL_NO_IMAGE_KHR) { return false; @@ -188,7 +187,7 @@ struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl, wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); } - if (!glEGLImageTargetTexture2DOES) { + if (!gles2_procs.glEGLImageTargetTexture2DOES) { return NULL; } @@ -230,7 +229,8 @@ struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl, glGenTextures(1, &texture->tex); glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->tex); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, texture->image); + gles2_procs.glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, + texture->image); POP_GLES2_DEBUG; return &texture->wlr_texture; @@ -242,7 +242,7 @@ struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl, wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); } - if (!glEGLImageTargetTexture2DOES) { + if (!gles2_procs.glEGLImageTargetTexture2DOES) { return NULL; } @@ -290,7 +290,8 @@ struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl, glGenTextures(1, &texture->tex); glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->tex); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, texture->image); + gles2_procs.glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, + texture->image); POP_GLES2_DEBUG; return &texture->wlr_texture; diff --git a/render/meson.build b/render/meson.build index 87577aba..79daba93 100644 --- a/render/meson.build +++ b/render/meson.build @@ -1,12 +1,3 @@ -glgen = find_program('../glgen.sh') - -glapi = custom_target( - 'glapi', - input: 'glapi.txt', - output: ['@BASENAME@.c', '@BASENAME@.h'], - command: [glgen, '@INPUT@', '@OUTDIR@'], -) - lib_wlr_render = static_library( 'wlr_render', files( @@ -20,7 +11,6 @@ lib_wlr_render = static_library( 'wlr_renderer.c', 'wlr_texture.c', ), - glapi, include_directories: wlr_inc, dependencies: [ egl, @@ -33,5 +23,4 @@ lib_wlr_render = static_library( wlr_render = declare_dependency( link_with: lib_wlr_render, - sources: glapi[1], )