aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/render/egl.h5
-rw-r--r--include/wlr/render/interface.h2
-rw-r--r--include/wlr/render/wlr_texture.h3
-rw-r--r--render/egl.c46
-rw-r--r--render/glapi.txt2
-rw-r--r--render/gles2/texture.c29
-rw-r--r--render/wlr_texture.c8
7 files changed, 92 insertions, 3 deletions
diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h
index 4d837138..17fef7ed 100644
--- a/include/wlr/render/egl.h
+++ b/include/wlr/render/egl.h
@@ -20,6 +20,7 @@ struct wlr_egl {
bool swap_buffers_with_damage;
bool dmabuf_import;
bool dmabuf_import_modifiers;
+ bool dmabuf_export;
bool bind_wayland_display;
} egl_exts;
@@ -85,6 +86,10 @@ int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, int **formats);
int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, int format,
uint64_t **modifiers);
+bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image,
+ int32_t width, int32_t height, uint32_t flags,
+ struct wlr_dmabuf_buffer_attribs *attribs);
+
/**
* Destroys an EGL image created with the given wlr_egl.
*/
diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h
index 2267d376..1f075e81 100644
--- a/include/wlr/render/interface.h
+++ b/include/wlr/render/interface.h
@@ -62,6 +62,8 @@ struct wlr_texture_impl {
enum wl_shm_format wl_fmt, uint32_t stride, uint32_t width,
uint32_t height, uint32_t src_x, uint32_t src_y, uint32_t dst_x,
uint32_t dst_y, const void *data);
+ bool (*to_dmabuf)(struct wlr_texture *texture,
+ struct wlr_dmabuf_buffer_attribs *attribs);
void (*destroy)(struct wlr_texture *texture);
};
diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h
index 239fc51b..481b2a37 100644
--- a/include/wlr/render/wlr_texture.h
+++ b/include/wlr/render/wlr_texture.h
@@ -48,6 +48,9 @@ bool wlr_texture_write_pixels(struct wlr_texture *texture,
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y,
const void *data);
+bool wlr_texture_to_dmabuf(struct wlr_texture *texture,
+ struct wlr_dmabuf_buffer_attribs *attribs);
+
/**
* Destroys this wlr_texture.
*/
diff --git a/render/egl.c b/render/egl.c
index 579bb5fe..1182a72f 100644
--- a/render/egl.c
+++ b/render/egl.c
@@ -178,8 +178,12 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display,
check_egl_ext(egl->exts_str, "EGL_EXT_image_dma_buf_import_modifiers")
&& eglQueryDmaBufFormatsEXT && eglQueryDmaBufModifiersEXT;
+ egl->egl_exts.dmabuf_export =
+ check_egl_ext(egl->exts_str, "EGL_MESA_image_dma_buf_export");
+
egl->egl_exts.bind_wayland_display =
check_egl_ext(egl->exts_str, "EGL_WL_bind_wayland_display");
+
print_dmabuf_formats(egl);
return true;
@@ -209,7 +213,7 @@ void wlr_egl_finish(struct wlr_egl *egl) {
}
bool wlr_egl_bind_display(struct wlr_egl *egl, struct wl_display *local_display) {
- if (!egl->egl_exts.bind_wayland_display) {
+ if (!egl->egl_exts.bind_wayland_display || !eglBindWaylandDisplayWL) {
return false;
}
@@ -414,7 +418,7 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
}
#ifndef DRM_FORMAT_BIG_ENDIAN
-# define DRM_FORMAT_BIG_ENDIAN 0x80000000
+#define DRM_FORMAT_BIG_ENDIAN 0x80000000
#endif
bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl,
struct wlr_dmabuf_buffer *dmabuf) {
@@ -446,7 +450,7 @@ bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl,
int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl,
int **formats) {
if (!egl->egl_exts.dmabuf_import ||
- !egl->egl_exts.dmabuf_import_modifiers) {
+ !egl->egl_exts.dmabuf_import_modifiers) {
wlr_log(L_DEBUG, "dmabuf extension not present");
return -1;
}
@@ -501,6 +505,42 @@ int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl,
return num;
}
+bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image,
+ int32_t width, int32_t height, uint32_t flags,
+ struct wlr_dmabuf_buffer_attribs *attribs) {
+ memset(attribs, 0, sizeof(struct wlr_dmabuf_buffer_attribs));
+
+ if (!egl->egl_exts.dmabuf_export || !eglExportDMABUFImageQueryMESA ||
+ !eglExportDMABUFImageMESA) {
+ return false;
+ }
+
+ // Only one set of modifiers is returned for all planes
+ EGLuint64KHR modifiers;
+ if (!eglExportDMABUFImageQueryMESA(egl->display, image,
+ (int *)&attribs->format, &attribs->n_planes, &modifiers)) {
+ return false;
+ }
+ if (attribs->n_planes > WLR_LINUX_DMABUF_MAX_PLANES) {
+ wlr_log(L_ERROR, "EGL returned %d planes, but only %d are supported",
+ attribs->n_planes, WLR_LINUX_DMABUF_MAX_PLANES);
+ return false;
+ }
+ for (int i = 0; i < attribs->n_planes; ++i) {
+ attribs->modifier[i] = modifiers;
+ }
+
+ if (!eglExportDMABUFImageMESA(egl->display, image, attribs->fd,
+ (EGLint *)attribs->stride, (EGLint *)attribs->offset)) {
+ return false;
+ }
+
+ attribs->width = width;
+ attribs->height = height;
+ attribs->flags = flags;
+ return true;
+}
+
bool wlr_egl_destroy_surface(struct wlr_egl *egl, EGLSurface surface) {
if (!surface) {
return true;
diff --git a/render/glapi.txt b/render/glapi.txt
index a8e4aaba..b1166f27 100644
--- a/render/glapi.txt
+++ b/render/glapi.txt
@@ -10,6 +10,8 @@ eglCreatePlatformWindowSurfaceEXT
-eglSwapBuffersWithDamageKHR
-eglQueryDmaBufFormatsEXT
-eglQueryDmaBufModifiersEXT
+-eglExportDMABUFImageQueryMESA
+-eglExportDMABUFImageMESA
-eglDebugMessageControlKHR
-glDebugMessageCallbackKHR
-glDebugMessageControlKHR
diff --git a/render/gles2/texture.c b/render/gles2/texture.c
index 37424802..742f9da0 100644
--- a/render/gles2/texture.c
+++ b/render/gles2/texture.c
@@ -74,6 +74,34 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture,
return true;
}
+static bool gles2_texture_to_dmabuf(struct wlr_texture *wlr_texture,
+ struct wlr_dmabuf_buffer_attribs *attribs) {
+ struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
+
+ if (!texture->image) {
+ assert(texture->type == WLR_GLES2_TEXTURE_GLTEX);
+
+ if (!eglCreateImageKHR) {
+ return false;
+ }
+
+ texture->image = eglCreateImageKHR(texture->egl->display,
+ texture->egl->context, EGL_GL_TEXTURE_2D_KHR,
+ (EGLClientBuffer)(uintptr_t)texture->gl_tex, NULL);
+ if (texture->image == EGL_NO_IMAGE_KHR) {
+ return false;
+ }
+ }
+
+ uint32_t flags = 0;
+ if (texture->inverted_y) {
+ flags |= WLR_DMABUF_BUFFER_ATTRIBS_FLAGS_Y_INVERT;
+ }
+
+ return wlr_egl_export_image_to_dmabuf(texture->egl, texture->image,
+ texture->width, texture->height, flags, attribs);
+}
+
static void gles2_texture_destroy(struct wlr_texture *wlr_texture) {
if (wlr_texture == NULL) {
return;
@@ -102,6 +130,7 @@ static void gles2_texture_destroy(struct wlr_texture *wlr_texture) {
static const struct wlr_texture_impl texture_impl = {
.get_size = gles2_texture_get_size,
.write_pixels = gles2_texture_write_pixels,
+ .to_dmabuf = gles2_texture_to_dmabuf,
.destroy = gles2_texture_destroy,
};
diff --git a/render/wlr_texture.c b/render/wlr_texture.c
index 9aecfd98..f7ce0b44 100644
--- a/render/wlr_texture.c
+++ b/render/wlr_texture.c
@@ -54,3 +54,11 @@ bool wlr_texture_write_pixels(struct wlr_texture *texture,
return texture->impl->write_pixels(texture, wl_fmt, stride, width, height,
src_x, src_y, dst_x, dst_y, data);
}
+
+bool wlr_texture_to_dmabuf(struct wlr_texture *texture,
+ struct wlr_dmabuf_buffer_attribs *attribs) {
+ if (!texture->impl->to_dmabuf) {
+ return false;
+ }
+ return texture->impl->to_dmabuf(texture, attribs);
+}