mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-12-15 08:56:26 -05:00
Add initial linux_dmabuf protocol support
Tested with
./weston-simple-dmabuf-drm
./weston-simple-dmabuf-drm --import-immediate=1
./weston-simple-dmabuf-drm --y-inverted=1
(and combinations)
Supports only single plane XRGB dmabufs for now.
This commit is contained in:
parent
2d0db16942
commit
14cdb6153f
12 changed files with 787 additions and 4 deletions
135
render/egl.c
135
render/egl.c
|
|
@ -167,6 +167,12 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display,
|
|||
check_egl_ext(egl->egl_exts_str, "EGL_EXT_swap_buffers_with_damage") ||
|
||||
check_egl_ext(egl->egl_exts_str, "EGL_KHR_swap_buffers_with_damage");
|
||||
|
||||
egl->egl_exts.dmabuf_import =
|
||||
check_egl_ext(egl->egl_exts_str, "EGL_EXT_image_dma_buf_import");
|
||||
egl->egl_exts.dmabuf_import_modifiers =
|
||||
check_egl_ext(egl->egl_exts_str, "EGL_EXT_image_dma_buf_import_modifiers")
|
||||
&& eglQueryDmaBufFormatsEXT && eglQueryDmaBufModifiersEXT;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
|
|
@ -299,3 +305,132 @@ bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
EGLImage wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
|
||||
struct wlr_dmabuf_buffer_attribs *attributes) {
|
||||
int atti = 0;
|
||||
EGLint attribs[20];
|
||||
attribs[atti++] = EGL_WIDTH;
|
||||
attribs[atti++] = attributes->width;
|
||||
attribs[atti++] = EGL_HEIGHT;
|
||||
attribs[atti++] = attributes->height;
|
||||
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
attribs[atti++] = attributes->format;
|
||||
|
||||
bool has_modifier = false;
|
||||
if (attributes->modifier[0] != DRM_FORMAT_MOD_INVALID) {
|
||||
if (!egl->egl_exts.dmabuf_import_modifiers) {
|
||||
return NULL;
|
||||
}
|
||||
has_modifier = true;
|
||||
}
|
||||
|
||||
/* TODO: YUV planes have up four planes but we only support a
|
||||
single EGLImage for now */
|
||||
if (attributes->n_planes > 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
||||
attribs[atti++] = attributes->fd[0];
|
||||
attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
||||
attribs[atti++] = attributes->offset[0];
|
||||
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||
attribs[atti++] = attributes->stride[0];
|
||||
if (has_modifier) {
|
||||
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||
attribs[atti++] = attributes->modifier[0] & 0xFFFFFFFF;
|
||||
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||
attribs[atti++] = attributes->modifier[0] >> 32;
|
||||
}
|
||||
attribs[atti++] = EGL_NONE;
|
||||
return eglCreateImageKHR(egl->display, EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
|
||||
}
|
||||
|
||||
#ifndef DRM_FORMAT_BIG_ENDIAN
|
||||
# define DRM_FORMAT_BIG_ENDIAN 0x80000000
|
||||
#endif
|
||||
bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl,
|
||||
struct wlr_dmabuf_buffer *dmabuf) {
|
||||
switch (dmabuf->attributes.format & ~DRM_FORMAT_BIG_ENDIAN) {
|
||||
/* YUV based formats not yet supported */
|
||||
case WL_SHM_FORMAT_YUYV:
|
||||
case WL_SHM_FORMAT_YVYU:
|
||||
case WL_SHM_FORMAT_UYVY:
|
||||
case WL_SHM_FORMAT_VYUY:
|
||||
case WL_SHM_FORMAT_AYUV:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
EGLImage egl_image = wlr_egl_create_image_from_dmabuf(egl,
|
||||
&dmabuf->attributes);
|
||||
if (egl_image) {
|
||||
/* We can import the image, good. No need to keep it
|
||||
since wlr_texture_upload_dmabuf will import it again */
|
||||
wlr_egl_destroy_image(egl, egl_image);
|
||||
return true;
|
||||
}
|
||||
/* TODO: import yuv dmabufs */
|
||||
return false;
|
||||
}
|
||||
|
||||
int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl,
|
||||
int **formats) {
|
||||
if (!egl->egl_exts.dmabuf_import ||
|
||||
!egl->egl_exts.dmabuf_import_modifiers) {
|
||||
wlr_log(L_ERROR, "dmabuf extension not present");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EGLint num;
|
||||
if (!eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) {
|
||||
wlr_log(L_ERROR, "failed to query number of dmabuf formats");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*formats = calloc(num, sizeof(int));
|
||||
if (*formats == NULL) {
|
||||
wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglQueryDmaBufFormatsEXT(egl->display, num, *formats, &num)) {
|
||||
wlr_log(L_ERROR, "failed to query dmabuf format");
|
||||
free(*formats);
|
||||
return -1;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl,
|
||||
int format, uint64_t **modifiers) {
|
||||
if (!egl->egl_exts.dmabuf_import ||
|
||||
!egl->egl_exts.dmabuf_import_modifiers) {
|
||||
wlr_log(L_ERROR, "dmabuf extension not present");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EGLint num;
|
||||
if (!eglQueryDmaBufModifiersEXT(egl->display, format, 0,
|
||||
NULL, NULL, &num)) {
|
||||
wlr_log(L_ERROR, "failed to query dmabuf number of modifiers");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*modifiers = calloc(num, sizeof(uint64_t));
|
||||
if (*modifiers == NULL) {
|
||||
wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglQueryDmaBufModifiersEXT(egl->display, format, num,
|
||||
*modifiers, NULL, &num)) {
|
||||
wlr_log(L_ERROR, "failed to query dmabuf modifiers");
|
||||
free(*modifiers);
|
||||
return -1;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue