Compare commits

...

7 Commits

Author SHA1 Message Date
Niels De Graef
1fd5e9bb0b WIP 2019-06-24 15:14:01 +02:00
Niels De Graef
940a485206 WIP 2019-06-24 15:14:01 +02:00
Niels De Graef
784b1750c4 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
2019-06-24 15:14:01 +02:00
Niels De Graef
f8747a2fe2 cogl: Add CoglMultiPlaneTexture for complex formats
Mutter always assumed that any texture it got was
representable by a `CoglTexture`, which does not have this kind of
concept. This also has the useful feature that each `CoglTexture`
corresponds to a single layer in a `CoglPipeline`.

To deal with this, we introduce a new object: a `CoglMultiPlaneTexture`
consists of multiple `CoglTexture`s, each representing a plane in the
texture we got. It also provides knows when to use a
CoglPixelFormatConversion.
2019-06-24 15:14:01 +02:00
Niels De Graef
89111517bd cogl: Add non-RGBA pixel formats
Up until now, we didn't support any YUV pixel formats. This was for
several reasons: first, we draw onto an RGBA framebuffer, so any
YUV-based color format needs to be converted to RGBA using a shader.

Next, some more complex pixel format have extra properties that we have
not had to deal with right now: they can be located on multiple "planes"
(which means components are not combined in a single texture or memory
block). Some pixel formats also have a notion of "subsampling", where
one does not save a component for each and every pixel, but rather for
every other pixel (possibly in both the horizontal and vertical sense).

To deal with this, we introduce a new type as well:
`CoglPixelFormatConversion` provides a wrapper for the necessary shaders
(which in Cogl are represented by `CoglSnippet`s).
2019-06-24 15:14:01 +02:00
Niels De Graef
990b0efc17 WIP: Add a COGL_TEXTURE_COMPONENTS_R 2019-06-24 15:14:01 +02:00
Niels De Graef
ce643392ec cogl: Replace G_8 with R_8 pixel format
Cogl doesn't use `COGL_PIXEL_FORMAT_G_8` anywhere, and it has differing
implementations depending on the driver (Mesa averages it out over the
diferent components, while NVIDIA stores it in the R component).

Furthermore, by having this new pixel format, we can use this for
single-component uploads, which will be useful when dealing with
non-trivial textures (such as YUV-based textures).
2019-06-24 15:14:01 +02:00
55 changed files with 2351 additions and 581 deletions

View File

@@ -173,7 +173,7 @@ test_coglbox_init (TestCoglbox *self)
priv->cogl_tex_id[3] = priv->cogl_tex_id[3] =
cogl_texture_new_from_file (file, cogl_texture_new_from_file (file,
COGL_TEXTURE_NONE, COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_R_8,
NULL); NULL);
g_free (file); g_free (file);

View File

