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] =
cogl_texture_new_from_file (file,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_G_8,
COGL_PIXEL_FORMAT_R_8,
NULL);
g_free (file);

View File

@@ -937,12 +937,12 @@ cogl_atlas_texture_new_from_data (CoglContext *ctx,
CoglBitmap *bmp;
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);
/* Rowstride from width if not given */
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 */
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
can use 1024x1024, otherwise we'll assume it will take 4 bytes
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;
else
size = 512;
@@ -291,7 +291,9 @@ _cogl_atlas_create_texture (CoglAtlas *atlas,
{
uint8_t *clear_data;
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 */
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_24_STENCIL_8:
case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
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 ();
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_RGBA_4444:
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_BGR_888:
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
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,
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)
{
component_type v = UNPACK_BYTE (src[0]);
dst[0] = v;
dst[1] = v;
dst[2] = v;
dst[3] = UNPACK_BYTE (255);
dst[0] = UNPACK_BYTE (*src);
dst[1] = 0;
dst[2] = 0;
dst[3] = 0;
dst += 4;
src++;
}
@@ -341,8 +336,8 @@ G_PASTE (_cogl_unpack_, component_size) (CoglPixelFormat format,
case COGL_PIXEL_FORMAT_A_8:
G_PASTE (_cogl_unpack_a_8_, component_size) (src, dst, width);
break;
case COGL_PIXEL_FORMAT_G_8:
G_PASTE (_cogl_unpack_g_8_, component_size) (src, dst, width);
case COGL_PIXEL_FORMAT_R_8:
G_PASTE (_cogl_unpack_r_8_, component_size) (src, dst, width);
break;
case COGL_PIXEL_FORMAT_RG_88:
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_24_STENCIL_8:
case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
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 ();
}
}
@@ -433,18 +458,13 @@ G_PASTE (_cogl_pack_a_8_, component_size) (const component_type *src,
}
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,
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)
{
component_type v = (src[0] + src[1] + src[2]) / 3;
*dst = PACK_BYTE (v);
*dst = PACK_BYTE (src[0]);
src += 4;
dst++;
}
@@ -702,8 +722,8 @@ G_PASTE (_cogl_pack_, component_size) (CoglPixelFormat format,
case COGL_PIXEL_FORMAT_A_8:
G_PASTE (_cogl_pack_a_8_, component_size) (src, dst, width);
break;
case COGL_PIXEL_FORMAT_G_8:
G_PASTE (_cogl_pack_g_8_, component_size) (src, dst, width);
case COGL_PIXEL_FORMAT_R_8:
G_PASTE (_cogl_pack_r_8_, component_size) (src, dst, width);
break;
case COGL_PIXEL_FORMAT_RG_88:
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_24_STENCIL_8:
case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
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 ();
}
}

View File

