egl/wayland: Use linux-dmabuf interface for buffers
When available, use the zwp_linux_dambuf_v1 interface to create buffers, which allows multiple planes and buffer modifiers to be used. Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
This commit is contained in:
parent
cfaca5742e
commit
02cc359372
|
@ -88,6 +88,7 @@ LIBOMXIL_BELLAGIO_REQUIRED=0.0
|
|||
LIBVA_REQUIRED=0.38.0
|
||||
VDPAU_REQUIRED=1.1
|
||||
WAYLAND_REQUIRED=1.11
|
||||
WAYLAND_PROTOCOLS_REQUIRED=1.8
|
||||
XCB_REQUIRED=1.9.3
|
||||
XCBDRI2_REQUIRED=1.8
|
||||
XCBGLX_REQUIRED=1.8.1
|
||||
|
@ -1686,7 +1687,9 @@ for plat in $platforms; do
|
|||
case "$plat" in
|
||||
wayland)
|
||||
|
||||
PKG_CHECK_MODULES([WAYLAND], [wayland-client >= $WAYLAND_REQUIRED wayland-server >= $WAYLAND_REQUIRED])
|
||||
PKG_CHECK_MODULES([WAYLAND], [wayland-client >= $WAYLAND_REQUIRED wayland-server >= $WAYLAND_REQUIRED wayland-protocols >= $WAYLAND_PROTOCOLS_REQUIRED])
|
||||
ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`
|
||||
AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir)
|
||||
|
||||
if test "x$WAYLAND_SCANNER" = "x:"; then
|
||||
AC_MSG_ERROR([wayland-scanner is needed to compile the wayland platform])
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
include Makefile.sources
|
||||
|
||||
BUILT_SOURCES =
|
||||
|
||||
AM_CFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src/egl/main \
|
||||
|
@ -61,11 +63,27 @@ endif
|
|||
endif
|
||||
|
||||
if HAVE_PLATFORM_WAYLAND
|
||||
WL_DMABUF_XML = $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
|
||||
|
||||
drivers/dri2/linux-dmabuf-unstable-v1-protocol.c: $(WL_DMABUF_XML)
|
||||
$(MKDIR_GEN)
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||
|
||||
drivers/dri2/linux-dmabuf-unstable-v1-client-protocol.h: $(WL_DMABUF_XML)
|
||||
$(MKDIR_GEN)
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
BUILT_SOURCES += \
|
||||
drivers/dri2/linux-dmabuf-unstable-v1-protocol.c \
|
||||
drivers/dri2/linux-dmabuf-unstable-v1-client-protocol.h
|
||||
|
||||
AM_CFLAGS += $(WAYLAND_CFLAGS)
|
||||
libEGL_common_la_LIBADD += $(WAYLAND_LIBS)
|
||||
libEGL_common_la_LIBADD += $(LIBDRM_LIBS)
|
||||
libEGL_common_la_LIBADD += $(top_builddir)/src/egl/wayland/wayland-drm/libwayland-drm.la
|
||||
dri2_backend_FILES += drivers/dri2/platform_wayland.c
|
||||
libEGL_common_la_LIBADD += $(top_builddir)/src/util/libmesautil.la
|
||||
dri2_backend_FILES += drivers/dri2/platform_wayland.c \
|
||||
drivers/dri2/linux-dmabuf-unstable-v1-protocol.c
|
||||
endif
|
||||
|
||||
if HAVE_PLATFORM_DRM
|
||||
|
@ -85,6 +103,7 @@ endif
|
|||
|
||||
AM_CFLAGS += \
|
||||
-I$(top_srcdir)/src/loader \
|
||||
-I$(top_builddir)/src/egl/drivers/dri2 \
|
||||
-I$(top_srcdir)/src/egl/drivers/dri2 \
|
||||
-I$(top_srcdir)/src/gbm/backends/dri \
|
||||
-I$(top_srcdir)/src/egl/wayland/wayland-egl \
|
||||
|
@ -118,7 +137,7 @@ g_egldispatchstubs.h: $(GLVND_GEN_DEPS)
|
|||
$(top_srcdir)/src/egl/generate/egl.xml \
|
||||
$(top_srcdir)/src/egl/generate/egl_other.xml > $@
|
||||
|
||||
BUILT_SOURCES = g_egldispatchstubs.c g_egldispatchstubs.h
|
||||
BUILT_SOURCES += g_egldispatchstubs.c g_egldispatchstubs.h
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
if USE_LIBGLVND
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
linux-dmabuf-unstable-v1-client-protocol.h
|
||||
linux-dmabuf-unstable-v1-protocol.c
|
|
@ -53,6 +53,7 @@
|
|||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
#include "wayland-drm.h"
|
||||
#include "wayland-drm-client-protocol.h"
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
|
@ -62,6 +63,7 @@
|
|||
#include "egl_dri2.h"
|
||||
#include "loader/loader.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "util/u_vector.h"
|
||||
|
||||
/* The kernel header drm_fourcc.h defines the DRM formats below. We duplicate
|
||||
* some of the definitions here so that building Mesa won't bleeding-edge
|
||||
|
@ -938,11 +940,16 @@ dri2_display_destroy(_EGLDisplay *disp)
|
|||
case _EGL_PLATFORM_WAYLAND:
|
||||
if (dri2_dpy->wl_drm)
|
||||
wl_drm_destroy(dri2_dpy->wl_drm);
|
||||
if (dri2_dpy->wl_dmabuf)
|
||||
zwp_linux_dmabuf_v1_destroy(dri2_dpy->wl_dmabuf);
|
||||
if (dri2_dpy->wl_shm)
|
||||
wl_shm_destroy(dri2_dpy->wl_shm);
|
||||
wl_registry_destroy(dri2_dpy->wl_registry);
|
||||
wl_event_queue_destroy(dri2_dpy->wl_queue);
|
||||
wl_proxy_wrapper_destroy(dri2_dpy->wl_dpy_wrapper);
|
||||
u_vector_finish(&dri2_dpy->wl_modifiers.argb8888);
|
||||
u_vector_finish(&dri2_dpy->wl_modifiers.xrgb8888);
|
||||
u_vector_finish(&dri2_dpy->wl_modifiers.rgb565);
|
||||
if (dri2_dpy->own_device) {
|
||||
wl_display_disconnect(dri2_dpy->wl_dpy);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
#include <wayland-client.h>
|
||||
#include "wayland-egl-priv.h"
|
||||
/* forward declarations of protocol elements */
|
||||
struct zwp_linux_dmabuf_v1;
|
||||
#endif
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
@ -73,6 +75,8 @@
|
|||
#include "eglimage.h"
|
||||
#include "eglsync.h"
|
||||
|
||||
#include "util/u_vector.h"
|
||||
|
||||
struct wl_buffer;
|
||||
|
||||
struct dri2_egl_driver
|
||||
|
@ -212,6 +216,12 @@ struct dri2_egl_display
|
|||
struct wl_drm *wl_drm;
|
||||
struct wl_shm *wl_shm;
|
||||
struct wl_event_queue *wl_queue;
|
||||
struct zwp_linux_dmabuf_v1 *wl_dmabuf;
|
||||
struct {
|
||||
struct u_vector xrgb8888;
|
||||
struct u_vector argb8888;
|
||||
struct u_vector rgb565;
|
||||
} wl_modifiers;
|
||||
bool authenticated;
|
||||
int formats;
|
||||
uint32_t capabilities;
|
||||
|
|
|
@ -36,14 +36,25 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <xf86drm.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "egl_dri2.h"
|
||||
#include "egl_dri2_fallbacks.h"
|
||||
#include "loader.h"
|
||||
#include "util/u_vector.h"
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "wayland-drm-client-protocol.h"
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
|
||||
#ifndef DRM_FORMAT_MOD_INVALID
|
||||
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
|
||||
#endif
|
||||
|
||||
#ifndef DRM_FORMAT_MOD_LINEAR
|
||||
#define DRM_FORMAT_MOD_LINEAR 0
|
||||
#endif
|
||||
|
||||
enum wl_drm_format_flags {
|
||||
HAS_ARGB8888 = 1,
|
||||
|
@ -331,6 +342,8 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
|
|||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
int use_flags;
|
||||
unsigned int dri_image_format;
|
||||
uint64_t *modifiers;
|
||||
int num_modifiers;
|
||||
|
||||
/* currently supports three WL DRM formats,
|
||||
* WL_DRM_FORMAT_ARGB8888, WL_DRM_FORMAT_XRGB8888,
|
||||
|
@ -339,12 +352,18 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
|
|||
switch (dri2_surf->format) {
|
||||
case WL_DRM_FORMAT_ARGB8888:
|
||||
dri_image_format = __DRI_IMAGE_FORMAT_ARGB8888;
|
||||
modifiers = u_vector_tail(&dri2_dpy->wl_modifiers.argb8888);
|
||||
num_modifiers = u_vector_length(&dri2_dpy->wl_modifiers.argb8888);
|
||||
break;
|
||||
case WL_DRM_FORMAT_XRGB8888:
|
||||
dri_image_format = __DRI_IMAGE_FORMAT_XRGB8888;
|
||||
modifiers = u_vector_tail(&dri2_dpy->wl_modifiers.xrgb8888);
|
||||
num_modifiers = u_vector_length(&dri2_dpy->wl_modifiers.xrgb8888);
|
||||
break;
|
||||
case WL_DRM_FORMAT_RGB565:
|
||||
dri_image_format = __DRI_IMAGE_FORMAT_RGB565;
|
||||
modifiers = u_vector_tail(&dri2_dpy->wl_modifiers.rgb565);
|
||||
num_modifiers = u_vector_length(&dri2_dpy->wl_modifiers.rgb565);
|
||||
break;
|
||||
default:
|
||||
/* format is not supported */
|
||||
|
@ -382,27 +401,60 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
|
|||
|
||||
if (dri2_dpy->is_different_gpu &&
|
||||
dri2_surf->back->linear_copy == NULL) {
|
||||
dri2_surf->back->linear_copy =
|
||||
dri2_dpy->image->createImage(dri2_dpy->dri_screen,
|
||||
dri2_surf->base.Width,
|
||||
dri2_surf->base.Height,
|
||||
dri_image_format,
|
||||
use_flags |
|
||||
__DRI_IMAGE_USE_LINEAR,
|
||||
NULL);
|
||||
/* The LINEAR modifier should be a perfect alias of the LINEAR use
|
||||
* flag; try the new interface first before the old, then fall back. */
|
||||
if (dri2_dpy->image->base.version >= 15 &&
|
||||
dri2_dpy->image->createImageWithModifiers) {
|
||||
uint64_t linear_mod = DRM_FORMAT_MOD_LINEAR;
|
||||
|
||||
dri2_surf->back->linear_copy =
|
||||
dri2_dpy->image->createImageWithModifiers(dri2_dpy->dri_screen,
|
||||
dri2_surf->base.Width,
|
||||
dri2_surf->base.Height,
|
||||
dri_image_format,
|
||||
&linear_mod,
|
||||
1,
|
||||
NULL);
|
||||
} else {
|
||||
dri2_surf->back->linear_copy =
|
||||
dri2_dpy->image->createImage(dri2_dpy->dri_screen,
|
||||
dri2_surf->base.Width,
|
||||
dri2_surf->base.Height,
|
||||
dri_image_format,
|
||||
use_flags |
|
||||
__DRI_IMAGE_USE_LINEAR,
|
||||
NULL);
|
||||
}
|
||||
if (dri2_surf->back->linear_copy == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dri2_surf->back->dri_image == NULL) {
|
||||
dri2_surf->back->dri_image =
|
||||
dri2_dpy->image->createImage(dri2_dpy->dri_screen,
|
||||
dri2_surf->base.Width,
|
||||
dri2_surf->base.Height,
|
||||
dri_image_format,
|
||||
dri2_dpy->is_different_gpu ?
|
||||
0 : use_flags,
|
||||
NULL);
|
||||
/* If our DRIImage implementation does not support
|
||||
* createImageWithModifiers, then fall back to the old createImage,
|
||||
* and hope it allocates an image which is acceptable to the winsys.
|
||||
*/
|
||||
if (num_modifiers && dri2_dpy->image->base.version >= 15 &&
|
||||
dri2_dpy->image->createImageWithModifiers) {
|
||||
dri2_surf->back->dri_image =
|
||||
dri2_dpy->image->createImageWithModifiers(dri2_dpy->dri_screen,
|
||||
dri2_surf->base.Width,
|
||||
dri2_surf->base.Height,
|
||||
dri_image_format,
|
||||
modifiers,
|
||||
num_modifiers,
|
||||
NULL);
|
||||
} else {
|
||||
dri2_surf->back->dri_image =
|
||||
dri2_dpy->image->createImage(dri2_dpy->dri_screen,
|
||||
dri2_surf->base.Width,
|
||||
dri2_surf->base.Height,
|
||||
dri_image_format,
|
||||
dri2_dpy->is_different_gpu ?
|
||||
0 : use_flags,
|
||||
NULL);
|
||||
}
|
||||
|
||||
dri2_surf->back->age = 0;
|
||||
}
|
||||
if (dri2_surf->back->dri_image == NULL)
|
||||
|
@ -643,17 +695,68 @@ create_wl_buffer(struct dri2_egl_display *dri2_dpy,
|
|||
__DRIimage *image)
|
||||
{
|
||||
struct wl_buffer *ret;
|
||||
int width, height, fourcc;
|
||||
int width, height, fourcc, num_planes;
|
||||
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width);
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, &height);
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FOURCC, &fourcc);
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NUM_PLANES,
|
||||
&num_planes);
|
||||
|
||||
if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
|
||||
if (dri2_dpy->wl_dmabuf && dri2_dpy->image->base.version >= 15) {
|
||||
struct zwp_linux_buffer_params_v1 *params;
|
||||
int mod_hi, mod_lo;
|
||||
int i;
|
||||
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
|
||||
&mod_hi);
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
|
||||
&mod_lo);
|
||||
|
||||
/* We don't need a wrapper for wl_dmabuf objects, because we have to
|
||||
* create the intermediate params object; we can set the queue on this,
|
||||
* and the wl_buffer inherits it race-free. */
|
||||
params = zwp_linux_dmabuf_v1_create_params(dri2_dpy->wl_dmabuf);
|
||||
if (dri2_surf)
|
||||
wl_proxy_set_queue((struct wl_proxy *) params, dri2_surf->wl_queue);
|
||||
|
||||
for (i = 0; i < num_planes; i++) {
|
||||
__DRIimage *p_image;
|
||||
int stride, offset, fd;
|
||||
|
||||
if (i == 0)
|
||||
p_image = image;
|
||||
else
|
||||
p_image = dri2_dpy->image->fromPlanar(image, i, NULL);
|
||||
if (!p_image) {
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dri2_dpy->image->queryImage(p_image, __DRI_IMAGE_ATTRIB_FD, &fd);
|
||||
dri2_dpy->image->queryImage(p_image, __DRI_IMAGE_ATTRIB_STRIDE,
|
||||
&stride);
|
||||
dri2_dpy->image->queryImage(p_image, __DRI_IMAGE_ATTRIB_OFFSET,
|
||||
&offset);
|
||||
if (image != p_image)
|
||||
dri2_dpy->image->destroyImage(p_image);
|
||||
|
||||
zwp_linux_buffer_params_v1_add(params, fd, i, offset, stride,
|
||||
mod_hi, mod_lo);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
ret = zwp_linux_buffer_params_v1_create_immed(params, width, height,
|
||||
fourcc, 0);
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
} else if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
|
||||
struct wl_drm *wl_drm =
|
||||
dri2_surf ? dri2_surf->wl_drm_wrapper : dri2_dpy->wl_drm;
|
||||
int fd, stride;
|
||||
|
||||
if (num_planes > 1)
|
||||
return NULL;
|
||||
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
|
||||
ret = wl_drm_create_prime_buffer(wl_drm, fd, width, height, fourcc, 0,
|
||||
|
@ -664,6 +767,9 @@ create_wl_buffer(struct dri2_egl_display *dri2_dpy,
|
|||
dri2_surf ? dri2_surf->wl_drm_wrapper : dri2_dpy->wl_drm;
|
||||
int name, stride;
|
||||
|
||||
if (num_planes > 1)
|
||||
return NULL;
|
||||
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
|
||||
dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
|
||||
ret = wl_drm_create_buffer(wl_drm, name, width, height, stride, fourcc);
|
||||
|
@ -948,6 +1054,47 @@ static const struct wl_drm_listener drm_listener = {
|
|||
.capabilities = drm_handle_capabilities
|
||||
};
|
||||
|
||||
static void
|
||||
dmabuf_ignore_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
|
||||
uint32_t format)
|
||||
{
|
||||
/* formats are implicitly advertised by the 'modifier' event, so ignore */
|
||||
}
|
||||
|
||||
static void
|
||||
dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
|
||||
uint32_t format, uint32_t modifier_hi,
|
||||
uint32_t modifier_lo)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = data;
|
||||
uint64_t *mod = NULL;
|
||||
|
||||
switch (format) {
|
||||
case WL_DRM_FORMAT_ARGB8888:
|
||||
mod = u_vector_add(&dri2_dpy->wl_modifiers.argb8888);
|
||||
break;
|
||||
case WL_DRM_FORMAT_XRGB8888:
|
||||
mod = u_vector_add(&dri2_dpy->wl_modifiers.xrgb8888);
|
||||
break;
|
||||
case WL_DRM_FORMAT_RGB565:
|
||||
mod = u_vector_add(&dri2_dpy->wl_modifiers.rgb565);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mod)
|
||||
return;
|
||||
|
||||
*mod = (uint64_t) modifier_hi << 32;
|
||||
*mod |= (uint64_t) (modifier_lo & 0xffffffff);
|
||||
}
|
||||
|
||||
static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
|
||||
.format = dmabuf_ignore_format,
|
||||
.modifier = dmabuf_handle_modifier,
|
||||
};
|
||||
|
||||
static void
|
||||
registry_handle_global_drm(void *data, struct wl_registry *registry,
|
||||
uint32_t name, const char *interface,
|
||||
|
@ -959,6 +1106,12 @@ registry_handle_global_drm(void *data, struct wl_registry *registry,
|
|||
dri2_dpy->wl_drm =
|
||||
wl_registry_bind(registry, name, &wl_drm_interface, MIN2(version, 2));
|
||||
wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy);
|
||||
} else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3) {
|
||||
dri2_dpy->wl_dmabuf =
|
||||
wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface,
|
||||
MIN2(version, 3));
|
||||
zwp_linux_dmabuf_v1_add_listener(dri2_dpy->wl_dmabuf, &dmabuf_listener,
|
||||
dri2_dpy);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1127,6 +1280,12 @@ dri2_initialize_wayland_drm(_EGLDriver *drv, _EGLDisplay *disp)
|
|||
dri2_dpy->wl_dpy = disp->PlatformDisplay;
|
||||
}
|
||||
|
||||
if (!u_vector_init(&dri2_dpy->wl_modifiers.xrgb8888, sizeof(uint64_t), 32) ||
|
||||
!u_vector_init(&dri2_dpy->wl_modifiers.argb8888, sizeof(uint64_t), 32) ||
|
||||
!u_vector_init(&dri2_dpy->wl_modifiers.rgb565, sizeof(uint64_t), 32)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
|
||||
|
||||
dri2_dpy->wl_dpy_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dpy);
|
||||
|
|
Loading…
Reference in New Issue