@@ -937,12 +937,12 @@ cogl_atlas_texture_new_from_data (CoglContext *ctx,
CoglBitmap *bmp; CoglBitmap *bmp;
CoglAtlasTexture *atlas_tex; CoglAtlasTexture *atlas_tex;
g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, NULL); g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, NULL);
g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail (data != NULL, NULL);
/* Rowstride from width if not given */ /* Rowstride from width if not given */
if (rowstride == 0) if (rowstride == 0)
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); rowstride = width * cogl_pixel_format_get_bytes_per_pixel_simple (format);
/* Wrap the data into a bitmap */ /* Wrap the data into a bitmap */
bmp = cogl_bitmap_new_for_data (ctx, bmp = cogl_bitmap_new_for_data (ctx,

View File

@@ -193,7 +193,7 @@ _cogl_atlas_get_initial_size (CoglPixelFormat format,
initial minimum size. If the format is only 1 byte per pixel we initial minimum size. If the format is only 1 byte per pixel we
can use 1024x1024, otherwise we'll assume it will take 4 bytes can use 1024x1024, otherwise we'll assume it will take 4 bytes
per pixel and use 512x512. */ per pixel and use 512x512. */
if (_cogl_pixel_format_get_bytes_per_pixel (format) == 1) if (cogl_pixel_format_get_bytes_per_pixel_simple (format) == 1)
size = 1024; size = 1024;
else else
size = 512; size = 512;
@@ -291,7 +291,9 @@ _cogl_atlas_create_texture (CoglAtlas *atlas,
{ {
uint8_t *clear_data; uint8_t *clear_data;
CoglBitmap *clear_bmp; CoglBitmap *clear_bmp;
int bpp = _cogl_pixel_format_get_bytes_per_pixel (atlas->texture_format); int bpp;
bpp = cogl_pixel_format_get_bytes_per_pixel_simple (atlas->texture_format);
/* Create a buffer of zeroes to initially clear the texture */ /* Create a buffer of zeroes to initially clear the texture */
clear_data = g_malloc0 (width * height * bpp); clear_data = g_malloc0 (width * height * bpp);

View File

@@ -320,7 +320,37 @@ _cogl_bitmap_needs_short_temp_buffer (CoglPixelFormat format)
case COGL_PIXEL_FORMAT_DEPTH_32: case COGL_PIXEL_FORMAT_DEPTH_32:
case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8: case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
case COGL_PIXEL_FORMAT_ANY: case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
case COGL_PIXEL_FORMAT_YUV: case COGL_PIXEL_FORMAT_YUV:
case COGL_PIXEL_FORMAT_YUYV:
case COGL_PIXEL_FORMAT_YVYU:
case COGL_PIXEL_FORMAT_UYVY:
case COGL_PIXEL_FORMAT_VYUY:
case COGL_PIXEL_FORMAT_AYUV:
case COGL_PIXEL_FORMAT_XRGB8888_A8:
case COGL_PIXEL_FORMAT_XBGR8888_A8:
case COGL_PIXEL_FORMAT_RGBX8888_A8:
case COGL_PIXEL_FORMAT_BGRX8888_A8:
case COGL_PIXEL_FORMAT_RGB888_A8:
case COGL_PIXEL_FORMAT_BGR888_A8:
case COGL_PIXEL_FORMAT_RGB565_A8:
case COGL_PIXEL_FORMAT_BGR565_A8:
case COGL_PIXEL_FORMAT_NV12:
case COGL_PIXEL_FORMAT_NV21:
case COGL_PIXEL_FORMAT_NV16:
case COGL_PIXEL_FORMAT_NV61:
case COGL_PIXEL_FORMAT_NV24:
case COGL_PIXEL_FORMAT_NV42:
case COGL_PIXEL_FORMAT_YUV410:
case COGL_PIXEL_FORMAT_YVU410:
case COGL_PIXEL_FORMAT_YUV411:
case COGL_PIXEL_FORMAT_YVU411:
case COGL_PIXEL_FORMAT_YUV420:
case COGL_PIXEL_FORMAT_YVU420:
case COGL_PIXEL_FORMAT_YUV422:
case COGL_PIXEL_FORMAT_YVU422:
case COGL_PIXEL_FORMAT_YUV444:
case COGL_PIXEL_FORMAT_YVU444:
g_assert_not_reached (); g_assert_not_reached ();
case COGL_PIXEL_FORMAT_A_8: case COGL_PIXEL_FORMAT_A_8:
@@ -328,7 +358,7 @@ _cogl_bitmap_needs_short_temp_buffer (CoglPixelFormat format)
case COGL_PIXEL_FORMAT_RGB_565: case COGL_PIXEL_FORMAT_RGB_565:
case COGL_PIXEL_FORMAT_RGBA_4444: case COGL_PIXEL_FORMAT_RGBA_4444:
case COGL_PIXEL_FORMAT_RGBA_5551: case COGL_PIXEL_FORMAT_RGBA_5551:
case COGL_PIXEL_FORMAT_G_8: case COGL_PIXEL_FORMAT_R_8:
case COGL_PIXEL_FORMAT_RGB_888: case COGL_PIXEL_FORMAT_RGB_888:
case COGL_PIXEL_FORMAT_BGR_888: case COGL_PIXEL_FORMAT_BGR_888:
case COGL_PIXEL_FORMAT_RGBA_8888: case COGL_PIXEL_FORMAT_RGBA_8888:

View File

@@ -65,21 +65,16 @@ G_PASTE (_cogl_unpack_a_8_, component_size) (const uint8_t *src,
} }
inline static void inline static void
G_PASTE (_cogl_unpack_g_8_, component_size) (const uint8_t *src, G_PASTE (_cogl_unpack_r_8_, component_size) (const uint8_t *src,
component_type *dst, component_type *dst,
int width) int width)
{ {
/* FIXME: I'm not sure if this is right. It looks like Nvidia and
Mesa handle luminance textures differently. Maybe we should
consider just removing luminance textures for Cogl 2.0 because
they have been removed in GL 3.0 */
while (width-- > 0) while (width-- > 0)
{ {
component_type v = UNPACK_BYTE (src[0]); dst[0] = UNPACK_BYTE (*src);
dst[0] = v; dst[1] = 0;
dst[1] = v; dst[2] = 0;
dst[2] = v; dst[3] = 0;
dst[3] = UNPACK_BYTE (255);
dst += 4; dst += 4;
src++; src++;
} }
@@ -341,8 +336,8 @@ G_PASTE (_cogl_unpack_, component_size) (CoglPixelFormat format,
case COGL_PIXEL_FORMAT_A_8: case COGL_PIXEL_FORMAT_A_8:
G_PASTE (_cogl_unpack_a_8_, component_size) (src, dst, width); G_PASTE (_cogl_unpack_a_8_, component_size) (src, dst, width);
break; break;
case COGL_PIXEL_FORMAT_G_8: case COGL_PIXEL_FORMAT_R_8:
G_PASTE (_cogl_unpack_g_8_, component_size) (src, dst, width); G_PASTE (_cogl_unpack_r_8_, component_size) (src, dst, width);
break; break;
case COGL_PIXEL_FORMAT_RG_88: case COGL_PIXEL_FORMAT_RG_88:
G_PASTE (_cogl_unpack_rg_88_, component_size) (src, dst, width); G_PASTE (_cogl_unpack_rg_88_, component_size) (src, dst, width);
@@ -400,7 +395,37 @@ G_PASTE (_cogl_unpack_, component_size) (CoglPixelFormat format,
case COGL_PIXEL_FORMAT_DEPTH_32: case COGL_PIXEL_FORMAT_DEPTH_32:
case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8: case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
case COGL_PIXEL_FORMAT_ANY: case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
case COGL_PIXEL_FORMAT_YUV: case COGL_PIXEL_FORMAT_YUV:
case COGL_PIXEL_FORMAT_YUYV:
case COGL_PIXEL_FORMAT_YVYU:
case COGL_PIXEL_FORMAT_UYVY:
case COGL_PIXEL_FORMAT_VYUY:
case COGL_PIXEL_FORMAT_AYUV:
case COGL_PIXEL_FORMAT_XRGB8888_A8:
case COGL_PIXEL_FORMAT_XBGR8888_A8:
case COGL_PIXEL_FORMAT_RGBX8888_A8:
case COGL_PIXEL_FORMAT_BGRX8888_A8:
case COGL_PIXEL_FORMAT_RGB888_A8:
case COGL_PIXEL_FORMAT_BGR888_A8:
case COGL_PIXEL_FORMAT_RGB565_A8:
case COGL_PIXEL_FORMAT_BGR565_A8:
case COGL_PIXEL_FORMAT_NV12:
case COGL_PIXEL_FORMAT_NV21:
case COGL_PIXEL_FORMAT_NV16:
case COGL_PIXEL_FORMAT_NV61:
case COGL_PIXEL_FORMAT_NV24:
case COGL_PIXEL_FORMAT_NV42:
case COGL_PIXEL_FORMAT_YUV410:
case COGL_PIXEL_FORMAT_YVU410:
case COGL_PIXEL_FORMAT_YUV411:
case COGL_PIXEL_FORMAT_YVU411:
case COGL_PIXEL_FORMAT_YUV420:
case COGL_PIXEL_FORMAT_YVU420:
case COGL_PIXEL_FORMAT_YUV422:
case COGL_PIXEL_FORMAT_YVU422:
case COGL_PIXEL_FORMAT_YUV444:
case COGL_PIXEL_FORMAT_YVU444:
g_assert_not_reached (); g_assert_not_reached ();
} }
} }
@@ -433,18 +458,13 @@ G_PASTE (_cogl_pack_a_8_, component_size) (const component_type *src,
} }
inline static void inline static void
G_PASTE (_cogl_pack_g_8_, component_size) (const component_type *src, G_PASTE (_cogl_pack_r_8_, component_size) (const component_type *src,
uint8_t *dst, uint8_t *dst,
int width) int width)
{ {
/* FIXME: I'm not sure if this is right. It looks like Nvidia and
Mesa handle luminance textures differently. Maybe we should
consider just removing luminance textures for Cogl 2.0 because
they have been removed in GL 3.0 */
while (width-- > 0) while (width-- > 0)
{ {
component_type v = (src[0] + src[1] + src[2]) / 3; *dst = PACK_BYTE (src[0]);
*dst = PACK_BYTE (v);
src += 4; src += 4;
dst++; dst++;
} }
@@ -702,8 +722,8 @@ G_PASTE (_cogl_pack_, component_size) (CoglPixelFormat format,
case COGL_PIXEL_FORMAT_A_8: case COGL_PIXEL_FORMAT_A_8:
G_PASTE (_cogl_pack_a_8_, component_size) (src, dst, width); G_PASTE (_cogl_pack_a_8_, component_size) (src, dst, width);
break; break;
case COGL_PIXEL_FORMAT_G_8: case COGL_PIXEL_FORMAT_R_8:
G_PASTE (_cogl_pack_g_8_, component_size) (src, dst, width); G_PASTE (_cogl_pack_r_8_, component_size) (src, dst, width);
break; break;
case COGL_PIXEL_FORMAT_RG_88: case COGL_PIXEL_FORMAT_RG_88:
G_PASTE (_cogl_pack_rg_88_, component_size) (src, dst, width); G_PASTE (_cogl_pack_rg_88_, component_size) (src, dst, width);
@@ -761,7 +781,37 @@ G_PASTE (_cogl_pack_, component_size) (CoglPixelFormat format,
case COGL_PIXEL_FORMAT_DEPTH_32: case COGL_PIXEL_FORMAT_DEPTH_32:
case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8: case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
case COGL_PIXEL_FORMAT_ANY: case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
case COGL_PIXEL_FORMAT_YUV: case COGL_PIXEL_FORMAT_YUV:
case COGL_PIXEL_FORMAT_YUYV:
case COGL_PIXEL_FORMAT_YVYU:
case COGL_PIXEL_FORMAT_UYVY:
case COGL_PIXEL_FORMAT_VYUY:
case COGL_PIXEL_FORMAT_AYUV:
case COGL_PIXEL_FORMAT_XRGB8888_A8:
case COGL_PIXEL_FORMAT_XBGR8888_A8:
case COGL_PIXEL_FORMAT_RGBX8888_A8:
case COGL_PIXEL_FORMAT_BGRX8888_A8:
case COGL_PIXEL_FORMAT_RGB888_A8:
case COGL_PIXEL_FORMAT_BGR888_A8:
case COGL_PIXEL_FORMAT_RGB565_A8:
case COGL_PIXEL_FORMAT_BGR565_A8:
case COGL_PIXEL_FORMAT_NV12:
case COGL_PIXEL_FORMAT_NV21:
case COGL_PIXEL_FORMAT_NV16:
case COGL_PIXEL_FORMAT_NV61:
case COGL_PIXEL_FORMAT_NV24:
case COGL_PIXEL_FORMAT_NV42:
case COGL_PIXEL_FORMAT_YUV410:
case COGL_PIXEL_FORMAT_YVU410:
case COGL_PIXEL_FORMAT_YUV411:
case COGL_PIXEL_FORMAT_YVU411:
case COGL_PIXEL_FORMAT_YUV420:
case COGL_PIXEL_FORMAT_YVU420:
case COGL_PIXEL_FORMAT_YUV422:
case COGL_PIXEL_FORMAT_YVU422:
case COGL_PIXEL_FORMAT_YUV444:
case COGL_PIXEL_FORMAT_YVU444:
g_assert_not_reached (); g_assert_not_reached ();
} }
} }

View File

@@ -136,7 +136,7 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src,
(dst->format & ~COGL_PREMULT_BIT), (dst->format & ~COGL_PREMULT_BIT),
FALSE); FALSE);
bpp = _cogl_pixel_format_get_bytes_per_pixel (src->format); bpp = cogl_pixel_format_get_bytes_per_pixel_simple (src->format);
if ((srcdata = _cogl_bitmap_map (src, COGL_BUFFER_ACCESS_READ, 0, error))) if ((srcdata = _cogl_bitmap_map (src, COGL_BUFFER_ACCESS_READ, 0, error)))
{ {
@@ -186,7 +186,7 @@ cogl_bitmap_new_for_data (CoglContext *context,
/* Rowstride from width if not given */ /* Rowstride from width if not given */
if (rowstride == 0) if (rowstride == 0)
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); rowstride = width * cogl_pixel_format_get_bytes_per_pixel_simple (format);
bmp = g_slice_new (CoglBitmap); bmp = g_slice_new (CoglBitmap);
bmp->context = context; bmp->context = context;
@@ -211,7 +211,7 @@ _cogl_bitmap_new_with_malloc_buffer (CoglContext *context,
GError **error) GError **error)
{ {
static CoglUserDataKey bitmap_free_key; static CoglUserDataKey bitmap_free_key;
int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
int rowstride = ((width * bpp) + 3) & ~3; int rowstride = ((width * bpp) + 3) & ~3;
uint8_t *data = g_try_malloc (rowstride * height); uint8_t *data = g_try_malloc (rowstride * height);
CoglBitmap *bitmap; CoglBitmap *bitmap;
@@ -308,7 +308,7 @@ cogl_bitmap_new_with_size (CoglContext *context,
/* for now we fallback to cogl_pixel_buffer_new, later, we could ask /* for now we fallback to cogl_pixel_buffer_new, later, we could ask
* libdrm a tiled buffer for instance */ * libdrm a tiled buffer for instance */
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); rowstride = width * cogl_pixel_format_get_bytes_per_pixel_simple (format);
pixel_buffer = pixel_buffer =
cogl_pixel_buffer_new (context, cogl_pixel_buffer_new (context,

View File

@@ -273,7 +273,7 @@ static gboolean
_cogl_blit_get_tex_data_begin (CoglBlitData *data) _cogl_blit_get_tex_data_begin (CoglBlitData *data)
{ {
data->format = _cogl_texture_get_format (data->src_tex); data->format = _cogl_texture_get_format (data->src_tex);
data->bpp = _cogl_pixel_format_get_bytes_per_pixel (data->format); data->bpp = cogl_pixel_format_get_bytes_per_pixel_simple (data->format);
data->image_data = g_malloc (data->bpp * data->src_width * data->image_data = g_malloc (data->bpp * data->src_width *
data->src_height); data->src_height);

View File

@@ -1315,7 +1315,7 @@ cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer,
CoglPixelFormat format, CoglPixelFormat format,
uint8_t *pixels) uint8_t *pixels)
{ {
int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
CoglBitmap *bitmap; CoglBitmap *bitmap;
gboolean ret; gboolean ret;

View File

@@ -297,8 +297,8 @@ copy_flipped_texture (CoglGLES2Context *gles2_ctx,
internal_format = COGL_PIXEL_FORMAT_A_8; internal_format = COGL_PIXEL_FORMAT_A_8;
break; break;
case GL_LUMINANCE: case GL_RED:
internal_format = COGL_PIXEL_FORMAT_G_8; internal_format = COGL_PIXEL_FORMAT_R_8;
break; break;
default: default:

View File

@@ -0,0 +1,157 @@
/*
* Authored By Niels De Graef <niels.degraef@barco.com>
*
* Copyright (C) 2018 Barco NV
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "cogl-config.h"
#include "cogl-object-private.h"
#include "cogl-multi-plane-texture.h"
#include "cogl-gtype-private.h"
#include "cogl-texture-private.h"
#include "cogl-texture-2d-sliced.h"
struct _CoglMultiPlaneTexture
{
CoglObject _parent;
CoglPixelFormat format;
uint8_t n_planes;
CoglTexture **planes;
};
static void
_cogl_multi_plane_texture_free (CoglMultiPlaneTexture *self);
COGL_OBJECT_DEFINE (MultiPlaneTexture, multi_plane_texture);
COGL_GTYPE_DEFINE_CLASS (MultiPlaneTexture, multi_plane_texture);
CoglPixelFormat
cogl_multi_plane_texture_get_format (CoglMultiPlaneTexture *self)
{
return self->format;
}
uint8_t
cogl_multi_plane_texture_get_n_planes (CoglMultiPlaneTexture *self)
{
return self->n_planes;
}
CoglTexture *
cogl_multi_plane_texture_get_plane (CoglMultiPlaneTexture *self, guint index)
{
g_return_val_if_fail (self->n_planes > 0, NULL);
g_return_val_if_fail (index < self->n_planes, NULL);
return self->planes[index];
}
CoglTexture **
cogl_multi_plane_texture_get_planes (CoglMultiPlaneTexture *self)
{
return self->planes;
}
guint
cogl_multi_plane_texture_get_width (CoglMultiPlaneTexture *self)
{
g_return_val_if_fail (self->n_planes > 0, 0);
return cogl_texture_get_width (self->planes[0]);
}
guint
cogl_multi_plane_texture_get_height (CoglMultiPlaneTexture *self)
{
g_return_val_if_fail (self->n_planes > 0, 0);
return cogl_texture_get_height (self->planes[0]);
}
static void
_cogl_multi_plane_texture_free (CoglMultiPlaneTexture *self)
{
uint8_t i = 0;
for (i = 0; i < self->n_planes; i++)
cogl_object_unref (self->planes[i]);
g_free (self->planes);
}
CoglMultiPlaneTexture *
cogl_multi_plane_texture_new (CoglPixelFormat format,
CoglTexture **planes, uint8_t n_planes)
{
CoglMultiPlaneTexture *self = g_slice_new0 (CoglMultiPlaneTexture);
_cogl_multi_plane_texture_object_new (self);
self->format = format;
self->n_planes = n_planes;
self->planes = planes;
return self;
}
CoglMultiPlaneTexture *
cogl_multi_plane_texture_new_single_plane (CoglPixelFormat format,
CoglTexture *plane)
{
CoglMultiPlaneTexture *self = g_slice_new0 (CoglMultiPlaneTexture);
_cogl_multi_plane_texture_object_new (self);
self->format = format;
self->n_planes = 1;
self->planes = g_malloc (sizeof (CoglTexture *));
self->planes[0] = plane;
return self;
}
char *
cogl_multi_plane_texture_to_string (CoglMultiPlaneTexture *self)
{
g_autoptr(GString) str = NULL;
g_autofree char *ret = NULL;
uint8_t i;
str = g_string_new ("");
g_string_append_printf (str, "CoglMultiPlaneTexture (%p) {\n", self);
g_string_append_printf (str, " .format = %s;\n", cogl_pixel_format_to_string (self->format));
g_string_append_printf (str, " .n_planes = %u;\n", self->n_planes);
g_string_append (str, " .planes = {\n");
for (i = 0; i < self->n_planes; i++)
{
CoglTexture *plane = self->planes[i];
g_string_append_printf (str, " (%p) { .format = %s },\n",
plane,
cogl_pixel_format_to_string (_cogl_texture_get_format (plane)));
}
g_string_append (str, " }\n");
g_string_append (str, "}");
ret = g_string_free (g_steal_pointer (&str), FALSE);
return g_steal_pointer (&ret);
}

View File

@@ -0,0 +1,187 @@
/*
* Authored By Niels De Graef <niels.degraef@barco.com>
*
* Copyright (C) 2018 Barco NV
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __COGL_MULTI_PLANE_TEXTURE_H__
#define __COGL_MULTI_PLANE_TEXTURE_H__
#include "cogl/cogl-texture.h"
G_BEGIN_DECLS
/**
* SECTION:cogl-multi-plane-texture
* @title: CoglMultiPlaneTexture
* @short_description: A non-primitive texture that can have multiple planes.
*
* #CoglMultiPlaneTexture allows one to deal with non-trivial formats that
* have multiple planes, requires subsampling and/or aren't in RGB. A common
* example of this are decoded video frames, which often use something in the
* YUV colorspace, combined with subsampling.
*
* The basic idea of a #CoglMultiPlaneTexture is the following:
* - Each plane is represented by a separate #CoglTexture. That means that you
* should add each of these planes as a layer to your CoglPipeline.
* - When dealing with a color space that is not RGB, you can ask the
* #CoglMultiPlaneTexture to create a shader for you that does the conversion
* in the GPU.
* - In case you need to deal with memory access in a format with subsampling,
* you can use cogl_multi_plane_texture_get_width() and its analogous version
* for the height to get the correct size of the texture.
*/
typedef struct _CoglMultiPlaneTexture CoglMultiPlaneTexture;
#define COGL_MULTI_PLANE_TEXTURE(tex) ((CoglMultiPlaneTexture *) tex)
/**
* cogl_multi_plane_texture_get_gtype:
*
* Returns: a #GType that can be used with the GLib type system.
*/
GType cogl_multi_plane_texture_get_gtype (void);
/**
* cogl_is_multi_plane_texture:
* @object: A #CoglObject pointer
*
* Gets whether the given @object references an existing CoglMultiPlaneTexture.
*
* Return value: %TRUE if the @object references a #CoglMultiPlaneTexture,
* %FALSE otherwise
*/
gboolean
cogl_is_multi_plane_texture (void *object);
/**
* cogl_multi_plane_texture_new:
* @format: The format of the #CoglMultiPlaneTexture
* @planes: (transfer full): The actual planes of the texture
* @n_planes: The number of planes
*
* Creates a #CoglMultiPlaneTexture with the given @format. Each of the
* #CoglTexture<!-- -->s represents a plane.
*
* Returns: (transfer full): A new #CoglMultiPlaneTexture. Use
* cogl_object_unref() when you're done with it.
*/
CoglMultiPlaneTexture * cogl_multi_plane_texture_new (CoglPixelFormat format,
CoglTexture **planes,
uint8_t n_planes);
/**
* cogl_multi_plane_texture_new_single_plane:
* @format: The format of the #CoglMultiPlaneTexture
* @plane: (transfer full): The actual planes of the texture
*
* Creates a #CoglMultiPlaneTexture for a "simple" texture, i.e. with only one
* plane.
*
* Returns: (transfer full): A new #CoglMultiPlaneTexture. Use
* cogl_object_unref() when you're done with it.
*/
CoglMultiPlaneTexture * cogl_multi_plane_texture_new_single_plane (CoglPixelFormat format,
CoglTexture *plane);
/**
* cogl_multi_plane_texture_get_format:
* @self: a #CoglMultiPlaneTexture
*
* Returns the pixel format that is used by this texture.
*
* Returns: The pixel format that is used by this #CoglMultiPlaneTexture.
*/
CoglPixelFormat cogl_multi_plane_texture_get_format (CoglMultiPlaneTexture *self);
/**
* cogl_multi_plane_texture_get_n_planes:
* @self: a #CoglMultiPlaneTexture
*
* Returns the number of planes for this texture. Note that this is entirely
* dependent on the #CoglPixelFormat that is used. For example, simple RGB
* textures will have a single plane, while some more convoluted formats like
* NV12 and YUV 4:4:4 can have 2 and 3 planes respectively.
*
* Returns: The number of planes in this #CoglMultiPlaneTexture.
*/
uint8_t cogl_multi_plane_texture_get_n_planes (CoglMultiPlaneTexture *self);
/**
* cogl_multi_plane_texture_get_plane:
* @self: a #CoglMultiPlaneTexture
* @index: the index of the plane
*
* Returns the n'th plane of the #CoglMultiPlaneTexture. Note that it is a
* programming error to use with an index larger than
* cogl_multi_plane_texture_get_n_planes().
*
* Returns: (transfer none): The plane at the given @index.
*/
CoglTexture * cogl_multi_plane_texture_get_plane (CoglMultiPlaneTexture *self,
guint index);
/**
* cogl_multi_plane_texture_get_planes:
* @self: a #CoglMultiPlaneTexture
*
* Returns all planes of the #CoglMultiPlaneTexture.
*
* Returns: (transfer none): The planes of this texture.
*/
CoglTexture ** cogl_multi_plane_texture_get_planes (CoglMultiPlaneTexture *self);
/**
* cogl_multi_plane_texture_get_width:
* @self: a #CoglMultiPlaneTexture
*
* Returns the width of the #CoglMultiPlaneTexture. Prefer this over calling
* cogl_texture_get_width() on one of the textures, as that might give a
* different size when dealing with subsampling.
*
* Returns: The width of the texture.
*/
guint cogl_multi_plane_texture_get_width (CoglMultiPlaneTexture *self);
/**
* cogl_multi_plane_texture_get_height:
* @self: a #CoglMultiPlaneTexture
*
* Returns the height of the #CoglMultiPlaneTexture. Prefer this over calling
* cogl_texture_get_height() on one of the textures, as that might give a
* different size when dealing with subsampling.
*
* Returns: The height of the texture.
*/
guint cogl_multi_plane_texture_get_height (CoglMultiPlaneTexture *self);
/**
* cogl_multi_plane_texture_to_string:
* @self: a #CoglMultiPlaneTexture
*
* Returns a string representation of @self, useful for debugging purposes.
*
* Returns: (transfer full): A string representation of @self. Use g_free() when
* done with it.
*/
char * cogl_multi_plane_texture_to_string (CoglMultiPlaneTexture *self);
G_END_DECLS
#endif

View File

@@ -0,0 +1,182 @@
/*
* Authored By Niels De Graef <niels.degraef@barco.com>
*
* Copyright (C) 2018 Barco NV
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "cogl-config.h"
#include "cogl-object-private.h"
#include "cogl-gtype-private.h"
#include "cogl-pixel-format-conversion.h"
#include "cogl-snippet.h"
#include "cogl-pipeline-layer-state.h"
#include "cogl-pipeline-state.h"
#define _COGL_YUV_TO_RGBA(res, y, u, v) \
"vec4 " res ";\n" \
res ".r = (" y ") + 1.59765625 * (" v ");\n" \
res ".g = (" y ") - 0.390625 * (" u ") - 0.8125 * (" v ");\n" \
res ".b = (" y ") + 2.015625 * (" u ");\n" \
res ".a = 1.0;\n"
/* Shader for a single YUV plane */
static const char yuv_to_rgba_shader[] =
"vec4\n"
"cogl_yuv_to_rgba (vec2 UV)\n"
"{\n"
" vec4 orig_color = texture2D(cogl_sampler0, UV);\n"
" float y = 1.16438356 * (orig_color.r - 0.0625);\n"
" float u = orig_color.g - 0.5;\n"
" float v = orig_color.b - 0.5;\n"
_COGL_YUV_TO_RGBA ("color", "y", "u", "v")
" return color;\n"
"}\n";
/* Shader for 1 Y-plane and 1 UV-plane */
static const char y_uv_to_rgba_shader[] =
"vec4\n"
"cogl_y_uv_to_rgba (vec2 UV)\n"
"{\n"
" float y = 1.1640625 * (texture2D (cogl_sampler0, UV).x - 0.0625);\n"
" vec2 uv = texture2D (cogl_sampler1, UV).rg;\n"
" uv -= 0.5;\n"
" float u = uv.x;\n"
" float v = uv.y;\n"
_COGL_YUV_TO_RGBA ("color", "y", "u", "v")
" return color;\n"
"}\n";
/* Shader for 1 Y-plane, 1 U-plane and 1 V-plane */
static const char y_u_v_to_rgba_shader[] =
"vec4\n"
"cogl_y_u_v_to_rgba (vec2 UV)\n"
"{\n"
" float y = 1.16438356 * (texture2D(cogl_sampler0, UV).x - 0.0625);\n"
" float u = texture2D(cogl_sampler1, UV).x - 0.5;\n"
" float v = texture2D(cogl_sampler2, UV).x - 0.5;\n"
_COGL_YUV_TO_RGBA ("color", "y", "u", "v")
" return color;\n"
"}\n";
struct _CoglPixelFormatConversion
{
CoglObject _parent;
CoglSnippet *vertex_declaration_snippet;
CoglSnippet *fragment_declaration_snippet;
CoglSnippet *fragment_execution_snippet;
};
static void
_cogl_pixel_format_conversion_free (CoglPixelFormatConversion *self);
COGL_OBJECT_DEFINE (PixelFormatConversion, pixel_format_conversion);
COGL_GTYPE_DEFINE_CLASS (PixelFormatConversion, pixel_format_conversion);
void
cogl_pixel_format_conversion_attach_to_pipeline (CoglPixelFormatConversion *self,
CoglPipeline *pipeline,
gint layer)
{
cogl_pipeline_add_snippet (pipeline, self->fragment_declaration_snippet);
cogl_pipeline_add_snippet (pipeline, self->vertex_declaration_snippet);
cogl_pipeline_add_layer_snippet (pipeline,
layer,
self->fragment_execution_snippet);
}
static gboolean
get_cogl_snippets (CoglPixelFormat format,
CoglSnippet **vertex_snippet_out,
CoglSnippet **fragment_snippet_out,
CoglSnippet **layer_snippet_out)
{
const char *global_hook;
const char *layer_hook;
switch (format)
{
case COGL_PIXEL_FORMAT_AYUV:
global_hook = yuv_to_rgba_shader;
layer_hook = "cogl_layer = cogl_yuv_to_rgba(cogl_tex_coord0_in.st);\n";
break;
case COGL_PIXEL_FORMAT_NV12:
/* XXX are we using Y_UV or Y_xUxV? Maybe check for RG support? */
global_hook = y_uv_to_rgba_shader;
layer_hook = "cogl_layer = cogl_y_uv_to_rgba(cogl_tex_coord0_in.st);\n";
break;
case COGL_PIXEL_FORMAT_YUV444:
case COGL_PIXEL_FORMAT_YUV422:
global_hook = y_u_v_to_rgba_shader;
layer_hook = "cogl_layer = cogl_y_u_v_to_rgba(cogl_tex_coord0_in.st);\n";
break;
default:
*vertex_snippet_out = NULL;
*fragment_snippet_out = NULL;
*layer_snippet_out = NULL;
return FALSE;
}
*vertex_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
global_hook,
NULL);
*fragment_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
global_hook,
NULL);
*layer_snippet_out = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT,
NULL,
layer_hook);
return TRUE;
}
static void
_cogl_pixel_format_conversion_free (CoglPixelFormatConversion *self)
{
cogl_clear_object (&self->vertex_declaration_snippet);
cogl_clear_object (&self->fragment_declaration_snippet);
cogl_clear_object (&self->fragment_execution_snippet);
}
CoglPixelFormatConversion *
cogl_pixel_format_conversion_new (CoglPixelFormat format)
{
CoglPixelFormatConversion *self;
CoglSnippet *vertex_declaration_snippet;
CoglSnippet *fragment_declaration_snippet;
CoglSnippet *fragment_execution_snippet;
if (!get_cogl_snippets (format,
&vertex_declaration_snippet,
&fragment_declaration_snippet,
&fragment_execution_snippet))
return NULL;
self = g_slice_new0 (CoglPixelFormatConversion);
_cogl_pixel_format_conversion_object_new (self);
self->vertex_declaration_snippet = vertex_declaration_snippet;
self->fragment_declaration_snippet = fragment_declaration_snippet;
self->fragment_execution_snippet = fragment_execution_snippet;
return self;
}

View File

@@ -0,0 +1,92 @@
/*
* Authored By Niels De Graef <niels.degraef@barco.com>
*
* Copyright (C) 2018 Barco NV
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __COGL_PIXEL_FORMAT_CONVERSION_H__
#define __COGL_PIXEL_FORMAT_CONVERSION_H__
#include "cogl/cogl-types.h"
#include "cogl/cogl-pipeline.h"
G_BEGIN_DECLS
/**
* SECTION:cogl-color-space-conversion
* @title: CoglPixelFormatConversion
* @short_description: A collection of snippets to handle pixel_format conversion
*
* In some use cases, one might generate non-RGBA textures (e.g. YUV), which is
* problematic if you then have to composite them in to an RGBA framebuffer. In
* comes #CoglPixelFormatConversion, which you can attach to a #CoglPipeline to
* do this all for you. Internally, it consists of nothing more than a
* collection of #CoglSnippets which do the right thing for you.
*/
typedef struct _CoglPixelFormatConversion CoglPixelFormatConversion;
#define COGL_PIXEL_FORMAT_CONVERSION(ptr) ((CoglPixelFormatConversion *) ptr)
/**
* cogl_multiplane_texture_get_gtype:
*
* Returns: a #GType that can be used with the GLib type system.
*/
GType cogl_pixel_format_conversion_get_gtype (void);
/*
* cogl_is_pixel_format_conversion:
* @object: A #CoglObject pointer
*
* Gets whether the given @object references an existing
* CoglPixelFormatConversion.
*
* Return value: %TRUE if the @object references a #CoglPixelFormatConversion,
* %FALSE otherwise
*/
gboolean
cogl_is_pixel_format_conversion (void *object);
/**
* cogl_pixel_format_conversion_new:
* @format: The input format
*
* Creates a #CoglPixelFormatConversion to convert the given @formatro RGBA. If
* no such conversion is needed, it will return %NULL.
*
* Returns: (transfer full) (nullable): A new #CoglPixelFormatConversion, or
* %NULL if none is needed.
*/
CoglPixelFormatConversion * cogl_pixel_format_conversion_new (CoglPixelFormat format);
/**
* cogl_pixel_format_conversion_attach_to_pipeline:
* @self: The #CoglPixelFormatConversion you want to add
* @pipeline: The #CoglPipeline which needs the color conversion
* @layer: The layer you want to perform the color space conversion at
*
* Adds color conversion to the given @pipeline at the given @layer.
*/
void cogl_pixel_format_conversion_attach_to_pipeline (CoglPixelFormatConversion *self,
CoglPipeline *pipeline,
int layer);
G_END_DECLS
#endif

View File

@@ -35,241 +35,667 @@
#include <stdlib.h> #include <stdlib.h>
#include "cogl-pixel-format.h" #include "cogl-pixel-format.h"
#include "cogl-texture.h"
/* An entry to map CoglPixelFormats to their respective properties */ /* An entry to map CoglPixelFormats to their respective properties */
typedef struct _CoglPixelFormatInfo typedef struct _CoglPixelFormatInfo
{ {
CoglPixelFormat cogl_format; CoglPixelFormat cogl_format;
const char *format_str; const char *format_str;
int bpp; /* Bytes per pixel */ int aligned; /* Is aligned? (bool; -1 if n/a) */
int aligned; /* Aligned components? (-1 if n/a) */ uint8_t n_planes;
/* Per plane-information */
uint8_t bpp[COGL_PIXEL_FORMAT_MAX_PLANES]; /* Bytes per pixel */
uint8_t hsub[COGL_PIXEL_FORMAT_MAX_PLANES]; /* horizontal subsampling */
uint8_t vsub[COGL_PIXEL_FORMAT_MAX_PLANES]; /* vertical subsampling */
CoglPixelFormat subformats[COGL_PIXEL_FORMAT_MAX_PLANES]; /* how to upload to GL */
} CoglPixelFormatInfo; } CoglPixelFormatInfo;
static const CoglPixelFormatInfo format_info_table[] = { static const CoglPixelFormatInfo format_info_table[] = {
{ {
.cogl_format = COGL_PIXEL_FORMAT_ANY, .cogl_format = COGL_PIXEL_FORMAT_ANY,
.format_str = "ANY", .format_str = "ANY",
.bpp = 0, .n_planes = 0,
.aligned = -1 .aligned = -1,
.bpp = { 0 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ANY }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_A_8, .cogl_format = COGL_PIXEL_FORMAT_A_8,
.format_str = "A_8", .format_str = "A_8",
.bpp = 1, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 1 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_A_8 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGB_565, .cogl_format = COGL_PIXEL_FORMAT_RGB_565,
.format_str = "RGB_565", .format_str = "RGB_565",
.bpp = 2, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 2 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGB_565 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGBA_4444, .cogl_format = COGL_PIXEL_FORMAT_RGBA_4444,
.format_str = "RGBA_4444", .format_str = "RGBA_4444",
.bpp = 2, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 2 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_4444 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGBA_5551, .cogl_format = COGL_PIXEL_FORMAT_RGBA_5551,
.format_str = "RGBA_5551", .format_str = "RGBA_5551",
.bpp = 2, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 2 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_5551 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_YUV, .cogl_format = COGL_PIXEL_FORMAT_YUV,
.format_str = "YUV", .format_str = "YUV",
.bpp = 0, .n_planes = 1,
.aligned = -1 .aligned = -1,
.bpp = { 0 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_YUV }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_G_8, .cogl_format = COGL_PIXEL_FORMAT_R_8,
.format_str = "G_8", .format_str = "R_8",
.bpp = 1, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 1 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RG_88, .cogl_format = COGL_PIXEL_FORMAT_RG_88,
.format_str = "RG_88", .format_str = "RG_88",
.bpp = 2, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 2 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RG_88 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGB_888, .cogl_format = COGL_PIXEL_FORMAT_RGB_888,
.format_str = "RGB_888", .format_str = "RGB_888",
.bpp = 3, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 3 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGB_888 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_BGR_888, .cogl_format = COGL_PIXEL_FORMAT_BGR_888,
.format_str = "BGR_888", .format_str = "BGR_888",
.bpp = 3, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 3 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_BGR_888 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGBA_8888, .cogl_format = COGL_PIXEL_FORMAT_RGBA_8888,
.format_str = "RGBA_8888", .format_str = "RGBA_8888",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_8888 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_BGRA_8888, .cogl_format = COGL_PIXEL_FORMAT_BGRA_8888,
.format_str = "BGRA_8888", .format_str = "BGRA_8888",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_BGRA_8888 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_ARGB_8888, .cogl_format = COGL_PIXEL_FORMAT_ARGB_8888,
.format_str = "ARGB_8888", .format_str = "ARGB_8888",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_ABGR_8888, .cogl_format = COGL_PIXEL_FORMAT_ABGR_8888,
.format_str = "ABGR_8888", .format_str = "ABGR_8888",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ABGR_8888 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGBA_1010102, .cogl_format = COGL_PIXEL_FORMAT_RGBA_1010102,
.format_str = "RGBA_1010102", .format_str = "RGBA_1010102",
.bpp = 4, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_1010102 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_BGRA_1010102, .cogl_format = COGL_PIXEL_FORMAT_BGRA_1010102,
.format_str = "BGRA_1010102", .format_str = "BGRA_1010102",
.bpp = 4, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_BGRA_1010102 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010, .cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010,
.format_str = "ARGB_2101010", .format_str = "ARGB_2101010",
.bpp = 4, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ARGB_2101010 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010, .cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010,
.format_str = "ABGR_2101010", .format_str = "ABGR_2101010",
.bpp = 4, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ABGR_2101010 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE, .cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE,
.format_str = "RGBA_8888_PRE", .format_str = "RGBA_8888_PRE",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_8888_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE, .cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE,
.format_str = "BGRA_8888_PRE", .format_str = "BGRA_8888_PRE",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_BGRA_8888_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE, .cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE,
.format_str = "ARGB_8888_PRE", .format_str = "ARGB_8888_PRE",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_ABGR_8888_PRE, .cogl_format = COGL_PIXEL_FORMAT_ABGR_8888_PRE,
.format_str = "ABGR_8888_PRE", .format_str = "ABGR_8888_PRE",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ABGR_8888_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGBA_4444_PRE, .cogl_format = COGL_PIXEL_FORMAT_RGBA_4444_PRE,
.format_str = "RGBA_4444_PRE", .format_str = "RGBA_4444_PRE",
.bpp = 2, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 2 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_4444_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGBA_5551_PRE, .cogl_format = COGL_PIXEL_FORMAT_RGBA_5551_PRE,
.format_str = "RGBA_5551_PRE", .format_str = "RGBA_5551_PRE",
.bpp = 2, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 2 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_5551_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_RGBA_1010102_PRE, .cogl_format = COGL_PIXEL_FORMAT_RGBA_1010102_PRE,
.format_str = "RGBA_1010102_PRE", .format_str = "RGBA_1010102_PRE",
.bpp = 4, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_1010102_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_BGRA_1010102_PRE, .cogl_format = COGL_PIXEL_FORMAT_BGRA_1010102_PRE,
.format_str = "BGRA_1010102_PRE", .format_str = "BGRA_1010102_PRE",
.bpp = 4, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_BGRA_1010102_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE, .cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE,
.format_str = "ARGB_2101010_PRE", .format_str = "ARGB_2101010_PRE",
.bpp = 4, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ARGB_2101010_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE, .cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE,
.format_str = "ABGR_2101010_PRE", .format_str = "ABGR_2101010_PRE",
.bpp = 4, .n_planes = 1,
.aligned = 0 .aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ABGR_2101010_PRE }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_16, .cogl_format = COGL_PIXEL_FORMAT_DEPTH_16,
.format_str = "DEPTH_16", .format_str = "DEPTH_16",
.bpp = 2, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 2 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_DEPTH_16 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_32, .cogl_format = COGL_PIXEL_FORMAT_DEPTH_32,
.format_str = "DEPTH_32", .format_str = "DEPTH_32",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_DEPTH_32 }
}, },
{ {
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8, .cogl_format = COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8,
.format_str = "DEPTH_24_STENCIL_8", .format_str = "DEPTH_24_STENCIL_8",
.bpp = 4, .n_planes = 1,
.aligned = 1 .aligned = 1,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 }
},
/* Packed YUV */
{
.cogl_format = COGL_PIXEL_FORMAT_YUYV,
.format_str = "YUYV",
.n_planes = 2,
.aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_YUYV, COGL_PIXEL_FORMAT_YUYV }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YVYU,
.format_str = "YVYU",
.n_planes = 2,
.aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_YVYU, COGL_PIXEL_FORMAT_YVYU }
},
{
.cogl_format = COGL_PIXEL_FORMAT_UYVY,
.format_str = "UYVY",
.n_planes = 2,
.aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_UYVY, COGL_PIXEL_FORMAT_UYVY }
},
{
.cogl_format = COGL_PIXEL_FORMAT_VYUY,
.format_str = "VYUY",
.n_planes = 2,
.aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_VYUY, COGL_PIXEL_FORMAT_VYUY }
},
{
.cogl_format = COGL_PIXEL_FORMAT_AYUV,
.format_str = "AYUV",
.n_planes = 2,
.aligned = 0,
.bpp = { 4 },
.hsub = { 1, 0, 0, 0 },
.vsub = { 1, 0, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_AYUV, COGL_PIXEL_FORMAT_AYUV }
},
/* 2 plane RGB + A */
{
.cogl_format = COGL_PIXEL_FORMAT_XRGB8888_A8,
.format_str = "XRGB8888_A8",
.n_planes = 2,
.aligned = 0,
.bpp = { 4, 1 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ARGB_8888, COGL_PIXEL_FORMAT_A_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_XBGR8888_A8,
.format_str = "XBGR8888_A8",
.n_planes = 2,
.aligned = 0,
.bpp = { 4, 1 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_ABGR_8888, COGL_PIXEL_FORMAT_A_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBX8888_A8,
.format_str = "RGBX8888_A8",
.n_planes = 2,
.aligned = 0,
.bpp = { 4, 1 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGBA_8888, COGL_PIXEL_FORMAT_A_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRX8888_A8,
.format_str = "BGRX8888_A8",
.n_planes = 2,
.aligned = 0,
.bpp = { 4, 1 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_BGRA_8888, COGL_PIXEL_FORMAT_A_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGB888_A8,
.format_str = "RGB888_A8",
.n_planes = 2,
.aligned = 0,
.bpp = { 3, 1 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGB_888, COGL_PIXEL_FORMAT_A_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGR888_A8,
.format_str = "BGR888_A8",
.n_planes = 2,
.aligned = 0,
.bpp = { 3, 1 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_BGR_888, COGL_PIXEL_FORMAT_A_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGB565_A8,
.format_str = "RGB565_A8",
.n_planes = 2,
.aligned = 0,
.bpp = { 2, 1 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGB_565, COGL_PIXEL_FORMAT_A_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGR565_A8,
.format_str = "BGR565_A8",
.n_planes = 2,
.aligned = 0,
.bpp = { 2, 1 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_RGB_565, COGL_PIXEL_FORMAT_A_8 }
},
/* 2 plane YUV */
{
.cogl_format = COGL_PIXEL_FORMAT_NV12,
.format_str = "NV12",
.n_planes = 2,
.aligned = 0,
.bpp = { 1, 2 },
.hsub = { 1, 2, 0, 0 },
.vsub = { 1, 2, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_RG_88 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_NV21,
.format_str = "NV21",
.n_planes = 2,
.aligned = 0,
.bpp = { 1, 2 },
.hsub = { 1, 2, 0, 0 },
.vsub = { 1, 2, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_RG_88 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_NV16,
.format_str = "NV16",
.n_planes = 2,
.aligned = 0,
.bpp = { 1, 2 },
.hsub = { 1, 2, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_RG_88 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_NV61,
.format_str = "NV61",
.n_planes = 2,
.aligned = 0,
.bpp = { 1, 2 },
.hsub = { 1, 2, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_RG_88 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_NV24,
.format_str = "NV24",
.n_planes = 2,
.aligned = 0,
.bpp = { 1, 2 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_RG_88 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_NV42,
.format_str = "NV42",
.n_planes = 2,
.aligned = 0,
.bpp = { 1, 2 },
.hsub = { 1, 1, 0, 0 },
.vsub = { 1, 1, 0, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_RG_88 }
},
/* 3 plane YUV */
{
.cogl_format = COGL_PIXEL_FORMAT_YUV410,
.format_str = "YUV410",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 4, 4, 0 },
.vsub = { 1, 4, 4, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YVU410,
.format_str = "YVU410",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 4, 4, 0 },
.vsub = { 1, 4, 4, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YUV411,
.format_str = "YUV411",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 4, 4, 0 },
.vsub = { 1, 1, 1, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YVU411,
.format_str = "YVU411",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 4, 4, 0 },
.vsub = { 1, 1, 1, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YUV420,
.format_str = "YUV420",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 2, 2, 0 },
.vsub = { 1, 2, 2, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YVU420,
.format_str = "YVU420",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 2, 2, 0 },
.vsub = { 1, 2, 2, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YUV422,
.format_str = "YUV422",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 2, 2, 0 },
.vsub = { 1, 1, 1, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YVU422,
.format_str = "YVU422",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 2, 2, 0 },
.vsub = { 1, 1, 1, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YUV444,
.format_str = "YUV444",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 1, 1, 0 },
.vsub = { 1, 1, 1, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
},
{
.cogl_format = COGL_PIXEL_FORMAT_YVU444,
.format_str = "YVU444",
.n_planes = 3,
.aligned = 0,
.bpp = { 1, 1, 1 },
.hsub = { 1, 1, 1, 0 },
.vsub = { 1, 1, 1, 0 },
.subformats = { COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8, COGL_PIXEL_FORMAT_R_8 }
}, },
}; };
/* uint8_t
* Returns the number of bytes-per-pixel of a given format. The bpp cogl_pixel_format_get_bytes_per_pixel_simple (CoglPixelFormat format)
* can be extracted from the least significant nibble of the pixel
* format (see CoglPixelFormat).
*
* The mapping is the following (see discussion on bug #660188):
*
* 0 = undefined
* 1, 8 = 1 bpp (e.g. A_8, G_8)
* 2 = 3 bpp, aligned (e.g. 888)
* 3 = 4 bpp, aligned (e.g. 8888)
* 4-6 = 2 bpp, not aligned (e.g. 565, 4444, 5551)
* 7 = undefined yuv
* 9 = 2 bpp, aligned
* 10 = undefined
* 11 = undefined
* 12 = 3 bpp, not aligned
* 13 = 4 bpp, not aligned (e.g. 2101010)
* 14-15 = undefined
*/
int
_cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format)
{ {
size_t i; size_t i;
for (i = 0; i < G_N_ELEMENTS (format_info_table); i++) for (i = 0; i < G_N_ELEMENTS (format_info_table); i++)
{ {
if (format_info_table[i].cogl_format == format) if (format_info_table[i].cogl_format == format)
return format_info_table[i].bpp; {
g_return_val_if_fail (format_info_table[i].n_planes == 1, 0);
return format_info_table[i].bpp[0];
}
}
g_assert_not_reached ();
}
void
cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format, uint8_t *bpp_out)
{
size_t i, j;
for (i = 0; i < G_N_ELEMENTS (format_info_table); i++)
{
if (format_info_table[i].cogl_format != format)
continue;
for (j = 0; j < format_info_table[i].n_planes; j++)
bpp_out[j] = format_info_table[i].bpp[j];
return;
} }
g_assert_not_reached (); g_assert_not_reached ();
} }
/* Note: this also refers to the mapping defined above for /* Note: this also refers to the mapping defined above for
* _cogl_pixel_format_get_bytes_per_pixel() */ * cogl_pixel_format_get_bytes_per_pixel() */
gboolean gboolean
_cogl_pixel_format_is_endian_dependant (CoglPixelFormat format) _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format)
{ {
@@ -295,6 +721,44 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format)
return aligned; return aligned;
} }
uint8_t
cogl_pixel_format_get_n_planes (CoglPixelFormat format)
{
size_t i;
for (i = 0; i < G_N_ELEMENTS (format_info_table); i++)
{
if (format_info_table[i].cogl_format == format)
return format_info_table[i].n_planes;
}
g_assert_not_reached ();
}
void
cogl_pixel_format_get_subsampling_factors (CoglPixelFormat format,
uint8_t *horizontal_factors,
uint8_t *vertical_factors)
{
size_t i, j;
for (i = 0; i < G_N_ELEMENTS (format_info_table); i++)
{
if (format_info_table[i].cogl_format != format)
continue;
for (j = 0; j < format_info_table[i].n_planes; j++)
{
horizontal_factors[j] = format_info_table[i].hsub[j];
vertical_factors[j] = format_info_table[i].vsub[j];
}
return;
}
g_assert_not_reached ();
}
const char * const char *
cogl_pixel_format_to_string (CoglPixelFormat format) cogl_pixel_format_to_string (CoglPixelFormat format)
{ {
@@ -308,3 +772,51 @@ cogl_pixel_format_to_string (CoglPixelFormat format)
g_assert_not_reached (); g_assert_not_reached ();
} }
void
cogl_pixel_format_get_subformats (CoglPixelFormat format,
CoglPixelFormat *formats_out)
{
size_t i, j;
for (i = 0; i < G_N_ELEMENTS (format_info_table); i++)
{
if (format_info_table[i].cogl_format != format)
continue;
for (j = 0; j < format_info_table[i].n_planes; j++)
formats_out[j] = format_info_table[i].subformats[j];
return;
}
g_assert_not_reached ();
}
void
cogl_pixel_format_get_cogl_components (CoglPixelFormat format,
guint *components_out)
{
switch (format)
{
case COGL_PIXEL_FORMAT_NV12:
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
components_out[1] = COGL_TEXTURE_COMPONENTS_RG;
break;
case COGL_PIXEL_FORMAT_NV21:
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
components_out[1] = COGL_TEXTURE_COMPONENTS_RG;
break;
case 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 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;
default:
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
}
}

View File

@@ -95,7 +95,7 @@ G_BEGIN_DECLS
* The mapping is the following (see discussion on bug #660188): * The mapping is the following (see discussion on bug #660188):
* *
* 0 = undefined * 0 = undefined
* 1, 8 = 1 bpp (e.g. A_8, G_8) * 1, 8 = 1 bpp (e.g. A_8, R_8)
* 2 = 3 bpp, aligned (e.g. 888) * 2 = 3 bpp, aligned (e.g. 888)
* 3 = 4 bpp, aligned (e.g. 8888) * 3 = 4 bpp, aligned (e.g. 8888)
* 4-6 = 2 bpp, not aligned (e.g. 565, 4444, 5551) * 4-6 = 2 bpp, not aligned (e.g. 565, 4444, 5551)
@@ -145,8 +145,8 @@ G_BEGIN_DECLS
* @COGL_PIXEL_FORMAT_RGB_565: RGB, 16 bits * @COGL_PIXEL_FORMAT_RGB_565: RGB, 16 bits
* @COGL_PIXEL_FORMAT_RGBA_4444: RGBA, 16 bits * @COGL_PIXEL_FORMAT_RGBA_4444: RGBA, 16 bits
* @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits * @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits
* @COGL_PIXEL_FORMAT_YUV: Not currently supported * @COGL_PIXEL_FORMAT_YUV: Obsolete. See the other YUV-based formats.
* @COGL_PIXEL_FORMAT_G_8: Single luminance component * @COGL_PIXEL_FORMAT_R_8: Single red component, 8 bits
* @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits * @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits
* @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits * @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits
* @COGL_PIXEL_FORMAT_RGBA_8888: RGBA, 32 bits * @COGL_PIXEL_FORMAT_RGBA_8888: RGBA, 32 bits
@@ -167,6 +167,35 @@ G_BEGIN_DECLS
* @COGL_PIXEL_FORMAT_BGRA_1010102_PRE: Premultiplied BGRA, 32 bits, 10 bpc * @COGL_PIXEL_FORMAT_BGRA_1010102_PRE: Premultiplied BGRA, 32 bits, 10 bpc
* @COGL_PIXEL_FORMAT_ARGB_2101010_PRE: Premultiplied ARGB, 32 bits, 10 bpc * @COGL_PIXEL_FORMAT_ARGB_2101010_PRE: Premultiplied ARGB, 32 bits, 10 bpc
* @COGL_PIXEL_FORMAT_ABGR_2101010_PRE: Premultiplied ABGR, 32 bits, 10 bpc * @COGL_PIXEL_FORMAT_ABGR_2101010_PRE: Premultiplied ABGR, 32 bits, 10 bpc
* @COGL_PIXEL_FORMAT_YUYV: YUYV, 32 bits, 16 bpc (Y), 8 bpc (U & V)
* @COGL_PIXEL_FORMAT_YVYU: YVYU, 32 bits, 16 bpc (Y), 8 bpc (V & U)
* @COGL_PIXEL_FORMAT_UYVY: UYVY, 32 bits, 16 bpc (Y), 8 bpc (V & U)
* @COGL_PIXEL_FORMAT_VYUY: VYUV, 32 bits, 16 bpc (Y), 8 bpc (V & U)
* @COGL_PIXEL_FORMAT_AYUV: AYUV, 32 bits, 8 bpc
* @COGL_PIXEL_FORMAT_XRGB8888_A8: 2 planes: 1 RGB-plane (64-bit), 1 alpha-plane
* @COGL_PIXEL_FORMAT_XBGR8888_A8: 2 planes: 1 BGR-plane (64-bit), 1 alpha-plane
* @COGL_PIXEL_FORMAT_RGBX8888_A8: 2 planes: 1 RGB-plane (64-bit), 1 alpha-plane
* @COGL_PIXEL_FORMAT_BGRX8888_A8: 2 planes: 1 BGR-plane (64-bit), 1 alpha-plane
* @COGL_PIXEL_FORMAT_RGB888_A8: 2 planes: 1 RGB-plane (32-bit), 1 alpha-plane
* @COGL_PIXEL_FORMAT_BGR888_A8: 2 planes: 1 BGR-plane (32-bit), 1 alpha-plane
* @COGL_PIXEL_FORMAT_RGB565_A8: 2 planes: 1 RGB-plane (16-bit), 1 alpha-plane
* @COGL_PIXEL_FORMAT_BGR565_A8: 2 planes: 1 BGR-plane (16-bit), 1 alpha-plane
* @COGL_PIXEL_FORMAT_NV12: 2 planes: 1 Y-plane, 1 UV-plane (2x2 subsampled)
* @COGL_PIXEL_FORMAT_NV21: 2 planes: 1 Y-plane, 1 VU-plane (2x2 subsampled)
* @COGL_PIXEL_FORMAT_NV16: 2 planes: 1 Y-plane, 1 UV-plane (2x1 subsampled)
* @COGL_PIXEL_FORMAT_NV61: 2 planes: 1 Y-plane, 1 VU-plane (2x1 subsampled)
* @COGL_PIXEL_FORMAT_NV24: 2 planes: 1 Y-plane, 1 UV-plane
* @COGL_PIXEL_FORMAT_NV42: 2 planes: 1 Y-plane, 1 VU-plane
* @COGL_PIXEL_FORMAT_YUV410: 3 planes: 1 Y-plane, 1 U-plane (4x4 subsampled), 1 V-plane (4x4 subsampled)
* @COGL_PIXEL_FORMAT_YVU410: 3 planes: 1 Y-plane, 1 V-plane (4x4 subsampled), 1 U-plane (4x4 subsampled)
* @COGL_PIXEL_FORMAT_YUV411: 3 planes: 1 Y-plane, 1 U-plane (4x1 subsampled), 1 V-plane (4x1 subsampled)
* @COGL_PIXEL_FORMAT_YVU411: 3 planes: 1 Y-plane, 1 V-plane (4x1 subsampled), 1 U-plane (4x1 subsampled)
* @COGL_PIXEL_FORMAT_YUV420: 3 planes: 1 Y-plane, 1 U-plane (2x2 subsampled), 1 V-plane (2x2 subsampled)
* @COGL_PIXEL_FORMAT_YVU420: 3 planes: 1 Y-plane, 1 V-plane (2x2 subsampled), 1 U-plane (2x2 subsampled)
* @COGL_PIXEL_FORMAT_YUV422: 3 planes: 1 Y-plane, 1 U-plane (2x1 subsampled), 1 V-plane (2x1 subsampled)
* @COGL_PIXEL_FORMAT_YVU422: 3 planes: 1 Y-plane, 1 V-plane (2x1 subsampled), 1 U-plane (2x1 subsampled)
* @COGL_PIXEL_FORMAT_YUV444: 3 planes: 1 Y-plane, 1 U-plane, 1 V-plane
* @COGL_PIXEL_FORMAT_YVU444: 3 planes: 1 Y-plane, 1 V-plane, 1 U-plane
* *
* Pixel formats used by Cogl. For the formats with a byte per * Pixel formats used by Cogl. For the formats with a byte per
* component, the order of the components specify the order in * component, the order of the components specify the order in
@@ -198,7 +227,7 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/
COGL_PIXEL_FORMAT_RGBA_4444 = 5 | COGL_A_BIT, COGL_PIXEL_FORMAT_RGBA_4444 = 5 | COGL_A_BIT,
COGL_PIXEL_FORMAT_RGBA_5551 = 6 | COGL_A_BIT, COGL_PIXEL_FORMAT_RGBA_5551 = 6 | COGL_A_BIT,
COGL_PIXEL_FORMAT_YUV = 7, COGL_PIXEL_FORMAT_YUV = 7,
COGL_PIXEL_FORMAT_G_8 = 8, COGL_PIXEL_FORMAT_R_8 = 8,
COGL_PIXEL_FORMAT_RG_88 = 9, COGL_PIXEL_FORMAT_RG_88 = 9,
@@ -230,20 +259,83 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/
COGL_PIXEL_FORMAT_DEPTH_16 = (9 | COGL_DEPTH_BIT), COGL_PIXEL_FORMAT_DEPTH_16 = (9 | COGL_DEPTH_BIT),
COGL_PIXEL_FORMAT_DEPTH_32 = (3 | COGL_DEPTH_BIT), COGL_PIXEL_FORMAT_DEPTH_32 = (3 | COGL_DEPTH_BIT),
COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 = (3 | COGL_DEPTH_BIT | COGL_STENCIL_BIT) COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 = (3 | COGL_DEPTH_BIT | COGL_STENCIL_BIT),
/* From here on out, we simply enumerate with sequential values in the most
* significant enum byte. See the comments above if you want to know why. */
/* The following list is basically synced with Linux's <drm_fourcc.h> */
/* Packed YUV */
COGL_PIXEL_FORMAT_YUYV = (1 << 24),
COGL_PIXEL_FORMAT_YVYU = (2 << 24),
COGL_PIXEL_FORMAT_UYVY = (3 << 24),
COGL_PIXEL_FORMAT_VYUY = (4 << 24),
COGL_PIXEL_FORMAT_AYUV = (5 << 24),
/* 2 plane RGB + A */
COGL_PIXEL_FORMAT_XRGB8888_A8 = ( 6 << 24),
COGL_PIXEL_FORMAT_XBGR8888_A8 = ( 7 << 24),
COGL_PIXEL_FORMAT_RGBX8888_A8 = ( 8 << 24),
COGL_PIXEL_FORMAT_BGRX8888_A8 = ( 9 << 24),
COGL_PIXEL_FORMAT_RGB888_A8 = (10 << 24),
COGL_PIXEL_FORMAT_BGR888_A8 = (11 << 24),
COGL_PIXEL_FORMAT_RGB565_A8 = (12 << 24),
COGL_PIXEL_FORMAT_BGR565_A8 = (13 << 24),
/* 2 plane YUV */
COGL_PIXEL_FORMAT_NV12 = (14 << 24),
COGL_PIXEL_FORMAT_NV21 = (15 << 24),
COGL_PIXEL_FORMAT_NV16 = (16 << 24),
COGL_PIXEL_FORMAT_NV61 = (17 << 24),
COGL_PIXEL_FORMAT_NV24 = (18 << 24),
COGL_PIXEL_FORMAT_NV42 = (19 << 24),
/* 3 plane YUV */
COGL_PIXEL_FORMAT_YUV410 = (20 << 24),
COGL_PIXEL_FORMAT_YVU410 = (21 << 24),
COGL_PIXEL_FORMAT_YUV411 = (22 << 24),
COGL_PIXEL_FORMAT_YVU411 = (23 << 24),
COGL_PIXEL_FORMAT_YUV420 = (24 << 24),
COGL_PIXEL_FORMAT_YVU420 = (25 << 24),
COGL_PIXEL_FORMAT_YUV422 = (26 << 24),
COGL_PIXEL_FORMAT_YVU422 = (27 << 24),
COGL_PIXEL_FORMAT_YUV444 = (28 << 24),
COGL_PIXEL_FORMAT_YVU444 = (29 << 24)
} CoglPixelFormat; } CoglPixelFormat;
/**
* COGL_PIXEL_FORMAT_MAX_PLANES:
*
* The maximum number of planes
*/
#define COGL_PIXEL_FORMAT_MAX_PLANES (4)
/* /*
* _cogl_pixel_format_get_bytes_per_pixel: * cogl_pixel_format_get_bytes_per_pixel:
* @format: a #CoglPixelFormat
* @bpp_out: (inout): A buffer that will be filled with the bytes-per-pixel for each
* plane
*
* Queries how many bytes a pixel of the given @format takes in each plane.
*
* Returns: The no. of bytes in one pixel of the given single-plane @format.
*/
void
cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format,
uint8_t *bpp_out);
/*
* cogl_pixel_format_get_bytes_per_pixel_simple:
* @format: a #CoglPixelFormat * @format: a #CoglPixelFormat
* *
* Queries how many bytes a pixel of the given @format takes. * Queries how many bytes a pixel of the given @format takes.
* *
* Return value: The number of bytes taken for a pixel of the given * Returns: The no. of bytes in one pixel of the given single-plane @format.
* @format.
*/ */
int uint8_t
_cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format); cogl_pixel_format_get_bytes_per_pixel_simple (CoglPixelFormat format);
/* /*
* _cogl_pixel_format_has_aligned_components: * _cogl_pixel_format_has_aligned_components:
@@ -284,6 +376,26 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format);
#define COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT(format) \ #define COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT(format) \
(((format) & COGL_A_BIT) && (format) != COGL_PIXEL_FORMAT_A_8) (((format) & COGL_A_BIT) && (format) != COGL_PIXEL_FORMAT_A_8)
/**
* cogl_pixel_format_get_n_planes:
* @format: The format for which to get the number of planes
*
* Returns the number of planes the given CoglPixelFormat specifies.
*/
uint8_t
cogl_pixel_format_get_n_planes (CoglPixelFormat format);
/**
* cogl_pixel_format_get_subsampling_factors:
* @format: The format to get the subsampling factors from.
*
* Returns the subsampling in both the horizontal as the vertical direction.
*/
void
cogl_pixel_format_get_subsampling_factors (CoglPixelFormat format,
uint8_t *horizontal_factors,
uint8_t *vertical_factors);
/** /**
* cogl_pixel_format_to_string: * cogl_pixel_format_to_string:
* @format: a #CoglPixelFormat * @format: a #CoglPixelFormat
@@ -295,6 +407,14 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format);
const char * const char *
cogl_pixel_format_to_string (CoglPixelFormat format); cogl_pixel_format_to_string (CoglPixelFormat format);
void
cogl_pixel_format_get_subformats (CoglPixelFormat format,
CoglPixelFormat *formats_out);
void
cogl_pixel_format_get_cogl_components (CoglPixelFormat format,
guint *components_out);
G_END_DECLS G_END_DECLS
#endif /* __COGL_PIXEL_FORMAT_H__ */ #endif /* __COGL_PIXEL_FORMAT_H__ */

View File

@@ -163,7 +163,7 @@ _cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds,
tex_2ds->slice_y_spans->len - 1); tex_2ds->slice_y_spans->len - 1);
if (last_x_span->waste > 0 || last_y_span->waste > 0) if (last_x_span->waste > 0 || last_y_span->waste > 0)
{ {
int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
CoglSpan *first_x_span CoglSpan *first_x_span
= &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0); = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0);
CoglSpan *first_y_span CoglSpan *first_y_span
@@ -209,7 +209,7 @@ _cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
{ {
int bmp_rowstride = cogl_bitmap_get_rowstride (source_bmp); int bmp_rowstride = cogl_bitmap_get_rowstride (source_bmp);
CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (source_format);
uint8_t *bmp_data; uint8_t *bmp_data;
const uint8_t *src; const uint8_t *src;
uint8_t *dst; uint8_t *dst;
@@ -972,7 +972,7 @@ cogl_texture_2d_sliced_new_from_data (CoglContext *ctx,
/* Rowstride from width if not given */ /* Rowstride from width if not given */
if (rowstride == 0) if (rowstride == 0)
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); rowstride = width * cogl_pixel_format_get_bytes_per_pixel_simple (format);
/* Wrap the data into a bitmap */ /* Wrap the data into a bitmap */
bmp = cogl_bitmap_new_for_data (ctx, bmp = cogl_bitmap_new_for_data (ctx,

View File

@@ -207,7 +207,7 @@ cogl_texture_2d_new_from_data (CoglContext *ctx,
/* Rowstride from width if not given */ /* Rowstride from width if not given */
if (rowstride == 0) if (rowstride == 0)
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); rowstride = width * cogl_pixel_format_get_bytes_per_pixel_simple (format);
/* Wrap the data into a bitmap */ /* Wrap the data into a bitmap */
bmp = cogl_bitmap_new_for_data (ctx, bmp = cogl_bitmap_new_for_data (ctx,
@@ -239,6 +239,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
int width, int width,
int height, int height,
CoglPixelFormat format, CoglPixelFormat format,
CoglTextureComponents components,
EGLImageKHR image, EGLImageKHR image,
GError **error) GError **error)
{ {
@@ -263,6 +264,9 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
tex = _cogl_texture_2d_create_base (ctx, width, height, format, loader); tex = _cogl_texture_2d_create_base (ctx, width, height, format, loader);
/* Make sure we've set the right components before allocating */
cogl_texture_set_components (COGL_TEXTURE (tex), components);
if (!cogl_texture_allocate (COGL_TEXTURE (tex), error)) if (!cogl_texture_allocate (COGL_TEXTURE (tex), error))
{ {
cogl_object_unref (tex); cogl_object_unref (tex);

View File

@@ -218,6 +218,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
int width, int width,
int height, int height,
CoglPixelFormat format, CoglPixelFormat format,
CoglTextureComponents components,
EGLImageKHR image, EGLImageKHR image,
GError **error); GError **error);

View File

@@ -430,10 +430,14 @@ _cogl_texture_set_region (CoglTexture *texture,
gboolean ret; gboolean ret;
g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, FALSE); g_return_val_if_fail (format != COGL_PIXEL_FORMAT_ANY, FALSE);
g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, FALSE);
/* Rowstride from width if none specified */ /* Rowstride from width if none specified */
if (rowstride == 0) if (rowstride == 0)
rowstride = _cogl_pixel_format_get_bytes_per_pixel (format) * width; {
uint8_t bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
rowstride = bpp * width;
}
/* Init source bitmap */ /* Init source bitmap */
source_bmp = cogl_bitmap_new_for_data (ctx, source_bmp = cogl_bitmap_new_for_data (ctx,
@@ -471,7 +475,7 @@ cogl_texture_set_region (CoglTexture *texture,
{ {
GError *ignore_error = NULL; GError *ignore_error = NULL;
const uint8_t *first_pixel; const uint8_t *first_pixel;
int bytes_per_pixel = _cogl_pixel_format_get_bytes_per_pixel (format); int bytes_per_pixel = cogl_pixel_format_get_bytes_per_pixel_simple (format);
gboolean status; gboolean status;
/* Rowstride from width if none specified */ /* Rowstride from width if none specified */
@@ -609,7 +613,7 @@ get_texture_bits_via_copy (CoglTexture *texture,
full_tex_width = cogl_texture_get_width (texture); full_tex_width = cogl_texture_get_width (texture);
full_tex_height = cogl_texture_get_height (texture); full_tex_height = cogl_texture_get_height (texture);
bpp = _cogl_pixel_format_get_bytes_per_pixel (dst_format); bpp = cogl_pixel_format_get_bytes_per_pixel_simple (dst_format);
full_rowstride = bpp * full_tex_width; full_rowstride = bpp * full_tex_width;
full_bits = g_malloc (full_rowstride * full_tex_height); full_bits = g_malloc (full_rowstride * full_tex_height);
@@ -658,7 +662,7 @@ texture_get_cb (CoglTexture *subtexture,
CoglTextureGetData *tg_data = user_data; CoglTextureGetData *tg_data = user_data;
CoglTexture *meta_texture = tg_data->meta_texture; CoglTexture *meta_texture = tg_data->meta_texture;
CoglPixelFormat closest_format = cogl_bitmap_get_format (tg_data->target_bmp); CoglPixelFormat closest_format = cogl_bitmap_get_format (tg_data->target_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (closest_format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (closest_format);
unsigned int rowstride = cogl_bitmap_get_rowstride (tg_data->target_bmp); unsigned int rowstride = cogl_bitmap_get_rowstride (tg_data->target_bmp);
int subtexture_width = cogl_texture_get_width (subtexture); int subtexture_width = cogl_texture_get_width (subtexture);
int subtexture_height = cogl_texture_get_height (subtexture); int subtexture_height = cogl_texture_get_height (subtexture);
@@ -748,7 +752,7 @@ cogl_texture_get_data (CoglTexture *texture,
tex_height = cogl_texture_get_height (texture); tex_height = cogl_texture_get_height (texture);
/* Rowstride from texture width if none specified */ /* Rowstride from texture width if none specified */
bpp = _cogl_pixel_format_get_bytes_per_pixel (format); bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
if (rowstride == 0) if (rowstride == 0)
rowstride = tex_width * bpp; rowstride = tex_width * bpp;
@@ -1103,6 +1107,11 @@ _cogl_texture_set_internal_format (CoglTexture *texture,
texture->components = COGL_TEXTURE_COMPONENTS_A; texture->components = COGL_TEXTURE_COMPONENTS_A;
return; return;
} }
else if (internal_format == COGL_PIXEL_FORMAT_R_8)
{
texture->components = COGL_TEXTURE_COMPONENTS_R;
return;
}
else if (internal_format == COGL_PIXEL_FORMAT_RG_88) else if (internal_format == COGL_PIXEL_FORMAT_RG_88)
{ {
texture->components = COGL_TEXTURE_COMPONENTS_RG; texture->components = COGL_TEXTURE_COMPONENTS_RG;
@@ -1149,6 +1158,8 @@ _cogl_texture_determine_internal_format (CoglTexture *texture,
} }
case COGL_TEXTURE_COMPONENTS_A: case COGL_TEXTURE_COMPONENTS_A:
return COGL_PIXEL_FORMAT_A_8; return COGL_PIXEL_FORMAT_A_8;
case COGL_TEXTURE_COMPONENTS_R:
return COGL_PIXEL_FORMAT_R_8;
case COGL_TEXTURE_COMPONENTS_RG: case COGL_TEXTURE_COMPONENTS_RG:
return COGL_PIXEL_FORMAT_RG_88; return COGL_PIXEL_FORMAT_RG_88;
case COGL_TEXTURE_COMPONENTS_RGB: case COGL_TEXTURE_COMPONENTS_RGB:

View File

@@ -139,6 +139,7 @@ cogl_is_texture (void *object);
typedef enum _CoglTextureComponents typedef enum _CoglTextureComponents
{ {
COGL_TEXTURE_COMPONENTS_A = 1, COGL_TEXTURE_COMPONENTS_A = 1,
COGL_TEXTURE_COMPONENTS_R,
COGL_TEXTURE_COMPONENTS_RG, COGL_TEXTURE_COMPONENTS_RG,
COGL_TEXTURE_COMPONENTS_RGB, COGL_TEXTURE_COMPONENTS_RGB,
COGL_TEXTURE_COMPONENTS_RGBA, COGL_TEXTURE_COMPONENTS_RGBA,

View File

@@ -330,7 +330,7 @@ cogl_read_pixels (int x,
CoglPixelFormat format, CoglPixelFormat format,
uint8_t *pixels) uint8_t *pixels)
{ {
int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
CoglBitmap *bitmap; CoglBitmap *bitmap;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);

View File

@@ -59,6 +59,7 @@
#include <cogl/cogl1-context.h> #include <cogl/cogl1-context.h>
#include <cogl/cogl-bitmap.h> #include <cogl/cogl-bitmap.h>
#include <cogl/cogl-color.h> #include <cogl/cogl-color.h>
#include <cogl/cogl-pixel-format-conversion.h>
#include <cogl/cogl-matrix.h> #include <cogl/cogl-matrix.h>
#include <cogl/cogl-matrix-stack.h> #include <cogl/cogl-matrix-stack.h>
#include <cogl/cogl-offscreen.h> #include <cogl/cogl-offscreen.h>
@@ -108,6 +109,7 @@
#include <cogl/cogl-sub-texture.h> #include <cogl/cogl-sub-texture.h>
#include <cogl/cogl-atlas-texture.h> #include <cogl/cogl-atlas-texture.h>
#include <cogl/cogl-meta-texture.h> #include <cogl/cogl-meta-texture.h>
#include <cogl/cogl-multi-plane-texture.h>
#include <cogl/cogl-primitive-texture.h> #include <cogl/cogl-primitive-texture.h>
#include <cogl/cogl-index-buffer.h> #include <cogl/cogl-index-buffer.h>
#include <cogl/cogl-attribute-buffer.h> #include <cogl/cogl-attribute-buffer.h>

View File

@@ -148,7 +148,7 @@ _cogl_texture_new_from_data (CoglContext *ctx,
/* Rowstride from width if not given */ /* Rowstride from width if not given */
if (rowstride == 0) if (rowstride == 0)
rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format); rowstride = width * cogl_pixel_format_get_bytes_per_pixel_simple (format);
/* Wrap the data into a bitmap */ /* Wrap the data into a bitmap */
bmp = cogl_bitmap_new_for_data (ctx, bmp = cogl_bitmap_new_for_data (ctx,

View File

@@ -1303,7 +1303,7 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
if (!tmp_bmp) if (!tmp_bmp)
goto EXIT; goto EXIT;
bpp = _cogl_pixel_format_get_bytes_per_pixel (read_format); bpp = cogl_pixel_format_get_bytes_per_pixel_simple (read_format);
rowstride = cogl_bitmap_get_rowstride (tmp_bmp); rowstride = cogl_bitmap_get_rowstride (tmp_bmp);
ctx->texture_driver->prep_gl_for_pixels_download (ctx, ctx->texture_driver->prep_gl_for_pixels_download (ctx,
@@ -1360,7 +1360,7 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
else else
shared_bmp = cogl_object_ref (bitmap); shared_bmp = cogl_object_ref (bitmap);
bpp = _cogl_pixel_format_get_bytes_per_pixel (bmp_format); bpp = cogl_pixel_format_get_bytes_per_pixel_simple (bmp_format);
ctx->texture_driver->prep_gl_for_pixels_download (ctx, ctx->texture_driver->prep_gl_for_pixels_download (ctx,
rowstride, rowstride,

View File

@@ -250,7 +250,7 @@ allocate_from_bitmap (CoglTexture2D *tex_2d,
if (data) if (data)
{ {
memcpy (tex_2d->first_pixel.data, data, memcpy (tex_2d->first_pixel.data, data,
_cogl_pixel_format_get_bytes_per_pixel (format)); cogl_pixel_format_get_bytes_per_pixel_simple (format));
_cogl_bitmap_unmap (upload_bmp); _cogl_bitmap_unmap (upload_bmp);
} }
else else
@@ -259,7 +259,7 @@ allocate_from_bitmap (CoglTexture2D *tex_2d,
"glGenerateMipmap fallback"); "glGenerateMipmap fallback");
g_error_free (ignore); g_error_free (ignore);
memset (tex_2d->first_pixel.data, 0, memset (tex_2d->first_pixel.data, 0,
_cogl_pixel_format_get_bytes_per_pixel (format)); cogl_pixel_format_get_bytes_per_pixel_simple (format));
} }
} }
@@ -789,7 +789,7 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
uint8_t *data = uint8_t *data =
_cogl_bitmap_map (upload_bmp, COGL_BUFFER_ACCESS_READ, 0, &ignore); _cogl_bitmap_map (upload_bmp, COGL_BUFFER_ACCESS_READ, 0, &ignore);
CoglPixelFormat bpp = CoglPixelFormat bpp =
_cogl_pixel_format_get_bytes_per_pixel (upload_format); cogl_pixel_format_get_bytes_per_pixel_simple (upload_format);
tex_2d->first_pixel.gl_format = gl_format; tex_2d->first_pixel.gl_format = gl_format;
tex_2d->first_pixel.gl_type = gl_type; tex_2d->first_pixel.gl_type = gl_type;
@@ -852,7 +852,7 @@ _cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d,
GLenum gl_format; GLenum gl_format;
GLenum gl_type; GLenum gl_type;
bpp = _cogl_pixel_format_get_bytes_per_pixel (format); bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
ctx->driver_vtable->pixel_format_to_gl (ctx, ctx->driver_vtable->pixel_format_to_gl (ctx,
format, format,

View File

@@ -58,18 +58,11 @@ _cogl_driver_pixel_format_from_gl_internal (CoglContext *context,
{ {
case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8:
case GL_ALPHA12: case GL_ALPHA16: case GL_ALPHA12: case GL_ALPHA16:
/* Cogl only supports one single-component texture so if we have
* ended up with a red texture then it is probably being used as
* a component-alpha texture */
case GL_RED:
*out_format = COGL_PIXEL_FORMAT_A_8; *out_format = COGL_PIXEL_FORMAT_A_8;
return TRUE; return TRUE;
case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_RED:
case GL_LUMINANCE12: case GL_LUMINANCE16: *out_format = COGL_PIXEL_FORMAT_R_8;
*out_format = COGL_PIXEL_FORMAT_G_8;
return TRUE; return TRUE;
case GL_RG: case GL_RG:
@@ -126,9 +119,9 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
} }
gltype = GL_UNSIGNED_BYTE; gltype = GL_UNSIGNED_BYTE;
break; break;
case COGL_PIXEL_FORMAT_G_8: case COGL_PIXEL_FORMAT_R_8:
glintformat = GL_LUMINANCE; glintformat = GL_RED;
glformat = GL_LUMINANCE; glformat = GL_RED;
gltype = GL_UNSIGNED_BYTE; gltype = GL_UNSIGNED_BYTE;
break; break;
@@ -267,7 +260,37 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
break; break;
case COGL_PIXEL_FORMAT_ANY: case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
case COGL_PIXEL_FORMAT_YUV: case COGL_PIXEL_FORMAT_YUV:
case COGL_PIXEL_FORMAT_YUYV:
case COGL_PIXEL_FORMAT_YVYU:
case COGL_PIXEL_FORMAT_UYVY:
case COGL_PIXEL_FORMAT_VYUY:
case COGL_PIXEL_FORMAT_AYUV:
case COGL_PIXEL_FORMAT_XRGB8888_A8:
case COGL_PIXEL_FORMAT_XBGR8888_A8:
case COGL_PIXEL_FORMAT_RGBX8888_A8:
case COGL_PIXEL_FORMAT_BGRX8888_A8:
case COGL_PIXEL_FORMAT_RGB888_A8:
case COGL_PIXEL_FORMAT_BGR888_A8:
case COGL_PIXEL_FORMAT_RGB565_A8:
case COGL_PIXEL_FORMAT_BGR565_A8:
case COGL_PIXEL_FORMAT_NV12:
case COGL_PIXEL_FORMAT_NV21:
case COGL_PIXEL_FORMAT_NV16:
case COGL_PIXEL_FORMAT_NV61:
case COGL_PIXEL_FORMAT_NV24:
case COGL_PIXEL_FORMAT_NV42:
case COGL_PIXEL_FORMAT_YUV410:
case COGL_PIXEL_FORMAT_YVU410:
case COGL_PIXEL_FORMAT_YUV411:
case COGL_PIXEL_FORMAT_YVU411:
case COGL_PIXEL_FORMAT_YUV420:
case COGL_PIXEL_FORMAT_YVU420:
case COGL_PIXEL_FORMAT_YUV422:
case COGL_PIXEL_FORMAT_YVU422:
case COGL_PIXEL_FORMAT_YUV444:
case COGL_PIXEL_FORMAT_YVU444:
g_assert_not_reached (); g_assert_not_reached ();
break; break;
} }

View File

@@ -196,7 +196,7 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
GLuint gl_handle; GLuint gl_handle;
uint8_t *data; uint8_t *data;
CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (source_format);
gboolean status = TRUE; gboolean status = TRUE;
GError *internal_error = NULL; GError *internal_error = NULL;
int level_width; int level_width;
@@ -302,7 +302,7 @@ _cogl_texture_driver_upload_to_gl (CoglContext *ctx,
{ {
uint8_t *data; uint8_t *data;
CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (source_format);
gboolean status = TRUE; gboolean status = TRUE;
GError *internal_error = NULL; GError *internal_error = NULL;

View File

@@ -86,9 +86,18 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
glformat = GL_ALPHA; glformat = GL_ALPHA;
gltype = GL_UNSIGNED_BYTE; gltype = GL_UNSIGNED_BYTE;
break; break;
case COGL_PIXEL_FORMAT_G_8:
glintformat = GL_LUMINANCE; case COGL_PIXEL_FORMAT_R_8:
glformat = GL_LUMINANCE; if (cogl_has_feature (context, COGL_FEATURE_ID_TEXTURE_RG))
{
glintformat = GL_RED;
glformat = GL_R8;
}
else
{
glintformat = GL_LUMINANCE;
glformat = GL_LUMINANCE;
}
gltype = GL_UNSIGNED_BYTE; gltype = GL_UNSIGNED_BYTE;
break; break;
@@ -198,7 +207,37 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
break; break;
case COGL_PIXEL_FORMAT_ANY: case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
case COGL_PIXEL_FORMAT_YUV: case COGL_PIXEL_FORMAT_YUV:
case COGL_PIXEL_FORMAT_YUYV:
case COGL_PIXEL_FORMAT_YVYU:
case COGL_PIXEL_FORMAT_UYVY:
case COGL_PIXEL_FORMAT_VYUY:
case COGL_PIXEL_FORMAT_AYUV:
case COGL_PIXEL_FORMAT_XRGB8888_A8:
case COGL_PIXEL_FORMAT_XBGR8888_A8:
case COGL_PIXEL_FORMAT_RGBX8888_A8:
case COGL_PIXEL_FORMAT_BGRX8888_A8:
case COGL_PIXEL_FORMAT_RGB888_A8:
case COGL_PIXEL_FORMAT_BGR888_A8:
case COGL_PIXEL_FORMAT_RGB565_A8:
case COGL_PIXEL_FORMAT_BGR565_A8:
case COGL_PIXEL_FORMAT_NV12:
case COGL_PIXEL_FORMAT_NV21:
case COGL_PIXEL_FORMAT_NV16:
case COGL_PIXEL_FORMAT_NV61:
case COGL_PIXEL_FORMAT_NV24:
case COGL_PIXEL_FORMAT_NV42:
case COGL_PIXEL_FORMAT_YUV410:
case COGL_PIXEL_FORMAT_YVU410:
case COGL_PIXEL_FORMAT_YUV411:
case COGL_PIXEL_FORMAT_YVU411:
case COGL_PIXEL_FORMAT_YUV420:
case COGL_PIXEL_FORMAT_YVU420:
case COGL_PIXEL_FORMAT_YUV422:
case COGL_PIXEL_FORMAT_YVU422:
case COGL_PIXEL_FORMAT_YUV444:
case COGL_PIXEL_FORMAT_YVU444:
g_assert_not_reached (); g_assert_not_reached ();
break; break;
} }

View File

@@ -96,6 +96,16 @@ _cogl_texture_driver_gen (CoglContext *ctx,
g_assert_not_reached(); g_assert_not_reached();
} }
/* GL-ES doesn't have GL_RED, so swizzle the alpha into a red component */
if (internal_format == COGL_PIXEL_FORMAT_R_8)
{
static const GLint alpha_swizzle[] = { GL_ALPHA, GL_ZERO, GL_ZERO, GL_ZERO };
GE( ctx, glTexParameteriv (gl_target,
GL_TEXTURE_SWIZZLE_RGBA,
alpha_swizzle) );
}
return tex; return tex;
} }
@@ -152,7 +162,7 @@ prepare_bitmap_alignment_for_upload (CoglContext *ctx,
GError **error) GError **error)
{ {
CoglPixelFormat format = cogl_bitmap_get_format (src_bmp); CoglPixelFormat format = cogl_bitmap_get_format (src_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format);
int src_rowstride = cogl_bitmap_get_rowstride (src_bmp); int src_rowstride = cogl_bitmap_get_rowstride (src_bmp);
int width = cogl_bitmap_get_width (src_bmp); int width = cogl_bitmap_get_width (src_bmp);
int alignment = 1; int alignment = 1;
@@ -195,7 +205,7 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
GLuint gl_handle; GLuint gl_handle;
uint8_t *data; uint8_t *data;
CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (source_format);
CoglBitmap *slice_bmp; CoglBitmap *slice_bmp;
int rowstride; int rowstride;
gboolean status = TRUE; gboolean status = TRUE;
@@ -337,7 +347,7 @@ _cogl_texture_driver_upload_to_gl (CoglContext *ctx,
GError **error) GError **error)
{ {
CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp); CoglPixelFormat source_format = cogl_bitmap_get_format (source_bmp);
int bpp = _cogl_pixel_format_get_bytes_per_pixel (source_format); int bpp = cogl_pixel_format_get_bytes_per_pixel_simple (source_format);
int rowstride; int rowstride;
int bmp_width = cogl_bitmap_get_width (source_bmp); int bmp_width = cogl_bitmap_get_width (source_bmp);
int bmp_height = cogl_bitmap_get_height (source_bmp); int bmp_height = cogl_bitmap_get_height (source_bmp);

View File

@@ -42,7 +42,6 @@ global:
_cogl_framebuffer_winsys_update_size; _cogl_framebuffer_winsys_update_size;
_cogl_winsys_egl_make_current; _cogl_winsys_egl_make_current;
_cogl_winsys_egl_ensure_current; _cogl_winsys_egl_ensure_current;
_cogl_pixel_format_get_bytes_per_pixel*;
_cogl_system_error_quark; _cogl_system_error_quark;
_cogl_util_next_p2; _cogl_util_next_p2;
@unit_tests_symbols@ @unit_tests_symbols@

View File

@@ -82,6 +82,7 @@ cogl_headers = [
'cogl-color.h', 'cogl-color.h',
'cogl-framebuffer.h', 'cogl-framebuffer.h',
'cogl-matrix.h', 'cogl-matrix.h',
'cogl-multi-plane-texture.h',
'cogl-object.h', 'cogl-object.h',
'cogl-offscreen.h', 'cogl-offscreen.h',
'cogl-onscreen.h', 'cogl-onscreen.h',
@@ -89,6 +90,7 @@ cogl_headers = [
'cogl-pipeline-state.h', 'cogl-pipeline-state.h',
'cogl-pipeline-layer-state.h', 'cogl-pipeline-layer-state.h',
'cogl-pixel-format.h', 'cogl-pixel-format.h',
'cogl-pixel-format-conversion.h',
'cogl-primitives.h', 'cogl-primitives.h',
'cogl-texture.h', 'cogl-texture.h',
'cogl-texture-2d.h', 'cogl-texture-2d.h',
@@ -249,10 +251,11 @@ cogl_sources = [
'cogl-bitmap-pixbuf.c', 'cogl-bitmap-pixbuf.c',
'cogl-clip-stack.h', 'cogl-clip-stack.h',
'cogl-clip-stack.c', 'cogl-clip-stack.c',
'cogl-feature-private.h',
'cogl-feature-private.c',
'cogl-color-private.h', 'cogl-color-private.h',
'cogl-color.c', 'cogl-color.c',
'cogl-pixel-format-conversion.c',
'cogl-feature-private.c',
'cogl-feature-private.h',
'cogl-buffer-private.h', 'cogl-buffer-private.h',
'cogl-buffer.c', 'cogl-buffer.c',
'cogl-pixel-buffer-private.h', 'cogl-pixel-buffer-private.h',
@@ -320,6 +323,7 @@ cogl_sources = [
'cogl-atlas-texture-private.h', 'cogl-atlas-texture-private.h',
'cogl-atlas-texture.c', 'cogl-atlas-texture.c',
'cogl-meta-texture.c', 'cogl-meta-texture.c',
'cogl-multi-plane-texture.c',
'cogl-primitive-texture.c', 'cogl-primitive-texture.c',
'cogl-blit.h', 'cogl-blit.h',
'cogl-blit.c', 'cogl-blit.c',

View File

@@ -730,7 +730,7 @@ _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
image->bits_per_pixel, image->bits_per_pixel,
image->byte_order == LSBFirst); image->byte_order == LSBFirst);
bpp = _cogl_pixel_format_get_bytes_per_pixel (image_format); bpp = cogl_pixel_format_get_bytes_per_pixel_simple (image_format);
offset = image->bytes_per_line * src_y + bpp * src_x; offset = image->bytes_per_line * src_y + bpp * src_x;
_cogl_texture_set_region (tex_pixmap->tex, _cogl_texture_set_region (tex_pixmap->tex,

View File

@@ -800,6 +800,7 @@ _cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
tex->width, tex->width,
tex->height, tex->height,
texture_format, texture_format,
COGL_TEXTURE_COMPONENTS_RGBA,
egl_tex_pixmap->image, egl_tex_pixmap->image,
NULL)); NULL));

View File

@@ -173,12 +173,7 @@ test_read_texture_formats (void)
test_read_byte (tex_2d, COGL_PIXEL_FORMAT_A_8, 0x78); test_read_byte (tex_2d, COGL_PIXEL_FORMAT_A_8, 0x78);
#if 0 test_read_byte (tex_2d, COGL_PIXEL_FORMAT_R_8, 0x12);
/* I'm not sure what's the right value to put here because Nvidia
and Mesa seem to behave differently so one of them must be
wrong. */
test_read_byte (tex_2d, COGL_PIXEL_FORMAT_G_8, 0x9c);
#endif
/* We should always be able to read into an RG buffer regardless of /* We should always be able to read into an RG buffer regardless of
* whether RG textures are supported because Cogl will do the * whether RG textures are supported because Cogl will do the

View File

@@ -135,12 +135,7 @@ void
test_write_texture_formats (void) test_write_texture_formats (void)
{ {
test_write_byte (test_ctx, COGL_PIXEL_FORMAT_A_8, 0x34, 0x00000034); test_write_byte (test_ctx, COGL_PIXEL_FORMAT_A_8, 0x34, 0x00000034);
#if 0 test_write_byte (test_ctx, COGL_PIXEL_FORMAT_R_8, 0x34, 0x34000000);
/* I'm not sure what's the right value to put here because Nvidia
and Mesa seem to behave differently so one of them must be
wrong. */
test_write_byte (test_ctx, COGL_PIXEL_FORMAT_G_8, 0x34, 0x340000ff);
#endif
/* We should always be able to read from an RG buffer regardless of /* We should always be able to read from an RG buffer regardless of
* whether RG textures are supported because Cogl will do the * whether RG textures are supported because Cogl will do the

View File

@@ -632,6 +632,7 @@ texture_has_alpha (CoglTexture *texture)
case COGL_TEXTURE_COMPONENTS_A: case COGL_TEXTURE_COMPONENTS_A:
case COGL_TEXTURE_COMPONENTS_RGBA: case COGL_TEXTURE_COMPONENTS_RGBA:
return TRUE; return TRUE;
case COGL_TEXTURE_COMPONENTS_R:
case COGL_TEXTURE_COMPONENTS_RG: case COGL_TEXTURE_COMPONENTS_RG:
case COGL_TEXTURE_COMPONENTS_RGB: case COGL_TEXTURE_COMPONENTS_RGB:
case COGL_TEXTURE_COMPONENTS_DEPTH: case COGL_TEXTURE_COMPONENTS_DEPTH:

View File

@@ -32,7 +32,7 @@
ClutterActor *meta_shaped_texture_new (void); ClutterActor *meta_shaped_texture_new (void);
void meta_shaped_texture_set_texture (MetaShapedTexture *stex, void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
CoglTexture *texture); CoglMultiPlaneTexture *texture);
void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
gboolean is_y_inverted); gboolean is_y_inverted);
void meta_shaped_texture_set_snippet (MetaShapedTexture *stex, void meta_shaped_texture_set_snippet (MetaShapedTexture *stex,

View File

@@ -89,7 +89,7 @@ struct _MetaShapedTexture
MetaTextureTower *paint_tower; MetaTextureTower *paint_tower;
CoglTexture *texture; CoglMultiPlaneTexture *texture;
CoglTexture *mask_texture; CoglTexture *mask_texture;
CoglSnippet *snippet; CoglSnippet *snippet;
@@ -97,6 +97,8 @@ struct _MetaShapedTexture
CoglPipeline *masked_pipeline; CoglPipeline *masked_pipeline;
CoglPipeline *unblended_pipeline; CoglPipeline *unblended_pipeline;
CoglPixelFormatConversion *pixel_format_conversion;
gboolean is_y_inverted; gboolean is_y_inverted;
/* The region containing only fully opaque pixels */ /* The region containing only fully opaque pixels */
@@ -277,9 +279,11 @@ set_clip_region (MetaShapedTexture *stex,
static void static void
meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex) meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
{ {
g_clear_pointer (&stex->base_pipeline, cogl_object_unref); cogl_clear_object (&stex->pixel_format_conversion);
g_clear_pointer (&stex->masked_pipeline, cogl_object_unref);
g_clear_pointer (&stex->unblended_pipeline, cogl_object_unref); cogl_clear_object (&stex->base_pipeline);
cogl_clear_object (&stex->masked_pipeline);
cogl_clear_object (&stex->unblended_pipeline);
} }
static void static void
@@ -297,7 +301,7 @@ meta_shaped_texture_dispose (GObject *object)
meta_texture_tower_free (stex->paint_tower); meta_texture_tower_free (stex->paint_tower);
stex->paint_tower = NULL; stex->paint_tower = NULL;
g_clear_pointer (&stex->texture, cogl_object_unref); cogl_clear_object (&stex->texture);
g_clear_pointer (&stex->opaque_region, cairo_region_destroy); g_clear_pointer (&stex->opaque_region, cairo_region_destroy);
meta_shaped_texture_set_mask_texture (stex, NULL); meta_shaped_texture_set_mask_texture (stex, NULL);
@@ -306,7 +310,7 @@ meta_shaped_texture_dispose (GObject *object)
meta_shaped_texture_reset_pipelines (stex); meta_shaped_texture_reset_pipelines (stex);
g_clear_pointer (&stex->snippet, cogl_object_unref); cogl_clear_object (&stex->snippet);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
} }
@@ -317,19 +321,23 @@ get_base_pipeline (MetaShapedTexture *stex,
{ {
CoglPipeline *pipeline; CoglPipeline *pipeline;
CoglMatrix matrix; CoglMatrix matrix;
CoglPixelFormat format;
uint8_t i, n_planes;
if (stex->base_pipeline) if (stex->base_pipeline)
return stex->base_pipeline; return stex->base_pipeline;
pipeline = cogl_pipeline_new (ctx); pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); format = cogl_multi_plane_texture_get_format (stex->texture);
cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0, n_planes = cogl_multi_plane_texture_get_n_planes (stex->texture);
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); for (i = 0; i < n_planes; i++)
cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1, {
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); cogl_pipeline_set_layer_wrap_mode_s (pipeline, i,
cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); cogl_pipeline_set_layer_wrap_mode_t (pipeline, i,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
}
cogl_matrix_init_identity (&matrix); cogl_matrix_init_identity (&matrix);
@@ -409,11 +417,24 @@ get_base_pipeline (MetaShapedTexture *stex,
0); 0);
} }
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); for (i = 0; i < n_planes + 1; i++)
cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix); cogl_pipeline_set_layer_matrix (pipeline, i, &matrix);
cogl_clear_object (&stex->pixel_format_conversion);
stex->pixel_format_conversion = cogl_pixel_format_conversion_new (format);
if (stex->pixel_format_conversion)
{
cogl_pixel_format_conversion_attach_to_pipeline (stex->pixel_format_conversion,
pipeline,
n_planes - 1);
}
if (stex->snippet) if (stex->snippet)
cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet); {
for (i = 0; i < n_planes; i++)
cogl_pipeline_add_layer_snippet (pipeline, i, stex->snippet);
}
stex->base_pipeline = pipeline; stex->base_pipeline = pipeline;
@@ -432,12 +453,14 @@ get_masked_pipeline (MetaShapedTexture *stex,
CoglContext *ctx) CoglContext *ctx)
{ {
CoglPipeline *pipeline; CoglPipeline *pipeline;
uint8_t n_planes;
if (stex->masked_pipeline) if (stex->masked_pipeline)
return stex->masked_pipeline; return stex->masked_pipeline;
pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
cogl_pipeline_set_layer_combine (pipeline, 1, n_planes = cogl_multi_plane_texture_get_n_planes (stex->texture);
cogl_pipeline_set_layer_combine (pipeline, n_planes,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])", "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL); NULL);
@@ -451,17 +474,15 @@ get_unblended_pipeline (MetaShapedTexture *stex,
CoglContext *ctx) CoglContext *ctx)
{ {
CoglPipeline *pipeline; CoglPipeline *pipeline;
CoglColor color;
if (stex->unblended_pipeline) if (stex->unblended_pipeline)
return stex->unblended_pipeline; return stex->unblended_pipeline;
pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
cogl_pipeline_set_blend (pipeline, cogl_pipeline_set_blend (pipeline,
"RGBA = ADD (SRC_COLOR, 0)", "RGBA = ADD (SRC_COLOR, 0)",
NULL); NULL);
cogl_pipeline_set_color (pipeline, &color); cogl_pipeline_set_color4ub (pipeline, 255, 255, 255, 255);
stex->unblended_pipeline = pipeline; stex->unblended_pipeline = pipeline;
@@ -503,23 +524,21 @@ paint_clipped_rectangle (MetaShapedTexture *stex,
} }
static void static void
set_cogl_texture (MetaShapedTexture *stex, set_planar_texture (MetaShapedTexture *stex,
CoglTexture *cogl_tex) CoglMultiPlaneTexture *planar_tex)
{ {
int width, height; int width, height;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
if (stex->texture) cogl_clear_object (&stex->texture);
cogl_object_unref (stex->texture); stex->texture = planar_tex;
stex->texture = cogl_tex; if (planar_tex != NULL)
if (cogl_tex != NULL)
{ {
cogl_object_ref (cogl_tex); cogl_object_ref (planar_tex);
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); width = cogl_multi_plane_texture_get_width (planar_tex);
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex)); height = cogl_multi_plane_texture_get_height (planar_tex);
} }
else else
{ {
@@ -540,8 +559,11 @@ set_cogl_texture (MetaShapedTexture *stex,
* previous buffer. We only queue a redraw in response to surface * previous buffer. We only queue a redraw in response to surface
* damage. */ * damage. */
/* if (FALSE) */
if (stex->create_mipmaps) if (stex->create_mipmaps)
meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex); {
meta_texture_tower_set_base_texture (stex->paint_tower, planar_tex);
}
} }
static gboolean static gboolean
@@ -559,10 +581,10 @@ texture_is_idle_and_not_mipmapped (gpointer user_data)
} }
static void static void
do_paint (MetaShapedTexture *stex, do_paint (MetaShapedTexture *stex,
CoglFramebuffer *fb, CoglFramebuffer *fb,
CoglTexture *paint_tex, CoglMultiPlaneTexture *paint_tex,
cairo_region_t *clip_region) cairo_region_t *clip_region)
{ {
double tex_scale; double tex_scale;
int dst_width, dst_height; int dst_width, dst_height;
@@ -575,8 +597,12 @@ do_paint (MetaShapedTexture *stex,
CoglContext *ctx; CoglContext *ctx;
ClutterActorBox alloc; ClutterActorBox alloc;
CoglPipelineFilter filter; CoglPipelineFilter filter;
uint8_t n_planes;
clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL);
n_planes = cogl_multi_plane_texture_get_n_planes (paint_tex);
ensure_size_valid (stex); ensure_size_valid (stex);
dst_width = stex->dst_width; dst_width = stex->dst_width;
@@ -682,8 +708,15 @@ do_paint (MetaShapedTexture *stex,
if (!cairo_region_is_empty (region)) if (!cairo_region_is_empty (region))
{ {
opaque_pipeline = get_unblended_pipeline (stex, ctx); opaque_pipeline = get_unblended_pipeline (stex, ctx);
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); for (i = 0; i < n_planes; i++)
{
CoglTexture *plane = cogl_multi_plane_texture_get_plane (paint_tex, i);
cogl_pipeline_set_layer_texture (opaque_pipeline, i, plane);
cogl_pipeline_set_layer_filters (opaque_pipeline, i, filter, filter);
}
n_rects = cairo_region_num_rectangles (region); n_rects = cairo_region_num_rectangles (region);
for (i = 0; i < n_rects; i++) for (i = 0; i < n_rects; i++)
@@ -714,6 +747,7 @@ do_paint (MetaShapedTexture *stex,
if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region)) if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region))
{ {
CoglPipeline *blended_pipeline; CoglPipeline *blended_pipeline;
guint i;
if (stex->mask_texture == NULL) if (stex->mask_texture == NULL)
{ {
@@ -722,16 +756,20 @@ do_paint (MetaShapedTexture *stex,
else else
{ {
blended_pipeline = get_masked_pipeline (stex, ctx); blended_pipeline = get_masked_pipeline (stex, ctx);
cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture); cogl_pipeline_set_layer_texture (blended_pipeline, n_planes, stex->mask_texture);
cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter); cogl_pipeline_set_layer_filters (blended_pipeline, n_planes, filter, filter);
} }
cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex); for (i = 0; i < n_planes; i++)
cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter); {
CoglTexture *plane = cogl_multi_plane_texture_get_plane (paint_tex, i);
CoglColor color; cogl_pipeline_set_layer_texture (blended_pipeline, i, plane);
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); cogl_pipeline_set_layer_filters (blended_pipeline, i, filter, filter);
cogl_pipeline_set_color (blended_pipeline, &color); }
cogl_pipeline_set_color4ub (blended_pipeline,
opacity, opacity, opacity, opacity);
if (blended_tex_region) if (blended_tex_region)
{ {
@@ -773,7 +811,7 @@ static void
meta_shaped_texture_paint (ClutterActor *actor) meta_shaped_texture_paint (ClutterActor *actor)
{ {
MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor); MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor);
CoglTexture *paint_tex; CoglMultiPlaneTexture *paint_tex;
CoglFramebuffer *fb; CoglFramebuffer *fb;
if (!stex->texture) if (!stex->texture)
@@ -828,11 +866,11 @@ meta_shaped_texture_paint (ClutterActor *actor)
} }
else else
{ {
paint_tex = COGL_TEXTURE (stex->texture); paint_tex = stex->texture;
} }
if (cogl_texture_get_width (paint_tex) == 0 || if (cogl_multi_plane_texture_get_width (paint_tex) == 0 ||
cogl_texture_get_height (paint_tex) == 0) cogl_multi_plane_texture_get_height (paint_tex) == 0)
return; return;
fb = cogl_get_draw_framebuffer (); fb = cogl_get_draw_framebuffer ();
@@ -906,7 +944,7 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
if (create_mipmaps != stex->create_mipmaps) if (create_mipmaps != stex->create_mipmaps)
{ {
CoglTexture *base_texture; CoglMultiPlaneTexture *base_texture;
stex->create_mipmaps = create_mipmaps; stex->create_mipmaps = create_mipmaps;
base_texture = create_mipmaps ? stex->texture : NULL; base_texture = create_mipmaps ? stex->texture : NULL;
meta_texture_tower_set_base_texture (stex->paint_tower, base_texture); meta_texture_tower_set_base_texture (stex->paint_tower, base_texture);
@@ -1089,15 +1127,15 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
/** /**
* meta_shaped_texture_set_texture: * meta_shaped_texture_set_texture:
* @stex: The #MetaShapedTexture * @stex: The #MetaShapedTexture
* @pixmap: The #CoglTexture to display * @pixmap: The #CoglMultiPlaneTexture to display
*/ */
void void
meta_shaped_texture_set_texture (MetaShapedTexture *stex, meta_shaped_texture_set_texture (MetaShapedTexture *stex,
CoglTexture *texture) CoglMultiPlaneTexture *texture)
{ {
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
set_cogl_texture (stex, texture); set_planar_texture (stex, texture);
} }
/** /**
@@ -1127,7 +1165,7 @@ meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
meta_shaped_texture_reset_pipelines (stex); meta_shaped_texture_reset_pipelines (stex);
g_clear_pointer (&stex->snippet, cogl_object_unref); cogl_clear_object (&stex->snippet);
if (snippet) if (snippet)
stex->snippet = cogl_object_ref (snippet); stex->snippet = cogl_object_ref (snippet);
} }
@@ -1138,11 +1176,12 @@ meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
* *
* Returns: (transfer none): the unshaped texture * Returns: (transfer none): the unshaped texture
*/ */
CoglTexture * CoglMultiPlaneTexture *
meta_shaped_texture_get_texture (MetaShapedTexture *stex) meta_shaped_texture_get_texture (MetaShapedTexture *stex)
{ {
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL); g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
return COGL_TEXTURE (stex->texture);
return stex->texture;
} }
/** /**
@@ -1247,7 +1286,15 @@ meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex)
static gboolean static gboolean
should_get_via_offscreen (MetaShapedTexture *stex) should_get_via_offscreen (MetaShapedTexture *stex)
{ {
if (!cogl_texture_is_get_data_supported (stex->texture)) CoglTexture *texture;
/* If we have more than 1 plane, we can't access the data */
if (cogl_multi_plane_texture_get_n_planes (stex->texture) > 1)
return TRUE;
/* We have only 1 plane -> access it directly */
texture = cogl_multi_plane_texture_get_plane (stex->texture, 0);
if (!cogl_texture_is_get_data_supported (texture))
return TRUE; return TRUE;
if (stex->has_viewport_src_rect || stex->has_viewport_dst_size) if (stex->has_viewport_src_rect || stex->has_viewport_dst_size)
@@ -1364,19 +1411,19 @@ get_image_via_offscreen (MetaShapedTexture *stex,
* Returns: (transfer full): a new cairo surface to be freed with * Returns: (transfer full): a new cairo surface to be freed with
* cairo_surface_destroy(). * cairo_surface_destroy().
*/ */
/* XXX Still need to fix this, but apparently only used for screenshot */
cairo_surface_t * cairo_surface_t *
meta_shaped_texture_get_image (MetaShapedTexture *stex, meta_shaped_texture_get_image (MetaShapedTexture *stex,
cairo_rectangle_int_t *clip) cairo_rectangle_int_t *clip)
{ {
cairo_rectangle_int_t *transformed_clip = NULL; cairo_rectangle_int_t *transformed_clip = NULL;
CoglTexture *texture, *mask_texture; CoglTexture *texture;
CoglTexture *mask_texture;
cairo_surface_t *surface; cairo_surface_t *surface;
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL); g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
texture = COGL_TEXTURE (stex->texture); if (stex->texture == NULL)
if (texture == NULL)
return NULL; return NULL;
ensure_size_valid (stex); ensure_size_valid (stex);
@@ -1409,6 +1456,9 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
if (should_get_via_offscreen (stex)) if (should_get_via_offscreen (stex))
return get_image_via_offscreen (stex, transformed_clip); return get_image_via_offscreen (stex, transformed_clip);
/* We know that we only have 1 plane at this point */
texture = cogl_multi_plane_texture_get_plane (stex->texture, 0);
if (transformed_clip) if (transformed_clip)
texture = cogl_texture_new_from_sub_texture (texture, texture = cogl_texture_new_from_sub_texture (texture,
transformed_clip->x, transformed_clip->x,

View File

@@ -45,7 +45,7 @@ struct _MetaSurfaceActorX11
MetaDisplay *display; MetaDisplay *display;
CoglTexture *texture; CoglMultiPlaneTexture *texture;
Pixmap pixmap; Pixmap pixmap;
Damage damage; Damage damage;
@@ -129,8 +129,9 @@ set_pixmap (MetaSurfaceActorX11 *self,
else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
g_warning ("NOTE: Not using GLX TFP!\n"); g_warning ("NOTE: Not using GLX TFP!\n");
self->texture = texture; self->texture = cogl_multi_plane_texture_new_single_plane (_cogl_texture_get_format (texture),
meta_shaped_texture_set_texture (stex, texture); texture);
meta_shaped_texture_set_texture (stex, self->texture);
} }
static void static void
@@ -187,6 +188,7 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height) int x, int y, int width, int height)
{ {
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
CoglTexture *texture;
self->received_damage = TRUE; self->received_damage = TRUE;
@@ -210,7 +212,8 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
if (!is_visible (self)) if (!is_visible (self))
return; return;
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (self->texture), texture = cogl_multi_plane_texture_get_plane (self->texture, 0);
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (texture),
x, y, width, height); x, y, width, height);
} }

View File

@@ -325,7 +325,8 @@ gboolean
meta_surface_actor_is_argb32 (MetaSurfaceActor *self) meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
{ {
MetaShapedTexture *stex = meta_surface_actor_get_texture (self); MetaShapedTexture *stex = meta_surface_actor_get_texture (self);
CoglTexture *texture = meta_shaped_texture_get_texture (stex); CoglMultiPlaneTexture *mtex = meta_shaped_texture_get_texture (stex);
CoglTexture *texture;
/* If we don't have a texture, like during initialization, assume /* If we don't have a texture, like during initialization, assume
* that we're ARGB32. * that we're ARGB32.
@@ -335,14 +336,20 @@ meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
* place. This prevents us from continually redirecting and * place. This prevents us from continually redirecting and
* unredirecting on every paint. * unredirecting on every paint.
*/ */
if (!texture) if (!mtex)
return !meta_surface_actor_is_unredirected (self); return !meta_surface_actor_is_unredirected (self);
/* Are we dealing with multiple planes? Then it can't be argb32 either */
if (cogl_multi_plane_texture_get_n_planes (mtex) != 1)
return FALSE;
texture = cogl_multi_plane_texture_get_plane (mtex, 0);
switch (cogl_texture_get_components (texture)) switch (cogl_texture_get_components (texture))
{ {
case COGL_TEXTURE_COMPONENTS_A: case COGL_TEXTURE_COMPONENTS_A:
case COGL_TEXTURE_COMPONENTS_RGBA: case COGL_TEXTURE_COMPONENTS_RGBA:
return TRUE; return TRUE;
case COGL_TEXTURE_COMPONENTS_R:
case COGL_TEXTURE_COMPONENTS_RG: case COGL_TEXTURE_COMPONENTS_RG:
case COGL_TEXTURE_COMPONENTS_RGB: case COGL_TEXTURE_COMPONENTS_RGB:
case COGL_TEXTURE_COMPONENTS_DEPTH: case COGL_TEXTURE_COMPONENTS_DEPTH:

View File

@@ -58,8 +58,8 @@ typedef struct
struct _MetaTextureTower struct _MetaTextureTower
{ {
int n_levels; int n_levels;
CoglTexture *textures[MAX_TEXTURE_LEVELS]; CoglMultiPlaneTexture *textures[MAX_TEXTURE_LEVELS];
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS]; GList *fbos[MAX_TEXTURE_LEVELS];
Box invalid[MAX_TEXTURE_LEVELS]; Box invalid[MAX_TEXTURE_LEVELS];
CoglPipeline *pipeline_template; CoglPipeline *pipeline_template;
}; };
@@ -112,8 +112,8 @@ meta_texture_tower_free (MetaTextureTower *tower)
* unset or until the tower is freed. * unset or until the tower is freed.
*/ */
void void
meta_texture_tower_set_base_texture (MetaTextureTower *tower, meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglTexture *texture) CoglMultiPlaneTexture *texture)
{ {
int i; int i;
@@ -126,22 +126,14 @@ meta_texture_tower_set_base_texture (MetaTextureTower *tower,
{ {
for (i = 1; i < tower->n_levels; i++) for (i = 1; i < tower->n_levels; i++)
{ {
if (tower->textures[i] != NULL) cogl_clear_object (&tower->textures[i]);
{
cogl_object_unref (tower->textures[i]);
tower->textures[i] = NULL;
}
if (tower->fbos[i] != NULL) g_list_free_full (tower->fbos[i], cogl_object_unref);
{ tower->fbos[i] = NULL;
cogl_object_unref (tower->fbos[i]);
tower->fbos[i] = NULL;
}
} }
cogl_object_unref (tower->textures[0]);
} }
cogl_clear_object (&tower->textures[0]);
tower->textures[0] = texture; tower->textures[0] = texture;
if (tower->textures[0] != NULL) if (tower->textures[0] != NULL)
@@ -150,8 +142,8 @@ meta_texture_tower_set_base_texture (MetaTextureTower *tower,
cogl_object_ref (tower->textures[0]); cogl_object_ref (tower->textures[0]);
width = cogl_texture_get_width (tower->textures[0]); width = cogl_multi_plane_texture_get_width (tower->textures[0]);
height = cogl_texture_get_height (tower->textures[0]); height = cogl_multi_plane_texture_get_height (tower->textures[0]);
tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height))); tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS); tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
@@ -192,8 +184,8 @@ meta_texture_tower_update_area (MetaTextureTower *tower,
if (tower->textures[0] == NULL) if (tower->textures[0] == NULL)
return; return;
texture_width = cogl_texture_get_width (tower->textures[0]); texture_width = cogl_multi_plane_texture_get_width (tower->textures[0]);
texture_height = cogl_texture_get_height (tower->textures[0]); texture_height = cogl_multi_plane_texture_get_height (tower->textures[0]);
invalid.x1 = x; invalid.x1 = x;
invalid.y1 = y; invalid.y1 = y;
@@ -351,9 +343,27 @@ texture_tower_create_texture (MetaTextureTower *tower,
int width, int width,
int height) int height)
{ {
tower->textures[level] = cogl_texture_new_with_size (width, height, CoglMultiPlaneTexture *base_tex = tower->textures[0];
COGL_TEXTURE_NO_AUTO_MIPMAP, GPtrArray *planes;
TEXTURE_FORMAT); uint8_t i, n_planes;
n_planes = cogl_multi_plane_texture_get_n_planes (base_tex);
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
for (i = 0; i < n_planes; i++)
{
CoglTexture *texture;
texture = cogl_texture_new_with_size (width, height,
COGL_TEXTURE_NO_AUTO_MIPMAP,
TEXTURE_FORMAT);
g_ptr_array_add (planes, texture);
}
tower->textures[level] = cogl_multi_plane_texture_new (
cogl_multi_plane_texture_get_format (base_tex),
(CoglTexture **) g_ptr_array_free (planes, FALSE),
n_planes);
tower->invalid[level].x1 = 0; tower->invalid[level].x1 = 0;
tower->invalid[level].y1 = 0; tower->invalid[level].y1 = 0;
@@ -365,51 +375,69 @@ static void
texture_tower_revalidate (MetaTextureTower *tower, texture_tower_revalidate (MetaTextureTower *tower,
int level) int level)
{ {
CoglTexture *source_texture = tower->textures[level - 1]; CoglMultiPlaneTexture *src_tex = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture); int src_width = cogl_multi_plane_texture_get_width (src_tex);
int source_texture_height = cogl_texture_get_height (source_texture); int src_height = cogl_multi_plane_texture_get_height (src_tex);
CoglTexture *dest_texture = tower->textures[level]; uint8_t src_tex_n_planes = cogl_multi_plane_texture_get_n_planes (src_tex);
int dest_texture_width = cogl_texture_get_width (dest_texture); CoglMultiPlaneTexture *dest_tex = tower->textures[level];
int dest_texture_height = cogl_texture_get_height (dest_texture); int dest_width = cogl_multi_plane_texture_get_width (dest_tex);
Box *invalid = &tower->invalid[level]; int dest_height = cogl_multi_plane_texture_get_height (dest_tex);
CoglFramebuffer *fb; uint8_t i;
GError *catch_error = NULL;
CoglPipeline *pipeline;
if (tower->fbos[level] == NULL)
tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);
fb = COGL_FRAMEBUFFER (tower->fbos[level]); /* FIXME: cogl_offscreen_texture_new_with_texture doesn't work for
* multi-plane textures, so we have to make an FBO for each layer */
if (!cogl_framebuffer_allocate (fb, &catch_error)) for (i = 0; i < src_tex_n_planes; i++)
{ {
g_error_free (catch_error); Box *invalid = &tower->invalid[level];
return; CoglTexture *src_plane, *dest_plane;
CoglFramebuffer *fb;
GError *catch_error = NULL;
CoglPipeline *pipeline;
src_plane = cogl_multi_plane_texture_get_plane (src_tex, i);
dest_plane = cogl_multi_plane_texture_get_plane (dest_tex, i);
if (g_list_nth (tower->fbos[level], i) != NULL)
{
fb = COGL_FRAMEBUFFER (g_list_nth (tower->fbos[level], i)->data);
}
else
{
fb = COGL_FRAMEBUFFER (cogl_offscreen_new_with_texture (dest_plane));
tower->fbos[level] = g_list_append (tower->fbos[level], fb);
}
if (!cogl_framebuffer_allocate (fb, &catch_error))
{
g_error_free (catch_error);
return;
}
cogl_framebuffer_orthographic (fb, 0, 0, dest_width, dest_height, -1., 1.);
if (!tower->pipeline_template)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
tower->pipeline_template = cogl_pipeline_new (ctx);
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
}
pipeline = cogl_pipeline_copy (tower->pipeline_template);
cogl_pipeline_set_layer_texture (pipeline, 0, src_plane);
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
invalid->x1, invalid->y1,
invalid->x2, invalid->y2,
(2. * invalid->x1) / src_width,
(2. * invalid->y1) / src_height,
(2. * invalid->x2) / src_width,
(2. * invalid->y2) / src_height);
cogl_object_unref (pipeline);
} }
cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);
if (!tower->pipeline_template)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
tower->pipeline_template = cogl_pipeline_new (ctx);
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
}
pipeline = cogl_pipeline_copy (tower->pipeline_template);
cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
invalid->x1, invalid->y1,
invalid->x2, invalid->y2,
(2. * invalid->x1) / source_texture_width,
(2. * invalid->y1) / source_texture_height,
(2. * invalid->x2) / source_texture_width,
(2. * invalid->y2) / source_texture_height);
cogl_object_unref (pipeline);
tower->invalid[level].x1 = tower->invalid[level].x2 = 0; tower->invalid[level].x1 = tower->invalid[level].x2 = 0;
tower->invalid[level].y1 = tower->invalid[level].y2 = 0; tower->invalid[level].y1 = tower->invalid[level].y2 = 0;
} }
@@ -427,7 +455,7 @@ texture_tower_revalidate (MetaTextureTower *tower,
* Return value: the COGL texture handle to use for painting, or * Return value: the COGL texture handle to use for painting, or
* %NULL if no base texture has yet been set. * %NULL if no base texture has yet been set.
*/ */
CoglTexture * CoglMultiPlaneTexture *
meta_texture_tower_get_paint_texture (MetaTextureTower *tower) meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
{ {
int texture_width, texture_height; int texture_width, texture_height;
@@ -438,8 +466,8 @@ meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
if (tower->textures[0] == NULL) if (tower->textures[0] == NULL)
return NULL; return NULL;
texture_width = cogl_texture_get_width (tower->textures[0]); texture_width = cogl_multi_plane_texture_get_width (tower->textures[0]);
texture_height = cogl_texture_get_height (tower->textures[0]); texture_height = cogl_multi_plane_texture_get_height (tower->textures[0]);
level = get_paint_level(texture_width, texture_height); level = get_paint_level(texture_width, texture_height);
if (level < 0) /* singular paint matrix, scaled to nothing */ if (level < 0) /* singular paint matrix, scaled to nothing */

View File

@@ -53,14 +53,14 @@ typedef struct _MetaTextureTower MetaTextureTower;
MetaTextureTower *meta_texture_tower_new (void); MetaTextureTower *meta_texture_tower_new (void);
void meta_texture_tower_free (MetaTextureTower *tower); void meta_texture_tower_free (MetaTextureTower *tower);
void meta_texture_tower_set_base_texture (MetaTextureTower *tower, void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglTexture *texture); CoglMultiPlaneTexture *texture);
void meta_texture_tower_update_area (MetaTextureTower *tower, void meta_texture_tower_update_area (MetaTextureTower *tower,
int x, int x,
int y, int y,
int width, int width,
int height); int height);
CoglTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower); CoglMultiPlaneTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
G_END_DECLS G_END_DECLS

View File

@@ -1502,7 +1502,8 @@ build_and_scan_frame_mask (MetaWindowActor *self,
guchar *mask_data; guchar *mask_data;
guint tex_width, tex_height; guint tex_width, tex_height;
MetaShapedTexture *stex; MetaShapedTexture *stex;
CoglTexture *paint_tex, *mask_texture; CoglMultiPlaneTexture *paint_tex;
CoglTexture *mask_texture;
int stride; int stride;
cairo_t *cr; cairo_t *cr;
cairo_surface_t *surface; cairo_surface_t *surface;
@@ -1517,8 +1518,8 @@ build_and_scan_frame_mask (MetaWindowActor *self,
if (paint_tex == NULL) if (paint_tex == NULL)
return; return;
tex_width = cogl_texture_get_width (paint_tex); tex_width = cogl_multi_plane_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex); tex_height = cogl_multi_plane_texture_get_height (paint_tex);
stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8, tex_width); stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8, tex_width);

View File

@@ -52,7 +52,7 @@ gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex,
int height); int height);
META_EXPORT META_EXPORT
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex); CoglMultiPlaneTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
META_EXPORT META_EXPORT
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,

View File

@@ -123,7 +123,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
stream = meta_wayland_egl_stream_new (buffer, NULL); stream = meta_wayland_egl_stream_new (buffer, NULL);
if (stream) if (stream)
{ {
CoglTexture2D *texture; CoglMultiPlaneTexture *texture;
texture = meta_wayland_egl_stream_create_texture (stream, NULL); texture = meta_wayland_egl_stream_create_texture (stream, NULL);
if (!texture) if (!texture)
@@ -131,7 +131,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
buffer->egl_stream.stream = stream; buffer->egl_stream.stream = stream;
buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_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); buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);
return TRUE; return TRUE;
@@ -163,43 +163,78 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
CoglTextureComponents *components_out) CoglTextureComponents *components_out)
{ {
CoglPixelFormat format; CoglPixelFormat format;
CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA;
switch (wl_shm_buffer_get_format (shm_buffer)) switch (wl_shm_buffer_get_format (shm_buffer))
{ {
#if G_BYTE_ORDER == G_BIG_ENDIAN #if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888: case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
break; break;
case WL_SHM_FORMAT_XRGB8888: case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888; format = COGL_PIXEL_FORMAT_ARGB_8888;
components = COGL_TEXTURE_COMPONENTS_RGB; components_out[0] = COGL_TEXTURE_COMPONENTS_RGB;
break; break;
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN #elif G_BYTE_ORDER == G_LITTLE_ENDIAN
case WL_SHM_FORMAT_ARGB8888: case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
break; break;
case WL_SHM_FORMAT_XRGB8888: case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888; format = COGL_PIXEL_FORMAT_BGRA_8888;
components = COGL_TEXTURE_COMPONENTS_RGB; components_out[0] = COGL_TEXTURE_COMPONENTS_RGB;
break; break;
#endif #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: default:
g_warn_if_reached (); g_warn_if_reached ();
format = COGL_PIXEL_FORMAT_ARGB_8888; format = COGL_PIXEL_FORMAT_ARGB_8888;
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
} }
if (format_out) if (format_out)
*format_out = format; *format_out = format;
if (components_out)
*components_out = components;
} }
static gboolean static gboolean
shm_buffer_attach (MetaWaylandBuffer *buffer, shm_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture, CoglMultiPlaneTexture **texture,
gboolean *changed_texture, gboolean *changed_texture,
GError **error) GError **error)
{ {
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (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; struct wl_shm_buffer *shm_buffer;
int stride, width, height; int stride, width, height;
CoglPixelFormat format; CoglPixelFormat format;
CoglTextureComponents components; CoglTextureComponents components[3];
CoglBitmap *bitmap; guint i, n_planes;
CoglTexture *new_texture; 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); shm_buffer = wl_shm_buffer_get (buffer->resource);
stride = wl_shm_buffer_get_stride (shm_buffer); stride = wl_shm_buffer_get_stride (shm_buffer);
width = wl_shm_buffer_get_width (shm_buffer); width = wl_shm_buffer_get_width (shm_buffer);
height = wl_shm_buffer_get_height (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 && if (*texture &&
cogl_texture_get_width (*texture) == width && cogl_multi_plane_texture_get_width (*texture) == width &&
cogl_texture_get_height (*texture) == height && cogl_multi_plane_texture_get_height (*texture) == height &&
cogl_texture_get_components (*texture) == components && /*XXX cogl_texture_get_components (*texture) == components && */
_cogl_texture_get_format (*texture) == format) cogl_multi_plane_texture_get_format (*texture) == format)
{ {
buffer->is_y_inverted = TRUE; buffer->is_y_inverted = TRUE;
*changed_texture = FALSE; *changed_texture = FALSE;
@@ -230,56 +274,92 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
cogl_clear_object (texture); cogl_clear_object (texture);
/* Safely access the data inside the buffer */
wl_shm_buffer_begin_access (shm_buffer); wl_shm_buffer_begin_access (shm_buffer);
data = wl_shm_buffer_get_data (shm_buffer);
bitmap = cogl_bitmap_new_for_data (cogl_context, planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
width, height, for (i = 0; i < n_planes; i++)
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))
{ {
g_clear_pointer (&new_texture, cogl_object_unref); int plane_stride;
if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE)) 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; 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); g_clear_error (error);
texture_sliced = texture_sliced =
cogl_texture_2d_sliced_new_from_bitmap (bitmap, cogl_texture_2d_sliced_new_from_bitmap (plane_bitmap,
COGL_TEXTURE_MAX_WASTE); COGL_TEXTURE_MAX_WASTE);
new_texture = COGL_TEXTURE (texture_sliced); plane_texture = COGL_TEXTURE (texture_sliced);
cogl_texture_set_components (new_texture, components);
if (!cogl_texture_allocate (new_texture, error)) cogl_texture_set_components (plane_texture, components[i]);
g_clear_pointer (&new_texture, cogl_object_unref);
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); wl_shm_buffer_end_access (shm_buffer);
if (!new_texture)
return FALSE;
*texture = new_texture;
*changed_texture = TRUE; *changed_texture = TRUE;
buffer->is_y_inverted = TRUE; buffer->is_y_inverted = TRUE;
return TRUE; return TRUE;
failure:
*texture = NULL;
return FALSE;
} }
static gboolean static gboolean
egl_image_buffer_attach (MetaWaylandBuffer *buffer, egl_image_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture, CoglMultiPlaneTexture **texture,
gboolean *changed_texture, gboolean *changed_texture,
GError **error) GError **error)
{ {
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaEgl *egl = meta_backend_get_egl (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); EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
int format, width, height, y_inverted; int format, width, height, y_inverted;
CoglPixelFormat cogl_format; CoglPixelFormat cogl_format;
EGLImageKHR egl_image; CoglTextureComponents components[3];
CoglTexture2D *texture_2d; guint i, n_planes;
GPtrArray *planes;
if (buffer->egl_image.texture) if (buffer->egl_image.texture)
{ {
@@ -299,6 +380,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
return TRUE; return TRUE;
} }
/* Query the necessary properties */
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource, if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
EGL_TEXTURE_FORMAT, &format, EGL_TEXTURE_FORMAT, &format,
error)) error))
@@ -319,6 +401,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
NULL)) NULL))
y_inverted = EGL_TRUE; y_inverted = EGL_TRUE;
/* Map the EGL texture format to CoglPixelFormat, if possible */
switch (format) switch (format)
{ {
case EGL_TEXTURE_RGB: case EGL_TEXTURE_RGB:
@@ -327,6 +410,12 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
case EGL_TEXTURE_RGBA: case EGL_TEXTURE_RGBA:
cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
break; 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: default:
g_set_error (error, G_IO_ERROR, g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED, G_IO_ERROR_FAILED,
@@ -334,27 +423,51 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
return FALSE; return FALSE;
} }
/* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used n_planes = cogl_pixel_format_get_n_planes (cogl_format);
* in conjunction with the EGL_WAYLAND_BUFFER_WL target. */ cogl_pixel_format_get_cogl_components (cogl_format, components);
egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT, planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
EGL_WAYLAND_BUFFER_WL, buffer->resource,
NULL,
error);
if (egl_image == EGL_NO_IMAGE_KHR)
return FALSE;
texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context, /* Each EGLImage is a plane in the final texture */
width, height, for (i = 0; i < n_planes; i++)
cogl_format, {
egl_image, EGLint egl_attribs[3];
error); 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) /* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be
return FALSE; * 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; buffer->is_y_inverted = !!y_inverted;
cogl_clear_object (texture); cogl_clear_object (texture);
@@ -362,14 +475,19 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
*changed_texture = TRUE; *changed_texture = TRUE;
return TRUE; return TRUE;
on_error:
g_ptr_array_free (planes, TRUE);
return FALSE;
} }
#ifdef HAVE_WAYLAND_EGLSTREAM #ifdef HAVE_WAYLAND_EGLSTREAM
static gboolean static gboolean
egl_stream_buffer_attach (MetaWaylandBuffer *buffer, egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture, CoglMultiPlaneTexture **texture,
gboolean *changed_texture, gboolean *changed_texture,
GError **error) GError **error)
{ {
MetaWaylandEglStream *stream = buffer->egl_stream.stream; 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. * meta_wayland_buffer_attach(), which also might free it, as described above.
*/ */
gboolean gboolean
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture, CoglMultiPlaneTexture **texture,
gboolean *changed_texture, gboolean *changed_texture,
GError **error) GError **error)
{ {
g_return_val_if_fail (buffer->resource, FALSE); g_return_val_if_fail (buffer->resource, FALSE);
@@ -466,55 +584,94 @@ meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer)
} }
static gboolean static gboolean
process_shm_buffer_damage (MetaWaylandBuffer *buffer, process_shm_buffer_damage (MetaWaylandBuffer *buffer,
CoglTexture *texture, CoglMultiPlaneTexture *texture,
cairo_region_t *region, cairo_region_t *region,
GError **error) GError **error)
{ {
struct wl_shm_buffer *shm_buffer; struct wl_shm_buffer *shm_buffer;
int i, n_rectangles;
gboolean set_texture_failed = FALSE; 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); n_rectangles = cairo_region_num_rectangles (region);
shm_buffer = wl_shm_buffer_get (buffer->resource); shm_buffer = wl_shm_buffer_get (buffer->resource);
/* Get the data */
wl_shm_buffer_begin_access (shm_buffer); 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); CoglTexture *plane;
int32_t stride = wl_shm_buffer_get_stride (shm_buffer); int plane_stride;
CoglPixelFormat format;
int bpp;
cairo_rectangle_int_t rect;
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL); plane = cogl_multi_plane_texture_get_plane (texture, i);
bpp = _cogl_pixel_format_get_bytes_per_pixel (format); plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i];
cairo_region_get_rectangle (region, i, &rect);
if (!_cogl_texture_set_region (texture, for (j = 0; j < n_rectangles; j++)
rect.width, rect.height,
format,
stride,
data + rect.x * bpp + rect.y * stride,
rect.x, rect.y,
0,
error))
{ {
set_texture_failed = TRUE; cairo_rectangle_int_t rect;
break; 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); wl_shm_buffer_end_access (shm_buffer);
return !set_texture_failed; return !set_texture_failed;
} }
void void
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
CoglTexture *texture, CoglMultiPlaneTexture *texture,
cairo_region_t *region) cairo_region_t *region)
{ {
gboolean res = FALSE; gboolean res = FALSE;
GError *error = NULL; GError *error = NULL;

View File

@@ -56,19 +56,19 @@ struct _MetaWaylandBuffer
MetaWaylandBufferType type; MetaWaylandBufferType type;
struct { struct {
CoglTexture *texture; CoglMultiPlaneTexture *texture;
} egl_image; } egl_image;
#ifdef HAVE_WAYLAND_EGLSTREAM #ifdef HAVE_WAYLAND_EGLSTREAM
struct { struct {
MetaWaylandEglStream *stream; MetaWaylandEglStream *stream;
CoglTexture *texture; CoglMultiPlaneTexture *texture;
} egl_stream; } egl_stream;
#endif #endif
struct { struct {
MetaWaylandDmaBufBuffer *dma_buf; MetaWaylandDmaBufBuffer *dma_buf;
CoglTexture *texture; CoglMultiPlaneTexture *texture;
} dma_buf; } dma_buf;
}; };
@@ -80,14 +80,14 @@ MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resou
struct wl_resource * meta_wayland_buffer_get_resource (MetaWaylandBuffer *buffer); struct wl_resource * meta_wayland_buffer_get_resource (MetaWaylandBuffer *buffer);
gboolean meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer);
gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer);
gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture, CoglMultiPlaneTexture **texture,
gboolean *changed_texture, gboolean *changed_texture,
GError **error); GError **error);
CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer); CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer);
gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
CoglTexture *texture, CoglMultiPlaneTexture *texture,
cairo_region_t *region); cairo_region_t *region);
#endif /* META_WAYLAND_BUFFER_H */ #endif /* META_WAYLAND_BUFFER_H */

