mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 12:55:58 +01:00
Support older wlr_linux_dmabuf_v1 clients
If a client uses an older version of the dmabuf protocol, use the `formats` event instead of `modifiers` (since that didn't exist in older versions). With a bit of necessary guessing, support dmabuf importing even when EGL_EXT_image_dma_buf_import_modifiers isn't present instead of failing up front.
This commit is contained in:
parent
4897267bd6
commit
affbfb6a28
3 changed files with 61 additions and 21 deletions
|
@ -16,6 +16,10 @@
|
||||||
#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
|
#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DRM_FORMAT_MOD_LINEAR
|
||||||
|
#define DRM_FORMAT_MOD_LINEAR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define WLR_DMABUF_MAX_PLANES 4
|
#define WLR_DMABUF_MAX_PLANES 4
|
||||||
|
|
||||||
enum wlr_dmabuf_attributes_flags {
|
enum wlr_dmabuf_attributes_flags {
|
||||||
|
|
49
render/egl.c
49
render/egl.c
|
@ -3,6 +3,7 @@
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <drm_fourcc.h>
|
||||||
#include <wlr/render/egl.h>
|
#include <wlr/render/egl.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "glapi.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,
|
EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
|
||||||
struct wlr_dmabuf_attributes *attributes) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_modifier = false;
|
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) {
|
if (!egl->exts.image_dmabuf_import_modifiers_ext) {
|
||||||
|
wlr_log(WLR_ERROR, "dmabuf modifiers extension not present");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
has_modifier = true;
|
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 wlr_egl_get_dmabuf_formats(struct wlr_egl *egl,
|
||||||
int **formats) {
|
int **formats) {
|
||||||
if (!egl->exts.image_dmabuf_import_ext ||
|
if (!egl->exts.image_dmabuf_import_ext) {
|
||||||
!egl->exts.image_dmabuf_import_modifiers_ext) {
|
wlr_log(WLR_DEBUG, "dmabuf import extension not present");
|
||||||
wlr_log(WLR_DEBUG, "dmabuf extension not present");
|
|
||||||
return -1;
|
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;
|
EGLint num;
|
||||||
if (!eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) {
|
if (!eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) {
|
||||||
wlr_log(WLR_ERROR, "failed to query number of dmabuf formats");
|
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 wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl,
|
||||||
int format, uint64_t **modifiers) {
|
int format, uint64_t **modifiers) {
|
||||||
if (!egl->exts.image_dmabuf_import_ext ||
|
if (!egl->exts.image_dmabuf_import_ext) {
|
||||||
!egl->exts.image_dmabuf_import_modifiers_ext) {
|
|
||||||
wlr_log(WLR_DEBUG, "dmabuf extension not present");
|
wlr_log(WLR_DEBUG, "dmabuf extension not present");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!egl->exts.image_dmabuf_import_modifiers_ext) {
|
||||||
|
*modifiers = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
EGLint num;
|
EGLint num;
|
||||||
if (!eglQueryDmaBufModifiersEXT(egl->display, format, 0,
|
if (!eglQueryDmaBufModifiersEXT(egl->display, format, 0,
|
||||||
NULL, NULL, &num)) {
|
NULL, NULL, &num)) {
|
||||||
|
|
|
@ -103,6 +103,7 @@ static void params_add(struct wl_client *client,
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->attributes.modifier = modifier;
|
buffer->attributes.modifier = modifier;
|
||||||
buffer->has_modifier = true;
|
buffer->has_modifier = true;
|
||||||
|
|
||||||
|
@ -382,13 +383,9 @@ struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_from_resource(
|
||||||
return dmabuf;
|
return dmabuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linux_dmabuf_send_modifiers(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
|
static void linux_dmabuf_send_formats(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource, uint32_t version) {
|
||||||
struct wlr_renderer *renderer = linux_dmabuf->renderer;
|
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;
|
uint64_t modifier_invalid = DRM_FORMAT_MOD_INVALID;
|
||||||
int *formats = NULL;
|
int *formats = NULL;
|
||||||
int num_formats = wlr_renderer_get_dmabuf_formats(renderer, &formats);
|
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;
|
modifiers = &modifier_invalid;
|
||||||
}
|
}
|
||||||
for (int j = 0; j < num_modifiers; j++) {
|
for (int j = 0; j < num_modifiers; j++) {
|
||||||
uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF;
|
if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
|
||||||
uint32_t modifier_hi = modifiers[j] >> 32;
|
uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF;
|
||||||
zwp_linux_dmabuf_v1_send_modifier(resource, formats[i],
|
uint32_t modifier_hi = modifiers[j] >> 32;
|
||||||
modifier_hi, modifier_lo);
|
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) {
|
if (modifiers != &modifier_invalid) {
|
||||||
free(modifiers);
|
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,
|
wl_resource_set_implementation(resource, &linux_dmabuf_impl,
|
||||||
linux_dmabuf, linux_dmabuf_resource_destroy);
|
linux_dmabuf, linux_dmabuf_resource_destroy);
|
||||||
wl_list_insert(&linux_dmabuf->resources, wl_resource_get_link(resource));
|
wl_list_insert(&linux_dmabuf->resources, wl_resource_get_link(resource));
|
||||||
|
linux_dmabuf_send_formats(linux_dmabuf, resource, version);
|
||||||
if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
|
|
||||||
linux_dmabuf_send_modifiers(linux_dmabuf, resource);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_linux_dmabuf_v1_destroy(struct wlr_linux_dmabuf_v1 *linux_dmabuf) {
|
void wlr_linux_dmabuf_v1_destroy(struct wlr_linux_dmabuf_v1 *linux_dmabuf) {
|
||||||
|
|
Loading…
Reference in a new issue