diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 3facd87d..82aa9505 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -53,9 +53,6 @@ struct wlr_egl { // Device extensions bool device_drm_ext; - - // Client extensions - bool device_query_ext; } exts; struct { @@ -73,7 +70,6 @@ struct wlr_egl { PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR; PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT; PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT; - PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT; } procs; struct wl_display *wl_display; @@ -91,15 +87,6 @@ struct wlr_egl { struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display, const EGLint *config_attribs); -/** - * Creates and EGL context from a given drm fd. This function uses the - * following extensions: - * - EXT_device_enumeration to get the list of available EGLDeviceEXT - * - EXT_device_drm to get the name of the EGLDeviceEXT - * - EXT_platform_device to create an EGLDisplay from an EGLDeviceEXT - */ -struct wlr_egl *wlr_egl_create_from_drm_fd(int drm_fd); - /** * Frees all related EGL resources, makes the context not-current and * unbinds a bound wayland display. diff --git a/render/egl.c b/render/egl.c index 4cc117c8..c1734a36 100644 --- a/render/egl.c +++ b/render/egl.c @@ -150,7 +150,8 @@ out: free(formats); } -static struct wlr_egl *egl_create(void) { +struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display, + const EGLint *config_attribs) { struct wlr_egl *egl = calloc(1, sizeof(struct wlr_egl)); if (egl == NULL) { wlr_log_errno(WLR_ERROR, "Allocation failed"); @@ -166,7 +167,6 @@ static struct wlr_egl *egl_create(void) { } return NULL; } - wlr_log(WLR_INFO, "Supported EGL client extensions: %s", client_exts_str); if (!check_egl_ext(client_exts_str, "EGL_EXT_platform_base")) { wlr_log(WLR_ERROR, "EGL_EXT_platform_base not supported"); @@ -177,18 +177,6 @@ static struct wlr_egl *egl_create(void) { load_egl_proc(&egl->procs.eglCreatePlatformWindowSurfaceEXT, "eglCreatePlatformWindowSurfaceEXT"); - if (check_egl_ext(client_exts_str, "EGL_EXT_device_enumeration")) { - load_egl_proc(&egl->procs.eglQueryDevicesEXT, "eglQueryDevicesEXT"); - } - - if (check_egl_ext(client_exts_str, "EGL_EXT_device_query")) { - egl->exts.device_query_ext = true; - load_egl_proc(&egl->procs.eglQueryDeviceStringEXT, - "eglQueryDeviceStringEXT"); - load_egl_proc(&egl->procs.eglQueryDisplayAttribEXT, - "eglQueryDisplayAttribEXT"); - } - if (check_egl_ext(client_exts_str, "EGL_KHR_debug")) { load_egl_proc(&egl->procs.eglDebugMessageControlKHR, "eglDebugMessageControlKHR"); @@ -205,31 +193,26 @@ static struct wlr_egl *egl_create(void) { if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) { wlr_log(WLR_ERROR, "Failed to bind to the OpenGL ES API"); - return NULL; + goto error; } - return egl; -} - -static bool egl_init(struct wlr_egl *egl, EGLenum platform, - void *remote_display, const EGLint *config_attribs) { egl->display = egl->procs.eglGetPlatformDisplayEXT(platform, remote_display, NULL); if (egl->display == EGL_NO_DISPLAY) { wlr_log(WLR_ERROR, "Failed to create EGL display"); - return false; + goto error; } EGLint major, minor; if (eglInitialize(egl->display, &major, &minor) == EGL_FALSE) { wlr_log(WLR_ERROR, "Failed to initialize EGL"); - return false; + goto error; } const char *display_exts_str = eglQueryString(egl->display, EGL_EXTENSIONS); if (display_exts_str == NULL) { wlr_log(WLR_ERROR, "Failed to query EGL display extensions"); - return false; + return NULL; } if (check_egl_ext(display_exts_str, "EGL_KHR_image_base")) { @@ -268,12 +251,17 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, } const char *device_exts_str = NULL; - if (egl->exts.device_query_ext) { + if (check_egl_ext(client_exts_str, "EGL_EXT_device_query")) { + load_egl_proc(&egl->procs.eglQueryDisplayAttribEXT, + "eglQueryDisplayAttribEXT"); + load_egl_proc(&egl->procs.eglQueryDeviceStringEXT, + "eglQueryDeviceStringEXT"); + EGLAttrib device_attrib; if (!egl->procs.eglQueryDisplayAttribEXT(egl->display, EGL_DEVICE_EXT, &device_attrib)) { wlr_log(WLR_ERROR, "eglQueryDisplayAttribEXT(EGL_DEVICE_EXT) failed"); - return false; + goto error; } egl->device = (EGLDeviceEXT)device_attrib; @@ -281,7 +269,7 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, egl->procs.eglQueryDeviceStringEXT(egl->device, EGL_EXTENSIONS); if (device_exts_str == NULL) { wlr_log(WLR_ERROR, "eglQueryDeviceStringEXT(EGL_EXTENSIONS) failed"); - return false; + goto error; } egl->exts.device_drm_ext = @@ -293,27 +281,28 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, if (!eglChooseConfig(egl->display, config_attribs, &egl->config, 1, &matched)) { wlr_log(WLR_ERROR, "eglChooseConfig failed"); - return false; + goto error; } if (matched == 0) { wlr_log(WLR_ERROR, "Failed to match an EGL config"); - return false; + goto error; } } else { if (!check_egl_ext(display_exts_str, "EGL_KHR_no_config_context") && !check_egl_ext(display_exts_str, "EGL_MESA_configless_context")) { wlr_log(WLR_ERROR, "EGL_KHR_no_config_context or " "EGL_MESA_configless_context not supported"); - return false; + goto error; } egl->config = EGL_NO_CONFIG_KHR; } + wlr_log(WLR_INFO, "Using EGL %d.%d", (int)major, (int)minor); + wlr_log(WLR_INFO, "Supported EGL client extensions: %s", client_exts_str); wlr_log(WLR_INFO, "Supported EGL display extensions: %s", display_exts_str); if (device_exts_str != NULL) { wlr_log(WLR_INFO, "Supported EGL device extensions: %s", device_exts_str); } - wlr_log(WLR_INFO, "Using EGL %d.%d", (int)major, (int)minor); wlr_log(WLR_INFO, "EGL vendor: %s", eglQueryString(egl->display, EGL_VENDOR)); init_dmabuf_formats(egl); @@ -328,8 +317,7 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, // On DRM, request a high priority context if possible bool request_high_priority = ext_context_priority && - (platform == EGL_PLATFORM_GBM_MESA - || platform == EGL_PLATFORM_DEVICE_EXT); + platform == EGL_PLATFORM_GBM_MESA; // Try to reschedule all of our rendering to be completed first. If it // fails, it will fallback to the default priority (MEDIUM). @@ -345,7 +333,7 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, EGL_NO_CONTEXT, attribs); if (egl->context == EGL_NO_CONTEXT) { wlr_log(WLR_ERROR, "Failed to create EGL context"); - return false; + goto error; } if (request_high_priority) { @@ -359,105 +347,6 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, } } - return true; -} - -struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display, - const EGLint *config_attribs) { - struct wlr_egl *egl = egl_create(); - if (egl == NULL) { - wlr_log(WLR_ERROR, "Failed to create EGL context"); - return NULL; - } - - if (!egl_init(egl, platform, remote_display, config_attribs)) { - wlr_log(WLR_ERROR, "Failed to initialize EGL context"); - eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - if (egl->display) { - eglTerminate(egl->display); - } - free(egl); - eglReleaseThread(); - return NULL; - } - - return egl; -} - -static bool device_has_name(const drmDevice *device, const char *name) { - for (size_t i = 0; i < DRM_NODE_MAX; i++) { - if (!(device->available_nodes & (1 << i))) { - continue; - } - if (strcmp(device->nodes[i], name) == 0) { - return true; - } - } - return false; -} - -struct wlr_egl *wlr_egl_create_from_drm_fd(int drm_fd) { - struct wlr_egl *egl = egl_create(); - if (egl == NULL) { - wlr_log(WLR_ERROR, "Failed to create EGL context"); - return NULL; - } - - if (egl->procs.eglQueryDevicesEXT == NULL) { - wlr_log(WLR_ERROR, "EGL_EXT_device_enumeration not supported"); - goto error; - } - - EGLint nb_devices = 0; - if (!egl->procs.eglQueryDevicesEXT(0, NULL, &nb_devices)) { - wlr_log(WLR_ERROR, "Failed to query EGL devices"); - goto error; - } - - EGLDeviceEXT *devices = calloc(nb_devices, sizeof(EGLDeviceEXT)); - if (devices == NULL) { - wlr_log_errno(WLR_ERROR, "Failed to allocate device list"); - goto error; - } - - if (!egl->procs.eglQueryDevicesEXT(nb_devices, devices, &nb_devices)) { - wlr_log(WLR_ERROR, "Failed to query EGL devices"); - goto error; - } - - drmDevice *device = NULL; - int ret = drmGetDevice(drm_fd, &device); - if (ret < 0) { - wlr_log(WLR_ERROR, "Failed to get DRM device: %s", strerror(-ret)); - goto error; - } - - EGLDeviceEXT egl_device = NULL; - for (int i = 0; i < nb_devices; i++) { - const char *egl_device_name = egl->procs.eglQueryDeviceStringEXT( - devices[i], EGL_DRM_DEVICE_FILE_EXT); - if (egl_device_name == NULL) { - continue; - } - - if (device_has_name(device, egl_device_name)) { - wlr_log(WLR_DEBUG, "Using EGL device %s", egl_device_name); - egl_device = devices[i]; - break; - } - } - - if (egl_device == NULL) { - wlr_log(WLR_ERROR, "Failed to find EGLDeviceEXT"); - goto error; - } - - if (!egl_init(egl, EGL_PLATFORM_DEVICE_EXT, egl_device, NULL)) { - wlr_log(WLR_ERROR, "Failed to initialize EGL context"); - goto error; - } - return egl; error: @@ -465,7 +354,6 @@ error: if (egl->display) { eglTerminate(egl->display); } - free(egl); eglReleaseThread(); return NULL; } @@ -851,6 +739,18 @@ bool wlr_egl_destroy_surface(struct wlr_egl *egl, EGLSurface surface) { return eglDestroySurface(egl->display, surface); } +static bool device_has_name(const drmDevice *device, const char *name) { + for (size_t i = 0; i < DRM_NODE_MAX; i++) { + if (!(device->available_nodes & (1 << i))) { + continue; + } + if (strcmp(device->nodes[i], name) == 0) { + return true; + } + } + return false; +} + static char *get_render_name(const char *name) { uint32_t flags = 0; int devices_len = drmGetDevices2(flags, NULL, 0); diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 7ce86695..4a565b1d 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -251,12 +251,22 @@ bool wlr_renderer_init_wl_display(struct wlr_renderer *r, } struct wlr_renderer *wlr_renderer_autocreate_with_drm_fd(int drm_fd) { - struct wlr_egl *egl = wlr_egl_create_from_drm_fd(drm_fd); - if (egl == NULL) { - wlr_log(WLR_ERROR, "Could not initialize EGL"); + struct gbm_device *gbm_device = gbm_create_device(drm_fd); + if (!gbm_device) { + wlr_log(WLR_ERROR, "Failed to create GBM device"); return NULL; } + struct wlr_egl *egl = wlr_egl_create(EGL_PLATFORM_GBM_KHR, gbm_device, + NULL); + if (egl == NULL) { + wlr_log(WLR_ERROR, "Could not initialize EGL"); + gbm_device_destroy(gbm_device); + return NULL; + } + + egl->gbm_device = gbm_device; + struct wlr_renderer *renderer = wlr_gles2_renderer_create(egl); if (!renderer) { wlr_log(WLR_ERROR, "Failed to create GLES2 renderer");