View File

@@ -58,7 +58,7 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface)
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_surface)); meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_surface));
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (priv->cursor_sprite); MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (priv->cursor_sprite);
CoglTexture *texture; CoglMultiPlaneTexture *texture;
if (!priv->cursor_renderer) if (!priv->cursor_renderer)
return; return;
@@ -66,8 +66,13 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface)
texture = meta_wayland_surface_get_texture (surface); texture = meta_wayland_surface_get_texture (surface);
if (texture) if (texture)
{ {
CoglTexture *plane;
/* XXX We assume that we get a simple (single-plane) texture here */
plane = cogl_multi_plane_texture_get_plane (texture, 0);
meta_cursor_sprite_set_texture (cursor_sprite, meta_cursor_sprite_set_texture (cursor_sprite,
texture, plane,
priv->hot_x * surface->scale, priv->hot_x * surface->scale,
priv->hot_y * surface->scale); priv->hot_y * surface->scale);
} }

View File

@@ -56,8 +56,9 @@ struct _MetaWaylandDmaBufBuffer
int width; int width;
int height; int height;
uint32_t drm_format; uint32_t drm_format;
uint64_t drm_modifier;
bool is_y_inverted; bool is_y_inverted;
uint64_t drm_modifier[META_WAYLAND_DMA_BUF_MAX_FDS];
int fds[META_WAYLAND_DMA_BUF_MAX_FDS]; int fds[META_WAYLAND_DMA_BUF_MAX_FDS];
int offsets[META_WAYLAND_DMA_BUF_MAX_FDS]; int offsets[META_WAYLAND_DMA_BUF_MAX_FDS];
unsigned int strides[META_WAYLAND_DMA_BUF_MAX_FDS]; unsigned int strides[META_WAYLAND_DMA_BUF_MAX_FDS];
@@ -65,6 +66,139 @@ struct _MetaWaylandDmaBufBuffer
G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJECT); G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJECT);
static CoglPixelFormat
drm_buffer_get_cogl_pixel_format (MetaWaylandDmaBufBuffer *dma_buf)
{
switch (dma_buf->drm_format)
{
/*
* NOTE: The cogl_format here is only used for texture color channel
* swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used
* for accessing the buffer memory. EGL will access the buffer
* memory according to the DRM fourcc code. Cogl will not mmap
* and access the buffer memory at all.
*/
case DRM_FORMAT_XRGB8888:
return COGL_PIXEL_FORMAT_RGB_888;
case DRM_FORMAT_ARGB8888:
return COGL_PIXEL_FORMAT_ARGB_8888_PRE;
case DRM_FORMAT_ARGB2101010:
return COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
case DRM_FORMAT_RGB565:
return COGL_PIXEL_FORMAT_RGB_565;
case DRM_FORMAT_YUYV:
return COGL_PIXEL_FORMAT_YUYV;
case DRM_FORMAT_NV12:
return COGL_PIXEL_FORMAT_NV12;
case DRM_FORMAT_NV21:
return COGL_PIXEL_FORMAT_NV21;
case DRM_FORMAT_YUV410:
return COGL_PIXEL_FORMAT_YUV410;
case DRM_FORMAT_YVU410:
return COGL_PIXEL_FORMAT_YVU410;
case DRM_FORMAT_YUV411:
return COGL_PIXEL_FORMAT_YUV411;
case DRM_FORMAT_YVU411:
return COGL_PIXEL_FORMAT_YVU411;
case DRM_FORMAT_YUV420:
return COGL_PIXEL_FORMAT_YUV420;
case DRM_FORMAT_YVU420:
return COGL_PIXEL_FORMAT_YVU420;
case DRM_FORMAT_YUV422:
return COGL_PIXEL_FORMAT_YUV422;
case DRM_FORMAT_YVU422:
return COGL_PIXEL_FORMAT_YVU422;
case DRM_FORMAT_YUV444:
return COGL_PIXEL_FORMAT_YUV444;
case DRM_FORMAT_YVU444:
return COGL_PIXEL_FORMAT_YVU444;
default:
return COGL_PIXEL_FORMAT_ANY;
}
}
static EGLImageKHR
create_egl_image_from_dmabuf (MetaEgl *egl,
EGLDisplay egl_display,
MetaWaylandDmaBufBuffer *dma_buf,
int32_t width,
int32_t height,
uint32_t drm_format,
GError **error)
{
EGLint attribs[64];
int attr_idx = 0;
attribs[attr_idx++] = EGL_WIDTH;
attribs[attr_idx++] = width;
attribs[attr_idx++] = EGL_HEIGHT;
attribs[attr_idx++] = height;
attribs[attr_idx++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[attr_idx++] = drm_format;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_FD_EXT;
attribs[attr_idx++] = dma_buf->fds[0];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
attribs[attr_idx++] = dma_buf->offsets[0];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attribs[attr_idx++] = dma_buf->strides[0];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier[0] & 0xffffffff;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier[0] >> 32;
if (dma_buf->fds[1] >= 0)
{
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_FD_EXT;
attribs[attr_idx++] = dma_buf->fds[1];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
attribs[attr_idx++] = dma_buf->offsets[1];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
attribs[attr_idx++] = dma_buf->strides[1];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier[1] & 0xffffffff;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier[1] >> 32;
}
if (dma_buf->fds[2] >= 0)
{
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_FD_EXT;
attribs[attr_idx++] = dma_buf->fds[2];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
attribs[attr_idx++] = dma_buf->offsets[2];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
attribs[attr_idx++] = dma_buf->strides[2];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier[2] & 0xffffffff;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier[2] >> 32;
}
if (dma_buf->fds[3] >= 0)
{
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_FD_EXT;
attribs[attr_idx++] = dma_buf->fds[3];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
attribs[attr_idx++] = dma_buf->offsets[3];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
attribs[attr_idx++] = dma_buf->strides[3];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier[3] & 0xffffffff;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier[3] >> 32;
}
attribs[attr_idx++] = EGL_NONE;
/* The EXT_image_dma_buf_import spec states that EGL_NO_CONTEXT is to be
* used in conjunction with the EGL_LINUX_DMA_BUF_EXT target. Similarly,
* the native buffer is named in the attribs. */
return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT, NULL, attribs,
error);
}
static gboolean static gboolean
meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
GError **error) GError **error)
@@ -76,137 +210,75 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
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;
CoglPixelFormat cogl_format; CoglPixelFormat cogl_format;
EGLImageKHR egl_image; CoglTextureComponents components[3];
CoglTexture2D *texture; CoglPixelFormat subformats[3];
EGLint attribs[64]; GPtrArray *planes;
int attr_idx = 0; guint i = 0, n_planes = 1;
if (buffer->dma_buf.texture) if (buffer->dma_buf.texture)
return TRUE; return TRUE;
switch (dma_buf->drm_format) cogl_format = drm_buffer_get_cogl_pixel_format (dma_buf);
if (cogl_format == COGL_PIXEL_FORMAT_ANY)
{ {
/* g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
* NOTE: The cogl_format here is only used for texture color channel
* swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used
* for accessing the buffer memory. EGL will access the buffer
* memory according to the DRM fourcc code. Cogl will not mmap
* and access the buffer memory at all.
*/
case DRM_FORMAT_XRGB8888:
cogl_format = COGL_PIXEL_FORMAT_RGB_888;
break;
case DRM_FORMAT_ARGB8888:
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
break;
case DRM_FORMAT_ARGB2101010:
cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
break;
case DRM_FORMAT_RGB565:
cogl_format = COGL_PIXEL_FORMAT_RGB_565;
break;
default:
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Unsupported buffer format %d", dma_buf->drm_format); "Unsupported buffer format %d", dma_buf->drm_format);
return FALSE; return FALSE;
} }
attribs[attr_idx++] = EGL_WIDTH; n_planes = cogl_pixel_format_get_n_planes (cogl_format);
attribs[attr_idx++] = dma_buf->width; cogl_pixel_format_get_subformats (cogl_format, subformats);
attribs[attr_idx++] = EGL_HEIGHT; cogl_pixel_format_get_cogl_components (cogl_format, components);
attribs[attr_idx++] = dma_buf->height; planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
attribs[attr_idx++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[attr_idx++] = dma_buf->drm_format;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_FD_EXT; /* Each EGLImage is a plane in the final CoglMultiPlaneTexture */
attribs[attr_idx++] = dma_buf->fds[0]; for (i = 0; i < n_planes; i++)
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
attribs[attr_idx++] = dma_buf->offsets[0];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attribs[attr_idx++] = dma_buf->strides[0];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier & 0xffffffff;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier >> 32;
if (dma_buf->fds[1] >= 0)
{ {
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_FD_EXT; EGLImageKHR egl_img;
attribs[attr_idx++] = dma_buf->fds[1]; CoglTexture2D *plane;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
attribs[attr_idx++] = dma_buf->offsets[1]; egl_img = create_egl_image_from_dmabuf (egl,
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; egl_display,
attribs[attr_idx++] = dma_buf->strides[1]; dma_buf,
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT; dma_buf->width, dma_buf->height,
attribs[attr_idx++] = dma_buf->drm_modifier & 0xffffffff; dma_buf->drm_format,
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT; error);
attribs[attr_idx++] = dma_buf->drm_modifier >> 32; if (egl_img == EGL_NO_IMAGE_KHR)
goto on_error;
plane = cogl_egl_texture_2d_new_from_image (cogl_context,
dma_buf->width,
dma_buf->height,
subformats[i],
components[i],
egl_img,
error);
meta_egl_destroy_image (egl, egl_display, egl_img, NULL);
if (!plane)
goto on_error;
g_ptr_array_add (planes, plane);
} }
if (dma_buf->fds[2] >= 0) buffer->dma_buf.texture = cogl_multi_plane_texture_new (cogl_format,
{ (CoglTexture **) g_ptr_array_free (planes, FALSE),
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_FD_EXT; n_planes);
attribs[attr_idx++] = dma_buf->fds[2];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
attribs[attr_idx++] = dma_buf->offsets[2];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
attribs[attr_idx++] = dma_buf->strides[2];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier & 0xffffffff;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier >> 32;
}
if (dma_buf->fds[3] >= 0)
{
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_FD_EXT;
attribs[attr_idx++] = dma_buf->fds[3];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
attribs[attr_idx++] = dma_buf->offsets[3];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
attribs[attr_idx++] = dma_buf->strides[3];
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier & 0xffffffff;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier >> 32;
}
attribs[attr_idx++] = EGL_NONE;
attribs[attr_idx++] = EGL_NONE;
/* The EXT_image_dma_buf_import spec states that EGL_NO_CONTEXT is to be used
* in conjunction with the EGL_LINUX_DMA_BUF_EXT target. Similarly, the
* native buffer is named in the attribs. */
egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT, NULL, attribs,
error);
if (egl_image == EGL_NO_IMAGE_KHR)
return FALSE;
texture = cogl_egl_texture_2d_new_from_image (cogl_context,
dma_buf->width,
dma_buf->height,
cogl_format,
egl_image,
error);
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
if (!texture)
return FALSE;
buffer->dma_buf.texture = COGL_TEXTURE (texture);
buffer->is_y_inverted = dma_buf->is_y_inverted; buffer->is_y_inverted = dma_buf->is_y_inverted;
return TRUE; return TRUE;
on_error:
g_ptr_array_free (planes, TRUE);
return FALSE;
} }
gboolean gboolean
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture, CoglMultiPlaneTexture **texture,
gboolean *changed_texture, gboolean *changed_texture,
GError **error) GError **error)
{ {
if (!meta_wayland_dma_buf_realize_texture (buffer, error)) if (!meta_wayland_dma_buf_realize_texture (buffer, error))
return FALSE; return FALSE;
@@ -260,8 +332,8 @@ buffer_params_add (struct wl_client *client,
return; return;
} }
if (dma_buf->drm_modifier != DRM_FORMAT_MOD_INVALID && if (dma_buf->drm_modifier[plane_idx] != DRM_FORMAT_MOD_INVALID &&
dma_buf->drm_modifier != drm_modifier) dma_buf->drm_modifier[plane_idx] != drm_modifier)
{ {
wl_resource_post_error (resource, wl_resource_post_error (resource,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER,
@@ -269,8 +341,9 @@ buffer_params_add (struct wl_client *client,
return; return;
} }
dma_buf->drm_modifier = drm_modifier;
dma_buf->fds[plane_idx] = fd; dma_buf->fds[plane_idx] = fd;
dma_buf->drm_modifier[plane_idx] = drm_modifier;
dma_buf->offsets[plane_idx] = offset; dma_buf->offsets[plane_idx] = offset;
dma_buf->strides[plane_idx] = stride; dma_buf->strides[plane_idx] = stride;
} }
@@ -550,6 +623,9 @@ dma_buf_bind (struct wl_client *client,
send_modifiers (resource, DRM_FORMAT_XRGB8888); send_modifiers (resource, DRM_FORMAT_XRGB8888);
send_modifiers (resource, DRM_FORMAT_ARGB2101010); send_modifiers (resource, DRM_FORMAT_ARGB2101010);
send_modifiers (resource, DRM_FORMAT_RGB565); send_modifiers (resource, DRM_FORMAT_RGB565);
send_modifiers (resource, DRM_FORMAT_AYUV);
send_modifiers (resource, DRM_FORMAT_NV12);
send_modifiers (resource, DRM_FORMAT_YUV422);
} }
gboolean gboolean
@@ -598,10 +674,12 @@ meta_wayland_dma_buf_buffer_init (MetaWaylandDmaBufBuffer *dma_buf)
{ {
int i; int i;
dma_buf->drm_modifier = DRM_FORMAT_MOD_INVALID;
for (i = 0; i < META_WAYLAND_DMA_BUF_MAX_FDS; i++) for (i = 0; i < META_WAYLAND_DMA_BUF_MAX_FDS; i++)
dma_buf->fds[i] = -1; {
dma_buf->drm_modifier[i] = DRM_FORMAT_MOD_INVALID;
dma_buf->fds[i] = -1;
}
} }
static void static void

View File

@@ -42,10 +42,10 @@ typedef struct _MetaWaylandDmaBufBuffer MetaWaylandDmaBufBuffer;
gboolean meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor); gboolean meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor);
gboolean gboolean
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture, CoglMultiPlaneTexture **texture,
gboolean *changed_texture, gboolean *changed_texture,
GError **error); GError **error);
MetaWaylandDmaBufBuffer * MetaWaylandDmaBufBuffer *
meta_wayland_dma_buf_from_buffer (MetaWaylandBuffer *buffer); meta_wayland_dma_buf_from_buffer (MetaWaylandBuffer *buffer);