@@ -136,7 +136,7 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src,
(dst->format & ~COGL_PREMULT_BIT),
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)))
{
@@ -186,7 +186,7 @@ cogl_bitmap_new_for_data (CoglContext *context,
/* Rowstride from width if not given */
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->context = context;
@@ -211,7 +211,7 @@ _cogl_bitmap_new_with_malloc_buffer (CoglContext *context,
GError **error)
{
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;
uint8_t *data = g_try_malloc (rowstride * height);
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
* 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 =
cogl_pixel_buffer_new (context,

View File

@@ -273,7 +273,7 @@ static gboolean
_cogl_blit_get_tex_data_begin (CoglBlitData *data)
{
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->src_height);

View File

@@ -1315,7 +1315,7 @@ cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer,
CoglPixelFormat format,
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;
gboolean ret;

View File

@@ -297,8 +297,8 @@ copy_flipped_texture (CoglGLES2Context *gles2_ctx,
internal_format = COGL_PIXEL_FORMAT_A_8;
break;
case GL_LUMINANCE:
internal_format = COGL_PIXEL_FORMAT_G_8;
case GL_RED:
internal_format = COGL_PIXEL_FORMAT_R_8;
break;
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 "cogl-pixel-format.h"
#include "cogl-texture.h"
/* An entry to map CoglPixelFormats to their respective properties */
typedef struct _CoglPixelFormatInfo
{
CoglPixelFormat cogl_format;
const char *format_str;
int bpp; /* Bytes per pixel */
int aligned; /* Aligned components? (-1 if n/a) */
int aligned; /* Is aligned? (bool; -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;
static const CoglPixelFormatInfo format_info_table[] = {
{
.cogl_format = COGL_PIXEL_FORMAT_ANY,
.format_str = "ANY",
.bpp = 0,
.aligned = -1
.n_planes = 0,
.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,
.format_str = "A_8",
.bpp = 1,
.aligned = 1
.n_planes = 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,
.format_str = "RGB_565",
.bpp = 2,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "RGBA_4444",
.bpp = 2,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "RGBA_5551",
.bpp = 2,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "YUV",
.bpp = 0,
.aligned = -1
.n_planes = 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,
.format_str = "G_8",
.bpp = 1,
.aligned = 1
.cogl_format = COGL_PIXEL_FORMAT_R_8,
.format_str = "R_8",
.n_planes = 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,
.format_str = "RG_88",
.bpp = 2,
.aligned = 1
.n_planes = 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,
.format_str = "RGB_888",
.bpp = 3,
.aligned = 1
.n_planes = 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,
.format_str = "BGR_888",
.bpp = 3,
.aligned = 1
.n_planes = 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,
.format_str = "RGBA_8888",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "BGRA_8888",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "ARGB_8888",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "ABGR_8888",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "RGBA_1010102",
.bpp = 4,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "BGRA_1010102",
.bpp = 4,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "ARGB_2101010",
.bpp = 4,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "ABGR_2101010",
.bpp = 4,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "RGBA_8888_PRE",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "BGRA_8888_PRE",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "ARGB_8888_PRE",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "ABGR_8888_PRE",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "RGBA_4444_PRE",
.bpp = 2,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "RGBA_5551_PRE",
.bpp = 2,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "RGBA_1010102_PRE",
.bpp = 4,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "BGRA_1010102_PRE",
.bpp = 4,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "ARGB_2101010_PRE",
.bpp = 4,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "ABGR_2101010_PRE",
.bpp = 4,
.aligned = 0
.n_planes = 1,
.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,
.format_str = "DEPTH_16",
.bpp = 2,
.aligned = 1
.n_planes = 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,
.format_str = "DEPTH_32",
.bpp = 4,
.aligned = 1
.n_planes = 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,
.format_str = "DEPTH_24_STENCIL_8",
.bpp = 4,
.aligned = 1
.n_planes = 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 }
},
};
/*
* Returns the number of bytes-per-pixel of a given format. The bpp
* 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)
uint8_t
cogl_pixel_format_get_bytes_per_pixel_simple (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].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 ();
}
/* 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
_cogl_pixel_format_is_endian_dependant (CoglPixelFormat format)
{
@@ -295,6 +721,44 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format)
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 *
cogl_pixel_format_to_string (CoglPixelFormat format)
{
@@ -308,3 +772,51 @@ cogl_pixel_format_to_string (CoglPixelFormat format)
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):
*
* 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)
* 3 = 4 bpp, aligned (e.g. 8888)
* 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_RGBA_4444: RGBA, 16 bits
* @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits
* @COGL_PIXEL_FORMAT_YUV: Not currently supported
* @COGL_PIXEL_FORMAT_G_8: Single luminance component
* @COGL_PIXEL_FORMAT_YUV: Obsolete. See the other YUV-based formats.
* @COGL_PIXEL_FORMAT_R_8: Single red component, 8 bits
* @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits
* @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 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_ARGB_2101010_PRE: Premultiplied ARGB, 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
* 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_5551 = 6 | COGL_A_BIT,
COGL_PIXEL_FORMAT_YUV = 7,
COGL_PIXEL_FORMAT_G_8 = 8,
COGL_PIXEL_FORMAT_R_8 = 8,
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_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;
/**
* 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
*
* Queries how many bytes a pixel of the given @format takes.
*
* Return value: The number of bytes taken for a pixel of the given
* @format.
* Returns: The no. of bytes in one pixel of the given single-plane @format.
*/
int
_cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format);
uint8_t
cogl_pixel_format_get_bytes_per_pixel_simple (CoglPixelFormat format);
/*
* _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) \
(((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:
* @format: a #CoglPixelFormat
@@ -295,6 +407,14 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format);
const char *
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
#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);
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
= &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0);
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);
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;
const uint8_t *src;
uint8_t *dst;
@@ -972,7 +972,7 @@ cogl_texture_2d_sliced_new_from_data (CoglContext *ctx,
/* Rowstride from width if not given */
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 */
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 */
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 */
bmp = cogl_bitmap_new_for_data (ctx,
@@ -239,6 +239,7 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
int width,
int height,
CoglPixelFormat format,
CoglTextureComponents components,
EGLImageKHR image,
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);
/* 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))
{
cogl_object_unref (tex);

View File

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

View File

@@ -430,10 +430,14 @@ _cogl_texture_set_region (CoglTexture *texture,
gboolean ret;
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 */
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 */
source_bmp = cogl_bitmap_new_for_data (ctx,
@@ -471,7 +475,7 @@ cogl_texture_set_region (CoglTexture *texture,
{
GError *ignore_error = NULL;
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;
/* 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_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_bits = g_malloc (full_rowstride * full_tex_height);
@@ -658,7 +662,7 @@ texture_get_cb (CoglTexture *subtexture,
CoglTextureGetData *tg_data = user_data;
CoglTexture *meta_texture = tg_data->meta_texture;
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);
int subtexture_width = cogl_texture_get_width (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);
/* 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)
rowstride = tex_width * bpp;
@@ -1103,6 +1107,11 @@ _cogl_texture_set_internal_format (CoglTexture *texture,
texture->components = COGL_TEXTURE_COMPONENTS_A;
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)
{
texture->components = COGL_TEXTURE_COMPONENTS_RG;
@@ -1149,6 +1158,8 @@ _cogl_texture_determine_internal_format (CoglTexture *texture,
}
case COGL_TEXTURE_COMPONENTS_A:
return COGL_PIXEL_FORMAT_A_8;
case COGL_TEXTURE_COMPONENTS_R:
return COGL_PIXEL_FORMAT_R_8;
case COGL_TEXTURE_COMPONENTS_RG:
return COGL_PIXEL_FORMAT_RG_88;
case COGL_TEXTURE_COMPONENTS_RGB:

View File

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

View File

@@ -330,7 +330,7 @@ cogl_read_pixels (int x,
CoglPixelFormat format,
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;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);

View File

@@ -59,6 +59,7 @@
#include <cogl/cogl1-context.h>
#include <cogl/cogl-bitmap.h>
#include <cogl/cogl-color.h>
#include <cogl/cogl-pixel-format-conversion.h>
#include <cogl/cogl-matrix.h>
#include <cogl/cogl-matrix-stack.h>
#include <cogl/cogl-offscreen.h>
@@ -108,6 +109,7 @@
#include <cogl/cogl-sub-texture.h>
#include <cogl/cogl-atlas-texture.h>
#include <cogl/cogl-meta-texture.h>
#include <cogl/cogl-multi-plane-texture.h>
#include <cogl/cogl-primitive-texture.h>
#include <cogl/cogl-index-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 */
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 */
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)
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);
ctx->texture_driver->prep_gl_for_pixels_download (ctx,
@@ -1360,7 +1360,7 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
else
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,
rowstride,

View File

@@ -250,7 +250,7 @@ allocate_from_bitmap (CoglTexture2D *tex_2d,
if (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);
}
else
@@ -259,7 +259,7 @@ allocate_from_bitmap (CoglTexture2D *tex_2d,
"glGenerateMipmap fallback");
g_error_free (ignore);
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 =
_cogl_bitmap_map (upload_bmp, COGL_BUFFER_ACCESS_READ, 0, &ignore);
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_type = gl_type;
@@ -852,7 +852,7 @@ _cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d,
GLenum gl_format;
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,
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_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;
return TRUE;
case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8:
case GL_LUMINANCE12: case GL_LUMINANCE16:
*out_format = COGL_PIXEL_FORMAT_G_8;
case GL_RED:
*out_format = COGL_PIXEL_FORMAT_R_8;
return TRUE;
case GL_RG:
@@ -126,9 +119,9 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
}
gltype = GL_UNSIGNED_BYTE;
break;
case COGL_PIXEL_FORMAT_G_8:
glintformat = GL_LUMINANCE;
glformat = GL_LUMINANCE;
case COGL_PIXEL_FORMAT_R_8:
glintformat = GL_RED;
glformat = GL_RED;
gltype = GL_UNSIGNED_BYTE;
break;
@@ -267,7 +260,37 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
break;
case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
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 ();
break;
}

View File

@@ -196,7 +196,7 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
GLuint gl_handle;
uint8_t *data;
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;
GError *internal_error = NULL;
int level_width;
@@ -302,7 +302,7 @@ _cogl_texture_driver_upload_to_gl (CoglContext *ctx,
{
uint8_t *data;
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;
GError *internal_error = NULL;

View File

@@ -86,9 +86,18 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
glformat = GL_ALPHA;
gltype = GL_UNSIGNED_BYTE;
break;
case COGL_PIXEL_FORMAT_G_8:
glintformat = GL_LUMINANCE;
glformat = GL_LUMINANCE;
case COGL_PIXEL_FORMAT_R_8:
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;
break;
@@ -198,7 +207,37 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
break;
case COGL_PIXEL_FORMAT_ANY:
/* No support for YUV or multi-plane formats */
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 ();
break;
}

View File

@@ -96,6 +96,16 @@ _cogl_texture_driver_gen (CoglContext *ctx,
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;
}
@@ -152,7 +162,7 @@ prepare_bitmap_alignment_for_upload (CoglContext *ctx,
GError **error)
{
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 width = cogl_bitmap_get_width (src_bmp);
int alignment = 1;
@@ -195,7 +205,7 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
GLuint gl_handle;
uint8_t *data;
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;
int rowstride;
gboolean status = TRUE;
@@ -337,7 +347,7 @@ _cogl_texture_driver_upload_to_gl (CoglContext *ctx,
GError **error)
{
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 bmp_width = cogl_bitmap_get_width (source_bmp);
int bmp_height = cogl_bitmap_get_height (source_bmp);

View File

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

View File

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

View File

@@ -730,7 +730,7 @@ _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
image->bits_per_pixel,
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;
_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->height,
texture_format,
COGL_TEXTURE_COMPONENTS_RGBA,
egl_tex_pixmap->image,
NULL));

View File

@@ -173,12 +173,7 @@ test_read_texture_formats (void)
test_read_byte (tex_2d, COGL_PIXEL_FORMAT_A_8, 0x78);
#if 0
/* 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
test_read_byte (tex_2d, COGL_PIXEL_FORMAT_R_8, 0x12);
/* We should always be able to read into an RG buffer regardless of
* whether RG textures are supported because Cogl will do the

View File

@@ -135,12 +135,7 @@ void
test_write_texture_formats (void)
{
test_write_byte (test_ctx, COGL_PIXEL_FORMAT_A_8, 0x34, 0x00000034);
#if 0
/* 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
test_write_byte (test_ctx, COGL_PIXEL_FORMAT_R_8, 0x34, 0x34000000);
/* We should always be able to read from an RG buffer regardless of
* 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_RGBA:
return TRUE;
case COGL_TEXTURE_COMPONENTS_R:
case COGL_TEXTURE_COMPONENTS_RG:
case COGL_TEXTURE_COMPONENTS_RGB:
case COGL_TEXTURE_COMPONENTS_DEPTH:

View File

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

View File

@@ -89,7 +89,7 @@ struct _MetaShapedTexture
MetaTextureTower *paint_tower;
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
CoglTexture *mask_texture;
CoglSnippet *snippet;
@@ -97,6 +97,8 @@ struct _MetaShapedTexture
CoglPipeline *masked_pipeline;
CoglPipeline *unblended_pipeline;
CoglPixelFormatConversion *pixel_format_conversion;
gboolean is_y_inverted;
/* The region containing only fully opaque pixels */
@@ -277,9 +279,11 @@ set_clip_region (MetaShapedTexture *stex,
static void
meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
{
g_clear_pointer (&stex->base_pipeline, cogl_object_unref);
g_clear_pointer (&stex->masked_pipeline, cogl_object_unref);
g_clear_pointer (&stex->unblended_pipeline, cogl_object_unref);
cogl_clear_object (&stex->pixel_format_conversion);
cogl_clear_object (&stex->base_pipeline);
cogl_clear_object (&stex->masked_pipeline);
cogl_clear_object (&stex->unblended_pipeline);
}
static void
@@ -297,7 +301,7 @@ meta_shaped_texture_dispose (GObject *object)
meta_texture_tower_free (stex->paint_tower);
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);
meta_shaped_texture_set_mask_texture (stex, NULL);
@@ -306,7 +310,7 @@ meta_shaped_texture_dispose (GObject *object)
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);
}
@@ -317,19 +321,23 @@ get_base_pipeline (MetaShapedTexture *stex,
{
CoglPipeline *pipeline;
CoglMatrix matrix;
CoglPixelFormat format;
uint8_t i, n_planes;
if (stex->base_pipeline)
return stex->base_pipeline;
pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
format = cogl_multi_plane_texture_get_format (stex->texture);
n_planes = cogl_multi_plane_texture_get_n_planes (stex->texture);
for (i = 0; i < n_planes; i++)
{
cogl_pipeline_set_layer_wrap_mode_s (pipeline, i,
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);
@@ -409,11 +417,24 @@ get_base_pipeline (MetaShapedTexture *stex,
0);
}
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix);
for (i = 0; i < n_planes + 1; i++)
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)
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;
@@ -432,12 +453,14 @@ get_masked_pipeline (MetaShapedTexture *stex,
CoglContext *ctx)
{
CoglPipeline *pipeline;
uint8_t n_planes;
if (stex->masked_pipeline)
return stex->masked_pipeline;
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])",
NULL);
@@ -451,17 +474,15 @@ get_unblended_pipeline (MetaShapedTexture *stex,
CoglContext *ctx)
{
CoglPipeline *pipeline;
CoglColor color;
if (stex->unblended_pipeline)
return stex->unblended_pipeline;
pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
cogl_pipeline_set_blend (pipeline,
"RGBA = ADD (SRC_COLOR, 0)",
NULL);
cogl_pipeline_set_color (pipeline, &color);
cogl_pipeline_set_color4ub (pipeline, 255, 255, 255, 255);
stex->unblended_pipeline = pipeline;
@@ -503,23 +524,21 @@ paint_clipped_rectangle (MetaShapedTexture *stex,
}
static void
set_cogl_texture (MetaShapedTexture *stex,
CoglTexture *cogl_tex)
set_planar_texture (MetaShapedTexture *stex,
CoglMultiPlaneTexture *planar_tex)
{
int width, height;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
if (stex->texture)
cogl_object_unref (stex->texture);
cogl_clear_object (&stex->texture);
stex->texture = planar_tex;
stex->texture = cogl_tex;
if (cogl_tex != NULL)
if (planar_tex != NULL)
{
cogl_object_ref (cogl_tex);
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
cogl_object_ref (planar_tex);
width = cogl_multi_plane_texture_get_width (planar_tex);
height = cogl_multi_plane_texture_get_height (planar_tex);
}
else
{
@@ -540,8 +559,11 @@ set_cogl_texture (MetaShapedTexture *stex,
* previous buffer. We only queue a redraw in response to surface
* damage. */
/* if (FALSE) */
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
@@ -559,10 +581,10 @@ texture_is_idle_and_not_mipmapped (gpointer user_data)
}
static void
do_paint (MetaShapedTexture *stex,
CoglFramebuffer *fb,
CoglTexture *paint_tex,
cairo_region_t *clip_region)
do_paint (MetaShapedTexture *stex,
CoglFramebuffer *fb,
CoglMultiPlaneTexture *paint_tex,
cairo_region_t *clip_region)
{
double tex_scale;
int dst_width, dst_height;
@@ -575,8 +597,12 @@ do_paint (MetaShapedTexture *stex,
CoglContext *ctx;
ClutterActorBox alloc;
CoglPipelineFilter filter;
uint8_t n_planes;
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);
dst_width = stex->dst_width;
@@ -682,8 +708,15 @@ do_paint (MetaShapedTexture *stex,
if (!cairo_region_is_empty (region))
{
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);
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))
{
CoglPipeline *blended_pipeline;
guint i;
if (stex->mask_texture == NULL)
{
@@ -722,16 +756,20 @@ do_paint (MetaShapedTexture *stex,
else
{
blended_pipeline = get_masked_pipeline (stex, ctx);
cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture);
cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
cogl_pipeline_set_layer_texture (blended_pipeline, n_planes, stex->mask_texture);
cogl_pipeline_set_layer_filters (blended_pipeline, n_planes, filter, filter);
}
cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
for (i = 0; i < n_planes; i++)
{
CoglTexture *plane = cogl_multi_plane_texture_get_plane (paint_tex, i);
CoglColor color;
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_pipeline_set_color (blended_pipeline, &color);
cogl_pipeline_set_layer_texture (blended_pipeline, i, plane);
cogl_pipeline_set_layer_filters (blended_pipeline, i, filter, filter);
}
cogl_pipeline_set_color4ub (blended_pipeline,
opacity, opacity, opacity, opacity);
if (blended_tex_region)
{
@@ -773,7 +811,7 @@ static void
meta_shaped_texture_paint (ClutterActor *actor)
{
MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor);
CoglTexture *paint_tex;
CoglMultiPlaneTexture *paint_tex;
CoglFramebuffer *fb;
if (!stex->texture)
@@ -828,11 +866,11 @@ meta_shaped_texture_paint (ClutterActor *actor)
}
else
{
paint_tex = COGL_TEXTURE (stex->texture);
paint_tex = stex->texture;
}
if (cogl_texture_get_width (paint_tex) == 0 ||
cogl_texture_get_height (paint_tex) == 0)
if (cogl_multi_plane_texture_get_width (paint_tex) == 0 ||
cogl_multi_plane_texture_get_height (paint_tex) == 0)
return;
fb = cogl_get_draw_framebuffer ();
@@ -906,7 +944,7 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
if (create_mipmaps != stex->create_mipmaps)
{
CoglTexture *base_texture;
CoglMultiPlaneTexture *base_texture;
stex->create_mipmaps = create_mipmaps;
base_texture = create_mipmaps ? stex->texture : NULL;
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:
* @stex: The #MetaShapedTexture
* @pixmap: The #CoglTexture to display
* @pixmap: The #CoglMultiPlaneTexture to display
*/
void
meta_shaped_texture_set_texture (MetaShapedTexture *stex,
CoglTexture *texture)
CoglMultiPlaneTexture *texture)
{
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);
g_clear_pointer (&stex->snippet, cogl_object_unref);
cogl_clear_object (&stex->snippet);
if (snippet)
stex->snippet = cogl_object_ref (snippet);
}
@@ -1138,11 +1176,12 @@ meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
*
* Returns: (transfer none): the unshaped texture
*/
CoglTexture *
CoglMultiPlaneTexture *
meta_shaped_texture_get_texture (MetaShapedTexture *stex)
{
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
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;
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
* cairo_surface_destroy().
*/
/* XXX Still need to fix this, but apparently only used for screenshot */
cairo_surface_t *
meta_shaped_texture_get_image (MetaShapedTexture *stex,
cairo_rectangle_int_t *clip)
{
cairo_rectangle_int_t *transformed_clip = NULL;
CoglTexture *texture, *mask_texture;
CoglTexture *texture;
CoglTexture *mask_texture;
cairo_surface_t *surface;
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL);
texture = COGL_TEXTURE (stex->texture);
if (texture == NULL)
if (stex->texture == NULL)
return NULL;
ensure_size_valid (stex);
@@ -1409,6 +1456,9 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
if (should_get_via_offscreen (stex))
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)
texture = cogl_texture_new_from_sub_texture (texture,
transformed_clip->x,

View File

@@ -45,7 +45,7 @@ struct _MetaSurfaceActorX11
MetaDisplay *display;
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
Pixmap pixmap;
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))))
g_warning ("NOTE: Not using GLX TFP!\n");
self->texture = texture;
meta_shaped_texture_set_texture (stex, texture);
self->texture = cogl_multi_plane_texture_new_single_plane (_cogl_texture_get_format (texture),
texture);
meta_shaped_texture_set_texture (stex, self->texture);
}
static void
@@ -187,6 +188,7 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
CoglTexture *texture;
self->received_damage = TRUE;
@@ -210,7 +212,8 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
if (!is_visible (self))
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);
}

View File

@@ -325,7 +325,8 @@ gboolean
meta_surface_actor_is_argb32 (MetaSurfaceActor *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
* that we're ARGB32.
@@ -335,14 +336,20 @@ meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
* place. This prevents us from continually redirecting and
* unredirecting on every paint.
*/
if (!texture)
if (!mtex)
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))
{
case COGL_TEXTURE_COMPONENTS_A:
case COGL_TEXTURE_COMPONENTS_RGBA:
return TRUE;
case COGL_TEXTURE_COMPONENTS_R:
case COGL_TEXTURE_COMPONENTS_RG:
case COGL_TEXTURE_COMPONENTS_RGB:
case COGL_TEXTURE_COMPONENTS_DEPTH:

View File

@@ -58,8 +58,8 @@ typedef struct
struct _MetaTextureTower
{
int n_levels;
CoglTexture *textures[MAX_TEXTURE_LEVELS];
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
CoglMultiPlaneTexture *textures[MAX_TEXTURE_LEVELS];
GList *fbos[MAX_TEXTURE_LEVELS];
Box invalid[MAX_TEXTURE_LEVELS];
CoglPipeline *pipeline_template;
};
@@ -112,8 +112,8 @@ meta_texture_tower_free (MetaTextureTower *tower)
* unset or until the tower is freed.
*/
void
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglTexture *texture)
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglMultiPlaneTexture *texture)
{
int i;
@@ -126,22 +126,14 @@ meta_texture_tower_set_base_texture (MetaTextureTower *tower,
{
for (i = 1; i < tower->n_levels; i++)
{
if (tower->textures[i] != NULL)
{
cogl_object_unref (tower->textures[i]);
tower->textures[i] = NULL;
}
cogl_clear_object (&tower->textures[i]);
if (tower->fbos[i] != NULL)
{
cogl_object_unref (tower->fbos[i]);
tower->fbos[i] = NULL;
}
g_list_free_full (tower->fbos[i], cogl_object_unref);
tower->fbos[i] = NULL;
}
cogl_object_unref (tower->textures[0]);
}
cogl_clear_object (&tower->textures[0]);
tower->textures[0] = texture;
if (tower->textures[0] != NULL)
@@ -150,8 +142,8 @@ meta_texture_tower_set_base_texture (MetaTextureTower *tower,
cogl_object_ref (tower->textures[0]);
width = cogl_texture_get_width (tower->textures[0]);
height = cogl_texture_get_height (tower->textures[0]);
width = cogl_multi_plane_texture_get_width (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 = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
@@ -192,8 +184,8 @@ meta_texture_tower_update_area (MetaTextureTower *tower,
if (tower->textures[0] == NULL)
return;
texture_width = cogl_texture_get_width (tower->textures[0]);
texture_height = cogl_texture_get_height (tower->textures[0]);
texture_width = cogl_multi_plane_texture_get_width (tower->textures[0]);
texture_height = cogl_multi_plane_texture_get_height (tower->textures[0]);
invalid.x1 = x;
invalid.y1 = y;
@@ -351,9 +343,27 @@ texture_tower_create_texture (MetaTextureTower *tower,
int width,
int height)
{
tower->textures[level] = cogl_texture_new_with_size (width, height,
COGL_TEXTURE_NO_AUTO_MIPMAP,
TEXTURE_FORMAT);
CoglMultiPlaneTexture *base_tex = tower->textures[0];
GPtrArray *planes;
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].y1 = 0;
@@ -365,51 +375,69 @@ static void
texture_tower_revalidate (MetaTextureTower *tower,
int level)
{
CoglTexture *source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
int source_texture_height = cogl_texture_get_height (source_texture);
CoglTexture *dest_texture = tower->textures[level];
int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture);
Box *invalid = &tower->invalid[level];
CoglFramebuffer *fb;
GError *catch_error = NULL;
CoglPipeline *pipeline;
CoglMultiPlaneTexture *src_tex = tower->textures[level - 1];
int src_width = cogl_multi_plane_texture_get_width (src_tex);
int src_height = cogl_multi_plane_texture_get_height (src_tex);
uint8_t src_tex_n_planes = cogl_multi_plane_texture_get_n_planes (src_tex);
CoglMultiPlaneTexture *dest_tex = tower->textures[level];
int dest_width = cogl_multi_plane_texture_get_width (dest_tex);
int dest_height = cogl_multi_plane_texture_get_height (dest_tex);
uint8_t i;
if (tower->fbos[level] == NULL)
tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);
fb = COGL_FRAMEBUFFER (tower->fbos[level]);
if (!cogl_framebuffer_allocate (fb, &catch_error))
/* FIXME: cogl_offscreen_texture_new_with_texture doesn't work for
* multi-plane textures, so we have to make an FBO for each layer */
for (i = 0; i < src_tex_n_planes; i++)
{
g_error_free (catch_error);
return;
Box *invalid = &tower->invalid[level];
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].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
* %NULL if no base texture has yet been set.
*/
CoglTexture *
CoglMultiPlaneTexture *
meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
{
int texture_width, texture_height;
@@ -438,8 +466,8 @@ meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
if (tower->textures[0] == NULL)
return NULL;
texture_width = cogl_texture_get_width (tower->textures[0]);
texture_height = cogl_texture_get_height (tower->textures[0]);
texture_width = cogl_multi_plane_texture_get_width (tower->textures[0]);
texture_height = cogl_multi_plane_texture_get_height (tower->textures[0]);
level = get_paint_level(texture_width, texture_height);
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);
void meta_texture_tower_free (MetaTextureTower *tower);
void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglTexture *texture);
void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglMultiPlaneTexture *texture);
void meta_texture_tower_update_area (MetaTextureTower *tower,
int x,
int y,
int width,
int height);
CoglTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
CoglMultiPlaneTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
G_END_DECLS

View File

@@ -1502,7 +1502,8 @@ build_and_scan_frame_mask (MetaWindowActor *self,
guchar *mask_data;
guint tex_width, tex_height;
MetaShapedTexture *stex;
CoglTexture *paint_tex, *mask_texture;
CoglMultiPlaneTexture *paint_tex;
CoglTexture *mask_texture;
int stride;
cairo_t *cr;
cairo_surface_t *surface;
@@ -1517,8 +1518,8 @@ build_and_scan_frame_mask (MetaWindowActor *self,
if (paint_tex == NULL)
return;
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
tex_width = cogl_multi_plane_texture_get_width (paint_tex);
tex_height = cogl_multi_plane_texture_get_height (paint_tex);
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);
META_EXPORT
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
CoglMultiPlaneTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
META_EXPORT
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);
if (stream)
{
CoglTexture2D *texture;
CoglMultiPlaneTexture *texture;
texture = meta_wayland_egl_stream_create_texture (stream, NULL);
if (!texture)
@@ -131,7 +131,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
buffer->egl_stream.stream = stream;
buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_STREAM;
buffer->egl_stream.texture = COGL_TEXTURE (texture);
buffer->egl_stream.texture = texture;
buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);
return TRUE;
@@ -163,43 +163,78 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
CoglTextureComponents *components_out)
{
CoglPixelFormat format;
CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA;
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888;
components = COGL_TEXTURE_COMPONENTS_RGB;
components_out[0] = COGL_TEXTURE_COMPONENTS_RGB;
break;
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888;
components = COGL_TEXTURE_COMPONENTS_RGB;
components_out[0] = COGL_TEXTURE_COMPONENTS_RGB;
break;
#endif
case WL_SHM_FORMAT_NV12:
format = COGL_PIXEL_FORMAT_NV12;
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
components_out[1] = COGL_TEXTURE_COMPONENTS_RG;
break;
case WL_SHM_FORMAT_NV21:
format = COGL_PIXEL_FORMAT_NV21;
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
components_out[1] = COGL_TEXTURE_COMPONENTS_RG;
break;
case WL_SHM_FORMAT_YUV422:
format = COGL_PIXEL_FORMAT_YUV422;
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
components_out[1] = COGL_TEXTURE_COMPONENTS_R;
components_out[2] = COGL_TEXTURE_COMPONENTS_R;
break;
case WL_SHM_FORMAT_YVU422:
format = COGL_PIXEL_FORMAT_YVU422;
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
components_out[1] = COGL_TEXTURE_COMPONENTS_R;
components_out[2] = COGL_TEXTURE_COMPONENTS_R;
break;
case WL_SHM_FORMAT_YUV444:
format = COGL_PIXEL_FORMAT_YUV444;
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
components_out[1] = COGL_TEXTURE_COMPONENTS_R;
components_out[2] = COGL_TEXTURE_COMPONENTS_R;
break;
case WL_SHM_FORMAT_YVU444:
format = COGL_PIXEL_FORMAT_YVU444;
components_out[0] = COGL_TEXTURE_COMPONENTS_R;
components_out[1] = COGL_TEXTURE_COMPONENTS_R;
components_out[2] = COGL_TEXTURE_COMPONENTS_R;
break;
default:
g_warn_if_reached ();
format = COGL_PIXEL_FORMAT_ARGB_8888;
components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA;
}
if (format_out)
*format_out = format;
if (components_out)
*components_out = components;
}
static gboolean
shm_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture,
gboolean *changed_texture,
GError **error)
shm_buffer_attach (MetaWaylandBuffer *buffer,
CoglMultiPlaneTexture **texture,
gboolean *changed_texture,
GError **error)
{
MetaBackend *backend = meta_get_backend ();
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
@@ -207,21 +242,30 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
struct wl_shm_buffer *shm_buffer;
int stride, width, height;
CoglPixelFormat format;
CoglTextureComponents components;
CoglBitmap *bitmap;
CoglTexture *new_texture;
CoglTextureComponents components[3];
guint i, n_planes;
uint8_t h_factors[3], v_factors[3], bpp[3];
CoglPixelFormat subformats[3];
gsize plane_offset = 0;
guint8 *data;
GPtrArray *planes;
/* Query the necessary parameters */
shm_buffer = wl_shm_buffer_get (buffer->resource);
stride = wl_shm_buffer_get_stride (shm_buffer);
width = wl_shm_buffer_get_width (shm_buffer);
height = wl_shm_buffer_get_height (shm_buffer);
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components);
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, components);
n_planes = cogl_pixel_format_get_n_planes (format);
cogl_pixel_format_get_subsampling_factors (format, h_factors, v_factors);
cogl_pixel_format_get_subformats (format, subformats);
cogl_pixel_format_get_bytes_per_pixel (format, bpp);
if (*texture &&
cogl_texture_get_width (*texture) == width &&
cogl_texture_get_height (*texture) == height &&
cogl_texture_get_components (*texture) == components &&
_cogl_texture_get_format (*texture) == format)
cogl_multi_plane_texture_get_width (*texture) == width &&
cogl_multi_plane_texture_get_height (*texture) == height &&
/*XXX cogl_texture_get_components (*texture) == components && */
cogl_multi_plane_texture_get_format (*texture) == format)
{
buffer->is_y_inverted = TRUE;
*changed_texture = FALSE;
@@ -230,56 +274,92 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
cogl_clear_object (texture);
/* Safely access the data inside the buffer */
wl_shm_buffer_begin_access (shm_buffer);
data = wl_shm_buffer_get_data (shm_buffer);
bitmap = cogl_bitmap_new_for_data (cogl_context,
width, height,
format,
stride,
wl_shm_buffer_get_data (shm_buffer));
new_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap));
cogl_texture_set_components (new_texture, components);
if (!cogl_texture_allocate (new_texture, error))
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
for (i = 0; i < n_planes; i++)
{
g_clear_pointer (&new_texture, cogl_object_unref);
if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE))
int plane_stride;
CoglBitmap *plane_bitmap;
CoglTexture *plane_texture;
/* Adjust the stride: map to the amount of pixels and calculate how many
* bytes that takes in the current plane */
plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i];
/* Define the bitmap that of this plane */
plane_bitmap = cogl_bitmap_new_for_data (cogl_context,
width / h_factors[i],
height / v_factors[i],
subformats[i],
plane_stride,
data + plane_offset);
g_assert (plane_bitmap);
/* Create a texture out of it so we can upload it to the GPU */
plane_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (plane_bitmap));
/* Separately set the components (necessary for e.g. XRGB, NV12) */
cogl_texture_set_components (plane_texture, components[i]);
if (!cogl_texture_allocate (plane_texture, error))
{
CoglTexture2DSliced *texture_sliced;
cogl_clear_object (&plane_texture);
/* If it didn't work due to an NPOT size, try again with an atlas texture */
if (!g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE))
{
cogl_object_unref (plane_bitmap);
goto failure;
}
g_clear_error (error);
texture_sliced =
cogl_texture_2d_sliced_new_from_bitmap (bitmap,
cogl_texture_2d_sliced_new_from_bitmap (plane_bitmap,
COGL_TEXTURE_MAX_WASTE);
new_texture = COGL_TEXTURE (texture_sliced);
cogl_texture_set_components (new_texture, components);
plane_texture = COGL_TEXTURE (texture_sliced);
if (!cogl_texture_allocate (new_texture, error))
g_clear_pointer (&new_texture, cogl_object_unref);
cogl_texture_set_components (plane_texture, components[i]);
if (!cogl_texture_allocate (plane_texture, error))
{
cogl_clear_object (&plane_texture);
goto failure;
}
}
g_ptr_array_add (planes, plane_texture);
/* Calculate the next plane start in the buffer (consider subsampling) */
plane_offset += plane_stride * (height / v_factors[i]);
}
cogl_object_unref (bitmap);
*texture = cogl_multi_plane_texture_new (format,
(CoglTexture **) g_ptr_array_free (planes, FALSE),
n_planes);
wl_shm_buffer_end_access (shm_buffer);
if (!new_texture)
return FALSE;
*texture = new_texture;
*changed_texture = TRUE;
buffer->is_y_inverted = TRUE;
return TRUE;
failure:
*texture = NULL;
return FALSE;
}
static gboolean
egl_image_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture,
gboolean *changed_texture,
GError **error)
egl_image_buffer_attach (MetaWaylandBuffer *buffer,
CoglMultiPlaneTexture **texture,
gboolean *changed_texture,
GError **error)
{
MetaBackend *backend = meta_get_backend ();
MetaEgl *egl = meta_backend_get_egl (backend);
@@ -288,8 +368,9 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
int format, width, height, y_inverted;
CoglPixelFormat cogl_format;
EGLImageKHR egl_image;
CoglTexture2D *texture_2d;
CoglTextureComponents components[3];
guint i, n_planes;
GPtrArray *planes;
if (buffer->egl_image.texture)
{
@@ -299,6 +380,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
return TRUE;
}
/* Query the necessary properties */
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
EGL_TEXTURE_FORMAT, &format,
error))
@@ -319,6 +401,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
NULL))
y_inverted = EGL_TRUE;
/* Map the EGL texture format to CoglPixelFormat, if possible */
switch (format)
{
case EGL_TEXTURE_RGB:
@@ -327,6 +410,12 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
case EGL_TEXTURE_RGBA:
cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
break;
case EGL_TEXTURE_Y_UV_WL:
cogl_format = COGL_PIXEL_FORMAT_NV12;
break;
case EGL_TEXTURE_Y_U_V_WL:
cogl_format = COGL_PIXEL_FORMAT_YUV444;
break;
default:
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
@@ -334,27 +423,51 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
return FALSE;
}
/* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used
* in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
EGL_WAYLAND_BUFFER_WL, buffer->resource,
NULL,
error);
if (egl_image == EGL_NO_IMAGE_KHR)
return FALSE;
n_planes = cogl_pixel_format_get_n_planes (cogl_format);
cogl_pixel_format_get_cogl_components (cogl_format, components);
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context,
width, height,
cogl_format,
egl_image,
error);
/* Each EGLImage is a plane in the final texture */
for (i = 0; i < n_planes; i++)
{
EGLint egl_attribs[3];
EGLImageKHR egl_img;
CoglTexture2D *texture_2d;
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
/* Specify that we want the i'th plane */
egl_attribs[0] = EGL_WAYLAND_PLANE_WL;
egl_attribs[1] = i;
egl_attribs[2] = EGL_NONE;
if (!texture_2d)
return FALSE;
/* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be
* used in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
egl_img = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
EGL_WAYLAND_BUFFER_WL, buffer->resource,
egl_attribs,
error);
buffer->egl_image.texture = COGL_TEXTURE (texture_2d);
if (G_UNLIKELY (egl_img == EGL_NO_IMAGE_KHR))
goto on_error;
texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context,
width, height,
cogl_format,
components[i],
egl_img,
error);
meta_egl_destroy_image (egl, egl_display, egl_img, NULL);
if (G_UNLIKELY (!texture_2d))
goto on_error;
g_ptr_array_add (planes, texture_2d);
}
buffer->egl_image.texture = cogl_multi_plane_texture_new (cogl_format,
(CoglTexture **) g_ptr_array_free (planes, FALSE),
n_planes);
buffer->is_y_inverted = !!y_inverted;
cogl_clear_object (texture);
@@ -362,14 +475,19 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
*changed_texture = TRUE;
return TRUE;
on_error:
g_ptr_array_free (planes, TRUE);
return FALSE;
}
#ifdef HAVE_WAYLAND_EGLSTREAM
static gboolean
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture,
gboolean *changed_texture,
GError **error)
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
CoglMultiPlaneTexture **texture,
gboolean *changed_texture,
GError **error)
{
MetaWaylandEglStream *stream = buffer->egl_stream.stream;
@@ -406,10 +524,10 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
* meta_wayland_buffer_attach(), which also might free it, as described above.
*/
gboolean
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture,
gboolean *changed_texture,
GError **error)
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
CoglMultiPlaneTexture **texture,
gboolean *changed_texture,
GError **error)
{
g_return_val_if_fail (buffer->resource, FALSE);
@@ -466,55 +584,94 @@ meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer)
}
static gboolean
process_shm_buffer_damage (MetaWaylandBuffer *buffer,
CoglTexture *texture,
cairo_region_t *region,
GError **error)
process_shm_buffer_damage (MetaWaylandBuffer *buffer,
CoglMultiPlaneTexture *texture,
cairo_region_t *region,
GError **error)
{
struct wl_shm_buffer *shm_buffer;
int i, n_rectangles;
gboolean set_texture_failed = FALSE;
CoglPixelFormat format;
CoglTextureComponents components[3];
uint8_t h_factors[3], v_factors[3], bpp[3];
CoglPixelFormat subformats[3];
gsize plane_offset = 0;
const uint8_t *data;
int32_t stride, height;
uint8_t i, n_planes;
int j, n_rectangles;
n_rectangles = cairo_region_num_rectangles (region);
shm_buffer = wl_shm_buffer_get (buffer->resource);
/* Get the data */
wl_shm_buffer_begin_access (shm_buffer);
data = wl_shm_buffer_get_data (shm_buffer);
for (i = 0; i < n_rectangles; i++)
/* Query the necessary properties */
stride = wl_shm_buffer_get_stride (shm_buffer);
height = wl_shm_buffer_get_height (shm_buffer);
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, components);
/* Fetch some properties from the pixel format */
n_planes = cogl_multi_plane_texture_get_n_planes (texture);
cogl_pixel_format_get_subformats (format, subformats);
cogl_pixel_format_get_subsampling_factors (format, h_factors, v_factors);
cogl_pixel_format_get_bytes_per_pixel (format, bpp);
for (i = 0; i < n_planes; i++)
{
const uint8_t *data = wl_shm_buffer_get_data (shm_buffer);
int32_t stride = wl_shm_buffer_get_stride (shm_buffer);
CoglPixelFormat format;
int bpp;
cairo_rectangle_int_t rect;
CoglTexture *plane;
int plane_stride;
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL);
bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
cairo_region_get_rectangle (region, i, &rect);
plane = cogl_multi_plane_texture_get_plane (texture, i);
plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i];
if (!_cogl_texture_set_region (texture,
rect.width, rect.height,
format,
stride,
data + rect.x * bpp + rect.y * stride,
rect.x, rect.y,
0,
error))
for (j = 0; j < n_rectangles; j++)
{
set_texture_failed = TRUE;
break;
cairo_rectangle_int_t rect;
gsize rect_offset;
cairo_region_get_rectangle (region, j, &rect);
/* It's possible we get a faulty rectangle of size zero: ignore */
if (rect.height == 0 || rect.width == 0)
continue;
rect_offset = plane_offset
+ rect.y * plane_stride / v_factors[i] /* Find the right row */
+ rect.x * bpp[i] / h_factors[i]; /* and the right column */
if (!_cogl_texture_set_region (plane,
rect.width / h_factors[i],
rect.height / v_factors[i],
subformats[i],
plane_stride,
data + rect_offset,
rect.x, rect.y,
0,
error))
{
set_texture_failed = TRUE;
goto out;
}
}
/* Calculate the next plane start in the buffer (consider subsampling) */
plane_offset += plane_stride * (height / v_factors[i]);
}
out:
wl_shm_buffer_end_access (shm_buffer);
return !set_texture_failed;
}
void
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
CoglTexture *texture,
cairo_region_t *region)
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
CoglMultiPlaneTexture *texture,
cairo_region_t *region)
{
gboolean res = FALSE;
GError *error = NULL;

View File

@@ -56,19 +56,19 @@ struct _MetaWaylandBuffer
MetaWaylandBufferType type;
struct {
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
} egl_image;
#ifdef HAVE_WAYLAND_EGLSTREAM
struct {
MetaWaylandEglStream *stream;
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
} egl_stream;
#endif
struct {
MetaWaylandDmaBufBuffer *dma_buf;
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
} 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);
gboolean meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer);
gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer);
gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture,
gboolean *changed_texture,
GError **error);
gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
CoglMultiPlaneTexture **texture,
gboolean *changed_texture,
GError **error);
CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer);
gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
CoglTexture *texture,
CoglMultiPlaneTexture *texture,
cairo_region_t *region);
#endif /* META_WAYLAND_BUFFER_H */

