summaryrefslogtreecommitdiff
path: root/cogl/cogl/cogl-pixel-format.c
diff options
context:
space:
mode:
authorNiels De Graef <Niels.DeGraef@barco.com>2018-11-14 12:22:02 +0100
committerNiels De Graef <niels.degraef@barco.com>2019-06-03 16:06:23 +0200
commita3fb239344b9455e94c5489be40a98ac53de5468 (patch)
tree555d1f6ce305dd2442f5b03150109121698d16d1 /cogl/cogl/cogl-pixel-format.c
parentd3ed857ebc346727c2ce12c3fa2ecfa1bd10a37d (diff)
downloadmutter-a3fb239344b9455e94c5489be40a98ac53de5468.tar.gz
WIP: wayland: add basic support for non-RGBA textureswip/nielsdg/add-yuv-support-gnome-3-32
Up until now, we didn't support sending YUV textures to the Wayland server. This was for several reasons: * We draw onto an RGBA framebuffer, so any other color format needs to be converted to that color space. Since we don't want to lose a lot of performance, this is ideally done on the GPU (using shaders). * YUV formats can consist of several planes (for example NV12, a common format in decoded video frames consists of a Y-plane and a subsampled UV-plane). Mutter always assumed that any texture it got was representable by a `CoglTexture`, which does not have this kind of concept. To deal with this, we introduce a new "texture": a `CoglMultiPlaneTexture` which consists of multiple CoglTextures, each representing a plane in the texture we got. It also provides support for CoglSnippets which can convert the colorspace if necessary. What changes are in this commit: * Introduce a new CoglMultiPlaneTexture object. Right now it is not implemented as a CoglTexture to prevent any confusion (but it is somewhat related to CoglMetaTexture) * Added some extra values to the CoglPixelFormat enum that deal with YUV * Make the necessary changes in MetaWaylandBuffer, so that it knows how to deal with incoming buffers (for example EGLImages and shm buffers) * This also introduces some changes in MetaDmaBuf, as that is also a different kind of buffer we can receive from wayland. Acknowledgements * There was a lot of prior art already done by the authors of Weston, CoglGstVideoSink and ClutterGstSink * My employer Barco for allowing me to work on this
Diffstat (limited to 'cogl/cogl/cogl-pixel-format.c')
-rw-r--r--cogl/cogl/cogl-pixel-format.c439
1 files changed, 408 insertions, 31 deletions
diff --git a/cogl/cogl/cogl-pixel-format.c b/cogl/cogl/cogl-pixel-format.c
index a8c0857a6..4225c6de1 100644
--- a/cogl/cogl/cogl-pixel-format.c
+++ b/cogl/cogl/cogl-pixel-format.c
@@ -43,6 +43,7 @@ typedef struct _CoglPixelFormatInfo
const char *format_str;
int bpp; /* Bytes per pixel */
int aligned; /* Aligned components? (-1 if n/a) */
+ uint8_t n_planes;
} CoglPixelFormatInfo;
static const CoglPixelFormatInfo format_info_table[] = {
@@ -50,187 +51,425 @@ static const CoglPixelFormatInfo format_info_table[] = {
.cogl_format = COGL_PIXEL_FORMAT_ANY,
.format_str = "ANY",
.bpp = 0,
- .aligned = -1
+ .aligned = -1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_A_8,
.format_str = "A_8",
.bpp = 1,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGB_565,
.format_str = "RGB_565",
.bpp = 2,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_4444,
.format_str = "RGBA_4444",
.bpp = 2,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_5551,
.format_str = "RGBA_5551",
.bpp = 2,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_YUV,
.format_str = "YUV",
.bpp = 0,
- .aligned = -1
+ .aligned = -1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_G_8,
.format_str = "G_8",
.bpp = 1,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RG_88,
.format_str = "RG_88",
.bpp = 2,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGB_888,
.format_str = "RGB_888",
.bpp = 3,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGR_888,
.format_str = "BGR_888",
.bpp = 3,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_8888,
.format_str = "RGBA_8888",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRA_8888,
.format_str = "BGRA_8888",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ARGB_8888,
.format_str = "ARGB_8888",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ABGR_8888,
.format_str = "ABGR_8888",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_1010102,
.format_str = "RGBA_1010102",
.bpp = 4,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRA_1010102,
.format_str = "BGRA_1010102",
.bpp = 4,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010,
.format_str = "ARGB_2101010",
.bpp = 4,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010,
.format_str = "ABGR_2101010",
.bpp = 4,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE,
.format_str = "RGBA_8888_PRE",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE,
.format_str = "BGRA_8888_PRE",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE,
.format_str = "ARGB_8888_PRE",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ABGR_8888_PRE,
.format_str = "ABGR_8888_PRE",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_4444_PRE,
.format_str = "RGBA_4444_PRE",
.bpp = 2,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_5551_PRE,
.format_str = "RGBA_5551_PRE",
.bpp = 2,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_RGBA_1010102_PRE,
.format_str = "RGBA_1010102_PRE",
.bpp = 4,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_BGRA_1010102_PRE,
.format_str = "BGRA_1010102_PRE",
.bpp = 4,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE,
.format_str = "ARGB_2101010_PRE",
.bpp = 4,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE,
.format_str = "ABGR_2101010_PRE",
.bpp = 4,
- .aligned = 0
+ .aligned = 0,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_16,
.format_str = "DEPTH_16",
.bpp = 2,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_32,
.format_str = "DEPTH_32",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
},
{
.cogl_format = COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8,
.format_str = "DEPTH_24_STENCIL_8",
.bpp = 4,
- .aligned = 1
+ .aligned = 1,
+ .n_planes = 1
+ },
+ /* Packed YUV */
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YUYV,
+ .format_str = "YUYV",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YVYU,
+ .format_str = "YVYU",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_UYVY,
+ .format_str = "UYVY",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_VYUY,
+ .format_str = "VYUY",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_AYUV,
+ .format_str = "AYUV",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ /* 2 plane RGB + A */
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_XRGB88888_A8,
+ .format_str = "XRGB88888_A8",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_XBGR88888_A8,
+ .format_str = "XBGR88888_A8",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_RGBX88888_A8,
+ .format_str = "RGBX88888_A8",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_BGRX88888_A8,
+ .format_str = "BGRX88888_A8",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_RGB888_A8,
+ .format_str = "RGB888_A8",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_BGR888_A8,
+ .format_str = "BGR888_A8",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_RGB565_A8,
+ .format_str = "RGB565_A8",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_BGR565_A8,
+ .format_str = "BGR565_A8",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ /* 2 plane YUV */
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_NV12,
+ .format_str = "NV12",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_NV21,
+ .format_str = "NV21",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_NV16,
+ .format_str = "NV16",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_NV61,
+ .format_str = "NV61",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_NV24,
+ .format_str = "NV24",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_NV42,
+ .format_str = "NV42",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ /* 3 plane YUV */
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YUV410,
+ .format_str = "YUV410",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YVU410,
+ .format_str = "YVU410",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YUV411,
+ .format_str = "YUV411",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YVU411,
+ .format_str = "YVU411",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YUV420,
+ .format_str = "YUV420",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YVU420,
+ .format_str = "YVU420",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YUV422,
+ .format_str = "YUV422",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YVU422,
+ .format_str = "YVU422",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YUV444,
+ .format_str = "YUV444",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
+ },
+ {
+ .cogl_format = COGL_PIXEL_FORMAT_YVU444,
+ .format_str = "YVU444",
+ .bpp = -1,
+ .aligned = 0,
+ .n_planes = 2
},
};
@@ -268,6 +507,45 @@ _cogl_pixel_format_get_bytes_per_pixel (CoglPixelFormat format)
g_assert_not_reached ();
}
+/*
+ * XXX document.
+ *
+ * XXX lol, this is even per macropixel, not per pixel :D
+ */
+void
+cogl_pixel_format_get_bits_per_pixel (CoglPixelFormat format, guint *bpp_out)
+{
+ /* "old" formats */
+ if (format & (0xff << 24))
+ {
+ switch (format)
+ {
+ case COGL_PIXEL_FORMAT_NV12:
+ case COGL_PIXEL_FORMAT_NV21:
+ bpp_out[0] = 8;
+ bpp_out[1] = 4;
+ break;
+ case COGL_PIXEL_FORMAT_YUV420:
+ case COGL_PIXEL_FORMAT_YVU420:
+ bpp_out[0] = 8;
+ bpp_out[1] = 2;
+ bpp_out[2] = 2;
+ break;
+ default:
+ g_warning ("FIXME");
+ }
+ }
+ else
+ {
+ int bpp_lut[] = { 0, 1, 3, 4,
+ 2, 2, 2, 0,
+ 1, 2, 0, 0,
+ 3, 4, 0, 0 };
+
+ bpp_out[0] = 8 * bpp_lut [format & 0xf];
+ }
+}
+
/* Note: this also refers to the mapping defined above for
* _cogl_pixel_format_get_bytes_per_pixel() */
gboolean
@@ -295,6 +573,105 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format)
return aligned;
}
+guint
+cogl_pixel_format_get_n_planes (CoglPixelFormat format)
+{
+ guint 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,
+ guint *horizontal_factors,
+ guint *vertical_factors)
+{
+ switch (format)
+ {
+ /* Packed formats (single plane) */
+ default:
+ horizontal_factors[0] = 1;
+ vertical_factors[0] = 1;
+ break;
+
+ /* 2 planes */
+ case COGL_PIXEL_FORMAT_NV12:
+ case COGL_PIXEL_FORMAT_NV21:
+ horizontal_factors[0] = 1;
+ vertical_factors[0] = 1;
+ horizontal_factors[1] = 2;
+ vertical_factors[1] = 2;
+ break;
+
+ case COGL_PIXEL_FORMAT_XRGB88888_A8:
+ case COGL_PIXEL_FORMAT_XBGR88888_A8:
+ case COGL_PIXEL_FORMAT_RGBX88888_A8:
+ case COGL_PIXEL_FORMAT_BGRX88888_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:
+ horizontal_factors[0] = 1;
+ vertical_factors[0] = 1;
+ horizontal_factors[1] = 1;
+ vertical_factors[1] = 1;
+ break;
+
+ /* 3 planes */
+ case COGL_PIXEL_FORMAT_YUV410:
+ case COGL_PIXEL_FORMAT_YVU410:
+ horizontal_factors[0] = 1;
+ vertical_factors[0] = 1;
+ horizontal_factors[1] = 4;
+ vertical_factors[1] = 4;
+ horizontal_factors[2] = 4;
+ vertical_factors[2] = 4;
+ break;
+ case COGL_PIXEL_FORMAT_YUV411:
+ case COGL_PIXEL_FORMAT_YVU411:
+ horizontal_factors[0] = 1;
+ vertical_factors[0] = 1;
+ horizontal_factors[1] = 4;
+ vertical_factors[1] = 1;
+ horizontal_factors[2] = 4;
+ vertical_factors[2] = 1;
+ break;
+ case COGL_PIXEL_FORMAT_YUV420:
+ case COGL_PIXEL_FORMAT_YVU420:
+ horizontal_factors[0] = 1;
+ vertical_factors[0] = 1;
+ horizontal_factors[1] = 2;
+ vertical_factors[1] = 2;
+ horizontal_factors[2] = 2;
+ vertical_factors[2] = 2;
+ break;
+ case COGL_PIXEL_FORMAT_YUV422:
+ case COGL_PIXEL_FORMAT_YVU422:
+ horizontal_factors[0] = 1;
+ vertical_factors[0] = 1;
+ horizontal_factors[1] = 2;
+ vertical_factors[1] = 1;
+ horizontal_factors[2] = 2;
+ vertical_factors[2] = 1;
+ break;
+ case COGL_PIXEL_FORMAT_YUV444:
+ case COGL_PIXEL_FORMAT_YVU444:
+ horizontal_factors[0] = 1;
+ vertical_factors[0] = 1;
+ horizontal_factors[1] = 1;
+ vertical_factors[1] = 1;
+ horizontal_factors[2] = 1;
+ vertical_factors[2] = 1;
+ break;
+ }
+}
+
const char *
cogl_pixel_format_to_string (CoglPixelFormat format)
{