wayland: Support complex (YUV) pixel formats
In the previous commits, we added the possibility to use pixel formats which are complex (YUV-based and/or multi-planar) inside Cogl. Use this new feature by assuming we get a CoglMultiPlaneTexture, rather than a "simple" CoglTexture. To easily test whether this works, one can use GStreamer pipelines (you'll need gst-plugins-bad for this to work): For normal BGRA (this should already work before this commit): ``` $ gst-launch-1.0 videotestsrc ! "video/x-raw" ! waylandsink ``` For NV12 (a popular video format): ``` $ gst-launch-1.0 videotestsrc ! "video/x-raw,format=NV12" ! waylandsink ``` For YUV 4:2:2 (another video format): ``` $ gst-launch-1.0 videotestsrc ! "video/x-raw,format=Y42B" ! waylandsink ``` You can also replace with other video sinks, like `vaapisink`. `glimagesink` also works, but for some reason seems to unconditionally convert to RGBA before submitting a texture (so it doesn't do a lot really). Fixes https://bugzilla.gnome.org/show_bug.cgi?id=705514
This commit is contained in:
@@ -123,7 +123,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
|
||||
stream = meta_wayland_egl_stream_new (buffer, NULL);
|
||||
if (stream)
|
||||
{
|
||||
CoglTexture2D *texture;
|
||||
CoglMultiPlaneTexture *texture;
|
||||
|
||||
texture = meta_wayland_egl_stream_create_texture (stream, NULL);
|
||||
if (!texture)
|
||||
@@ -131,7 +131,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
|
||||
|
||||
buffer->egl_stream.stream = stream;
|
||||
buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_STREAM;
|
||||
buffer->egl_stream.texture = COGL_TEXTURE (texture);
|
||||
buffer->egl_stream.texture = texture;
|
||||
buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);
|
||||
|
||||
return TRUE;
|
||||
@@ -163,43 +163,78 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
|
||||
CoglTextureComponents *components_out)
|
||||
{
|
||||
CoglPixelFormat format;
|
||||
CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA;
|
||||
|
||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||
{
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
components = COGL_TEXTURE_COMPONENTS_RGB;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_RGB;
|
||||
break;
|
||||
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
components = COGL_TEXTURE_COMPONENTS_RGB;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_RGB;
|
||||
break;
|
||||
#endif
|
||||
case WL_SHM_FORMAT_NV12:
|
||||
format = COGL_PIXEL_FORMAT_NV12;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[1] = COGL_TEXTURE_COMPONENTS_RG;
|
||||
break;
|
||||
case WL_SHM_FORMAT_NV21:
|
||||
format = COGL_PIXEL_FORMAT_NV21;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[1] = COGL_TEXTURE_COMPONENTS_RG;
|
||||
break;
|
||||
case WL_SHM_FORMAT_YUV422:
|
||||
format = COGL_PIXEL_FORMAT_YUV422;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[1] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[2] = COGL_TEXTURE_COMPONENTS_R;
|
||||
break;
|
||||
case WL_SHM_FORMAT_YVU422:
|
||||
format = COGL_PIXEL_FORMAT_YVU422;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[1] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[2] = COGL_TEXTURE_COMPONENTS_R;
|
||||
break;
|
||||
case WL_SHM_FORMAT_YUV444:
|
||||
format = COGL_PIXEL_FORMAT_YUV444;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[1] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[2] = COGL_TEXTURE_COMPONENTS_R;
|
||||
break;
|
||||
case WL_SHM_FORMAT_YVU444:
|
||||
format = COGL_PIXEL_FORMAT_YVU444;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[1] = COGL_TEXTURE_COMPONENTS_R;
|
||||
components_out[2] = COGL_TEXTURE_COMPONENTS_R;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
|
||||
}
|
||||
|
||||
if (format_out)
|
||||
*format_out = format;
|
||||
if (components_out)
|
||||
*components_out = components;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglMultiPlaneTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
@@ -207,21 +242,30 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
int stride, width, height;
|
||||
CoglPixelFormat format;
|
||||
CoglTextureComponents components;
|
||||
CoglBitmap *bitmap;
|
||||
CoglTexture *new_texture;
|
||||
CoglTextureComponents components[3];
|
||||
guint i, n_planes;
|
||||
uint8_t h_factors[3], v_factors[3], bpp[3];
|
||||
CoglPixelFormat subformats[3];
|
||||
gsize plane_offset = 0;
|
||||
guint8 *data;
|
||||
GPtrArray *planes;
|
||||
|
||||
/* Query the necessary parameters */
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
stride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
width = wl_shm_buffer_get_width (shm_buffer);
|
||||
height = wl_shm_buffer_get_height (shm_buffer);
|
||||
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components);
|
||||
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, components);
|
||||
n_planes = cogl_pixel_format_get_n_planes (format);
|
||||
cogl_pixel_format_get_subsampling_factors (format, h_factors, v_factors);
|
||||
cogl_pixel_format_get_subformats (format, subformats);
|
||||
cogl_pixel_format_get_bytes_per_pixel (format, bpp);
|
||||
|
||||
if (*texture &&
|
||||
cogl_texture_get_width (*texture) == width &&
|
||||
cogl_texture_get_height (*texture) == height &&
|
||||
cogl_texture_get_components (*texture) == components &&
|
||||
_cogl_texture_get_format (*texture) == format)
|
||||
cogl_multi_plane_texture_get_width (*texture) == width &&
|
||||
cogl_multi_plane_texture_get_height (*texture) == height &&
|
||||
/*XXX cogl_texture_get_components (*texture) == components && */
|
||||
cogl_multi_plane_texture_get_format (*texture) == format)
|
||||
{
|
||||
buffer->is_y_inverted = TRUE;
|
||||
*changed_texture = FALSE;
|
||||
@@ -230,56 +274,92 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
|
||||
cogl_clear_object (texture);
|
||||
|
||||
/* Safely access the data inside the buffer */
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
data = wl_shm_buffer_get_data (shm_buffer);
|
||||
|
||||
bitmap = cogl_bitmap_new_for_data (cogl_context,
|
||||
width, height,
|
||||
format,
|
||||
stride,
|
||||
wl_shm_buffer_get_data (shm_buffer));
|
||||
|
||||
new_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap));
|
||||
cogl_texture_set_components (new_texture, components);
|
||||
|
||||
if (!cogl_texture_allocate (new_texture, error))
|
||||
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
g_clear_pointer (&new_texture, cogl_object_unref);
|
||||
if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE))
|
||||
int plane_stride;
|
||||
CoglBitmap *plane_bitmap;
|
||||
CoglTexture *plane_texture;
|
||||
|
||||
/* Adjust the stride: map to the amount of pixels and calculate how many
|
||||
* bytes that takes in the current plane */
|
||||
plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i];
|
||||
|
||||
/* Define the bitmap that of this plane */
|
||||
plane_bitmap = cogl_bitmap_new_for_data (cogl_context,
|
||||
width / h_factors[i],
|
||||
height / v_factors[i],
|
||||
subformats[i],
|
||||
plane_stride,
|
||||
data + plane_offset);
|
||||
g_assert (plane_bitmap);
|
||||
|
||||
/* Create a texture out of it so we can upload it to the GPU */
|
||||
plane_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (plane_bitmap));
|
||||
|
||||
/* Separately set the components (necessary for e.g. XRGB, NV12) */
|
||||
cogl_texture_set_components (plane_texture, components[i]);
|
||||
|
||||
if (!cogl_texture_allocate (plane_texture, error))
|
||||
{
|
||||
CoglTexture2DSliced *texture_sliced;
|
||||
|
||||
cogl_clear_object (&plane_texture);
|
||||
|
||||
/* If it didn't work due to an NPOT size, try again with an atlas texture */
|
||||
if (!g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE))
|
||||
{
|
||||
cogl_object_unref (plane_bitmap);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
g_clear_error (error);
|
||||
|
||||
texture_sliced =
|
||||
cogl_texture_2d_sliced_new_from_bitmap (bitmap,
|
||||
cogl_texture_2d_sliced_new_from_bitmap (plane_bitmap,
|
||||
COGL_TEXTURE_MAX_WASTE);
|
||||
new_texture = COGL_TEXTURE (texture_sliced);
|
||||
cogl_texture_set_components (new_texture, components);
|
||||
plane_texture = COGL_TEXTURE (texture_sliced);
|
||||
|
||||
if (!cogl_texture_allocate (new_texture, error))
|
||||
g_clear_pointer (&new_texture, cogl_object_unref);
|
||||
cogl_texture_set_components (plane_texture, components[i]);
|
||||
|
||||
if (!cogl_texture_allocate (plane_texture, error))
|
||||
{
|
||||
cogl_clear_object (&plane_texture);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
g_ptr_array_add (planes, plane_texture);
|
||||
|
||||
/* Calculate the next plane start in the buffer (consider subsampling) */
|
||||
plane_offset += plane_stride * (height / v_factors[i]);
|
||||
}
|
||||
|
||||
cogl_object_unref (bitmap);
|
||||
*texture = cogl_multi_plane_texture_new (format,
|
||||
(CoglTexture **) g_ptr_array_free (planes, FALSE),
|
||||
n_planes);
|
||||
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
|
||||
if (!new_texture)
|
||||
return FALSE;
|
||||
|
||||
*texture = new_texture;
|
||||
*changed_texture = TRUE;
|
||||
buffer->is_y_inverted = TRUE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
failure:
|
||||
*texture = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglMultiPlaneTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
@@ -288,8 +368,9 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
int format, width, height, y_inverted;
|
||||
CoglPixelFormat cogl_format;
|
||||
EGLImageKHR egl_image;
|
||||
CoglTexture2D *texture_2d;
|
||||
CoglTextureComponents components[3];
|
||||
guint i, n_planes;
|
||||
GPtrArray *planes;
|
||||
|
||||
if (buffer->egl_image.texture)
|
||||
{
|
||||
@@ -299,6 +380,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Query the necessary properties */
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
|
||||
EGL_TEXTURE_FORMAT, &format,
|
||||
error))
|
||||
@@ -319,6 +401,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
NULL))
|
||||
y_inverted = EGL_TRUE;
|
||||
|
||||
/* Map the EGL texture format to CoglPixelFormat, if possible */
|
||||
switch (format)
|
||||
{
|
||||
case EGL_TEXTURE_RGB:
|
||||
@@ -327,6 +410,12 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
case EGL_TEXTURE_RGBA:
|
||||
cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||
break;
|
||||
case EGL_TEXTURE_Y_UV_WL:
|
||||
cogl_format = COGL_PIXEL_FORMAT_NV12;
|
||||
break;
|
||||
case EGL_TEXTURE_Y_U_V_WL:
|
||||
cogl_format = COGL_PIXEL_FORMAT_YUV444;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
@@ -334,27 +423,51 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used
|
||||
* in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
|
||||
egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
|
||||
EGL_WAYLAND_BUFFER_WL, buffer->resource,
|
||||
NULL,
|
||||
error);
|
||||
if (egl_image == EGL_NO_IMAGE_KHR)
|
||||
return FALSE;
|
||||
n_planes = cogl_pixel_format_get_n_planes (cogl_format);
|
||||
cogl_pixel_format_get_cogl_components (cogl_format, components);
|
||||
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
|
||||
|
||||
texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
egl_image,
|
||||
error);
|
||||
/* Each EGLImage is a plane in the final texture */
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
EGLint egl_attribs[3];
|
||||
EGLImageKHR egl_img;
|
||||
CoglTexture2D *texture_2d;
|
||||
|
||||
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
||||
/* Specify that we want the i'th plane */
|
||||
egl_attribs[0] = EGL_WAYLAND_PLANE_WL;
|
||||
egl_attribs[1] = i;
|
||||
egl_attribs[2] = EGL_NONE;
|
||||
|
||||
if (!texture_2d)
|
||||
return FALSE;
|
||||
/* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be
|
||||
* used in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
|
||||
egl_img = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
|
||||
EGL_WAYLAND_BUFFER_WL, buffer->resource,
|
||||
egl_attribs,
|
||||
error);
|
||||
|
||||
buffer->egl_image.texture = COGL_TEXTURE (texture_2d);
|
||||
if (G_UNLIKELY (egl_img == EGL_NO_IMAGE_KHR))
|
||||
goto on_error;
|
||||
|
||||
texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
components[i],
|
||||
egl_img,
|
||||
error);
|
||||
|
||||
meta_egl_destroy_image (egl, egl_display, egl_img, NULL);
|
||||
|
||||
if (G_UNLIKELY (!texture_2d))
|
||||
goto on_error;
|
||||
|
||||
g_ptr_array_add (planes, texture_2d);
|
||||
}
|
||||
|
||||
|
||||
buffer->egl_image.texture = cogl_multi_plane_texture_new (cogl_format,
|
||||
(CoglTexture **) g_ptr_array_free (planes, FALSE),
|
||||
n_planes);
|
||||
buffer->is_y_inverted = !!y_inverted;
|
||||
|
||||
cogl_clear_object (texture);
|
||||
@@ -362,14 +475,19 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
*changed_texture = TRUE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
on_error:
|
||||
g_ptr_array_free (planes, TRUE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAYLAND_EGLSTREAM
|
||||
static gboolean
|
||||
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglMultiPlaneTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaWaylandEglStream *stream = buffer->egl_stream.stream;
|
||||
|
||||
@@ -406,10 +524,10 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
* meta_wayland_buffer_attach(), which also might free it, as described above.
|
||||
*/
|
||||
gboolean
|
||||
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglMultiPlaneTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (buffer->resource, FALSE);
|
||||
|
||||
@@ -466,55 +584,94 @@ meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_shm_buffer_damage (MetaWaylandBuffer *buffer,
|
||||
CoglTexture *texture,
|
||||
cairo_region_t *region,
|
||||
GError **error)
|
||||
process_shm_buffer_damage (MetaWaylandBuffer *buffer,
|
||||
CoglMultiPlaneTexture *texture,
|
||||
cairo_region_t *region,
|
||||
GError **error)
|
||||
{
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
int i, n_rectangles;
|
||||
gboolean set_texture_failed = FALSE;
|
||||
CoglPixelFormat format;
|
||||
CoglTextureComponents components[3];
|
||||
uint8_t h_factors[3], v_factors[3], bpp[3];
|
||||
CoglPixelFormat subformats[3];
|
||||
gsize plane_offset = 0;
|
||||
const uint8_t *data;
|
||||
int32_t stride, height;
|
||||
uint8_t i, n_planes;
|
||||
int j, n_rectangles;
|
||||
|
||||
n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
|
||||
/* Get the data */
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
data = wl_shm_buffer_get_data (shm_buffer);
|
||||
|
||||
for (i = 0; i < n_rectangles; i++)
|
||||
/* Query the necessary properties */
|
||||
stride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
height = wl_shm_buffer_get_height (shm_buffer);
|
||||
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, components);
|
||||
|
||||
/* Fetch some properties from the pixel format */
|
||||
n_planes = cogl_multi_plane_texture_get_n_planes (texture);
|
||||
cogl_pixel_format_get_subformats (format, subformats);
|
||||
cogl_pixel_format_get_subsampling_factors (format, h_factors, v_factors);
|
||||
cogl_pixel_format_get_bytes_per_pixel (format, bpp);
|
||||
|
||||
for (i = 0; i < n_planes; i++)
|
||||
{
|
||||
const uint8_t *data = wl_shm_buffer_get_data (shm_buffer);
|
||||
int32_t stride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
CoglPixelFormat format;
|
||||
int bpp;
|
||||
cairo_rectangle_int_t rect;
|
||||
CoglTexture *plane;
|
||||
int plane_stride;
|
||||
|
||||
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL);
|
||||
bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
plane = cogl_multi_plane_texture_get_plane (texture, i);
|
||||
plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i];
|
||||
|
||||
if (!_cogl_texture_set_region (texture,
|
||||
rect.width, rect.height,
|
||||
format,
|
||||
stride,
|
||||
data + rect.x * bpp + rect.y * stride,
|
||||
rect.x, rect.y,
|
||||
0,
|
||||
error))
|
||||
for (j = 0; j < n_rectangles; j++)
|
||||
{
|
||||
set_texture_failed = TRUE;
|
||||
break;
|
||||
cairo_rectangle_int_t rect;
|
||||
gsize rect_offset;
|
||||
|
||||
cairo_region_get_rectangle (region, j, &rect);
|
||||
|
||||
/* It's possible we get a faulty rectangle of size zero: ignore */
|
||||
if (rect.height == 0 || rect.width == 0)
|
||||
continue;
|
||||
|
||||
rect_offset = plane_offset
|
||||
+ rect.y * plane_stride / v_factors[i] /* Find the right row */
|
||||
+ rect.x * bpp[i] / h_factors[i]; /* and the right column */
|
||||
|
||||
if (!_cogl_texture_set_region (plane,
|
||||
rect.width / h_factors[i],
|
||||
rect.height / v_factors[i],
|
||||
subformats[i],
|
||||
plane_stride,
|
||||
data + rect_offset,
|
||||
rect.x, rect.y,
|
||||
0,
|
||||
error))
|
||||
{
|
||||
set_texture_failed = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the next plane start in the buffer (consider subsampling) */
|
||||
plane_offset += plane_stride * (height / v_factors[i]);
|
||||
}
|
||||
|
||||
out:
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
|
||||
return !set_texture_failed;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
||||
CoglTexture *texture,
|
||||
cairo_region_t *region)
|
||||
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
||||
CoglMultiPlaneTexture *texture,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
GError *error = NULL;
|
||||
|
Reference in New Issue
Block a user