View File

@@ -132,7 +132,7 @@ struct _MetaWaylandEglStream
EGLStreamKHR egl_stream; EGLStreamKHR egl_stream;
MetaWaylandBuffer *buffer; MetaWaylandBuffer *buffer;
CoglTexture2D *texture; CoglMultiPlaneTexture *texture;
gboolean is_y_inverted; gboolean is_y_inverted;
}; };
@@ -183,7 +183,7 @@ stream_texture_destroyed (gpointer data)
} }
static gboolean static gboolean
alloc_egl_stream_texture (CoglTexture2D *texture, alloc_egl_stream_texture (CoglTexture2D *texture_2d,
gpointer user_data, gpointer user_data,
GError **error) GError **error)
{ {
@@ -199,7 +199,7 @@ alloc_egl_stream_texture (CoglTexture2D *texture,
error); error);
} }
CoglTexture2D * CoglMultiPlaneTexture *
meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
GError **error) GError **error)
{ {
@@ -208,7 +208,7 @@ meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
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);
CoglTexture2D *texture; CoglTexture2D *texture_2d;
int width, height; int width, height;
int y_inverted; int y_inverted;
@@ -230,29 +230,30 @@ meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
NULL)) NULL))
y_inverted = EGL_TRUE; y_inverted = EGL_TRUE;
texture = texture_2d =
cogl_texture_2d_new_from_egl_image_external (cogl_context, cogl_texture_2d_new_from_egl_image_external (cogl_context,
width, height, width, height,
alloc_egl_stream_texture, alloc_egl_stream_texture,
g_object_ref (stream), g_object_ref (stream),
stream_texture_destroyed, stream_texture_destroyed,
error); error);
if (!texture) if (!texture_2d)
{ {
g_object_unref (stream); g_object_unref (stream);
return NULL; return NULL;
} }
if (!cogl_texture_allocate (COGL_TEXTURE (texture), error)) if (!cogl_texture_allocate (COGL_TEXTURE (texture_2d), error))
{ {
cogl_object_unref (texture); cogl_object_unref (texture_2d);
return NULL; return NULL;
} }
stream->texture = texture; stream->texture = cogl_multi_plane_texture_new_single_plane (COGL_PIXEL_FORMAT_ANY,
COGL_TEXTURE (texture_2d));
stream->is_y_inverted = !!y_inverted; stream->is_y_inverted = !!y_inverted;
return texture; return stream->texture;
} }
gboolean gboolean