View File

@@ -58,7 +58,7 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface)
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_surface));
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (priv->cursor_sprite);
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
if (!priv->cursor_renderer)
return;
@@ -66,8 +66,13 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface)
texture = meta_wayland_surface_get_texture (surface);
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,
texture,
plane,
priv->hot_x * surface->scale,
priv->hot_y * surface->scale);
}

View File

@@ -56,8 +56,9 @@ struct _MetaWaylandDmaBufBuffer
int width;
int height;
uint32_t drm_format;
uint64_t drm_modifier;
bool is_y_inverted;
uint64_t drm_modifier[META_WAYLAND_DMA_BUF_MAX_FDS];
int fds[META_WAYLAND_DMA_BUF_MAX_FDS];
int offsets[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);
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
meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
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);
MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf;
CoglPixelFormat cogl_format;
EGLImageKHR egl_image;
CoglTexture2D *texture;
EGLint attribs[64];
int attr_idx = 0;
CoglTextureComponents components[3];
CoglPixelFormat subformats[3];
GPtrArray *planes;
guint i = 0, n_planes = 1;
if (buffer->dma_buf.texture)
return TRUE;
switch (dma_buf->drm_format)
cogl_format = drm_buffer_get_cogl_pixel_format (dma_buf);
if (cogl_format == COGL_PIXEL_FORMAT_ANY)
{
/*
* 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,
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unsupported buffer format %d", dma_buf->drm_format);
return FALSE;
}
attribs[attr_idx++] = EGL_WIDTH;
attribs[attr_idx++] = dma_buf->width;
attribs[attr_idx++] = EGL_HEIGHT;
attribs[attr_idx++] = dma_buf->height;
attribs[attr_idx++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[attr_idx++] = dma_buf->drm_format;
n_planes = cogl_pixel_format_get_n_planes (cogl_format);
cogl_pixel_format_get_subformats (cogl_format, subformats);
cogl_pixel_format_get_cogl_components (cogl_format, components);
planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
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 & 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)
/* Each EGLImage is a plane in the final CoglMultiPlaneTexture */
for (i = 0; i < n_planes; i++)
{
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 & 0xffffffff;
attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
attribs[attr_idx++] = dma_buf->drm_modifier >> 32;
EGLImageKHR egl_img;
CoglTexture2D *plane;
egl_img = create_egl_image_from_dmabuf (egl,
egl_display,
dma_buf,
dma_buf->width, dma_buf->height,
dma_buf->drm_format,
error);
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)
{
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 & 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->dma_buf.texture = cogl_multi_plane_texture_new (cogl_format,
(CoglTexture **) g_ptr_array_free (planes, FALSE),
n_planes);
buffer->is_y_inverted = dma_buf->is_y_inverted;
return TRUE;
on_error:
g_ptr_array_free (planes, TRUE);
return FALSE;
}
gboolean
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture,
gboolean *changed_texture,
GError **error)
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
CoglMultiPlaneTexture **texture,
gboolean *changed_texture,
GError **error)
{
if (!meta_wayland_dma_buf_realize_texture (buffer, error))
return FALSE;
@@ -260,8 +332,8 @@ buffer_params_add (struct wl_client *client,
return;
}
if (dma_buf->drm_modifier != DRM_FORMAT_MOD_INVALID &&
dma_buf->drm_modifier != drm_modifier)
if (dma_buf->drm_modifier[plane_idx] != DRM_FORMAT_MOD_INVALID &&
dma_buf->drm_modifier[plane_idx] != drm_modifier)
{
wl_resource_post_error (resource,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER,
@@ -269,8 +341,9 @@ buffer_params_add (struct wl_client *client,
return;
}
dma_buf->drm_modifier = drm_modifier;
dma_buf->fds[plane_idx] = fd;
dma_buf->drm_modifier[plane_idx] = drm_modifier;
dma_buf->offsets[plane_idx] = offset;
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_ARGB2101010);
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
@@ -598,10 +674,12 @@ meta_wayland_dma_buf_buffer_init (MetaWaylandDmaBufBuffer *dma_buf)
{
int i;
dma_buf->drm_modifier = DRM_FORMAT_MOD_INVALID;
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

View File

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

View File

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

View File

@@ -45,8 +45,8 @@ MetaWaylandEglStream * meta_wayland_egl_stream_new (MetaWaylandBuffer *buffer,
gboolean meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream,
GError **error);
CoglTexture2D * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
GError **error);
CoglMultiPlaneTexture * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
GError **error);
CoglSnippet * meta_wayland_egl_stream_create_snippet (void);
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;
MetaWindow *window;
MetaWaylandBuffer *buffer;
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
double scale;
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);
texture = meta_wayland_surface_get_texture (surface);
window->buffer_rect.width = cogl_texture_get_width (texture) * scale;
window->buffer_rect.height = cogl_texture_get_height (texture) * scale;
window->buffer_rect.width = cogl_multi_plane_texture_get_width (texture) * scale;
window->buffer_rect.height = cogl_multi_plane_texture_get_height (texture) * scale;
}
static void

