aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/render/dmabuf.h4
-rw-r--r--render/egl.c49
-rw-r--r--types/wlr_linux_dmabuf_v1.c29
3 files changed, 61 insertions, 21 deletions
diff --git a/include/wlr/render/dmabuf.h b/include/wlr/render/dmabuf.h
index 33c3a129..32cfe874 100644
--- a/include/wlr/render/dmabuf.h
+++ b/include/wlr/render/dmabuf.h
@@ -16,6 +16,10 @@
#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
#endif
+#ifndef DRM_FORMAT_MOD_LINEAR
+#define DRM_FORMAT_MOD_LINEAR 0
+#endif
+
#define WLR_DMABUF_MAX_PLANES 4
enum wlr_dmabuf_attributes_flags {
diff --git a/render/egl.c b/render/egl.c
index 96e48c06..585baaeb 100644
--- a/render/egl.c
+++ b/render/egl.c
@@ -3,6 +3,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdlib.h>
+#include <drm_fourcc.h>
#include <wlr/render/egl.h>
#include <wlr/util/log.h>
#include "glapi.h"
@@ -382,13 +383,21 @@ EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl,
EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
struct wlr_dmabuf_attributes *attributes) {
- if (!egl->exts.image_base_khr) {
+ if (!egl->exts.image_base_khr || !egl->exts.image_dmabuf_import_ext) {
+ wlr_log(WLR_ERROR, "dmabuf import extension not present");
return NULL;
}
bool has_modifier = false;
- if (attributes->modifier != DRM_FORMAT_MOD_INVALID) {
+
+ // we assume the same way we assumed formats without the import_modifiers
+ // extension that mod_linear is supported. The special mod mod_invalid
+ // is sometimes used to signal modifier unawareness which is what we
+ // have here
+ if (attributes->modifier != DRM_FORMAT_MOD_INVALID &&
+ attributes->modifier != DRM_FORMAT_MOD_LINEAR) {
if (!egl->exts.image_dmabuf_import_modifiers_ext) {
+ wlr_log(WLR_ERROR, "dmabuf modifiers extension not present");
return NULL;
}
has_modifier = true;
@@ -460,12 +469,34 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl,
int **formats) {
- if (!egl->exts.image_dmabuf_import_ext ||
- !egl->exts.image_dmabuf_import_modifiers_ext) {
- wlr_log(WLR_DEBUG, "dmabuf extension not present");
+ if (!egl->exts.image_dmabuf_import_ext) {
+ wlr_log(WLR_DEBUG, "dmabuf import extension not present");
return -1;
}
+ // when we only have the image_dmabuf_import extension we can't query
+ // which formats are supported. These two are on almost always
+ // supported; it's the intended way to just try to create buffers.
+ // Just a guess but better than not supporting dmabufs at all,
+ // given that the modifiers extension isn't supported everywhere.
+ if (!egl->exts.image_dmabuf_import_modifiers_ext) {
+ static const int fallback_formats[] = {
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XRGB8888,
+ };
+ static unsigned num = sizeof(fallback_formats) /
+ sizeof(fallback_formats[0]);
+
+ *formats = calloc(num, sizeof(int));
+ if (!*formats) {
+ wlr_log_errno(WLR_ERROR, "Allocation failed");
+ return -1;
+ }
+
+ memcpy(*formats, fallback_formats, num * sizeof(**formats));
+ return num;
+ }
+
EGLint num;
if (!eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) {
wlr_log(WLR_ERROR, "failed to query number of dmabuf formats");
@@ -488,12 +519,16 @@ int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl,
int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl,
int format, uint64_t **modifiers) {
- if (!egl->exts.image_dmabuf_import_ext ||
- !egl->exts.image_dmabuf_import_modifiers_ext) {
+ if (!egl->exts.image_dmabuf_import_ext) {
wlr_log(WLR_DEBUG, "dmabuf extension not present");
return -1;
}
+ if(!egl->exts.image_dmabuf_import_modifiers_ext) {
+ *modifiers = NULL;
+ return 0;
+ }
+
EGLint num;
if (!eglQueryDmaBufModifiersEXT(egl->display, format, 0,
NULL, NULL, &num)) {
diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c
index f72e7c07..eb7b2f9e 100644
--- a/types/wlr_linux_dmabuf_v1.c
+++ b/types/wlr_linux_dmabuf_v1.c
@@ -103,6 +103,7 @@ static void params_add(struct wl_client *client,
close(fd);
return;
}
+
buffer->attributes.modifier = modifier;
buffer->has_modifier = true;
@@ -382,13 +383,9 @@ struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_from_resource(
return dmabuf;
}
-static void linux_dmabuf_send_modifiers(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
- struct wl_resource *resource) {
+static void linux_dmabuf_send_formats(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
+ struct wl_resource *resource, uint32_t version) {
struct wlr_renderer *renderer = linux_dmabuf->renderer;
- /*
- * Use EGL_EXT_image_dma_buf_import_modifiers to query and advertise
- * format/modifier codes.
- */
uint64_t modifier_invalid = DRM_FORMAT_MOD_INVALID;
int *formats = NULL;
int num_formats = wlr_renderer_get_dmabuf_formats(renderer, &formats);
@@ -410,10 +407,17 @@ static void linux_dmabuf_send_modifiers(struct wlr_linux_dmabuf_v1 *linux_dmabuf
modifiers = &modifier_invalid;
}
for (int j = 0; j < num_modifiers; j++) {
- uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF;
- uint32_t modifier_hi = modifiers[j] >> 32;
- zwp_linux_dmabuf_v1_send_modifier(resource, formats[i],
- modifier_hi, modifier_lo);
+ if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
+ uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF;
+ uint32_t modifier_hi = modifiers[j] >> 32;
+ zwp_linux_dmabuf_v1_send_modifier(resource,
+ formats[i],
+ modifier_hi,
+ modifier_lo);
+ } else if (modifiers[j] == DRM_FORMAT_MOD_LINEAR ||
+ modifiers == &modifier_invalid) {
+ zwp_linux_dmabuf_v1_send_format(resource, formats[i]);
+ }
}
if (modifiers != &modifier_invalid) {
free(modifiers);
@@ -439,10 +443,7 @@ static void linux_dmabuf_bind(struct wl_client *client, void *data,
wl_resource_set_implementation(resource, &linux_dmabuf_impl,
linux_dmabuf, linux_dmabuf_resource_destroy);
wl_list_insert(&linux_dmabuf->resources, wl_resource_get_link(resource));
-
- if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
- linux_dmabuf_send_modifiers(linux_dmabuf, resource);
- }
+ linux_dmabuf_send_formats(linux_dmabuf, resource, version);
}
void wlr_linux_dmabuf_v1_destroy(struct wlr_linux_dmabuf_v1 *linux_dmabuf) {