View File

@@ -45,8 +45,8 @@ MetaWaylandEglStream * meta_wayland_egl_stream_new (MetaWaylandBuffer *buffer,
gboolean meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream, gboolean meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream,
GError **error); GError **error);
CoglTexture2D * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, CoglMultiPlaneTexture * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
GError **error); GError **error);
CoglSnippet * meta_wayland_egl_stream_create_snippet (void); CoglSnippet * meta_wayland_egl_stream_create_snippet (void);
gboolean meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream); gboolean meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream);

View File

@@ -153,7 +153,7 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role
MetaWaylandSurfaceRoleClass *surface_role_class; MetaWaylandSurfaceRoleClass *surface_role_class;
MetaWindow *window; MetaWindow *window;
MetaWaylandBuffer *buffer; MetaWaylandBuffer *buffer;
CoglTexture *texture; CoglMultiPlaneTexture *texture;
double scale; double scale;
surface_role_class = surface_role_class =
@@ -171,8 +171,8 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role
scale = meta_wayland_actor_surface_calculate_scale (actor_surface); scale = meta_wayland_actor_surface_calculate_scale (actor_surface);
texture = meta_wayland_surface_get_texture (surface); texture = meta_wayland_surface_get_texture (surface);
window->buffer_rect.width = cogl_texture_get_width (texture) * scale; window->buffer_rect.width = cogl_multi_plane_texture_get_width (texture) * scale;
window->buffer_rect.height = cogl_texture_get_height (texture) * scale; window->buffer_rect.height = cogl_multi_plane_texture_get_height (texture) * scale;
} }
static void static void

