wayland/dma-buf: Add support for YUV formats
Implement importing of multi-plane formats. For now, only support importing planes individually using "sub-formats". This is the most commonly driver-supported approach in the moment, used by other Wayland compositors as well. In the future we will additionally want to support importing the formats directly and let the drivers handle conversion internally. Co-Authored-By: Robert Mader <robert.mader@collabora.com> Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2191>
This commit is contained in:
parent
b15e14e027
commit
239912cc1f
@ -51,6 +51,7 @@
|
|||||||
#include "cogl/cogl-egl.h"
|
#include "cogl/cogl-egl.h"
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
#include "common/meta-cogl-drm-formats.h"
|
#include "common/meta-cogl-drm-formats.h"
|
||||||
|
#include "compositor/meta-multi-texture-format-private.h"
|
||||||
#include "meta/meta-backend.h"
|
#include "meta/meta-backend.h"
|
||||||
#include "wayland/meta-wayland-buffer.h"
|
#include "wayland/meta-wayland-buffer.h"
|
||||||
#include "wayland/meta-wayland-private.h"
|
#include "wayland/meta-wayland-private.h"
|
||||||
@ -343,12 +344,8 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
|||||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||||
MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf;
|
MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf;
|
||||||
uint32_t n_planes;
|
MetaMultiTextureFormat multi_format;
|
||||||
uint64_t modifiers[META_WAYLAND_DMA_BUF_MAX_FDS];
|
|
||||||
CoglPixelFormat cogl_format;
|
CoglPixelFormat cogl_format;
|
||||||
EGLImageKHR egl_image;
|
|
||||||
CoglEglImageFlags flags;
|
|
||||||
CoglTexture2D *cogl_texture;
|
|
||||||
#ifdef HAVE_NATIVE_BACKEND
|
#ifdef HAVE_NATIVE_BACKEND
|
||||||
MetaDrmFormatBuf format_buf;
|
MetaDrmFormatBuf format_buf;
|
||||||
#endif
|
#endif
|
||||||
@ -358,7 +355,7 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
|||||||
|
|
||||||
if (!meta_cogl_pixel_format_from_drm_format (dma_buf->drm_format,
|
if (!meta_cogl_pixel_format_from_drm_format (dma_buf->drm_format,
|
||||||
&cogl_format,
|
&cogl_format,
|
||||||
NULL))
|
&multi_format))
|
||||||
{
|
{
|
||||||
g_set_error (error, G_IO_ERROR,
|
g_set_error (error, G_IO_ERROR,
|
||||||
G_IO_ERROR_FAILED,
|
G_IO_ERROR_FAILED,
|
||||||
@ -368,49 +365,140 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
|||||||
|
|
||||||
#ifdef HAVE_NATIVE_BACKEND
|
#ifdef HAVE_NATIVE_BACKEND
|
||||||
meta_topic (META_DEBUG_WAYLAND,
|
meta_topic (META_DEBUG_WAYLAND,
|
||||||
"[dma-buf] wl_buffer@%u DRM format %s -> CoglPixelFormat %s",
|
"[dma-buf] wl_buffer@%u DRM format %s "
|
||||||
|
"-> MetaMultiTextureFormat %s / CoglPixelFormat %s",
|
||||||
wl_resource_get_id (meta_wayland_buffer_get_resource (buffer)),
|
wl_resource_get_id (meta_wayland_buffer_get_resource (buffer)),
|
||||||
meta_drm_format_to_string (&format_buf, dma_buf->drm_format),
|
meta_drm_format_to_string (&format_buf, dma_buf->drm_format),
|
||||||
|
meta_multi_texture_format_to_string (multi_format),
|
||||||
cogl_pixel_format_to_string (cogl_format));
|
cogl_pixel_format_to_string (cogl_format));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++)
|
if (multi_format == META_MULTI_TEXTURE_FORMAT_SIMPLE)
|
||||||
{
|
{
|
||||||
if (dma_buf->fds[n_planes] < 0)
|
EGLImageKHR egl_image;
|
||||||
break;
|
CoglEglImageFlags flags;
|
||||||
|
CoglTexture2D *cogl_texture;
|
||||||
|
uint64_t modifiers[META_WAYLAND_DMA_BUF_MAX_FDS];
|
||||||
|
uint32_t n_planes;
|
||||||
|
|
||||||
modifiers[n_planes] = dma_buf->drm_modifier;
|
for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++)
|
||||||
|
{
|
||||||
|
if (dma_buf->fds[n_planes] < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
modifiers[n_planes] = dma_buf->drm_modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
egl_image = meta_egl_create_dmabuf_image (egl,
|
||||||
|
egl_display,
|
||||||
|
dma_buf->width,
|
||||||
|
dma_buf->height,
|
||||||
|
dma_buf->drm_format,
|
||||||
|
n_planes,
|
||||||
|
dma_buf->fds,
|
||||||
|
dma_buf->strides,
|
||||||
|
dma_buf->offsets,
|
||||||
|
modifiers,
|
||||||
|
error);
|
||||||
|
if (egl_image == EGL_NO_IMAGE_KHR)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA;
|
||||||
|
cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||||
|
dma_buf->width,
|
||||||
|
dma_buf->height,
|
||||||
|
cogl_format,
|
||||||
|
egl_image,
|
||||||
|
flags,
|
||||||
|
error);
|
||||||
|
|
||||||
|
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
||||||
|
|
||||||
|
if (!cogl_texture)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
buffer->dma_buf.texture =
|
||||||
|
meta_multi_texture_new_simple (COGL_TEXTURE (cogl_texture));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CoglTexture **textures;
|
||||||
|
g_autoptr (GPtrArray) planes = NULL;
|
||||||
|
CoglPixelFormat subformats[META_WAYLAND_DMA_BUF_MAX_FDS];
|
||||||
|
uint8_t horizontal_factors[META_WAYLAND_DMA_BUF_MAX_FDS];
|
||||||
|
uint8_t vertical_factors[META_WAYLAND_DMA_BUF_MAX_FDS];
|
||||||
|
uint8_t plane_indices[META_WAYLAND_DMA_BUF_MAX_FDS];
|
||||||
|
int n_planes, i;
|
||||||
|
|
||||||
egl_image = meta_egl_create_dmabuf_image (egl,
|
n_planes = meta_multi_texture_format_get_n_planes (multi_format);
|
||||||
egl_display,
|
|
||||||
dma_buf->width,
|
|
||||||
dma_buf->height,
|
|
||||||
dma_buf->drm_format,
|
|
||||||
n_planes,
|
|
||||||
dma_buf->fds,
|
|
||||||
dma_buf->strides,
|
|
||||||
dma_buf->offsets,
|
|
||||||
modifiers,
|
|
||||||
error);
|
|
||||||
if (egl_image == EGL_NO_IMAGE_KHR)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA;
|
/* Each EGLImage is a plane in the final CoglMultiPlaneTexture */
|
||||||
cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context,
|
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
|
||||||
dma_buf->width,
|
meta_multi_texture_format_get_subformats (multi_format, subformats);
|
||||||
dma_buf->height,
|
meta_multi_texture_format_get_plane_indices (multi_format, plane_indices);
|
||||||
cogl_format,
|
meta_multi_texture_format_get_subsampling_factors (multi_format,
|
||||||
egl_image,
|
horizontal_factors,
|
||||||
flags,
|
vertical_factors);
|
||||||
error);
|
|
||||||
|
|
||||||
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
for (i = 0; i < n_planes; i++)
|
||||||
|
{
|
||||||
|
EGLImageKHR egl_image;
|
||||||
|
CoglEglImageFlags flags;
|
||||||
|
CoglTexture2D *cogl_texture;
|
||||||
|
uint32_t drm_format = 0;
|
||||||
|
int plane_index, j;
|
||||||
|
|
||||||
if (!cogl_texture)
|
for (j = 0; j < G_N_ELEMENTS (meta_cogl_drm_format_map); j++)
|
||||||
return FALSE;
|
{
|
||||||
|
if (meta_cogl_drm_format_map[j].cogl_format == subformats[i])
|
||||||
|
{
|
||||||
|
drm_format = meta_cogl_drm_format_map[j].drm_format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_return_val_if_fail (drm_format != 0, FALSE);
|
||||||
|
|
||||||
buffer->dma_buf.texture = meta_multi_texture_new_simple (COGL_TEXTURE (cogl_texture));
|
plane_index = plane_indices[i];
|
||||||
|
|
||||||
|
egl_image = meta_egl_create_dmabuf_image (egl,
|
||||||
|
egl_display,
|
||||||
|
dma_buf->width /
|
||||||
|
horizontal_factors[i],
|
||||||
|
dma_buf->height /
|
||||||
|
vertical_factors[i],
|
||||||
|
drm_format,
|
||||||
|
1,
|
||||||
|
&dma_buf->fds[plane_index],
|
||||||
|
&dma_buf->strides[plane_index],
|
||||||
|
&dma_buf->offsets[plane_index],
|
||||||
|
&dma_buf->drm_modifier,
|
||||||
|
error);
|
||||||
|
if (egl_image == EGL_NO_IMAGE_KHR)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA;
|
||||||
|
cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||||
|
dma_buf->width,
|
||||||
|
dma_buf->height,
|
||||||
|
subformats[i],
|
||||||
|
egl_image,
|
||||||
|
flags,
|
||||||
|
error);
|
||||||
|
|
||||||
|
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
||||||
|
|
||||||
|
if (!cogl_texture)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_ptr_array_add (planes, cogl_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
textures = (CoglTexture**) g_ptr_array_free (g_steal_pointer (&planes),
|
||||||
|
FALSE);
|
||||||
|
buffer->dma_buf.texture = meta_multi_texture_new (multi_format,
|
||||||
|
textures,
|
||||||
|
n_planes);
|
||||||
|
}
|
||||||
buffer->is_y_inverted = dma_buf->is_y_inverted;
|
buffer->is_y_inverted = dma_buf->is_y_inverted;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
Loading…
Reference in New Issue
Block a user