View File

@@ -246,7 +246,7 @@ get_buffer_width (MetaWaylandSurface *surface)
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
if (buffer)
return cogl_texture_get_width (surface->texture);
return cogl_multi_plane_texture_get_width (surface->texture);
else
return 0;
}
@@ -257,7 +257,7 @@ get_buffer_height (MetaWaylandSurface *surface)
MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
if (buffer)
return cogl_texture_get_height (surface->texture);
return cogl_multi_plane_texture_get_height (surface->texture);
else
return 0;
}
@@ -721,7 +721,7 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
if (changed_texture && meta_wayland_surface_get_actor (surface))
{
MetaShapedTexture *stex;
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
CoglSnippet *snippet;
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);
}
CoglTexture *
CoglMultiPlaneTexture *
meta_wayland_surface_get_texture (MetaWaylandSurface *surface)
{
return surface->texture;

View File

@@ -149,7 +149,7 @@ struct _MetaWaylandSurface
GHashTable *outputs_to_destroy_notify_id;
MetaMonitorTransform buffer_transform;
CoglTexture *texture;
CoglMultiPlaneTexture *texture;
/* Buffer reference state. */
struct {
@@ -319,7 +319,7 @@ void meta_wayland_surface_restore_shortcuts (MetaWaylandSurface *
gboolean meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface,
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);

View File

@@ -305,6 +305,26 @@ meta_wayland_log_func (const char *fmt,
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
meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
{
@@ -317,6 +337,8 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
compositor->wayland_display = wl_display_create ();
if (compositor->wayland_display == NULL)
g_error ("Failed to create the global wl_display");
add_supported_shm_formats (compositor->wayland_display);
}
static void