mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	render: add wlr_egl_create_from_drm_fd function
This function relies on the extension EGL_WL_bind_wayland_display being present. If not, the creation of `wlr_egl` will fallback on using GBM
This commit is contained in:
		
							parent
							
								
									84dea55b20
								
							
						
					
					
						commit
						074e36deb6
					
				
					 4 changed files with 173 additions and 49 deletions
				
			
		
							
								
								
									
										15
									
								
								include/render/egl.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								include/render/egl.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					#ifndef RENDER_EGL_H
 | 
				
			||||||
 | 
					#define RENDER_EGL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <wlr/render/egl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -51,6 +51,9 @@ struct wlr_egl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Device extensions
 | 
							// Device extensions
 | 
				
			||||||
		bool device_drm_ext;
 | 
							bool device_drm_ext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Client extensions
 | 
				
			||||||
 | 
							bool device_query_ext;
 | 
				
			||||||
	} exts;
 | 
						} exts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
| 
						 | 
					@ -65,6 +68,7 @@ struct wlr_egl {
 | 
				
			||||||
		PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR;
 | 
							PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR;
 | 
				
			||||||
		PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT;
 | 
							PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT;
 | 
				
			||||||
		PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT;
 | 
							PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT;
 | 
				
			||||||
 | 
							PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT;
 | 
				
			||||||
	} procs;
 | 
						} procs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_display *wl_display;
 | 
						struct wl_display *wl_display;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										191
									
								
								render/egl.c
									
										
									
									
									
								
							
							
						
						
									
										191
									
								
								render/egl.c
									
										
									
									
									
								
							| 
						 | 
					@ -11,6 +11,8 @@
 | 
				
			||||||
#include <wlr/util/region.h>
 | 
					#include <wlr/util/region.h>
 | 
				
			||||||