View File

@@ -246,7 +246,7 @@ get_buffer_width (MetaWaylandSurface *surface)
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
if (buffer) if (buffer)
return cogl_texture_get_width (surface->texture); return cogl_multi_plane_texture_get_width (surface->texture);
else else
return 0; return 0;
} }
@@ -257,7 +257,7 @@ get_buffer_height (MetaWaylandSurface *surface)
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
if (buffer) if (buffer)
return cogl_texture_get_height (surface->texture); return cogl_multi_plane_texture_get_height (surface->texture);
else else
return 0; return 0;
} }
@@ -721,7 +721,7 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
if (changed_texture && meta_wayland_surface_get_actor (surface)) if (changed_texture && meta_wayland_surface_get_actor (surface))
{ {
MetaShapedTexture *stex; MetaShapedTexture *stex;
CoglTexture *texture; CoglMultiPlaneTexture *texture;
CoglSnippet *snippet; CoglSnippet *snippet;
gboolean is_y_inverted; gboolean is_y_inverted;
@@ -1846,7 +1846,7 @@ meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface,
return g_hash_table_contains (surface->shortcut_inhibited_seats, seat); return g_hash_table_contains (surface->shortcut_inhibited_seats, seat);
} }
CoglTexture * CoglMultiPlaneTexture *
meta_wayland_surface_get_texture (MetaWaylandSurface *surface) meta_wayland_surface_get_texture (MetaWaylandSurface *surface)
{ {
return surface->texture; return surface->texture;

View File

@@ -149,7 +149,7 @@ struct _MetaWaylandSurface
GHashTable *outputs_to_destroy_notify_id; GHashTable *outputs_to_destroy_notify_id;
MetaMonitorTransform buffer_transform; MetaMonitorTransform buffer_transform;
CoglTexture *texture; CoglMultiPlaneTexture *texture;
/* Buffer reference state. */ /* Buffer reference state. */
struct { struct {
@@ -319,7 +319,7 @@ void meta_wayland_surface_restore_shortcuts (MetaWaylandSurface *
gboolean meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, gboolean meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface,
MetaWaylandSeat *seat); MetaWaylandSeat *seat);
CoglTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface); CoglMultiPlaneTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface);
MetaSurfaceActor * meta_wayland_surface_get_actor (MetaWaylandSurface *surface); MetaSurfaceActor * meta_wayland_surface_get_actor (MetaWaylandSurface *surface);

View File

@@ -305,6 +305,26 @@ meta_wayland_log_func (const char *fmt,
g_free (str); g_free (str);
} }
static void
add_supported_shm_formats (struct wl_display *display)
{
guint i;
/* Note that a Wayland compositor should support WL_SHM_FORMAT_ARGB8888 and
* WL_SHM_FORMAT_XRGB8888 by default, so no need to add it here. */
static const guint32 SUPPORTED_FORMATS[] = {
WL_SHM_FORMAT_NV12,
WL_SHM_FORMAT_NV21,
WL_SHM_FORMAT_YUV422,
WL_SHM_FORMAT_YUV444,
};
for (i = 0; i < G_N_ELEMENTS (SUPPORTED_FORMATS); i++)
{
wl_display_add_shm_format (display, SUPPORTED_FORMATS[i]);
}
}
static void static void
meta_wayland_compositor_init (MetaWaylandCompositor *compositor) meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
{ {
@@ -317,6 +337,8 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
compositor->wayland_display = wl_display_create (); compositor->wayland_display = wl_display_create ();
if (compositor->wayland_display == NULL) if (compositor->wayland_display == NULL)
g_error ("Failed to create the global wl_display"); g_error ("Failed to create the global wl_display");
add_supported_shm_formats (compositor->wayland_display);
} }
static void static void