diff options
| -rw-r--r-- | include/wlr/render/egl.h | 3 | ||||
| -rw-r--r-- | render/egl.c | 72 | ||||
| -rw-r--r-- | render/gles2/texture.c | 14 | 
3 files changed, 73 insertions, 16 deletions
diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 627e9aaf..98435d91 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -65,6 +65,7 @@ struct wlr_egl {  	struct wl_display *wl_display;  	struct wlr_drm_format_set dmabuf_formats; +	EGLBoolean **external_only_dmabuf_formats;  };  // TODO: Allocate and return a wlr_egl @@ -106,7 +107,7 @@ EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl,   * of the dmabuf with wlr_egl_check_import_dmabuf once first.   */  EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, -	struct wlr_dmabuf_attributes *attributes); +	struct wlr_dmabuf_attributes *attributes, bool *external_only);  /**   * Get the available dmabuf formats diff --git a/render/egl.c b/render/egl.c index 275ef6f9..a2f7bd9a 100644 --- a/render/egl.c +++ b/render/egl.c @@ -87,7 +87,7 @@ static void load_egl_proc(void *proc_ptr, const char *name) {  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); +	uint64_t **modifiers, EGLBoolean **external_only);  static void init_dmabuf_formats(struct wlr_egl *egl) {  	int *formats; @@ -96,11 +96,20 @@ static void init_dmabuf_formats(struct wlr_egl *egl) {  		return;  	} +	egl->external_only_dmabuf_formats = calloc(formats_len, sizeof(EGLBoolean *)); +	if (egl->external_only_dmabuf_formats == NULL) { +		wlr_log_errno(WLR_ERROR, "Allocation failed"); +		goto out; +	} + +	size_t external_formats_len = 0;  	for (int i = 0; i < formats_len; i++) {  		uint32_t fmt = formats[i];  		uint64_t *modifiers; -		int modifiers_len = get_egl_dmabuf_modifiers(egl, fmt, &modifiers); +		EGLBoolean *external_only; +		int modifiers_len = +			get_egl_dmabuf_modifiers(egl, fmt, &modifiers, &external_only);  		if (modifiers_len < 0) {  			continue;  		} @@ -114,6 +123,9 @@ static void init_dmabuf_formats(struct wlr_egl *egl) {  		}  		free(modifiers); + +		egl->external_only_dmabuf_formats[external_formats_len] = external_only; +		external_formats_len++;  	}  	char *str_formats = malloc(formats_len * 5 + 1); @@ -305,6 +317,11 @@ void wlr_egl_finish(struct wlr_egl *egl) {  		return;  	} +	for (size_t i = 0; i < egl->dmabuf_formats.len; i++) { +		free(egl->external_only_dmabuf_formats[i]); +	} +	free(egl->external_only_dmabuf_formats); +  	wlr_drm_format_set_finish(&egl->dmabuf_formats);  	eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); @@ -479,8 +496,29 @@ EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl,  		EGL_WAYLAND_BUFFER_WL, data, attribs);  } +static bool dmabuf_format_is_external_only(struct wlr_egl *egl, +		uint32_t format, uint64_t modifier) { +	for (size_t i = 0; i < egl->dmabuf_formats.len; i++) { +		struct wlr_drm_format *fmt = egl->dmabuf_formats.formats[i]; +		if (fmt->format == format) { +			if (egl->external_only_dmabuf_formats[i] == NULL) { +				break; +			} +			for (size_t j = 0; j < fmt->len; j++) { +				if (fmt->modifiers[j] == modifier) { +					return egl->external_only_dmabuf_formats[i][j]; +				} +			} +			break; +		} +	} +	// No info, we're doomed. Choose GL_TEXTURE_EXTERNAL_OES and hope for the +	// best. +	return true; +} +  EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, -		struct wlr_dmabuf_attributes *attributes) { +		struct wlr_dmabuf_attributes *attributes, bool *external_only) {  	if (!egl->exts.image_base_khr || !egl->exts.image_dmabuf_import_ext) {  		wlr_log(WLR_ERROR, "dmabuf import extension not present");  		return NULL; @@ -561,8 +599,16 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,  	attribs[atti++] = EGL_NONE;  	assert(atti < sizeof(attribs)/sizeof(attribs[0])); -	return egl->procs.eglCreateImageKHR(egl->display, EGL_NO_CONTEXT, +	EGLImageKHR image = egl->procs.eglCreateImageKHR(egl->display, EGL_NO_CONTEXT,  		EGL_LINUX_DMA_BUF_EXT, NULL, attribs); +	if (image == EGL_NO_IMAGE_KHR) { +		wlr_log(WLR_ERROR, "eglCreateImageKHR failed"); +		return EGL_NO_IMAGE_KHR; +	} + +	*external_only = dmabuf_format_is_external_only(egl, +		attributes->format, attributes->modifier); +	return image;  }  static int get_egl_dmabuf_formats(struct wlr_egl *egl, int **formats) { @@ -615,13 +661,15 @@ 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) { +		uint64_t **modifiers, EGLBoolean **external_only) { +	*modifiers = NULL; +	*external_only = NULL; +  	if (!egl->exts.image_dmabuf_import_ext) {  		wlr_log(WLR_DEBUG, "DMA-BUF extension not present");  		return -1;  	}  	if (!egl->exts.image_dmabuf_import_modifiers_ext) { -		*modifiers = NULL;  		return 0;  	} @@ -632,18 +680,24 @@ static int get_egl_dmabuf_modifiers(struct wlr_egl *egl, int format,  		return -1;  	}  	if (num == 0) { -		*modifiers = NULL;  		return 0;  	}  	*modifiers = calloc(num, sizeof(uint64_t));  	if (*modifiers == NULL) { -		wlr_log(WLR_ERROR, "Allocation failed: %s", strerror(errno)); +		wlr_log_errno(WLR_ERROR, "Allocation failed"); +		return -1; +	} +	*external_only = calloc(num, sizeof(EGLBoolean)); +	if (*external_only == NULL) { +		wlr_log_errno(WLR_ERROR, "Allocation failed"); +		free(*modifiers); +		*modifiers = NULL;  		return -1;  	}  	if (!egl->procs.eglQueryDmaBufModifiersEXT(egl->display, format, num, -		*modifiers, NULL, &num)) { +			*modifiers, *external_only, &num)) {  		wlr_log(WLR_ERROR, "Failed to query dmabuf modifiers");  		free(*modifiers);  		return -1; diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 64a0d9f1..0187a462 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -273,26 +273,28 @@ struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl,  	wlr_texture_init(&texture->wlr_texture, &texture_impl,  		attribs->width, attribs->height);  	texture->egl = egl; -	texture->target = GL_TEXTURE_EXTERNAL_OES;  	texture->has_alpha = true;  	texture->wl_format = 0xFFFFFFFF; // texture can't be written anyways  	texture->inverted_y =  		(attribs->flags & WLR_DMABUF_ATTRIBUTES_FLAGS_Y_INVERT) != 0; -	texture->image = wlr_egl_create_image_from_dmabuf(egl, attribs); +	bool external_only; +	texture->image = +		wlr_egl_create_image_from_dmabuf(egl, attribs, &external_only);  	if (texture->image == EGL_NO_IMAGE_KHR) {  		wlr_log(WLR_ERROR, "Failed to create EGL image from DMA-BUF");  		free(texture);  		return NULL;  	} +	texture->target = external_only ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; +  	PUSH_GLES2_DEBUG;  	glGenTextures(1, &texture->tex); -	glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->tex); -	gles2_procs.glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, -		texture->image); -	glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); +	glBindTexture(texture->target, texture->tex); +	gles2_procs.glEGLImageTargetTexture2DOES(texture->target, texture->image); +	glBindTexture(texture->target, 0);  	POP_GLES2_DEBUG;  | 