#include <xf86drm.h>
 | 
					#include <xf86drm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "render/egl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static enum wlr_log_importance egl_log_importance_to_wlr(EGLint type) {
 | 
					static enum wlr_log_importance egl_log_importance_to_wlr(EGLint type) {
 | 
				
			||||||
	switch (type) {
 | 
						switch (type) {
 | 
				
			||||||
	case EGL_DEBUG_MSG_CRITICAL_KHR: return WLR_ERROR;
 | 
						case EGL_DEBUG_MSG_CRITICAL_KHR: return WLR_ERROR;
 | 
				
			||||||
| 
						 | 
					@ -155,7 +157,7 @@ out:
 | 
				
			||||||
	free(formats);
 | 
						free(formats);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
					static struct wlr_egl *egl_create(void) {
 | 
				
			||||||
	struct wlr_egl *egl = calloc(1, sizeof(struct wlr_egl));
 | 
						struct wlr_egl *egl = calloc(1, sizeof(struct wlr_egl));
 | 
				
			||||||
	if (egl == NULL) {
 | 
						if (egl == NULL) {
 | 
				
			||||||
		wlr_log_errno(WLR_ERROR, "Allocation failed");
 | 
							wlr_log_errno(WLR_ERROR, "Allocation failed");
 | 
				
			||||||
| 
						 | 
					@ -171,12 +173,11 @@ struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						wlr_log(WLR_INFO, "Supported EGL client extensions: %s", client_exts_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (platform == EGL_PLATFORM_GBM_KHR) {
 | 
						if (!check_egl_ext(client_exts_str, "EGL_KHR_platform_gbm")) {
 | 
				
			||||||
		if (!check_egl_ext(client_exts_str, "EGL_KHR_platform_gbm")) {
 | 
							wlr_log(WLR_ERROR, "EGL_KHR_platform_gbm not supported");
 | 
				
			||||||
			wlr_log(WLR_ERROR, "EGL_KHR_platform_gbm not supported");
 | 
							return NULL;
 | 
				
			||||||
			return NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!check_egl_ext(client_exts_str, "EGL_EXT_platform_base")) {
 | 
						if (!check_egl_ext(client_exts_str, "EGL_EXT_platform_base")) {
 | 
				
			||||||
| 
						 | 
					@ -186,6 +187,18 @@ struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
	load_egl_proc(&egl->procs.eglGetPlatformDisplayEXT,
 | 
						load_egl_proc(&egl->procs.eglGetPlatformDisplayEXT,
 | 
				
			||||||
		"eglGetPlatformDisplayEXT");
 | 
							"eglGetPlatformDisplayEXT");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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")) {
 | 
						if (check_egl_ext(client_exts_str, "EGL_KHR_debug")) {
 | 
				
			||||||
		load_egl_proc(&egl->procs.eglDebugMessageControlKHR,
 | 
							load_egl_proc(&egl->procs.eglDebugMessageControlKHR,
 | 
				
			||||||
			"eglDebugMessageControlKHR");
 | 
								"eglDebugMessageControlKHR");
 | 
				
			||||||
| 
						 | 
					@ -202,26 +215,31 @@ struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
 | 
						if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "Failed to bind to the OpenGL ES API");
 | 
							wlr_log(WLR_ERROR, "Failed to bind to the OpenGL ES API");
 | 
				
			||||||
		goto error;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return egl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool egl_init(struct wlr_egl *egl, EGLenum platform,
 | 
				
			||||||
 | 
							void *remote_display) {
 | 
				
			||||||
	egl->display = egl->procs.eglGetPlatformDisplayEXT(platform,
 | 
						egl->display = egl->procs.eglGetPlatformDisplayEXT(platform,
 | 
				
			||||||
		remote_display, NULL);
 | 
							remote_display, NULL);
 | 
				
			||||||
	if (egl->display == EGL_NO_DISPLAY) {
 | 
						if (egl->display == EGL_NO_DISPLAY) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "Failed to create EGL display");
 | 
							wlr_log(WLR_ERROR, "Failed to create EGL display");
 | 
				
			||||||
		goto error;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EGLint major, minor;
 | 
						EGLint major, minor;
 | 
				
			||||||
	if (eglInitialize(egl->display, &major, &minor) == EGL_FALSE) {
 | 
						if (eglInitialize(egl->display, &major, &minor) == EGL_FALSE) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "Failed to initialize EGL");
 | 
							wlr_log(WLR_ERROR, "Failed to initialize EGL");
 | 
				
			||||||
		goto error;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *display_exts_str = eglQueryString(egl->display, EGL_EXTENSIONS);
 | 
						const char *display_exts_str = eglQueryString(egl->display, EGL_EXTENSIONS);
 | 
				
			||||||
	if (display_exts_str == NULL) {
 | 
						if (display_exts_str == NULL) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "Failed to query EGL display extensions");
 | 
							wlr_log(WLR_ERROR, "Failed to query EGL display extensions");
 | 
				
			||||||
		return NULL;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (check_egl_ext(display_exts_str, "EGL_KHR_image_base")) {
 | 
						if (check_egl_ext(display_exts_str, "EGL_KHR_image_base")) {
 | 
				
			||||||
| 
						 | 
					@ -249,20 +267,19 @@ struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
			"eglUnbindWaylandDisplayWL");
 | 
								"eglUnbindWaylandDisplayWL");
 | 
				
			||||||
		load_egl_proc(&egl->procs.eglQueryWaylandBufferWL,
 | 
							load_egl_proc(&egl->procs.eglQueryWaylandBufferWL,
 | 
				
			||||||
			"eglQueryWaylandBufferWL");
 | 
								"eglQueryWaylandBufferWL");
 | 
				
			||||||
 | 
						} else if (platform == EGL_PLATFORM_DEVICE_EXT) {
 | 
				
			||||||
 | 
							wlr_log(WLR_DEBUG, "EGL_WL_bind_wayland_display not supported");
 | 
				
			||||||
 | 
							wlr_log(WLR_DEBUG, "Falling back to GBM platform");
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *device_exts_str = NULL;
 | 
						const char *device_exts_str = NULL;
 | 
				
			||||||
	if (check_egl_ext(client_exts_str, "EGL_EXT_device_query")) {
 | 
						if (egl->exts.device_query_ext) {
 | 
				
			||||||
		load_egl_proc(&egl->procs.eglQueryDisplayAttribEXT,
 | 
					 | 
				
			||||||
			"eglQueryDisplayAttribEXT");
 | 
					 | 
				
			||||||
		load_egl_proc(&egl->procs.eglQueryDeviceStringEXT,
 | 
					 | 
				
			||||||
			"eglQueryDeviceStringEXT");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		EGLAttrib device_attrib;
 | 
							EGLAttrib device_attrib;
 | 
				
			||||||
		if (!egl->procs.eglQueryDisplayAttribEXT(egl->display,
 | 
							if (!egl->procs.eglQueryDisplayAttribEXT(egl->display,
 | 
				
			||||||
				EGL_DEVICE_EXT, &device_attrib)) {
 | 
									EGL_DEVICE_EXT, &device_attrib)) {
 | 
				
			||||||
			wlr_log(WLR_ERROR, "eglQueryDisplayAttribEXT(EGL_DEVICE_EXT) failed");
 | 
								wlr_log(WLR_ERROR, "eglQueryDisplayAttribEXT(EGL_DEVICE_EXT) failed");
 | 
				
			||||||
			goto error;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		egl->device = (EGLDeviceEXT)device_attrib;
 | 
							egl->device = (EGLDeviceEXT)device_attrib;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -270,7 +287,7 @@ struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
			egl->procs.eglQueryDeviceStringEXT(egl->device, EGL_EXTENSIONS);
 | 
								egl->procs.eglQueryDeviceStringEXT(egl->device, EGL_EXTENSIONS);
 | 
				
			||||||
		if (device_exts_str == NULL) {
 | 
							if (device_exts_str == NULL) {
 | 
				
			||||||
			wlr_log(WLR_ERROR, "eglQueryDeviceStringEXT(EGL_EXTENSIONS) failed");
 | 
								wlr_log(WLR_ERROR, "eglQueryDeviceStringEXT(EGL_EXTENSIONS) failed");
 | 
				
			||||||
			goto error;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (check_egl_ext(device_exts_str, "EGL_MESA_device_software")) {
 | 
							if (check_egl_ext(device_exts_str, "EGL_MESA_device_software")) {
 | 
				
			||||||
| 
						 | 
					@ -296,21 +313,19 @@ struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
			!check_egl_ext(display_exts_str, "EGL_MESA_configless_context")) {
 | 
								!check_egl_ext(display_exts_str, "EGL_MESA_configless_context")) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "EGL_KHR_no_config_context or "
 | 
							wlr_log(WLR_ERROR, "EGL_KHR_no_config_context or "
 | 
				
			||||||
			"EGL_MESA_configless_context not supported");
 | 
								"EGL_MESA_configless_context not supported");
 | 
				
			||||||
		goto error;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!check_egl_ext(display_exts_str, "EGL_KHR_surfaceless_context")) {
 | 
						if (!check_egl_ext(display_exts_str, "EGL_KHR_surfaceless_context")) {
 | 
				
			||||||
		wlr_log(WLR_ERROR,
 | 
							wlr_log(WLR_ERROR, "EGL_KHR_surfaceless_context not supported");
 | 
				
			||||||
			"EGL_KHR_surfaceless_context not supported");
 | 
							return false;
 | 
				
			||||||
		goto error;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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);
 | 
						wlr_log(WLR_INFO, "Supported EGL display extensions: %s", display_exts_str);
 | 
				
			||||||
	if (device_exts_str != NULL) {
 | 
						if (device_exts_str != NULL) {
 | 
				
			||||||
		wlr_log(WLR_INFO, "Supported EGL device extensions: %s", device_exts_str);
 | 
							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));
 | 
						wlr_log(WLR_INFO, "EGL vendor: %s", eglQueryString(egl->display, EGL_VENDOR));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_dmabuf_formats(egl);
 | 
						init_dmabuf_formats(egl);
 | 
				
			||||||
| 
						 | 
					@ -341,7 +356,7 @@ struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
		EGL_NO_CONTEXT, attribs);
 | 
							EGL_NO_CONTEXT, attribs);
 | 
				
			||||||
	if (egl->context == EGL_NO_CONTEXT) {
 | 
						if (egl->context == EGL_NO_CONTEXT) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "Failed to create EGL context");
 | 
							wlr_log(WLR_ERROR, "Failed to create EGL context");
 | 
				
			||||||
		goto error;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (request_high_priority) {
 | 
						if (request_high_priority) {
 | 
				
			||||||
| 
						 | 
					@ -355,13 +370,123 @@ struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return egl;
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_egl *wlr_egl_create(EGLenum platform, void *remote_display) {
 | 
				
			||||||
 | 
						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)) {
 | 
				
			||||||
 | 
							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)) {
 | 
				
			||||||
 | 
							return egl;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Fallback to GBM
 | 
				
			||||||
 | 
						struct gbm_device *gbm_device = gbm_create_device(drm_fd);
 | 
				
			||||||
 | 
						if (!gbm_device) {
 | 
				
			||||||
 | 
							wlr_log(WLR_ERROR, "Failed to create GBM device");
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (egl_init(egl, EGL_PLATFORM_GBM_KHR, gbm_device)) {
 | 
				
			||||||
 | 
							return egl;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_log(WLR_ERROR, "Failed to initialize EGL context");
 | 
				
			||||||
 | 
						gbm_device_destroy(gbm_device);
 | 
				
			||||||
error:
 | 
					error:
 | 
				
			||||||
	eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | 
					 | 
				
			||||||
	if (egl->display) {
 | 
						if (egl->display) {
 | 
				
			||||||
 | 
							eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
 | 
				
			||||||
 | 
								EGL_NO_CONTEXT);
 | 
				
			||||||
		eglTerminate(egl->display);
 | 
							eglTerminate(egl->display);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						free(egl);
 | 
				
			||||||
	eglReleaseThread();
 | 
						eglReleaseThread();
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -691,18 +816,6 @@ const struct wlr_drm_format_set *wlr_egl_get_dmabuf_render_formats(
 | 
				
			||||||
	return &egl->dmabuf_render_formats;
 | 
						return &egl->dmabuf_render_formats;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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) {
 | 
					static char *get_render_name(const char *name) {
 | 
				
			||||||
	uint32_t flags = 0;
 | 
						uint32_t flags = 0;
 | 
				
			||||||
	int devices_len = drmGetDevices2(flags, NULL, 0);
 | 
						int devices_len = drmGetDevices2(flags, NULL, 0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include <wlr/types/wlr_matrix.h>
 | 
					#include <wlr/types/wlr_matrix.h>
 | 
				
			||||||
#include <wlr/util/log.h>
 | 
					#include <wlr/util/log.h>
 | 
				
			||||||
#include "util/signal.h"
 | 
					#include "util/signal.h"
 | 
				
			||||||
 | 
					#include "render/egl.h"
 | 
				
			||||||
#include "render/pixel_format.h"
 | 
					#include "render/pixel_format.h"
 | 
				
			||||||
#include "render/wlr_renderer.h"
 | 
					#include "render/wlr_renderer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -221,21 +222,12 @@ bool wlr_renderer_init_wl_display(struct wlr_renderer *r,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_renderer *wlr_renderer_autocreate_with_drm_fd(int drm_fd) {
 | 
					struct wlr_renderer *wlr_renderer_autocreate_with_drm_fd(int drm_fd) {
 | 
				
			||||||
	struct gbm_device *gbm_device = gbm_create_device(drm_fd);
 | 
						struct wlr_egl *egl = wlr_egl_create_from_drm_fd(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);
 | 
					 | 
				
			||||||
	if (egl == NULL) {
 | 
						if (egl == NULL) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "Could not initialize EGL");
 | 
							wlr_log(WLR_ERROR, "Could not initialize EGL");
 | 
				
			||||||
		gbm_device_destroy(gbm_device);
 | 
					 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	egl->gbm_device = gbm_device;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct wlr_renderer *renderer = wlr_gles2_renderer_create(egl);
 | 
						struct wlr_renderer *renderer = wlr_gles2_renderer_create(egl);
 | 
				
			||||||
	if (!renderer) {
 | 
						if (!renderer) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "Failed to create GLES2 renderer");
 | 
							wlr_log(WLR_ERROR, "Failed to create GLES2 renderer");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue