diff --git a/clutter/clutter/clutter-backend.c b/clutter/clutter/clutter-backend.c index e61e0b8c59852bdf41da7e54cc771355a4e5bc83..f81de71d299610cc51094e7590ea9e84b94a1bd5 100644 --- a/clutter/clutter/clutter-backend.c +++ b/clutter/clutter/clutter-backend.c @@ -282,7 +282,7 @@ static const struct { const char *driver_desc; CoglDriver driver_id; } all_known_drivers[] = { - { "gl3", "OpenGL 3.2 core profile", COGL_DRIVER_GL3 }, + { "gl3", "OpenGL 3.1 core profile", COGL_DRIVER_GL3 }, { "gles2", "OpenGL ES 2.0", COGL_DRIVER_GLES2 }, { "any", "Default Cogl driver", COGL_DRIVER_ANY }, }; diff --git a/cogl/cogl/cogl-bitmap-conversion.c b/cogl/cogl/cogl-bitmap-conversion.c index b97f90e7d5b16882b93f62056b70b86d385cae18..108cb6677b388b9f7591dfb61fe38099acbcb536 100644 --- a/cogl/cogl/cogl-bitmap-conversion.c +++ b/cogl/cogl/cogl-bitmap-conversion.c @@ -331,9 +331,13 @@ _cogl_bitmap_needs_short_temp_buffer (CoglPixelFormat format) case COGL_PIXEL_FORMAT_G_8: case COGL_PIXEL_FORMAT_RGB_888: case COGL_PIXEL_FORMAT_BGR_888: + case COGL_PIXEL_FORMAT_RGBX_8888: case COGL_PIXEL_FORMAT_RGBA_8888: + case COGL_PIXEL_FORMAT_BGRX_8888: case COGL_PIXEL_FORMAT_BGRA_8888: + case COGL_PIXEL_FORMAT_XRGB_8888: case COGL_PIXEL_FORMAT_ARGB_8888: + case COGL_PIXEL_FORMAT_XBGR_8888: case COGL_PIXEL_FORMAT_ABGR_8888: case COGL_PIXEL_FORMAT_RGBA_8888_PRE: case COGL_PIXEL_FORMAT_BGRA_8888_PRE: @@ -353,7 +357,9 @@ _cogl_bitmap_needs_short_temp_buffer (CoglPixelFormat format) case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + case COGL_PIXEL_FORMAT_RGBX_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616: + case COGL_PIXEL_FORMAT_BGRX_FP_16161616: case COGL_PIXEL_FORMAT_BGRA_FP_16161616: case COGL_PIXEL_FORMAT_XRGB_FP_16161616: case COGL_PIXEL_FORMAT_ARGB_FP_16161616: diff --git a/cogl/cogl/cogl-bitmap-packing.h b/cogl/cogl/cogl-bitmap-packing.h index 9448e57ad6da4a612dca347dd1232ce66ff38add..12cc1c7f7cae9cb13e0be9ba0448526771116891 100644 --- a/cogl/cogl/cogl-bitmap-packing.h +++ b/cogl/cogl/cogl-bitmap-packing.h @@ -133,6 +133,22 @@ G_PASTE (_cogl_unpack_bgr_888_, component_size) (const uint8_t *src, } } +inline static void +G_PASTE (_cogl_unpack_bgrx_8888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[2]); + dst[1] = UNPACK_BYTE (src[1]); + dst[2] = UNPACK_BYTE (src[0]); + dst[3] = UNPACK_BYTE (255); + dst += 4; + src += 4; + } +} + inline static void G_PASTE (_cogl_unpack_bgra_8888_, component_size) (const uint8_t *src, component_type *dst, @@ -149,6 +165,22 @@ G_PASTE (_cogl_unpack_bgra_8888_, component_size) (const uint8_t *src, } } +inline static void +G_PASTE (_cogl_unpack_xrgb_8888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[1]); + dst[1] = UNPACK_BYTE (src[2]); + dst[2] = UNPACK_BYTE (src[3]); + dst[3] = UNPACK_BYTE (255); + dst += 4; + src += 4; + } +} + inline static void G_PASTE (_cogl_unpack_argb_8888_, component_size) (const uint8_t *src, component_type *dst, @@ -165,6 +197,22 @@ G_PASTE (_cogl_unpack_argb_8888_, component_size) (const uint8_t *src, } } +inline static void +G_PASTE (_cogl_unpack_xbgr_8888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[3]); + dst[1] = UNPACK_BYTE (src[2]); + dst[2] = UNPACK_BYTE (src[1]); + dst[3] = UNPACK_BYTE (255); + dst += 4; + src += 4; + } +} + inline static void G_PASTE (_cogl_unpack_abgr_8888_, component_size) (const uint8_t *src, component_type *dst, @@ -181,6 +229,22 @@ G_PASTE (_cogl_unpack_abgr_8888_, component_size) (const uint8_t *src, } } +inline static void +G_PASTE (_cogl_unpack_rgbx_8888_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = UNPACK_BYTE (src[0]); + dst[1] = UNPACK_BYTE (src[1]); + dst[2] = UNPACK_BYTE (src[2]); + dst[3] = UNPACK_BYTE (255); + dst += 4; + src += 4; + } +} + inline static void G_PASTE (_cogl_unpack_rgba_8888_, component_size) (const uint8_t *src, component_type *dst, @@ -265,7 +329,7 @@ G_PASTE (_cogl_unpack_rgba_1010102_, component_size) (const uint8_t *src, dst[2] = UNPACK_10 ((v >> 2) & 0x3ff); dst[3] = UNPACK_2 (v & 3); dst += 4; - src += 2; + src += 4; } } @@ -283,7 +347,25 @@ G_PASTE (_cogl_unpack_bgra_1010102_, component_size) (const uint8_t *src, dst[0] = UNPACK_10 ((v >> 2) & 0x3ff); dst[3] = UNPACK_2 (v & 3); dst += 4; - src += 2; + src += 4; + } +} + +inline static void +G_PASTE (_cogl_unpack_xrgb_2101010_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint32_t v = *(const uint32_t *) src; + + dst[3] = UNPACK_2 (0x3); + dst[0] = UNPACK_10 ((v >> 20) & 0x3ff); + dst[1] = UNPACK_10 ((v >> 10) & 0x3ff); + dst[2] = UNPACK_10 (v & 0x3ff); + dst += 4; + src += 4; } } @@ -301,7 +383,25 @@ G_PASTE (_cogl_unpack_argb_2101010_, component_size) (const uint8_t *src, dst[1] = UNPACK_10 ((v >> 10) & 0x3ff); dst[2] = UNPACK_10 (v & 0x3ff); dst += 4; - src += 2; + src += 4; + } +} + +inline static void +G_PASTE (_cogl_unpack_xbgr_2101010_, component_size) (const uint8_t *src, + component_type *dst, + int width) +{ + while (width-- > 0) + { + uint32_t v = *(const uint32_t *) src; + + dst[3] = UNPACK_2 (0x3); + dst[2] = UNPACK_10 ((v >> 20) & 0x3ff); + dst[1] = UNPACK_10 ((v >> 10) & 0x3ff); + dst[0] = UNPACK_10 (v & 0x3ff); + dst += 4; + src += 4; } } @@ -319,7 +419,7 @@ G_PASTE (_cogl_unpack_abgr_2101010_, component_size) (const uint8_t *src, dst[1] = UNPACK_10 ((v >> 10) & 0x3ff); dst[0] = UNPACK_10 (v & 0x3ff); dst += 4; - src += 2; + src += 4; } } @@ -361,18 +461,30 @@ G_PASTE (_cogl_unpack_, component_size) (CoglPixelFormat format, case COGL_PIXEL_FORMAT_BGR_888: G_PASTE (_cogl_unpack_bgr_888_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_RGBX_8888: + G_PASTE (_cogl_unpack_rgbx_8888_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_RGBA_8888: case COGL_PIXEL_FORMAT_RGBA_8888_PRE: G_PASTE (_cogl_unpack_rgba_8888_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_BGRX_8888: + G_PASTE (_cogl_unpack_bgrx_8888_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_BGRA_8888: case COGL_PIXEL_FORMAT_BGRA_8888_PRE: G_PASTE (_cogl_unpack_bgra_8888_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_XRGB_8888: + G_PASTE (_cogl_unpack_xrgb_8888_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_ARGB_8888: case COGL_PIXEL_FORMAT_ARGB_8888_PRE: G_PASTE (_cogl_unpack_argb_8888_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_XBGR_8888: + G_PASTE (_cogl_unpack_xbgr_8888_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_ABGR_8888: case COGL_PIXEL_FORMAT_ABGR_8888_PRE: G_PASTE (_cogl_unpack_abgr_8888_, component_size) (src, dst, width); @@ -397,16 +509,22 @@ G_PASTE (_cogl_unpack_, component_size) (CoglPixelFormat format, G_PASTE (_cogl_unpack_bgra_1010102_, component_size) (src, dst, width); break; case COGL_PIXEL_FORMAT_XRGB_2101010: + G_PASTE (_cogl_unpack_xrgb_2101010_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_ARGB_2101010: case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: G_PASTE (_cogl_unpack_argb_2101010_, component_size) (src, dst, width); break; case COGL_PIXEL_FORMAT_XBGR_2101010: + G_PASTE (_cogl_unpack_xbgr_2101010_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_ABGR_2101010: case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: G_PASTE (_cogl_unpack_abgr_2101010_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_RGBX_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616: + case COGL_PIXEL_FORMAT_BGRX_FP_16161616: case COGL_PIXEL_FORMAT_BGRA_FP_16161616: case COGL_PIXEL_FORMAT_XRGB_FP_16161616: case COGL_PIXEL_FORMAT_ARGB_FP_16161616: @@ -516,6 +634,22 @@ G_PASTE (_cogl_pack_bgr_888_, component_size) (const component_type *src, } } +inline static void +G_PASTE (_cogl_pack_bgrx_8888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[2] = PACK_BYTE (src[0]); + dst[1] = PACK_BYTE (src[1]); + dst[0] = PACK_BYTE (src[2]); + dst[3] = PACK_BYTE (255); + src += 4; + dst += 4; + } +} + inline static void G_PASTE (_cogl_pack_bgra_8888_, component_size) (const component_type *src, uint8_t *dst, @@ -532,6 +666,22 @@ G_PASTE (_cogl_pack_bgra_8888_, component_size) (const component_type *src, } } +inline static void +G_PASTE (_cogl_pack_xrgb_8888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[1] = PACK_BYTE (src[0]); + dst[2] = PACK_BYTE (src[1]); + dst[3] = PACK_BYTE (src[2]); + dst[0] = PACK_BYTE (255); + src += 4; + dst += 4; + } +} + inline static void G_PASTE (_cogl_pack_argb_8888_, component_size) (const component_type *src, uint8_t *dst, @@ -548,6 +698,22 @@ G_PASTE (_cogl_pack_argb_8888_, component_size) (const component_type *src, } } +inline static void +G_PASTE (_cogl_pack_xbgr_8888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[3] = PACK_BYTE (src[0]); + dst[2] = PACK_BYTE (src[1]); + dst[1] = PACK_BYTE (src[2]); + dst[0] = PACK_BYTE (255); + src += 4; + dst += 4; + } +} + inline static void G_PASTE (_cogl_pack_abgr_8888_, component_size) (const component_type *src, uint8_t *dst, @@ -564,6 +730,22 @@ G_PASTE (_cogl_pack_abgr_8888_, component_size) (const component_type *src, } } +inline static void +G_PASTE (_cogl_pack_rgbx_8888_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + dst[0] = PACK_BYTE (src[0]); + dst[1] = PACK_BYTE (src[1]); + dst[2] = PACK_BYTE (src[2]); + dst[3] = PACK_BYTE (255); + src += 4; + dst += 4; + } +} + inline static void G_PASTE (_cogl_pack_rgba_8888_, component_size) (const component_type *src, uint8_t *dst, @@ -669,6 +851,24 @@ G_PASTE (_cogl_pack_bgra_1010102_, component_size) (const component_type *src, } } +inline static void +G_PASTE (_cogl_pack_xrgb_2101010_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint32_t *v = (uint32_t *) dst; + + *v = ((0x3 << 30) | + (PACK_10 (src[0]) << 20) | + (PACK_10 (src[1]) << 10) | + PACK_10 (src[2])); + src += 4; + dst += 4; + } +} + inline static void G_PASTE (_cogl_pack_argb_2101010_, component_size) (const component_type *src, uint8_t *dst, @@ -687,6 +887,24 @@ G_PASTE (_cogl_pack_argb_2101010_, component_size) (const component_type *src, } } +inline static void +G_PASTE (_cogl_pack_xbgr_2101010_, component_size) (const component_type *src, + uint8_t *dst, + int width) +{ + while (width-- > 0) + { + uint32_t *v = (uint32_t *) dst; + + *v = ((0x3 << 30) | + (PACK_10 (src[2]) << 20) | + (PACK_10 (src[1]) << 10) | + PACK_10 (src[0])); + src += 4; + dst += 4; + } +} + inline static void G_PASTE (_cogl_pack_abgr_2101010_, component_size) (const component_type *src, uint8_t *dst, @@ -744,18 +962,30 @@ G_PASTE (_cogl_pack_, component_size) (CoglPixelFormat format, case COGL_PIXEL_FORMAT_BGR_888: G_PASTE (_cogl_pack_bgr_888_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_RGBX_8888: + G_PASTE (_cogl_pack_rgbx_8888_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_RGBA_8888: case COGL_PIXEL_FORMAT_RGBA_8888_PRE: G_PASTE (_cogl_pack_rgba_8888_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_BGRX_8888: + G_PASTE (_cogl_pack_bgrx_8888_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_BGRA_8888: case COGL_PIXEL_FORMAT_BGRA_8888_PRE: G_PASTE (_cogl_pack_bgra_8888_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_XRGB_8888: + G_PASTE (_cogl_pack_xrgb_8888_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_ARGB_8888: case COGL_PIXEL_FORMAT_ARGB_8888_PRE: G_PASTE (_cogl_pack_argb_8888_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_XBGR_8888: + G_PASTE (_cogl_pack_xbgr_8888_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_ABGR_8888: case COGL_PIXEL_FORMAT_ABGR_8888_PRE: G_PASTE (_cogl_pack_abgr_8888_, component_size) (src, dst, width); @@ -780,16 +1010,22 @@ G_PASTE (_cogl_pack_, component_size) (CoglPixelFormat format, G_PASTE (_cogl_pack_bgra_1010102_, component_size) (src, dst, width); break; case COGL_PIXEL_FORMAT_XRGB_2101010: + G_PASTE (_cogl_pack_xrgb_2101010_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_ARGB_2101010: case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: G_PASTE (_cogl_pack_argb_2101010_, component_size) (src, dst, width); break; case COGL_PIXEL_FORMAT_XBGR_2101010: + G_PASTE (_cogl_pack_xbgr_2101010_, component_size) (src, dst, width); + break; case COGL_PIXEL_FORMAT_ABGR_2101010: case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: G_PASTE (_cogl_pack_abgr_2101010_, component_size) (src, dst, width); break; + case COGL_PIXEL_FORMAT_RGBX_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616: + case COGL_PIXEL_FORMAT_BGRX_FP_16161616: case COGL_PIXEL_FORMAT_BGRA_FP_16161616: case COGL_PIXEL_FORMAT_XRGB_FP_16161616: case COGL_PIXEL_FORMAT_ARGB_FP_16161616: diff --git a/cogl/cogl/cogl-pixel-format.c b/cogl/cogl/cogl-pixel-format.c index 0210af0462192b11c02a097258750c81dcf41f77..c60d293bf988fde269f4bbadf2d8d3d4d1b8275a 100644 --- a/cogl/cogl/cogl-pixel-format.c +++ b/cogl/cogl/cogl-pixel-format.c @@ -118,6 +118,13 @@ static const CoglPixelFormatInfo format_info_table[] = { .n_planes = 1, .aligned = 1, .bpp = { 3 }, + }, + { + .cogl_format = COGL_PIXEL_FORMAT_RGBX_8888, + .format_str = "RGBX_8888", + .n_planes = 1, + .aligned = 1, + .bpp = { 4 }, }, { .cogl_format = COGL_PIXEL_FORMAT_RGBA_8888, @@ -126,6 +133,13 @@ static const CoglPixelFormatInfo format_info_table[] = { .aligned = 1, .bpp = { 4 }, }, + { + .cogl_format = COGL_PIXEL_FORMAT_BGRX_8888, + .format_str = "BGRX_8888", + .n_planes = 1, + .aligned = 1, + .bpp = { 4 }, + }, { .cogl_format = COGL_PIXEL_FORMAT_BGRA_8888, .format_str = "BGRA_8888", @@ -133,6 +147,13 @@ static const CoglPixelFormatInfo format_info_table[] = { .aligned = 1, .bpp = { 4 }, }, + { + .cogl_format = COGL_PIXEL_FORMAT_XRGB_8888, + .format_str = "XRGB_8888", + .n_planes = 1, + .aligned = 1, + .bpp = { 4 }, + }, { .cogl_format = COGL_PIXEL_FORMAT_ARGB_8888, .format_str = "ARGB_8888", @@ -140,6 +161,13 @@ static const CoglPixelFormatInfo format_info_table[] = { .aligned = 1, .bpp = { 4 }, }, + { + .cogl_format = COGL_PIXEL_FORMAT_XBGR_8888, + .format_str = "XBGR_8888", + .n_planes = 1, + .aligned = 1, + .bpp = { 4 }, + }, { .cogl_format = COGL_PIXEL_FORMAT_ABGR_8888, .format_str = "ABGR_8888", @@ -259,6 +287,13 @@ static const CoglPixelFormatInfo format_info_table[] = { .aligned = 0, .bpp = { 4 }, }, + { + .cogl_format = COGL_PIXEL_FORMAT_RGBX_FP_16161616, + .format_str = "RGBX_FP_16161616", + .n_planes = 1, + .bpp = { 8 }, + .aligned = 1 + }, { .cogl_format = COGL_PIXEL_FORMAT_RGBA_FP_16161616, .format_str = "RGBA_FP_16161616", @@ -266,6 +301,13 @@ static const CoglPixelFormatInfo format_info_table[] = { .bpp = { 8 }, .aligned = 1 }, + { + .cogl_format = COGL_PIXEL_FORMAT_BGRX_FP_16161616, + .format_str = "BGRX_FP_16161616", + .n_planes = 1, + .bpp = { 8 }, + .aligned = 1 + }, { .cogl_format = COGL_PIXEL_FORMAT_BGRA_FP_16161616, .format_str = "BGRA_FP_16161616", diff --git a/cogl/cogl/cogl-pixel-format.h b/cogl/cogl/cogl-pixel-format.h index 8a21371a850111da11087ee931befdc99bd7747c..1b65418056f6977c76e81b3d847396cd6b6450af 100644 --- a/cogl/cogl/cogl-pixel-format.h +++ b/cogl/cogl/cogl-pixel-format.h @@ -150,13 +150,19 @@ G_BEGIN_DECLS * @COGL_PIXEL_FORMAT_G_8: Single luminance component * @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits * @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits + * @COGL_PIXEL_FORMAT_RGBX_8888: RGBX, 32 bits * @COGL_PIXEL_FORMAT_RGBA_8888: RGBA, 32 bits + * @COGL_PIXEL_FORMAT_BGRX_8888: BGRX, 32 bits * @COGL_PIXEL_FORMAT_BGRA_8888: BGRA, 32 bits + * @COGL_PIXEL_FORMAT_XRGB_8888: XRGB, 32 bits * @COGL_PIXEL_FORMAT_ARGB_8888: ARGB, 32 bits + * @COGL_PIXEL_FORMAT_XBGR_8888: XBGR, 32 bits * @COGL_PIXEL_FORMAT_ABGR_8888: ABGR, 32 bits * @COGL_PIXEL_FORMAT_RGBA_1010102 : RGBA, 32 bits, 10 bpc * @COGL_PIXEL_FORMAT_BGRA_1010102 : BGRA, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_XRGB_2101010 : XRGB, 32 bits, 10 bpc * @COGL_PIXEL_FORMAT_ARGB_2101010 : ARGB, 32 bits, 10 bpc + * @COGL_PIXEL_FORMAT_XBGR_2101010 : XBGR, 32 bits, 10 bpc * @COGL_PIXEL_FORMAT_ABGR_2101010 : ABGR, 32 bits, 10 bpc * @COGL_PIXEL_FORMAT_RGBA_8888_PRE: Premultiplied RGBA, 32 bits * @COGL_PIXEL_FORMAT_BGRA_8888_PRE: Premultiplied BGRA, 32 bits @@ -168,7 +174,9 @@ 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_RGBX_FP_16161616: RGBX half floating point, 64 bit * @COGL_PIXEL_FORMAT_RGBA_FP_16161616: RGBA half floating point, 64 bit + * @COGL_PIXEL_FORMAT_BGRX_FP_16161616: BGRX half floating point, 64 bit * @COGL_PIXEL_FORMAT_BGRA_FP_16161616: BGRA half floating point, 64 bit * @COGL_PIXEL_FORMAT_ARGB_FP_16161616: ARGB half floating point, 64 bit * @COGL_PIXEL_FORMAT_ABGR_FP_16161616: ABGR half floating point, 64 bit @@ -212,9 +220,13 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/ COGL_PIXEL_FORMAT_RGB_888 = 2, COGL_PIXEL_FORMAT_BGR_888 = (2 | COGL_BGR_BIT), + COGL_PIXEL_FORMAT_RGBX_8888 = 3, COGL_PIXEL_FORMAT_RGBA_8888 = (3 | COGL_A_BIT), + COGL_PIXEL_FORMAT_BGRX_8888 = (3 | COGL_BGR_BIT), COGL_PIXEL_FORMAT_BGRA_8888 = (3 | COGL_A_BIT | COGL_BGR_BIT), + COGL_PIXEL_FORMAT_XRGB_8888 = (3 | COGL_AFIRST_BIT ), COGL_PIXEL_FORMAT_ARGB_8888 = (3 | COGL_A_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_XBGR_8888 = (3 | COGL_BGR_BIT | COGL_AFIRST_BIT), COGL_PIXEL_FORMAT_ABGR_8888 = (3 | COGL_A_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT), COGL_PIXEL_FORMAT_RGBA_1010102 = (13 | COGL_A_BIT), @@ -224,7 +236,9 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/ COGL_PIXEL_FORMAT_XBGR_2101010 = (13 | COGL_BGR_BIT | COGL_AFIRST_BIT), COGL_PIXEL_FORMAT_ABGR_2101010 = (13 | COGL_A_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_RGBX_FP_16161616 = 11, COGL_PIXEL_FORMAT_RGBA_FP_16161616 = (11 | COGL_A_BIT), + COGL_PIXEL_FORMAT_BGRX_FP_16161616 = (11 | COGL_BGR_BIT), COGL_PIXEL_FORMAT_BGRA_FP_16161616 = (11 | COGL_A_BIT | COGL_BGR_BIT), COGL_PIXEL_FORMAT_XRGB_FP_16161616 = (11 | COGL_AFIRST_BIT), COGL_PIXEL_FORMAT_ARGB_FP_16161616 = (11 | COGL_A_BIT | COGL_AFIRST_BIT), diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c index f809d9382ea6b4dc98b857f263c0113da3e83802..fc955262d0b91f6d594c98c515bca228a46d73f5 100644 --- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c @@ -537,8 +537,16 @@ cogl_gl_framebuffer_read_pixels_into_bitmap (CoglFramebufferDriver *driver, _cogl_bitmap_gl_unbind (tmp_bmp); + if (!(internal_format & COGL_A_BIT)) + { + _cogl_bitmap_set_format (tmp_bmp, read_format & ~COGL_PREMULT_BIT); + _cogl_bitmap_set_format (bitmap, format & ~COGL_PREMULT_BIT); + } + succeeded = _cogl_bitmap_convert_into_bitmap (tmp_bmp, bitmap, error); + _cogl_bitmap_set_format (bitmap, format); + cogl_object_unref (tmp_bmp); if (!succeeded) @@ -603,7 +611,8 @@ cogl_gl_framebuffer_read_pixels_into_bitmap (CoglFramebufferDriver *driver, /* Convert to the premult format specified by the caller in-place. This will do nothing if the premult status is already correct. */ - if (_cogl_bitmap_convert_premult_status (shared_bmp, format, error)) + if (!(internal_format & COGL_A_BIT) || + _cogl_bitmap_convert_premult_status (shared_bmp, format, error)) succeeded = TRUE; cogl_object_unref (shared_bmp); diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c index 7843921fad510922a0aa605ea278a10395b41ce3..ec6f1f270bc66f9a8ae2723ff1ff62eac5f3353e 100644 --- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c +++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c @@ -190,12 +190,22 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, glformat = GL_BGR; gltype = GL_UNSIGNED_BYTE; break; + case COGL_PIXEL_FORMAT_RGBX_8888: + glintformat = GL_RGB; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_BYTE; + break; case COGL_PIXEL_FORMAT_RGBA_8888: case COGL_PIXEL_FORMAT_RGBA_8888_PRE: glintformat = GL_RGBA; glformat = GL_RGBA; gltype = GL_UNSIGNED_BYTE; break; + case COGL_PIXEL_FORMAT_BGRX_8888: + glintformat = GL_RGB; + glformat = GL_BGRA; + gltype = GL_UNSIGNED_BYTE; + break; case COGL_PIXEL_FORMAT_BGRA_8888: case COGL_PIXEL_FORMAT_BGRA_8888_PRE: glintformat = GL_RGBA; @@ -206,6 +216,15 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, /* The following two types of channel ordering * have no GL equivalent unless defined using * system word byte ordering */ + case COGL_PIXEL_FORMAT_XRGB_8888: + glintformat = GL_RGB; + glformat = GL_BGRA; +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + gltype = GL_UNSIGNED_INT_8_8_8_8; +#else + gltype = GL_UNSIGNED_INT_8_8_8_8_REV; +#endif + break; case COGL_PIXEL_FORMAT_ARGB_8888: case COGL_PIXEL_FORMAT_ARGB_8888_PRE: glintformat = GL_RGBA; @@ -217,6 +236,15 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, #endif break; + case COGL_PIXEL_FORMAT_XBGR_8888: + glintformat = GL_RGB; + glformat = GL_RGBA; +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + gltype = GL_UNSIGNED_INT_8_8_8_8; +#else + gltype = GL_UNSIGNED_INT_8_8_8_8_REV; +#endif + break; case COGL_PIXEL_FORMAT_ABGR_8888: case COGL_PIXEL_FORMAT_ABGR_8888_PRE: glintformat = GL_RGBA; @@ -243,6 +271,10 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, break; case COGL_PIXEL_FORMAT_XBGR_2101010: + glintformat = GL_RGB; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_INT_2_10_10_10_REV; + break; case COGL_PIXEL_FORMAT_ABGR_2101010: case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: glintformat = GL_RGBA; @@ -251,6 +283,10 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, break; case COGL_PIXEL_FORMAT_XRGB_2101010: + glintformat = GL_RGB; + glformat = GL_BGRA; + gltype = GL_UNSIGNED_INT_2_10_10_10_REV; + break; case COGL_PIXEL_FORMAT_ARGB_2101010: case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: glintformat = GL_RGBA; @@ -279,12 +315,22 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, gltype = GL_UNSIGNED_SHORT_5_5_5_1; break; + case COGL_PIXEL_FORMAT_RGBX_FP_16161616: + glintformat = GL_RGB; + glformat = GL_RGBA; + gltype = GL_HALF_FLOAT; + break; case COGL_PIXEL_FORMAT_RGBA_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE: glintformat = GL_RGBA; glformat = GL_RGBA; gltype = GL_HALF_FLOAT; break; + case COGL_PIXEL_FORMAT_BGRX_FP_16161616: + glintformat = GL_RGB; + glformat = GL_BGRA; + gltype = GL_HALF_FLOAT; + break; case COGL_PIXEL_FORMAT_BGRA_FP_16161616: case COGL_PIXEL_FORMAT_BGRA_FP_16161616_PRE: glintformat = GL_RGBA; @@ -292,6 +338,10 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, gltype = GL_HALF_FLOAT; break; case COGL_PIXEL_FORMAT_XRGB_FP_16161616: + glintformat = GL_RGB; + glformat = GL_BGRA; + gltype = GL_HALF_FLOAT; + break; case COGL_PIXEL_FORMAT_ARGB_FP_16161616: case COGL_PIXEL_FORMAT_ARGB_FP_16161616_PRE: glintformat = GL_RGBA; @@ -299,6 +349,10 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, gltype = GL_HALF_FLOAT; break; case COGL_PIXEL_FORMAT_XBGR_FP_16161616: + glintformat = GL_RGB; + glformat = GL_RGBA; + gltype = GL_HALF_FLOAT; + break; case COGL_PIXEL_FORMAT_ABGR_FP_16161616: case COGL_PIXEL_FORMAT_ABGR_FP_16161616_PRE: glintformat = GL_RGBA; diff --git a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c index 6c59e2471146f3dcae2d04ecf9c2ca7dc5a0455a..caee72b2c806845f612e627470f15266561c6688 100644 --- a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c +++ b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c @@ -405,6 +405,7 @@ _cogl_texture_driver_upload_supported (CoglContext *ctx, case COGL_PIXEL_FORMAT_A_8: case COGL_PIXEL_FORMAT_G_8: case COGL_PIXEL_FORMAT_RG_88: + case COGL_PIXEL_FORMAT_BGRX_8888: case COGL_PIXEL_FORMAT_BGRA_8888: case COGL_PIXEL_FORMAT_BGRA_8888_PRE: case COGL_PIXEL_FORMAT_RGB_888: @@ -419,10 +420,13 @@ _cogl_texture_driver_upload_supported (CoglContext *ctx, case COGL_PIXEL_FORMAT_XRGB_2101010: case COGL_PIXEL_FORMAT_ARGB_2101010: case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + case COGL_PIXEL_FORMAT_RGBX_8888: case COGL_PIXEL_FORMAT_RGBA_8888: case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + case COGL_PIXEL_FORMAT_XRGB_8888: case COGL_PIXEL_FORMAT_ARGB_8888: case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + case COGL_PIXEL_FORMAT_XBGR_8888: case COGL_PIXEL_FORMAT_ABGR_8888: case COGL_PIXEL_FORMAT_ABGR_8888_PRE: case COGL_PIXEL_FORMAT_RGB_565: @@ -431,6 +435,7 @@ _cogl_texture_driver_upload_supported (CoglContext *ctx, case COGL_PIXEL_FORMAT_RGBA_5551: case COGL_PIXEL_FORMAT_RGBA_5551_PRE: return TRUE; + case COGL_PIXEL_FORMAT_BGRX_FP_16161616: case COGL_PIXEL_FORMAT_BGRA_FP_16161616: case COGL_PIXEL_FORMAT_XRGB_FP_16161616: case COGL_PIXEL_FORMAT_ARGB_FP_16161616: @@ -439,6 +444,7 @@ _cogl_texture_driver_upload_supported (CoglContext *ctx, case COGL_PIXEL_FORMAT_BGRA_FP_16161616_PRE: case COGL_PIXEL_FORMAT_ARGB_FP_16161616_PRE: case COGL_PIXEL_FORMAT_ABGR_FP_16161616_PRE: + case COGL_PIXEL_FORMAT_RGBX_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE: if (_cogl_has_private_feature diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c index 7e3a29b82c1933547fd9826a2fa3f39f6c56ab43..e328320a43b98c237cec53ad6cd6f8228c274c8f 100644 --- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c +++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c @@ -178,6 +178,17 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, #endif G_GNUC_FALLTHROUGH; + + case COGL_PIXEL_FORMAT_BGRX_8888: + case COGL_PIXEL_FORMAT_RGBX_8888: + case COGL_PIXEL_FORMAT_XRGB_8888: + case COGL_PIXEL_FORMAT_XBGR_8888: + glintformat = GL_RGBA; + glformat = GL_RGBA; + gltype = GL_UNSIGNED_BYTE; + required_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; + break; + case COGL_PIXEL_FORMAT_RGBA_8888: case COGL_PIXEL_FORMAT_RGBA_8888_PRE: case COGL_PIXEL_FORMAT_ARGB_8888: @@ -212,6 +223,7 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, gltype = GL_UNSIGNED_SHORT_5_5_5_1; break; + case COGL_PIXEL_FORMAT_BGRX_FP_16161616: case COGL_PIXEL_FORMAT_BGRA_FP_16161616: case COGL_PIXEL_FORMAT_XRGB_FP_16161616: case COGL_PIXEL_FORMAT_ARGB_FP_16161616: @@ -223,6 +235,7 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context, g_warning ("Unhandled 16 bpc pixel format used"); G_GNUC_FALLTHROUGH; + case COGL_PIXEL_FORMAT_RGBX_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE: if (!_cogl_has_private_feature diff --git a/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c index 978ffeb8bee017e2b20fc38c05a988aa2856a781..0259430387ba799e9d806536d77d95339332afc5 100644 --- a/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c +++ b/cogl/cogl/driver/gl/gles/cogl-texture-driver-gles.c @@ -448,6 +448,7 @@ _cogl_texture_driver_upload_supported (CoglContext *ctx, case COGL_PIXEL_FORMAT_A_8: case COGL_PIXEL_FORMAT_G_8: case COGL_PIXEL_FORMAT_RG_88: + case COGL_PIXEL_FORMAT_BGRX_8888: case COGL_PIXEL_FORMAT_BGRA_8888: case COGL_PIXEL_FORMAT_BGRA_8888_PRE: case COGL_PIXEL_FORMAT_RGB_888: @@ -472,10 +473,13 @@ _cogl_texture_driver_upload_supported (CoglContext *ctx, #else return FALSE; #endif + case COGL_PIXEL_FORMAT_RGBX_8888: case COGL_PIXEL_FORMAT_RGBA_8888: case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + case COGL_PIXEL_FORMAT_XRGB_8888: case COGL_PIXEL_FORMAT_ARGB_8888: case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + case COGL_PIXEL_FORMAT_XBGR_8888: case COGL_PIXEL_FORMAT_ABGR_8888: case COGL_PIXEL_FORMAT_ABGR_8888_PRE: case COGL_PIXEL_FORMAT_RGB_565: @@ -484,6 +488,7 @@ _cogl_texture_driver_upload_supported (CoglContext *ctx, case COGL_PIXEL_FORMAT_RGBA_5551: case COGL_PIXEL_FORMAT_RGBA_5551_PRE: return TRUE; + case COGL_PIXEL_FORMAT_BGRX_FP_16161616: case COGL_PIXEL_FORMAT_BGRA_FP_16161616: case COGL_PIXEL_FORMAT_XRGB_FP_16161616: case COGL_PIXEL_FORMAT_ARGB_FP_16161616: @@ -493,6 +498,7 @@ _cogl_texture_driver_upload_supported (CoglContext *ctx, case COGL_PIXEL_FORMAT_ARGB_FP_16161616_PRE: case COGL_PIXEL_FORMAT_ABGR_FP_16161616_PRE: return FALSE; + case COGL_PIXEL_FORMAT_RGBX_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616: case COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE: if (_cogl_has_private_feature diff --git a/meson.build b/meson.build index 20dbfd9ce1a59ede9ec7a660efe0f8579df7d879..a25859008a23c776f3ee4b9eecaf2880ffaab101 100644 --- a/meson.build +++ b/meson.build @@ -212,6 +212,7 @@ if have_gles2 endif if have_wayland + libdrm_dep = dependency('libdrm') wayland_server_dep = dependency('wayland-server', version: wayland_server_req) wayland_client_dep = dependency('wayland-client', version: wayland_server_req) wayland_cursor_dep = dependency('wayland-cursor') diff --git a/src/backends/meta-cogl-utils.c b/src/backends/meta-cogl-utils.c new file mode 100644 index 0000000000000000000000000000000000000000..25c3a151f0903c45adbbc33e1ea4dc7352612896 --- /dev/null +++ b/src/backends/meta-cogl-utils.c @@ -0,0 +1,52 @@ +/* meta-cogl-utils.c + * + * Copyright 2020 Georges Basile Stavracas Neto + * + * 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. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ + +#include "config.h" + +#include "backends/meta-cogl-utils.h" + +gboolean +meta_cogl_pixel_format_from_drm_format (uint32_t drm_format, + CoglPixelFormat *out_format, + MetaMultiTextureFormat *out_multi_texture_format) +{ + const size_t n = G_N_ELEMENTS (drm_format_to_cogl_pixel_format_map); + size_t i; + + for (i = 0; i < n; i++) + { + if (drm_format_to_cogl_pixel_format_map[i].drm_format == drm_format) + break; + } + + if (i == n) + return FALSE; + + if (out_format) + *out_format = drm_format_to_cogl_pixel_format_map[i].cogl_format; + + if (out_multi_texture_format) + *out_multi_texture_format = drm_format_to_cogl_pixel_format_map[i].multi_texture_format; + + return TRUE; +} diff --git a/src/backends/meta-cogl-utils.h b/src/backends/meta-cogl-utils.h new file mode 100644 index 0000000000000000000000000000000000000000..7625383b43196b1db8a7a898274b7d36be3e732d --- /dev/null +++ b/src/backends/meta-cogl-utils.h @@ -0,0 +1,85 @@ +/* meta-cogl-utils.h + * + * Copyright 2020 Georges Basile Stavracas Neto + * + * 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. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ + +#ifndef META_COGL_UTILS_H +#define META_COGL_UTILS_H + +#include + +#include "cogl/cogl.h" +#include "meta/meta-multi-texture-format.h" + +G_BEGIN_DECLS + +typedef struct _PixelFormatMap { + uint32_t drm_format; + CoglPixelFormat cogl_format; + MetaMultiTextureFormat multi_texture_format; +} PixelFormatMap; + +static const PixelFormatMap drm_format_to_cogl_pixel_format_map[] = { +/* DRM formats are defined as little-endian, not machine endian. */ +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + { DRM_FORMAT_R8, COGL_PIXEL_FORMAT_G_8, META_MULTI_TEXTURE_FORMAT_INVALID }, + { DRM_FORMAT_GR88, COGL_PIXEL_FORMAT_RG_88, META_MULTI_TEXTURE_FORMAT_INVALID }, + { DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_XBGR_8888, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_XRGB_8888, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRX_8888, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBX_8888, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_XRGB2101010, COGL_PIXEL_FORMAT_XRGB_2101010, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_ARGB2101010, COGL_PIXEL_FORMAT_ARGB_2101010_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_XBGR2101010, COGL_PIXEL_FORMAT_XBGR_2101010, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_ABGR2101010, COGL_PIXEL_FORMAT_ABGR_2101010_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_XRGB16161616F, COGL_PIXEL_FORMAT_BGRX_FP_16161616, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_ARGB16161616F, COGL_PIXEL_FORMAT_BGRA_FP_16161616_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_XBGR16161616F, COGL_PIXEL_FORMAT_RGBX_FP_16161616, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_ABGR16161616F, COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_YUYV, COGL_PIXEL_FORMAT_ANY, META_MULTI_TEXTURE_FORMAT_YUYV }, + { DRM_FORMAT_NV12, COGL_PIXEL_FORMAT_ANY, META_MULTI_TEXTURE_FORMAT_NV12 }, + { DRM_FORMAT_YUV420, COGL_PIXEL_FORMAT_ANY, META_MULTI_TEXTURE_FORMAT_YUV420 }, +#elif G_BYTE_ORDER == G_BIG_ENDIAN + { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBX_8888, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRX_8888, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_XRGB_8888, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_XBGR_8888, META_MULTI_TEXTURE_FORMAT_SIMPLE }, + { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, META_MULTI_TEXTURE_FORMAT_SIMPLE }, +#else +#error "unexpected G_BYTE_ORDER" +#endif +}; + +gboolean meta_cogl_pixel_format_from_drm_format (uint32_t drm_format, + CoglPixelFormat *out_format, + MetaMultiTextureFormat *out_multi_texture_format); + +G_END_DECLS + +#endif /* META_COGL_UTILS_H */ diff --git a/src/backends/native/meta-cogl-utils.c b/src/backends/native/meta-cogl-utils.c deleted file mode 100644 index f4586661a4aa89a6e60a35f5805555d1e2d6460c..0000000000000000000000000000000000000000 --- a/src/backends/native/meta-cogl-utils.c +++ /dev/null @@ -1,93 +0,0 @@ -/* meta-cogl-utils.c - * - * Copyright 2020 Georges Basile Stavracas Neto - * - * 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. - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - */ - -#include "backends/native/meta-cogl-utils.h" - -#include - -typedef struct _PixelFormatMap { - uint32_t drm_format; - CoglPixelFormat cogl_format; - CoglTextureComponents cogl_components; -} PixelFormatMap; - -static const PixelFormatMap pixel_format_map[] = { -/* DRM formats are defined as little-endian, not machine endian. */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - { DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ABGR2101010, COGL_PIXEL_FORMAT_RGBA_1010102_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XBGR2101010, COGL_PIXEL_FORMAT_RGBA_1010102_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ARGB2101010, COGL_PIXEL_FORMAT_BGRA_1010102_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XRGB2101010, COGL_PIXEL_FORMAT_BGRA_1010102_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_BGRA1010102, COGL_PIXEL_FORMAT_ARGB_2101010_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_BGRX1010102, COGL_PIXEL_FORMAT_ARGB_2101010_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_RGBA1010102, COGL_PIXEL_FORMAT_ABGR_2101010_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_RGBX1010102, COGL_PIXEL_FORMAT_ABGR_2101010_PRE, COGL_TEXTURE_COMPONENTS_RGB }, -#elif G_BYTE_ORDER == G_BIG_ENDIAN - /* DRM_FORMAT_RGB565 cannot be expressed. */ - { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, -#else -#error "unexpected G_BYTE_ORDER" -#endif -}; - -gboolean -meta_cogl_pixel_format_from_drm_format (uint32_t drm_format, - CoglPixelFormat *out_format, - CoglTextureComponents *out_components) -{ - const size_t n = G_N_ELEMENTS (pixel_format_map); - size_t i; - - for (i = 0; i < n; i++) - { - if (pixel_format_map[i].drm_format == drm_format) - break; - } - - if (i == n) - return FALSE; - - if (out_format) - *out_format = pixel_format_map[i].cogl_format; - - if (out_components) - *out_components = pixel_format_map[i].cogl_components; - - return TRUE; -} diff --git a/src/backends/native/meta-drm-buffer-gbm.c b/src/backends/native/meta-drm-buffer-gbm.c index 212c7a77614a9671b04efd4805fbcf6161c7ff86..cd49b8f605d736c6ba386d35bdb83cc03c5f54e1 100644 --- a/src/backends/native/meta-drm-buffer-gbm.c +++ b/src/backends/native/meta-drm-buffer-gbm.c @@ -32,7 +32,7 @@ #include #include "backends/meta-backend-private.h" -#include "backends/native/meta-cogl-utils.h" +#include "backends/meta-cogl-utils.h" #include "backends/native/meta-device-pool.h" #include "backends/native/meta-drm-buffer-private.h" diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index bcb791bc464a715d5c77638eae9ab72642a84be9..50e4bd0baecc8818d80eb04eee8460a43777f172 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -31,8 +31,8 @@ #include +#include "backends/meta-cogl-utils.h" #include "backends/meta-egl-ext.h" -#include "backends/native/meta-cogl-utils.h" #include "backends/native/meta-crtc-kms.h" #include "backends/native/meta-device-pool.h" #include "backends/native/meta-drm-buffer-dumb.h" @@ -751,9 +751,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre g_assert (cogl_framebuffer_get_width (framebuffer) == width); g_assert (cogl_framebuffer_get_height (framebuffer) == height); - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); + ret = meta_cogl_pixel_format_from_drm_format (drm_format, &cogl_format, NULL); g_assert (ret); dmabuf_fd = meta_drm_buffer_dumb_ensure_dmabuf_fd (buffer_dumb, &error); @@ -855,9 +853,7 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen, g_assert (cogl_framebuffer_get_width (framebuffer) == width); g_assert (cogl_framebuffer_get_height (framebuffer) == height); - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); + ret = meta_cogl_pixel_format_from_drm_format (drm_format, &cogl_format, NULL); g_assert (ret); dumb_bitmap = cogl_bitmap_new_for_data (cogl_context, diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 4da361e2bf37c59db04ee66bf59a25c97a3e5b9d..8a2e834f87c826b87d752ce7c67c39ede3484400 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -46,12 +46,12 @@ #include #include +#include "backends/meta-cogl-utils.h" #include "backends/meta-cursor-tracker-private.h" #include "backends/meta-gles3.h" #include "backends/meta-logical-monitor.h" #include "backends/native/meta-backend-native-private.h" #include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-cogl-utils.h" #include "backends/native/meta-crtc-kms.h" #include "backends/native/meta-crtc-virtual.h" #include "backends/native/meta-device-pool.h" @@ -633,9 +633,7 @@ meta_renderer_native_create_dma_buf_framebuffer (MetaRendererNative *renderer_n CoglOffscreen *cogl_fbo; int ret; - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); + ret = meta_cogl_pixel_format_from_drm_format (drm_format, &cogl_format, NULL); g_assert (ret); strides[0] = stride; diff --git a/src/compositor/meta-multi-texture-format-private.h b/src/compositor/meta-multi-texture-format-private.h new file mode 100644 index 0000000000000000000000000000000000000000..c1ecbb988c52798831b9ae987a87bb0d1f0741da --- /dev/null +++ b/src/compositor/meta-multi-texture-format-private.h @@ -0,0 +1,49 @@ +/* + * Authored By Niels De Graef + * + * 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 . + */ + +#ifndef META_MULTI_TEXTURE_FORMAT_PRIVATE_H +#define META_MULTI_TEXTURE_FORMAT_PRIVATE_H + +#include + +#include "meta/meta-multi-texture-format.h" + +G_BEGIN_DECLS + +const char * meta_multi_texture_format_to_string (MetaMultiTextureFormat format); + +int meta_multi_texture_format_get_n_planes (MetaMultiTextureFormat format); + +void meta_multi_texture_format_get_subformats (MetaMultiTextureFormat format, + const CoglPixelFormat **formats_out); + +void meta_multi_texture_format_get_plane_indices (MetaMultiTextureFormat format, + const uint8_t **plane_indices_out); + +void meta_multi_texture_format_get_subsampling_factors (MetaMultiTextureFormat format, + const uint8_t **horizontal_factors_out, + const uint8_t **vertical_factors_out); + +gboolean meta_multi_texture_format_get_snippets (MetaMultiTextureFormat format, + CoglSnippet **fragment_globals_snippet, + CoglSnippet **fragment_snippet); + +G_END_DECLS + +#endif /* META_MULTI_TEXTURE_FORMAT_PRIVATE_H */ diff --git a/src/compositor/meta-multi-texture-format.c b/src/compositor/meta-multi-texture-format.c new file mode 100644 index 0000000000000000000000000000000000000000..8df2f5e38ca10f54c3ab94cf54bd2486a3ad8c66 --- /dev/null +++ b/src/compositor/meta-multi-texture-format.c @@ -0,0 +1,217 @@ +/* + * Authored By Niels De Graef + * + * 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 . + */ + +/** + * SECTION:meta-multi-texture-format + * @title: MetaMultiTextureFormat + * @short_description: A representation for complex pixel formats + * + * Some pixel formats that are used in the wild are a bit more complex than + * just ARGB and all its variants. For example: a component might be put in a + * different plane (i.e. at a different place in memory). Another example are + * formats that use Y, U, and V components rather than RGB; if we composit them + * onto an RGBA framebuffer, we have to make sure for example that these get + * converted to the right color format first (using e.g. a shader). + */ + +#include "config.h" + +#include "compositor/meta-multi-texture-format-private.h" + +#include +#include +#include + +static const char *shader_global_conversions = + "vec4 yuv_to_rgb(vec4 yuva) \n" + "{ \n" + " vec4 res; \n" + " float Y = 1.16438356 * (yuva.x - 0.0625); \n" + " float su = yuva.y - 0.5; \n" + " float sv = yuva.z - 0.5; \n" + " res.r = Y + 1.59602678 * sv; \n" + " res.g = Y - 0.39176229 * su - 0.81296764 * sv; \n" + " res.b = Y + 2.01723214 * su; \n" + " res.rgb *= yuva.w; \n" + " res.a = yuva.w; \n" + " return res; \n" + "} \n"; + +static const char rgba_shader[] = + "cogl_color_out = \n" + " texture2D(cogl_sampler0, cogl_tex_coord0_in.st) * cogl_color_in.a; \n"; + +/* Shader for a single YUV plane */ +static const char y_xuxv_shader[] = + "vec4 yuva = vec4(0.0, 0.0, 0.0, cogl_color_in.a); \n" + "yuva.x = texture2D(cogl_sampler0, cogl_tex_coord0_in.st).x; \n" + "yuva.yz = texture2D(cogl_sampler1, cogl_tex_coord1_in.st).ga; \n" + "cogl_color_out = yuv_to_rgb(yuva); \n"; + +/* Shader for 1 Y-plane and 1 UV-plane */ +static const char nv12_shader[] = + "vec4 yuva = vec4(0.0, 0.0, 0.0, cogl_color_in.a); \n" + "yuva.x = texture2D(cogl_sampler0, cogl_tex_coord0_in.st).x; \n" + "yuva.yz = texture2D(cogl_sampler1, cogl_tex_coord1_in.st).rg; \n" + "cogl_color_out = yuv_to_rgb(yuva); \n"; + +/* Shader for 1 Y-plane, 1 U-plane and 1 V-plane */ +static const char yuv420_shader[] = + "vec4 yuva = vec4(0.0, 0.0, 0.0, cogl_color_in.a); \n" + "yuva.x = texture2D(cogl_sampler0, cogl_tex_coord0_in.st).x; \n" + "yuva.y = texture2D(cogl_sampler1, cogl_tex_coord1_in.st).x; \n" + "yuva.z = texture2D(cogl_sampler2, cogl_tex_coord2_in.st).x; \n" + "cogl_color_out = yuv_to_rgb(yuva); \n"; + +typedef struct _MetaMultiTextureFormatInfo +{ + MetaMultiTextureFormat multi_format; + const char *name; + uint8_t n_planes; + + /* Per plane-information */ + CoglPixelFormat subformats[COGL_PIXEL_FORMAT_MAX_PLANES]; /* influences how we deal with it on a GL level */ + uint8_t plane_indices[COGL_PIXEL_FORMAT_MAX_PLANES]; /* source plane */ + uint8_t hsub[COGL_PIXEL_FORMAT_MAX_PLANES]; /* horizontal subsampling */ + uint8_t vsub[COGL_PIXEL_FORMAT_MAX_PLANES]; /* vertical subsampling */ + + /* Shaders */ + const char *rgb_shader; /* Shader to convert to RGBA (or NULL) */ +} MetaMultiTextureFormatInfo; + +/* NOTE: The actual enum values are used as the index, so you don't need to + * loop over the table */ +static MetaMultiTextureFormatInfo multi_format_table[] = { + /* Invalid */ + {}, + /* Simple */ + { + .name = "", + .n_planes = 1, + .subformats = { COGL_PIXEL_FORMAT_ANY }, + .plane_indices = { 0 }, + .hsub = { 1 }, + .vsub = { 1 }, + .rgb_shader = rgba_shader, + }, + /* Packed YUV */ + { + .name = "YUYV", + .n_planes = 2, + .subformats = { COGL_PIXEL_FORMAT_RG_88, COGL_PIXEL_FORMAT_BGRA_8888_PRE }, + .plane_indices = { 0, 0 }, + .hsub = { 1, 2 }, + .vsub = { 1, 1 }, + .rgb_shader = y_xuxv_shader, + }, + /* 2 plane YUV */ + { + .name = "NV12", + .n_planes = 2, + .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_RG_88 }, + .plane_indices = { 0, 1 }, + .hsub = { 1, 2 }, + .vsub = { 1, 2 }, + .rgb_shader = nv12_shader, + }, + /* 3 plane YUV */ + { + .name = "YUV420", + .n_planes = 3, + .subformats = { COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8, COGL_PIXEL_FORMAT_G_8 }, + .plane_indices = { 0, 1, 2 }, + .hsub = { 1, 2, 2 }, + .vsub = { 1, 2, 2 }, + .rgb_shader = yuv420_shader, + }, +}; + +const char * +meta_multi_texture_format_to_string (MetaMultiTextureFormat format) +{ + g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), NULL); + + return multi_format_table[format].name; +} + +int +meta_multi_texture_format_get_n_planes (MetaMultiTextureFormat format) +{ + g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), 0); + + return multi_format_table[format].n_planes; +} + +void +meta_multi_texture_format_get_subformats (MetaMultiTextureFormat format, + const CoglPixelFormat **formats_out) +{ + g_return_if_fail (format < G_N_ELEMENTS (multi_format_table)); + + *formats_out = multi_format_table[format].subformats; +} + +void +meta_multi_texture_format_get_plane_indices (MetaMultiTextureFormat format, + const uint8_t **plane_indices_out) +{ + g_return_if_fail (format < G_N_ELEMENTS (multi_format_table)); + + *plane_indices_out = multi_format_table[format].plane_indices; +} + +void +meta_multi_texture_format_get_subsampling_factors (MetaMultiTextureFormat format, + const uint8_t **horizontal_factors_out, + const uint8_t **vertical_factors_out) +{ + g_return_if_fail (format < G_N_ELEMENTS (multi_format_table)); + + *horizontal_factors_out = multi_format_table[format].hsub; + *vertical_factors_out = multi_format_table[format].vsub; +} + +gboolean +meta_multi_texture_format_get_snippets (MetaMultiTextureFormat format, + CoglSnippet **fragment_globals_snippet, + CoglSnippet **fragment_snippet) +{ + g_return_val_if_fail (format < G_N_ELEMENTS (multi_format_table), FALSE); + + if (multi_format_table[format].rgb_shader == NULL) + return FALSE; + + if (fragment_globals_snippet) + { + *fragment_globals_snippet = + cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS, + shader_global_conversions, + NULL); + } + + if (fragment_snippet) + { + *fragment_snippet = + cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, + NULL, + multi_format_table[format].rgb_shader); + } + + return TRUE; +} diff --git a/src/compositor/meta-multi-texture.c b/src/compositor/meta-multi-texture.c new file mode 100644 index 0000000000000000000000000000000000000000..c756ddaead582f29618b1d55d3b1ebf64f439a84 --- /dev/null +++ b/src/compositor/meta-multi-texture.c @@ -0,0 +1,290 @@ +/* + * Authored By Niels De Graef + * + * 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 . + */ + +/** + * SECTION:meta-multi-texture + * @title: MetaMultiTexture + * @short_description: A texture that can have multiple planes. + * + * #MetaMultiTexture 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 #MetaMultiTexture 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 + * #MetaMultiTexture 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 meta_multi_texture_get_width() and its analogous version + * for the height to get the correct size of the texture. + */ + +#include "config.h" + +#include "meta/meta-multi-texture.h" + +#include "meta/meta-enum-types.h" + +struct _MetaMultiTexture +{ + GObject parent_instance; + + MetaMultiTextureFormat format; + + int n_planes; + CoglTexture **planes; +}; + +G_DEFINE_TYPE (MetaMultiTexture, meta_multi_texture, G_TYPE_OBJECT); + +/** + * meta_multi_texture_get_format: + * @multi_texture: a #MetaMultiTexture + * + * Returns the #MetaMultiTextureFormat that is used by this texture. + * + * Returns: The texture format that is used by this #MetaMultiTexture. + */ +MetaMultiTextureFormat +meta_multi_texture_get_format (MetaMultiTexture *multi_texture) +{ + g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), META_MULTI_TEXTURE_FORMAT_SIMPLE); + + return multi_texture->format; +} + +/** + * meta_multi_texture_is_simple: + * @multi_texture: a #MetaMultiTexture + * + * A small function that checks whether the given multi texture uses a "simple" + * format, i.e. one that can be represented by a #CoglPixelFormat. + * + * Returns: Whether the texture format is #META_MULTI_TEXTURE_FORMAT_SIMPLE + */ +gboolean +meta_multi_texture_is_simple (MetaMultiTexture *multi_texture) +{ + g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), FALSE); + + return multi_texture->format == META_MULTI_TEXTURE_FORMAT_SIMPLE; +} + +/** + * meta_multi_texture_get_n_planes: + * @multi_texture: a #MetaMultiTexture + * + * 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 #MetaMultiTexture. + */ +int +meta_multi_texture_get_n_planes (MetaMultiTexture *multi_texture) +{ + g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), 0); + + return multi_texture->n_planes; +} + +/** + * meta_multi_texture_get_plane: + * @multi_texture: a #MetaMultiTexture + * @index: the index of the plane + * + * Returns the n'th plane of the #MetaMultiTexture. Note that it's a programming + * error to use with an index larger than meta_multi_texture_get_n_planes(). + * + * Returns: (transfer none): The plane at the given @index. + */ +CoglTexture * +meta_multi_texture_get_plane (MetaMultiTexture *multi_texture, + int index) +{ + g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), 0); + g_return_val_if_fail (index < multi_texture->n_planes, NULL); + + return multi_texture->planes[index]; +} + +/** + * meta_multi_texture_get_width: + * @multi_texture: a #MetaMultiTexture + * + * Returns the width of the #MetaMultiTexture. 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. + */ +int +meta_multi_texture_get_width (MetaMultiTexture *multi_texture) +{ + g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), 0); + + return cogl_texture_get_width (multi_texture->planes[0]); +} + +/** + * meta_multi_texture_get_height: + * @multi_texture: a #MetaMultiTexture + * + * Returns the height of the #MetaMultiTexture. 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. + */ +int +meta_multi_texture_get_height (MetaMultiTexture *multi_texture) +{ + g_return_val_if_fail (META_IS_MULTI_TEXTURE (multi_texture), 0); + + return cogl_texture_get_height (multi_texture->planes[0]); +} + +static void +meta_multi_texture_finalize (GObject *object) +{ + MetaMultiTexture *multi_texture = META_MULTI_TEXTURE (object); + int i; + + for (i = 0; i < multi_texture->n_planes; i++) + cogl_clear_object (&multi_texture->planes[i]); + + g_free (multi_texture->planes); + + G_OBJECT_CLASS (meta_multi_texture_parent_class)->finalize (object); +} + +static void +meta_multi_texture_init (MetaMultiTexture *multi_texture) +{ +} + +static void +meta_multi_texture_class_init (MetaMultiTextureClass *klass) +{ + GObjectClass *gobj_class = G_OBJECT_CLASS (klass); + + gobj_class->finalize = meta_multi_texture_finalize; +} + +/** + * meta_multi_texture_new: + * @format: The format of the #MetaMultiTexture + * @planes: (transfer full): The actual planes of the texture + * @n_planes: The number of planes + * + * Creates a #MetaMultiTexture with the given @format. Each of the + * #CoglTextures represents a plane. + * + * Returns: (transfer full): A new #MetaMultiTexture. Use g_object_unref() when + * you're done with it. + */ +MetaMultiTexture * +meta_multi_texture_new (MetaMultiTextureFormat format, + CoglTexture **planes, + int n_planes) +{ + MetaMultiTexture *multi_texture; + + g_return_val_if_fail (planes != NULL, NULL); + g_return_val_if_fail (n_planes > 0, NULL); + + multi_texture = g_object_new (META_TYPE_MULTI_TEXTURE, NULL); + multi_texture->format = format; + multi_texture->n_planes = n_planes; + multi_texture->planes = planes; + + return multi_texture; +} + +/** + * meta_multi_texture_new_simple: + * @plane: (transfer full): The single plane of the texture + * + * Creates a #MetaMultiTexture for a "simple" texture, i.e. with only one + * plane, in a format that can be represented using #CoglPixelFormat. + * + * Returns: (transfer full): A new #MetaMultiTexture. Use g_object_unref() when + * you're done with it. + */ +MetaMultiTexture * +meta_multi_texture_new_simple (CoglTexture *plane) +{ + MetaMultiTexture *multi_texture; + + g_return_val_if_fail (plane != NULL, NULL); + + multi_texture = g_object_new (META_TYPE_MULTI_TEXTURE, NULL); + multi_texture->format = META_MULTI_TEXTURE_FORMAT_SIMPLE; + multi_texture->n_planes = 1; + multi_texture->planes = g_malloc (sizeof (CoglTexture *)); + multi_texture->planes[0] = plane; + + return multi_texture; +} + +/** + * meta_multi_texture_to_string: + * @multi_texture: a #MetaMultiTexture + * + * Returns a string representation of @multi_texture, useful for debugging + * purposes. + * + * Returns: (transfer full): A string representation of @multi_texture. Use + * g_free() when done with it. + */ +char * +meta_multi_texture_to_string (MetaMultiTexture *multi_texture) +{ + g_autoptr (GString) str = NULL; + g_autofree char *format_str = NULL; + g_autofree char *ret = NULL; + uint8_t i; + + str = g_string_new (""); + g_string_append_printf (str, "MetaMultiTexture (%p) {\n", multi_texture); + format_str = g_enum_to_string (META_TYPE_MULTI_TEXTURE_FORMAT, multi_texture->format); + g_string_append_printf (str, " .format = %s;\n", format_str); + g_string_append_printf (str, " .n_planes = %u;\n", multi_texture->n_planes); + g_string_append (str, " .planes = {\n"); + + for (i = 0; i < multi_texture->n_planes; i++) + { + CoglTexture *plane = multi_texture->planes[i]; + CoglPixelFormat plane_format = _cogl_texture_get_format (plane); + + g_string_append_printf (str, " (%p) { .format = %s },\n", + plane, + cogl_pixel_format_to_string (plane_format)); + } + + g_string_append (str, " }\n"); + g_string_append (str, "}"); + + ret = g_string_free (g_steal_pointer (&str), FALSE); + return g_steal_pointer (&ret); +} diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h index f9f22f51083c0087bd4887da8d2ae18c4cf67d63..97bd2554186cd87314f7fa494cf1ee58e34a9cca 100644 --- a/src/compositor/meta-shaped-texture-private.h +++ b/src/compositor/meta-shaped-texture-private.h @@ -30,9 +30,41 @@ #include "backends/meta-monitor-manager-private.h" #include "meta/meta-shaped-texture.h" +typedef enum _MetaShapedTexturePremult +{ + META_SHAPED_TEXTURE_PREMULT_ELECTRICAL = 0, + META_SHAPED_TEXTURE_PREMULT_OPTICAL, + META_SHAPED_TEXTURE_PREMULT_STRAIGHT, +} MetaShapedTexturePremult; + +typedef enum _MetaShapedTextureCoefficients +{ + META_SHAPED_TEXTURE_COEFFICIENTS_NONE = 0, + META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_FULL, + META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_LIMITED, + META_SHAPED_TEXTURE_COEFFICIENTS_BT709_FULL, + META_SHAPED_TEXTURE_COEFFICIENTS_BT709_LIMITED, +} MetaShapedTextureCoefficients; + +typedef enum _MetaShapedTextureChromaLoc +{ + META_SHAPED_TEXTURE_CHROMA_LOC_NONE = 0, + META_SHAPED_TEXTURE_CHROMA_LOC_CENTER, +} MetaShapedTextureChromaLoc; + +typedef struct _MetaShapedTextureColorRepr +{ + MetaShapedTexturePremult premult; + MetaShapedTextureCoefficients coeffs; + MetaShapedTextureChromaLoc chroma_loc; +} MetaShapedTextureColorRepr; + +void meta_shaped_texture_color_repr_copy (MetaShapedTextureColorRepr *src, + MetaShapedTextureColorRepr *dst); + MetaShapedTexture * meta_shaped_texture_new (void); void meta_shaped_texture_set_texture (MetaShapedTexture *stex, - CoglTexture *texture); + MetaMultiTexture *multi_texture); void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, gboolean is_y_inverted); void meta_shaped_texture_set_snippet (MetaShapedTexture *stex, @@ -78,4 +110,10 @@ void meta_shaped_texture_ensure_size_valid (MetaShapedTexture *stex); gboolean meta_shaped_texture_should_get_via_offscreen (MetaShapedTexture *stex); +void meta_shaped_texture_set_color_repr (MetaShapedTexture *stex, + MetaShapedTextureColorRepr *color_repr); + +META_EXPORT_TEST +const MetaShapedTextureColorRepr * meta_shaped_texture_get_color_repr (MetaShapedTexture *stex); + #endif diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 2181c7680342fa144c9ca28c8a9795c4f7a952ad..68c627f3531951ba7761ed76be24cd9832c2e365 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -35,6 +35,7 @@ #include "config.h" #include "backends/meta-monitor-transform.h" +#include "compositor/meta-multi-texture-format-private.h" #include "compositor/meta-shaped-texture-private.h" #include "core/boxes-private.h" @@ -69,11 +70,12 @@ struct _MetaShapedTexture { GObject parent; - CoglTexture *texture; + MetaMultiTexture *texture; CoglTexture *mask_texture; CoglSnippet *snippet; CoglPipeline *base_pipeline; + CoglPipeline *combined_pipeline; CoglPipeline *unmasked_pipeline; CoglPipeline *unmasked_tower_pipeline; CoglPipeline *masked_pipeline; @@ -106,6 +108,8 @@ struct _MetaShapedTexture int buffer_scale; guint create_mipmaps : 1; + + MetaShapedTextureColorRepr color_repr; }; G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, G_TYPE_OBJECT, @@ -225,6 +229,7 @@ static void meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex) { g_clear_pointer (&stex->base_pipeline, cogl_object_unref); + g_clear_pointer (&stex->combined_pipeline, cogl_object_unref); g_clear_pointer (&stex->unmasked_pipeline, cogl_object_unref); g_clear_pointer (&stex->unmasked_tower_pipeline, cogl_object_unref); g_clear_pointer (&stex->masked_pipeline, cogl_object_unref); @@ -259,19 +264,23 @@ get_base_pipeline (MetaShapedTexture *stex, { CoglPipeline *pipeline; graphene_matrix_t matrix; + int 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); + + /* We'll add as many layers as there are planes in the multi texture, + * plus an extra one for the mask */ + n_planes = meta_multi_texture_get_n_planes (stex->texture); + for (i = 0; i < (n_planes + 1); 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); + } graphene_matrix_init_identity (&matrix); @@ -320,17 +329,55 @@ get_base_pipeline (MetaShapedTexture *stex, graphene_matrix_scale (&matrix, 1, -1, 1); } - cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); + for (i = 0; i < n_planes; i++) + cogl_pipeline_set_layer_matrix (pipeline, i, &matrix); stex->base_pipeline = pipeline; - return stex->base_pipeline; + return pipeline; +} + +static CoglPipeline * +get_combined_pipeline (MetaShapedTexture *stex, + CoglContext *ctx) +{ + MetaMultiTextureFormat format; + CoglPipeline *pipeline; + CoglSnippet *fragment_globals_snippet; + CoglSnippet *fragment_snippet; + int i, n_planes; + + if (stex->combined_pipeline) + return stex->combined_pipeline; + + pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); + format = meta_multi_texture_get_format (stex->texture); + n_planes = meta_multi_texture_get_n_planes (stex->texture); + + for (i = 0; i < n_planes; i++) + { + cogl_pipeline_set_layer_combine (pipeline, i, + "RGBA = REPLACE(TEXTURE)", NULL); + } + + meta_multi_texture_format_get_snippets (format, + &fragment_globals_snippet, + &fragment_snippet); + cogl_pipeline_add_snippet (pipeline, fragment_globals_snippet); + cogl_pipeline_add_snippet (pipeline, fragment_snippet); + + cogl_clear_object (&fragment_globals_snippet); + cogl_clear_object (&fragment_snippet); + + stex->combined_pipeline = pipeline; + + return pipeline; } static CoglPipeline * get_unmasked_pipeline (MetaShapedTexture *stex, CoglContext *ctx, - CoglTexture *tex) + MetaMultiTexture *tex) { if (stex->texture == tex) { @@ -339,7 +386,7 @@ get_unmasked_pipeline (MetaShapedTexture *stex, if (stex->unmasked_pipeline) return stex->unmasked_pipeline; - pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); + pipeline = cogl_pipeline_copy (get_combined_pipeline (stex, ctx)); if (stex->snippet) cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet); @@ -362,8 +409,10 @@ get_unmasked_pipeline (MetaShapedTexture *stex, static CoglPipeline * get_masked_pipeline (MetaShapedTexture *stex, CoglContext *ctx, - CoglTexture *tex) + MetaMultiTexture *tex) { + g_assert (meta_multi_texture_get_n_planes (stex->texture) == 1); + if (stex->texture == tex) { CoglPipeline *pipeline; @@ -401,7 +450,7 @@ get_masked_pipeline (MetaShapedTexture *stex, static CoglPipeline * get_unblended_pipeline (MetaShapedTexture *stex, CoglContext *ctx, - CoglTexture *tex) + MetaMultiTexture *tex) { if (stex->texture == tex) { @@ -410,7 +459,7 @@ get_unblended_pipeline (MetaShapedTexture *stex, if (stex->unblended_pipeline) return stex->unblended_pipeline; - pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); + pipeline = cogl_pipeline_copy (get_combined_pipeline (stex, ctx)); cogl_pipeline_set_layer_combine (pipeline, 0, "RGBA = REPLACE (TEXTURE)", NULL); @@ -527,18 +576,18 @@ paint_clipped_rectangle_node (MetaShapedTexture *stex, } static void -set_cogl_texture (MetaShapedTexture *stex, - CoglTexture *cogl_tex) +set_multi_texture (MetaShapedTexture *stex, + MetaMultiTexture *multi_tex) { int width, height; - cogl_clear_object (&stex->texture); + g_clear_object (&stex->texture); - if (cogl_tex != NULL) + if (multi_tex != NULL) { - stex->texture = cogl_object_ref (cogl_tex); - width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); - height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex)); + stex->texture = g_object_ref (multi_tex); + width = meta_multi_texture_get_width (multi_tex); + height = meta_multi_texture_get_height (multi_tex); } else { @@ -584,10 +633,11 @@ do_paint_content (MetaShapedTexture *stex, CoglContext *ctx; CoglPipelineFilter min_filter, mag_filter; MetaTransforms transforms; - CoglTexture *paint_tex = stex->texture; + MetaMultiTexture *paint_tex = stex->texture; CoglFramebuffer *framebuffer; int sample_width, sample_height; gboolean debug_paint_opaque_region; + int n_planes; meta_shaped_texture_ensure_size_valid (stex); @@ -622,8 +672,8 @@ do_paint_content (MetaShapedTexture *stex, } else { - sample_width = cogl_texture_get_width (stex->texture); - sample_height = cogl_texture_get_height (stex->texture); + sample_width = meta_multi_texture_get_width (stex->texture); + sample_height = meta_multi_texture_get_height (stex->texture); } if (meta_monitor_transform_is_rotated (stex->transform)) flip_ints (&sample_width, &sample_height); @@ -692,6 +742,8 @@ do_paint_content (MetaShapedTexture *stex, } } + n_planes = meta_multi_texture_get_n_planes (paint_tex); + /* First, paint the unblended parts, which are part of the opaque region. */ if (use_opaque_region) { @@ -714,8 +766,15 @@ do_paint_content (MetaShapedTexture *stex, CoglPipeline *opaque_pipeline; opaque_pipeline = get_unblended_pipeline (stex, ctx, paint_tex); - cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); - cogl_pipeline_set_layer_filters (opaque_pipeline, 0, min_filter, mag_filter); + + for (i = 0; i < n_planes; i++) + { + CoglTexture *plane = meta_multi_texture_get_plane (paint_tex, i); + + cogl_pipeline_set_layer_texture (opaque_pipeline, i, plane); + cogl_pipeline_set_layer_filters (opaque_pipeline, i, + min_filter, mag_filter); + } n_rects = cairo_region_num_rectangles (region); for (i = 0; i < n_rects; i++) @@ -755,6 +814,7 @@ do_paint_content (MetaShapedTexture *stex, { CoglPipeline *blended_pipeline; CoglColor color; + int i; if (stex->mask_texture == NULL) { @@ -763,12 +823,17 @@ do_paint_content (MetaShapedTexture *stex, else { blended_pipeline = get_masked_pipeline (stex, ctx, paint_tex); - cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture); - cogl_pipeline_set_layer_filters (blended_pipeline, 1, min_filter, mag_filter); + cogl_pipeline_set_layer_texture (blended_pipeline, n_planes, stex->mask_texture); + cogl_pipeline_set_layer_filters (blended_pipeline, n_planes, min_filter, mag_filter); } - cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex); - cogl_pipeline_set_layer_filters (blended_pipeline, 0, min_filter, mag_filter); + for (i = 0; i < n_planes; i++) + { + CoglTexture *plane = meta_multi_texture_get_plane (paint_tex, i); + + cogl_pipeline_set_layer_texture (blended_pipeline, i, plane); + cogl_pipeline_set_layer_filters (blended_pipeline, i, min_filter, mag_filter); + } cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); cogl_pipeline_set_color (blended_pipeline, &color); @@ -1055,18 +1120,18 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, /** * meta_shaped_texture_set_texture: * @stex: The #MetaShapedTexture - * @pixmap: The #CoglTexture to display + * @pixmap: The #MetaMultiTexture to display */ void meta_shaped_texture_set_texture (MetaShapedTexture *stex, - CoglTexture *texture) + MetaMultiTexture *texture) { g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); if (stex->texture == texture) return; - set_cogl_texture (stex, texture); + set_multi_texture (stex, texture); } /** @@ -1107,11 +1172,11 @@ meta_shaped_texture_set_snippet (MetaShapedTexture *stex, * * Returns: (transfer none): the unshaped texture */ -CoglTexture * +MetaMultiTexture * 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; } /** @@ -1143,13 +1208,18 @@ meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex) gboolean meta_shaped_texture_has_alpha (MetaShapedTexture *stex) { - CoglTexture *texture; + MetaMultiTexture *multi_texture; + CoglTexture *cogl_texture; - texture = stex->texture; - if (!texture) + multi_texture = stex->texture; + if (!multi_texture) return TRUE; - switch (cogl_texture_get_components (texture)) + if (!meta_multi_texture_is_simple (multi_texture)) + return FALSE; + + cogl_texture = meta_multi_texture_get_plane (multi_texture, 0); + switch (cogl_texture_get_components (cogl_texture)) { case COGL_TEXTURE_COMPONENTS_A: case COGL_TEXTURE_COMPONENTS_RGBA: @@ -1167,12 +1237,12 @@ meta_shaped_texture_has_alpha (MetaShapedTexture *stex) gboolean meta_shaped_texture_is_opaque (MetaShapedTexture *stex) { - CoglTexture *texture; + MetaMultiTexture *multi_texture; cairo_rectangle_int_t opaque_rect; - texture = stex->texture; - if (!texture) - return FALSE; + multi_texture = stex->texture; + if (!multi_texture) + return TRUE; if (!meta_shaped_texture_has_alpha (stex)) return TRUE; @@ -1301,10 +1371,16 @@ meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex) gboolean meta_shaped_texture_should_get_via_offscreen (MetaShapedTexture *stex) { + CoglTexture *cogl_texture; + if (stex->mask_texture != NULL) return TRUE; - if (!cogl_texture_is_get_data_supported (stex->texture)) + if (meta_multi_texture_get_n_planes (stex->texture) > 1) + return FALSE; + + cogl_texture = meta_multi_texture_get_plane (stex->texture, 0); + if (!cogl_texture_is_get_data_supported (cogl_texture)) return TRUE; if (stex->has_viewport_src_rect || stex->has_viewport_dst_size) @@ -1353,9 +1429,7 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex, 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; if (meta_shaped_texture_should_get_via_offscreen (stex)) @@ -1388,6 +1462,9 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex, }; } + /* We know that we only have 1 plane at this point */ + texture = meta_multi_texture_get_plane (stex->texture, 0); + if (image_clip) texture = COGL_TEXTURE (cogl_sub_texture_new (cogl_context, texture, @@ -1559,3 +1636,26 @@ meta_shaped_texture_get_unscaled_height (MetaShapedTexture *stex) return unscaled_size.height; } + +void +meta_shaped_texture_set_color_repr (MetaShapedTexture *stex, + MetaShapedTextureColorRepr *color_repr) +{ + meta_shaped_texture_color_repr_copy (color_repr, &stex->color_repr); +} + + +const MetaShapedTextureColorRepr * +meta_shaped_texture_get_color_repr (MetaShapedTexture *stex) +{ + return &stex->color_repr; +} + +void +meta_shaped_texture_color_repr_copy (MetaShapedTextureColorRepr *src, + MetaShapedTextureColorRepr *dst) +{ + dst->premult = src->premult; + dst->coeffs = src->coeffs; + dst->chroma_loc = src->chroma_loc; +} diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c index 8fba241a6e2bf9dfecac86e913a0634d10a4fd92..53d9823360d9586854f1b312b709f2a14eb8addd 100644 --- a/src/compositor/meta-surface-actor-x11.c +++ b/src/compositor/meta-surface-actor-x11.c @@ -46,7 +46,7 @@ struct _MetaSurfaceActorX11 MetaDisplay *display; - CoglTexture *texture; + MetaMultiTexture *texture; Pixmap pixmap; Damage damage; @@ -109,7 +109,7 @@ detach_pixmap (MetaSurfaceActorX11 *self) self->pixmap = None; meta_x11_error_trap_pop (display->x11_display); - g_clear_pointer (&self->texture, cogl_object_unref); + g_clear_object (&self->texture); } static void @@ -119,23 +119,23 @@ set_pixmap (MetaSurfaceActorX11 *self, CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); GError *error = NULL; - CoglTexture *texture; + CoglTexture *cogl_texture; g_assert (self->pixmap == None); self->pixmap = pixmap; - texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, self->pixmap, FALSE, &error)); + cogl_texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, self->pixmap, FALSE, &error)); if (error != NULL) { g_warning ("Failed to allocate stex texture: %s", error->message); g_error_free (error); } - else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) + else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (cogl_texture)))) g_warning ("NOTE: Not using GLX TFP!"); - self->texture = texture; - meta_shaped_texture_set_texture (stex, texture); + self->texture = meta_multi_texture_new_simple (cogl_texture); + meta_shaped_texture_set_texture (stex, self->texture); } static void @@ -195,6 +195,7 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, int height) { MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + CoglTexturePixmapX11 *pixmap; self->received_damage = TRUE; @@ -218,8 +219,12 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, if (!meta_surface_actor_x11_is_visible (self)) return; - cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (self->texture), - x, y, width, height); + /* We don't support multi-plane or YUV based formats in X */ + if (!meta_multi_texture_is_simple (self->texture)) + return; + + pixmap = COGL_TEXTURE_PIXMAP_X11 (meta_multi_texture_get_plane (self->texture, 0)); + cogl_texture_pixmap_x11_update_area (pixmap, x, y, width, height); meta_surface_actor_update_area (actor, x, y, width, height); } diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h index f69cb15275e840c314c257482e74e7dfece3d9a9..1564976e7f109389829882910ca7c9f43f14a000 100644 --- a/src/compositor/meta-surface-actor.h +++ b/src/compositor/meta-surface-actor.h @@ -6,6 +6,7 @@ #include "config.h" #include "backends/meta-backend-types.h" +#include "core/util-private.h" #include "meta/meta-shaped-texture.h" #include "meta/window.h" @@ -27,6 +28,7 @@ struct _MetaSurfaceActorClass gboolean (* is_opaque) (MetaSurfaceActor *actor); }; +META_EXPORT_TEST MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); void meta_surface_actor_update_area (MetaSurfaceActor *self, diff --git a/src/compositor/meta-texture-mipmap.c b/src/compositor/meta-texture-mipmap.c index 177704b97fc29751e4703eebf2b5a0618e6cbfd7..e3a127cd2cb1f0144674d9355cb0c2d7308883f2 100644 --- a/src/compositor/meta-texture-mipmap.c +++ b/src/compositor/meta-texture-mipmap.c @@ -25,14 +25,15 @@ #include "config.h" #include "compositor/meta-texture-mipmap.h" +#include "compositor/meta-multi-texture-format-private.h" #include #include struct _MetaTextureMipmap { - CoglTexture *base_texture; - CoglTexture *mipmap_texture; + MetaMultiTexture *base_texture; + MetaMultiTexture *mipmap_texture; CoglPipeline *pipeline; CoglFramebuffer *fb; gboolean invalid; @@ -68,8 +69,8 @@ meta_texture_mipmap_free (MetaTextureMipmap *mipmap) g_return_if_fail (mipmap != NULL); cogl_clear_object (&mipmap->pipeline); - cogl_clear_object (&mipmap->base_texture); - cogl_clear_object (&mipmap->mipmap_texture); + g_clear_object (&mipmap->base_texture); + g_clear_object (&mipmap->mipmap_texture); g_clear_object (&mipmap->fb); g_free (mipmap); @@ -87,20 +88,20 @@ meta_texture_mipmap_free (MetaTextureMipmap *mipmap) */ void meta_texture_mipmap_set_base_texture (MetaTextureMipmap *mipmap, - CoglTexture *texture) + MetaMultiTexture *texture) { g_return_if_fail (mipmap != NULL); if (texture == mipmap->base_texture) return; - cogl_clear_object (&mipmap->base_texture); + g_clear_object (&mipmap->base_texture); mipmap->base_texture = texture; if (mipmap->base_texture != NULL) { - cogl_object_ref (mipmap->base_texture); + g_object_ref (mipmap->base_texture); mipmap->invalid = TRUE; } } @@ -117,7 +118,7 @@ static void free_mipmaps (MetaTextureMipmap *mipmap) { g_clear_object (&mipmap->fb); - cogl_clear_object (&mipmap->mipmap_texture); + g_clear_object (&mipmap->mipmap_texture); } void @@ -150,8 +151,8 @@ ensure_mipmap_texture (MetaTextureMipmap *mipmap) * then just use the original texture instead of mipmap texture, which is * faster anyway. */ - width = cogl_texture_get_width (mipmap->base_texture) / 2; - height = cogl_texture_get_height (mipmap->base_texture) / 2; + width = meta_multi_texture_get_width (mipmap->base_texture) / 2; + height = meta_multi_texture_get_height (mipmap->base_texture) / 2; if (!width || !height) { @@ -160,11 +161,12 @@ ensure_mipmap_texture (MetaTextureMipmap *mipmap) } if (!mipmap->mipmap_texture || - cogl_texture_get_width (mipmap->mipmap_texture) != width || - cogl_texture_get_height (mipmap->mipmap_texture) != height) + meta_multi_texture_get_width (mipmap->mipmap_texture) != width || + meta_multi_texture_get_height (mipmap->mipmap_texture) != height) { CoglOffscreen *offscreen; CoglTexture2D *tex2d; + CoglTexture *tex; free_mipmaps (mipmap); @@ -172,9 +174,10 @@ ensure_mipmap_texture (MetaTextureMipmap *mipmap) if (!tex2d) return; - mipmap->mipmap_texture = COGL_TEXTURE (tex2d); + tex = COGL_TEXTURE (tex2d); + mipmap->mipmap_texture = meta_multi_texture_new_simple (tex); - offscreen = cogl_offscreen_new_with_texture (mipmap->mipmap_texture); + offscreen = cogl_offscreen_new_with_texture (tex); if (!offscreen) { free_mipmaps (mipmap); @@ -197,16 +200,49 @@ ensure_mipmap_texture (MetaTextureMipmap *mipmap) if (mipmap->invalid) { + int n_planes, i; + + n_planes = meta_multi_texture_get_n_planes (mipmap->base_texture); + if (!mipmap->pipeline) { + MetaMultiTextureFormat format = + meta_multi_texture_get_format (mipmap->base_texture); + CoglSnippet *fragment_globals_snippet; + CoglSnippet *fragment_snippet; + mipmap->pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_blend (mipmap->pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); - cogl_pipeline_set_layer_filters (mipmap->pipeline, 0, - COGL_PIPELINE_FILTER_LINEAR, - COGL_PIPELINE_FILTER_LINEAR); + cogl_pipeline_set_blend (mipmap->pipeline, + "RGBA = ADD (SRC_COLOR, 0)", + NULL); + + for (i = 0; i < n_planes; i++) + { + cogl_pipeline_set_layer_filters (mipmap->pipeline, i, + COGL_PIPELINE_FILTER_LINEAR, + COGL_PIPELINE_FILTER_LINEAR); + cogl_pipeline_set_layer_combine (mipmap->pipeline, i, + "RGBA = REPLACE(TEXTURE)", + NULL); + } + + meta_multi_texture_format_get_snippets (format, + &fragment_globals_snippet, + &fragment_snippet); + cogl_pipeline_add_snippet (mipmap->pipeline, fragment_globals_snippet); + cogl_pipeline_add_snippet (mipmap->pipeline, fragment_snippet); + + cogl_clear_object (&fragment_globals_snippet); + cogl_clear_object (&fragment_snippet); + } + + for (i = 0; i < n_planes; i++) + { + CoglTexture *plane = meta_multi_texture_get_plane (mipmap->base_texture, i); + + cogl_pipeline_set_layer_texture (mipmap->pipeline, i, plane); } - cogl_pipeline_set_layer_texture (mipmap->pipeline, 0, mipmap->base_texture); cogl_framebuffer_draw_textured_rectangle (mipmap->fb, mipmap->pipeline, 0, 0, width, height, @@ -229,7 +265,7 @@ ensure_mipmap_texture (MetaTextureMipmap *mipmap) * Return value: the COGL texture handle to use for painting, or * %NULL if no base texture has yet been set. */ -CoglTexture * +MetaMultiTexture * meta_texture_mipmap_get_paint_texture (MetaTextureMipmap *mipmap) { g_return_val_if_fail (mipmap != NULL, NULL); diff --git a/src/compositor/meta-texture-mipmap.h b/src/compositor/meta-texture-mipmap.h index 3a6c4560482501658aee04544a4be4aa26023a02..8b47162a9f382bc822ee734e4daa62ec9e8e5719 100644 --- a/src/compositor/meta-texture-mipmap.h +++ b/src/compositor/meta-texture-mipmap.h @@ -24,6 +24,7 @@ #define META_TEXTURE_MIPMAP_H #include "clutter/clutter.h" +#include "meta/meta-multi-texture.h" G_BEGIN_DECLS @@ -42,9 +43,9 @@ MetaTextureMipmap *meta_texture_mipmap_new (void); void meta_texture_mipmap_free (MetaTextureMipmap *mipmap); void meta_texture_mipmap_set_base_texture (MetaTextureMipmap *mipmap, - CoglTexture *texture); + MetaMultiTexture *texture); -CoglTexture *meta_texture_mipmap_get_paint_texture (MetaTextureMipmap *mipmap); +MetaMultiTexture *meta_texture_mipmap_get_paint_texture (MetaTextureMipmap *mipmap); void meta_texture_mipmap_invalidate (MetaTextureMipmap *mipmap); diff --git a/src/meson.build b/src/meson.build index 4af81aa8c6f25b46a1d4f3b8466e6c7600cb42da..5391cb72da491ec4116c591c75d0716cc4d40f1c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -133,6 +133,9 @@ if have_wayland mutter_pkg_deps += [ wayland_server_dep, ] + mutter_pkg_private_deps += [ + libdrm_dep, + ] endif if have_libsystemd @@ -307,6 +310,9 @@ mutter_sources = [ 'compositor/meta-later.c', 'compositor/meta-module.c', 'compositor/meta-module.h', + 'compositor/meta-multi-texture.c', + 'compositor/meta-multi-texture-format.c', + 'compositor/meta-multi-texture-format-private.h', 'compositor/meta-plugin.c', 'compositor/meta-plugin-manager.c', 'compositor/meta-plugin-manager.h', @@ -559,6 +565,8 @@ endif if have_wayland mutter_sources += [ + 'backends/meta-cogl-utils.c', + 'backends/meta-cogl-utils.h', 'compositor/meta-surface-actor-wayland.c', 'compositor/meta-surface-actor-wayland.h', 'compositor/meta-window-actor-wayland.c', @@ -582,6 +590,8 @@ if have_wayland 'wayland/meta-wayland.c', 'wayland/meta-wayland-client.c', 'wayland/meta-wayland-client-private.h', + 'wayland/meta-wayland-color-representation.c', + 'wayland/meta-wayland-color-representation.h', 'wayland/meta-wayland-cursor-surface.c', 'wayland/meta-wayland-cursor-surface.h', 'wayland/meta-wayland-data-device.c', @@ -708,6 +718,8 @@ endif if have_native_backend mutter_sources += [ + 'backends/meta-cogl-utils.c', + 'backends/meta-cogl-utils.h', 'backends/native/dbus-utils.c', 'backends/native/dbus-utils.h', 'backends/native/meta-backend-native.c', @@ -718,8 +730,6 @@ if have_native_backend 'backends/native/meta-barrier-native.h', 'backends/native/meta-clutter-backend-native.c', 'backends/native/meta-clutter-backend-native.h', - 'backends/native/meta-cogl-utils.c', - 'backends/native/meta-cogl-utils.h', 'backends/native/meta-crtc-kms.c', 'backends/native/meta-crtc-kms.h', 'backends/native/meta-crtc-native.c', @@ -1013,6 +1023,7 @@ if have_wayland # - protocol stability ('private', 'stable' or 'unstable') # - protocol version (if stability is 'unstable') wayland_protocols = [ + ['color-representation', 'staging', 'v1', ], ['fractional-scale', 'staging', 'v1', ], ['gtk-shell', 'private', ], ['keyboard-shortcuts-inhibit', 'unstable', 'v1', ], diff --git a/src/meta/meson.build b/src/meta/meson.build index dece2feb33c9336a9fac9907da8bfa8a3e636d19..688ff30048209f51213cccd9ad1f0bcf324af036 100644 --- a/src/meta/meson.build +++ b/src/meta/meson.build @@ -24,6 +24,8 @@ mutter_public_headers = [ 'meta-launch-context.h', 'meta-later.h', 'meta-monitor-manager.h', + 'meta-multi-texture.h', + 'meta-multi-texture-format.h', 'meta-plugin.h', 'meta-remote-access-controller.h', 'meta-selection.h', diff --git a/src/meta/meta-multi-texture-format.h b/src/meta/meta-multi-texture-format.h new file mode 100644 index 0000000000000000000000000000000000000000..21afc02e083ed97e1bc602aa6f92e172e330d0de --- /dev/null +++ b/src/meta/meta-multi-texture-format.h @@ -0,0 +1,46 @@ +/* + * Authored By Niels De Graef + * + * 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 . + */ + +#ifndef META_MULTI_TEXTURE_FORMAT_H +#define META_MULTI_TEXTURE_FORMAT_H + +#include + +G_BEGIN_DECLS + +/** + * MetaMultiTextureFormat: + * @META_MULTI_TEXTURE_FORMAT_INVALID: Invalid value + * @META_MULTI_TEXTURE_FORMAT_SIMPLE: Any format supported by Cogl (see #CoglPixelFormat) + * @META_MULTI_TEXTURE_FORMAT_YUYV: YUYV, 32 bits, 16 bpc (Y), 8 bpc (U & V) + * @META_MULTI_TEXTURE_FORMAT_NV12: 2 planes: 1 Y-plane, 1 UV-plane (2x2 subsampled) + * @META_MULTI_TEXTURE_FORMAT_YUV420: 3 planes: 1 Y-plane, 1 U-plane (2x2 subsampled), 1 V-plane (2x2 subsampled) + */ +typedef enum _MetaMultiTextureFormat +{ + META_MULTI_TEXTURE_FORMAT_INVALID, + META_MULTI_TEXTURE_FORMAT_SIMPLE, + META_MULTI_TEXTURE_FORMAT_YUYV, + META_MULTI_TEXTURE_FORMAT_NV12, + META_MULTI_TEXTURE_FORMAT_YUV420, +} MetaMultiTextureFormat; + +G_END_DECLS + +#endif /* META_MULTI_TEXTURE_FORMAT_H */ diff --git a/src/meta/meta-multi-texture.h b/src/meta/meta-multi-texture.h new file mode 100644 index 0000000000000000000000000000000000000000..505439d4cb4325af8806685f8c47a14bd799c01d --- /dev/null +++ b/src/meta/meta-multi-texture.h @@ -0,0 +1,74 @@ +/* + * Authored By Niels De Graef + * + * 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 META_MULTI_TEXTURE_H +#define META_MULTI_TEXTURE_H + +#include +#include +#include + +#include "meta/meta-multi-texture-format.h" + +G_BEGIN_DECLS + +#define META_TYPE_MULTI_TEXTURE (meta_multi_texture_get_type ()) +META_EXPORT +G_DECLARE_FINAL_TYPE (MetaMultiTexture, + meta_multi_texture, + META, + MULTI_TEXTURE, + GObject) + + +META_EXPORT +MetaMultiTexture * meta_multi_texture_new (MetaMultiTextureFormat format, + CoglTexture **planes, + int n_planes); + +META_EXPORT +MetaMultiTexture * meta_multi_texture_new_simple (CoglTexture *plane); + +META_EXPORT +MetaMultiTextureFormat meta_multi_texture_get_format (MetaMultiTexture *multi_texture); + +META_EXPORT +gboolean meta_multi_texture_is_simple (MetaMultiTexture *multi_texture); + +META_EXPORT +int meta_multi_texture_get_n_planes (MetaMultiTexture *multi_texture); + +META_EXPORT +CoglTexture * meta_multi_texture_get_plane (MetaMultiTexture *multi_texture, + int index); + +META_EXPORT +int meta_multi_texture_get_width (MetaMultiTexture *multi_texture); + +META_EXPORT +int meta_multi_texture_get_height (MetaMultiTexture *multi_texture); + +META_EXPORT +char * meta_multi_texture_to_string (MetaMultiTexture *multi_texture); + +G_END_DECLS + +#endif /* META_MULTI_TEXTURE_H */ diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h index 2ca0e6e61dbe972cb09cc18d1709b4b75a7a4147..1714addf62683ef8e9206769588b32f9258c0cd6 100644 --- a/src/meta/meta-shaped-texture.h +++ b/src/meta/meta-shaped-texture.h @@ -28,6 +28,7 @@ #include "clutter/clutter.h" #include +#include G_BEGIN_DECLS @@ -45,7 +46,7 @@ void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, gboolean create_mipmaps); META_EXPORT -CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex); +MetaMultiTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex); META_EXPORT void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, diff --git a/src/tests/cogl/conform/test-offscreen-texture-formats.c b/src/tests/cogl/conform/test-offscreen-texture-formats.c index 7b6e61ec7000e6a3a563f809a6c789155120cc0e..589b689694172add155b38d6908b141824872d95 100644 --- a/src/tests/cogl/conform/test-offscreen-texture-formats.c +++ b/src/tests/cogl/conform/test-offscreen-texture-formats.c @@ -36,8 +36,8 @@ rgb10_to_rgb8 (int rgb10) { float r; - r = rgb10 / (float) (1 << 10); - return (int) (r * (float) (1 << 8)); + r = rgb10 / (float) ((1 << 10) - 1); + return (int) (r * (float) ((1 << 8) - 1)); } static int @@ -45,8 +45,8 @@ rgb8_to_rgb10 (int rgb8) { float r; - r = rgb8 / (float) (1 << 8); - return (int) (r * (float) (1 << 10)); + r = rgb8 / (float) ((1 << 8) - 1); + return (int) (r * (float) ((1 << 10) - 1)); } static void @@ -55,25 +55,28 @@ test_offscreen_texture_formats_store_rgb10 (void) const int rgb10_red = 514; const int rgb10_green = 258; const int rgb10_blue = 18; + const int rgb10_alpha = 2; float red; float green; float blue; + float alpha; GError *error = NULL; CoglPixelFormat formats[] = { - COGL_PIXEL_FORMAT_ABGR_2101010, - COGL_PIXEL_FORMAT_ARGB_2101010, COGL_PIXEL_FORMAT_XRGB_2101010, - COGL_PIXEL_FORMAT_RGBA_1010102, - COGL_PIXEL_FORMAT_BGRA_1010102, + COGL_PIXEL_FORMAT_ARGB_2101010_PRE, COGL_PIXEL_FORMAT_XBGR_2101010, + COGL_PIXEL_FORMAT_ABGR_2101010_PRE, + COGL_PIXEL_FORMAT_RGBA_1010102_PRE, + COGL_PIXEL_FORMAT_BGRA_1010102_PRE, }; int i; /* The extra fraction is there to avoid rounding inconsistencies in OpenGL * implementations. */ - red = (rgb10_red / (float) (1 << 10)) + 0.00001; - green = (rgb10_green / (float) (1 << 10)) + 0.00001; - blue = (rgb10_blue / (float) (1 << 10)) + 0.00001; + red = (rgb10_red / (float) ((1 << 10) - 1)) + 0.00001; + green = (rgb10_green / (float) ((1 << 10) - 1)) + 0.00001; + blue = (rgb10_blue / (float) ((1 << 10) - 1)) + 0.00001; + alpha = (rgb10_alpha / (float) ((1 << 2) - 1)) + 0.00001; /* Make sure that that the color value can't be represented using rgb8. */ g_assert_cmpint (rgb8_to_rgb10 (rgb10_to_rgb8 (rgb10_red)), !=, rgb10_red); @@ -85,8 +88,7 @@ test_offscreen_texture_formats_store_rgb10 (void) CoglTexture2D *tex; CoglOffscreen *offscreen; uint32_t rgb8_readback[4]; - uint8_t *rgb8_buf; - int j; + int j, k; /* Allocate 2x2 to ensure we avoid any fast paths. */ tex = cogl_texture_2d_new_with_format (test_ctx, 2, 2, formats[i]); @@ -97,72 +99,182 @@ test_offscreen_texture_formats_store_rgb10 (void) cogl_framebuffer_clear4f (COGL_FRAMEBUFFER (offscreen), COGL_BUFFER_BIT_COLOR, - red, green, blue, 1.0); + red, green, blue, alpha); for (j = 0; j < G_N_ELEMENTS (formats); j++) { uint32_t rgb10_readback[4]; - int channels[3]; - int alpha; + int alpha_out; cogl_framebuffer_read_pixels (COGL_FRAMEBUFFER (offscreen), 0, 0, 2, 2, formats[j], (uint8_t *) &rgb10_readback); - switch (formats[j]) - { - case COGL_PIXEL_FORMAT_RGBA_1010102: - case COGL_PIXEL_FORMAT_BGRA_1010102: - channels[0] = get_bits (rgb10_readback[0], 31, 22); - channels[1] = get_bits (rgb10_readback[0], 21, 12); - channels[2] = get_bits (rgb10_readback[0], 11, 2); - alpha = get_bits (rgb10_readback[0], 1, 0); - break; - case COGL_PIXEL_FORMAT_XRGB_2101010: - case COGL_PIXEL_FORMAT_ARGB_2101010: - case COGL_PIXEL_FORMAT_XBGR_2101010: - case COGL_PIXEL_FORMAT_ABGR_2101010: - alpha = get_bits (rgb10_readback[0], 31, 30); - channels[0] = get_bits (rgb10_readback[0], 29, 20); - channels[1] = get_bits (rgb10_readback[0], 19, 10); - channels[2] = get_bits (rgb10_readback[0], 9, 0); - break; - default: - g_assert_not_reached (); - } - - g_assert_cmpint (alpha, ==, 0x3); - - switch (formats[j]) + for (k = 0; k < 4; k++) { - case COGL_PIXEL_FORMAT_RGBA_1010102: - case COGL_PIXEL_FORMAT_XRGB_2101010: - case COGL_PIXEL_FORMAT_ARGB_2101010: - g_assert_cmpint (channels[0], ==, rgb10_red); - g_assert_cmpint (channels[1], ==, rgb10_green); - g_assert_cmpint (channels[2], ==, rgb10_blue); - break; - case COGL_PIXEL_FORMAT_BGRA_1010102: - case COGL_PIXEL_FORMAT_XBGR_2101010: - case COGL_PIXEL_FORMAT_ABGR_2101010: - g_assert_cmpint (channels[0], ==, rgb10_blue); - g_assert_cmpint (channels[1], ==, rgb10_green); - g_assert_cmpint (channels[2], ==, rgb10_red); - break; - default: - g_assert_not_reached (); + int channels[3]; + + switch (formats[j]) + { + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + channels[0] = get_bits (rgb10_readback[k], 31, 22); + channels[1] = get_bits (rgb10_readback[k], 21, 12); + channels[2] = get_bits (rgb10_readback[k], 11, 2); + alpha_out = get_bits (rgb10_readback[k], 1, 0); + break; + case COGL_PIXEL_FORMAT_XRGB_2101010: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + case COGL_PIXEL_FORMAT_XBGR_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + alpha_out = get_bits (rgb10_readback[k], 31, 30); + channels[0] = get_bits (rgb10_readback[k], 29, 20); + channels[1] = get_bits (rgb10_readback[k], 19, 10); + channels[2] = get_bits (rgb10_readback[k], 9, 0); + break; + default: + g_assert_not_reached (); + } + + if ((formats[i] & COGL_A_BIT) && (formats[j] & COGL_A_BIT)) + g_assert_cmpint (alpha_out, ==, rgb10_alpha); + else if (!(formats[i] & COGL_A_BIT) && !(formats[j] & COGL_A_BIT)) + g_assert_cmpint (alpha_out, ==, 0x3); + + switch (formats[j]) + { + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + case COGL_PIXEL_FORMAT_XRGB_2101010: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + g_assert_cmpint (channels[0], ==, rgb10_red); + g_assert_cmpint (channels[1], ==, rgb10_green); + g_assert_cmpint (channels[2], ==, rgb10_blue); + break; + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + case COGL_PIXEL_FORMAT_XBGR_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + g_assert_cmpint (channels[0], ==, rgb10_blue); + g_assert_cmpint (channels[1], ==, rgb10_green); + g_assert_cmpint (channels[2], ==, rgb10_red); + break; + default: + g_assert_not_reached (); + } } } cogl_framebuffer_read_pixels (COGL_FRAMEBUFFER (offscreen), 0, 0, 2, 2, - COGL_PIXEL_FORMAT_RGBA_8888, + COGL_PIXEL_FORMAT_RGBX_8888, (uint8_t *) &rgb8_readback); - rgb8_buf = (uint8_t *) &rgb8_readback[0]; + for (k = 0; k < 4; k++) + { + uint8_t *rgb8_buf = (uint8_t *) &rgb8_readback[k]; - g_assert_cmpint (rgb8_buf[0], ==, rgb10_to_rgb8 (rgb10_red)); - g_assert_cmpint (rgb8_buf[1], ==, rgb10_to_rgb8 (rgb10_green)); - g_assert_cmpint (rgb8_buf[2], ==, rgb10_to_rgb8 (rgb10_blue)); - g_assert_cmpint (rgb8_buf[3], ==, 0xff); + g_assert_cmpint (rgb8_buf[0], ==, rgb10_to_rgb8 (rgb10_red)); + g_assert_cmpint (rgb8_buf[1], ==, rgb10_to_rgb8 (rgb10_green)); + g_assert_cmpint (rgb8_buf[2], ==, rgb10_to_rgb8 (rgb10_blue)); + + if (!(formats[i] & COGL_A_BIT)) + g_assert_cmpint (rgb8_buf[3], ==, 0xff); + } + + g_object_unref (offscreen); + cogl_object_unref (tex); + } +} + +static void +test_offscreen_texture_formats_store_rgb8 (void) +{ + CoglColor color; + const uint8_t red = 0xab; + const uint8_t green = 0x1f; + const uint8_t blue = 0x50; + const uint8_t alpha = 0x34; + CoglPixelFormat formats[] = { + COGL_PIXEL_FORMAT_RGBX_8888, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + COGL_PIXEL_FORMAT_BGRX_8888, + COGL_PIXEL_FORMAT_BGRA_8888_PRE, + COGL_PIXEL_FORMAT_XRGB_8888, + COGL_PIXEL_FORMAT_ARGB_8888_PRE, + COGL_PIXEL_FORMAT_XBGR_8888, + COGL_PIXEL_FORMAT_ABGR_8888_PRE, + }; + int i; + + cogl_color_init_from_4ub (&color, red, green, blue, alpha); + + for (i = 0; i < G_N_ELEMENTS (formats); i++) + { + CoglTexture2D *tex; + CoglOffscreen *offscreen; + GError *error = NULL; + int j; + + /* Allocate 2x2 to ensure we avoid any fast paths. */ + tex = cogl_texture_2d_new_with_format (test_ctx, 2, 2, formats[i]); + + offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex)); + cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error); + g_assert_no_error (error); + + cogl_framebuffer_clear (COGL_FRAMEBUFFER (offscreen), + COGL_BUFFER_BIT_COLOR, + &color); + + for (j = 0; j < G_N_ELEMENTS (formats); j++) + { + uint8_t rgba_readback[4 * 4] = {}; + int alpha_out; + int k; + + cogl_framebuffer_read_pixels (COGL_FRAMEBUFFER (offscreen), 0, 0, 2, 2, + formats[j], + (uint8_t *) &rgba_readback); + + for (k = 0; k < 4; k++) + { + switch (formats[j]) + { + case COGL_PIXEL_FORMAT_RGBX_8888: + case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + g_assert_cmpint (rgba_readback[k * 4 + 0], ==, red); + g_assert_cmpint (rgba_readback[k * 4 + 1], ==, green); + g_assert_cmpint (rgba_readback[k * 4 + 2], ==, blue); + alpha_out = rgba_readback[k * 4 + 3]; + break; + case COGL_PIXEL_FORMAT_XRGB_8888: + case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + alpha_out = rgba_readback[k * 4 + 0]; + g_assert_cmpint (rgba_readback[k * 4 + 1], ==, red); + g_assert_cmpint (rgba_readback[k * 4 + 2], ==, green); + g_assert_cmpint (rgba_readback[k * 4 + 3], ==, blue); + break; + case COGL_PIXEL_FORMAT_BGRX_8888: + case COGL_PIXEL_FORMAT_BGRA_8888_PRE: + g_assert_cmpint (rgba_readback[k * 4 + 0], ==, blue); + g_assert_cmpint (rgba_readback[k * 4 + 1], ==, green); + g_assert_cmpint (rgba_readback[k * 4 + 2], ==, red); + alpha_out = rgba_readback[k * 4 + 3]; + break; + case COGL_PIXEL_FORMAT_XBGR_8888: + case COGL_PIXEL_FORMAT_ABGR_8888_PRE: + alpha_out = rgba_readback[k * 4 + 0]; + g_assert_cmpint (rgba_readback[k * 4 + 1], ==, blue); + g_assert_cmpint (rgba_readback[k * 4 + 2], ==, green); + g_assert_cmpint (rgba_readback[k * 4 + 3], ==, red); + break; + default: + g_assert_not_reached (); + } + + if ((formats[i] & COGL_A_BIT) && (formats[j] & COGL_A_BIT)) + g_assert_cmpint (alpha_out, ==, alpha); + else if (!(formats[i] & COGL_A_BIT) && !(formats[j] & COGL_A_BIT)) + g_assert_cmpint (alpha_out, ==, 0xff); + } + } g_object_unref (offscreen); cogl_object_unref (tex); @@ -175,63 +287,265 @@ test_offscreen_texture_formats_paint_rgb10 (void) const int rgb10_red = 514; const int rgb10_green = 258; const int rgb10_blue = 18; + const int rgb10_alpha = 2; float red; float green; float blue; - CoglTexture2D *tex_src; - CoglOffscreen *offscreen_src; - CoglTexture2D *tex_dst; - CoglOffscreen *offscreen_dst; - CoglPipeline *pipeline; - uint32_t rgb10_readback[4]; - GError *error = NULL; + float alpha; + CoglPixelFormat formats[] = { + COGL_PIXEL_FORMAT_XRGB_2101010, + COGL_PIXEL_FORMAT_ARGB_2101010_PRE, + COGL_PIXEL_FORMAT_XBGR_2101010, + COGL_PIXEL_FORMAT_ABGR_2101010_PRE, + COGL_PIXEL_FORMAT_RGBA_1010102_PRE, + COGL_PIXEL_FORMAT_BGRA_1010102_PRE, + }; + int i; /* The extra fraction is there to avoid rounding inconsistencies in OpenGL * implementations. */ - red = (rgb10_red / (float) (1 << 10)) + 0.00001; - green = (rgb10_green / (float) (1 << 10)) + 0.00001; - blue = (rgb10_blue / (float) (1 << 10)) + 0.00001; + red = (rgb10_red / (float) ((1 << 10 ) - 1)) + 0.00001; + green = (rgb10_green / (float) ((1 << 10) - 1)) + 0.00001; + blue = (rgb10_blue / (float) ((1 << 10) - 1)) + 0.00001; + alpha = (rgb10_alpha / (float) ((1 << 2) - 1)) + 0.00001; /* Make sure that that the color value can't be represented using rgb8. */ g_assert_cmpint (rgb8_to_rgb10 (rgb10_to_rgb8 (rgb10_red)), !=, rgb10_red); g_assert_cmpint (rgb8_to_rgb10 (rgb10_to_rgb8 (rgb10_green)), !=, rgb10_green); g_assert_cmpint (rgb8_to_rgb10 (rgb10_to_rgb8 (rgb10_blue)), !=, rgb10_blue); - tex_src = cogl_texture_2d_new_with_format (test_ctx, 2, 2, - COGL_PIXEL_FORMAT_RGBA_1010102); - offscreen_src = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex_src)); - cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen_src), &error); - g_assert_no_error (error); - - tex_dst = cogl_texture_2d_new_with_format (test_ctx, 2, 2, - COGL_PIXEL_FORMAT_ABGR_2101010); - offscreen_dst = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex_dst)); - cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen_dst), &error); - g_assert_no_error (error); - - cogl_framebuffer_clear4f (COGL_FRAMEBUFFER (offscreen_src), - COGL_BUFFER_BIT_COLOR, - red, green, blue, 1.0); - - pipeline = cogl_pipeline_new (test_ctx); - cogl_pipeline_set_layer_texture (pipeline, 0, tex_src); - cogl_framebuffer_draw_rectangle (COGL_FRAMEBUFFER (offscreen_dst), - pipeline, - -1.0, -1.0, 1.0, 1.0); - cogl_object_unref (pipeline); - - cogl_framebuffer_read_pixels (COGL_FRAMEBUFFER (offscreen_dst), 0, 0, 2, 2, - COGL_PIXEL_FORMAT_ABGR_2101010, - (uint8_t *) &rgb10_readback); - g_assert_cmpint (get_bits (rgb10_readback[0], 31, 30), ==, 0x3); - g_assert_cmpint (get_bits (rgb10_readback[0], 29, 20), ==, rgb10_blue); - g_assert_cmpint (get_bits (rgb10_readback[0], 19, 10), ==, rgb10_green); - g_assert_cmpint (get_bits (rgb10_readback[0], 9, 0), ==, rgb10_red); + for (i = 0; i < G_N_ELEMENTS (formats); i++) + { + CoglTexture2D *tex_src; + CoglOffscreen *offscreen_src; + GError *error = NULL; + int j; + + tex_src = cogl_texture_2d_new_with_format (test_ctx, 2, 2, formats[i]); + offscreen_src = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex_src)); + cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen_src), &error); + g_assert_no_error (error); + + for (j = 0; j < G_N_ELEMENTS (formats); j++) + { + CoglTexture2D *tex_dst; + CoglOffscreen *offscreen_dst; + CoglPipeline *pipeline; + uint32_t rgb10_readback[4]; + int k; + + tex_dst = cogl_texture_2d_new_with_format (test_ctx, 2, 2, formats[j]); + offscreen_dst = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex_dst)); + cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen_dst), &error); + g_assert_no_error (error); + + cogl_framebuffer_clear4f (COGL_FRAMEBUFFER (offscreen_src), + COGL_BUFFER_BIT_COLOR, + red, green, blue, alpha); + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_blend (pipeline, + "RGBA = ADD (SRC_COLOR, 0)", NULL); + cogl_pipeline_set_layer_texture (pipeline, 0, tex_src); + cogl_framebuffer_draw_rectangle (COGL_FRAMEBUFFER (offscreen_dst), + pipeline, + -1.0, -1.0, 1.0, 1.0); + cogl_object_unref (pipeline); + + cogl_framebuffer_read_pixels (COGL_FRAMEBUFFER (offscreen_dst), + 0, 0, 2, 2, formats[j], + (uint8_t *) &rgb10_readback); + + for (k = 0; k < 4; k++) + { + int channels[3]; + int alpha_out; + + switch (formats[j]) + { + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + channels[0] = get_bits (rgb10_readback[k], 31, 22); + channels[1] = get_bits (rgb10_readback[k], 21, 12); + channels[2] = get_bits (rgb10_readback[k], 11, 2); + alpha_out = get_bits (rgb10_readback[k], 1, 0); + break; + case COGL_PIXEL_FORMAT_XRGB_2101010: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + case COGL_PIXEL_FORMAT_XBGR_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + alpha_out = get_bits (rgb10_readback[k], 31, 30); + channels[0] = get_bits (rgb10_readback[k], 29, 20); + channels[1] = get_bits (rgb10_readback[k], 19, 10); + channels[2] = get_bits (rgb10_readback[k], 9, 0); + break; + default: + g_assert_not_reached (); + } + + if ((formats[i] & COGL_A_BIT) && (formats[j] & COGL_A_BIT)) + g_assert_cmpint (alpha_out, ==, rgb10_alpha); + else if (!(formats[i] & COGL_A_BIT) && !(formats[j] & COGL_A_BIT)) + g_assert_cmpint (alpha_out, ==, 0x3); + + switch (formats[j]) + { + case COGL_PIXEL_FORMAT_RGBA_1010102_PRE: + case COGL_PIXEL_FORMAT_XRGB_2101010: + case COGL_PIXEL_FORMAT_ARGB_2101010_PRE: + g_assert_cmpint (channels[0], ==, rgb10_red); + g_assert_cmpint (channels[1], ==, rgb10_green); + g_assert_cmpint (channels[2], ==, rgb10_blue); + break; + case COGL_PIXEL_FORMAT_BGRA_1010102_PRE: + case COGL_PIXEL_FORMAT_XBGR_2101010: + case COGL_PIXEL_FORMAT_ABGR_2101010_PRE: + g_assert_cmpint (channels[0], ==, rgb10_blue); + g_assert_cmpint (channels[1], ==, rgb10_green); + g_assert_cmpint (channels[2], ==, rgb10_red); + break; + default: + g_assert_not_reached (); + } + } + + g_object_unref (offscreen_dst); + cogl_object_unref (tex_dst); + } + + g_object_unref (offscreen_src); + cogl_object_unref (tex_src); + } +} + +static void +test_offscreen_texture_formats_paint_rgb8 (void) +{ + CoglColor color; + const uint8_t red = 0xab; + const uint8_t green = 0x1f; + const uint8_t blue = 0x50; + const uint8_t alpha = 0x34; + CoglPixelFormat formats[] = { + COGL_PIXEL_FORMAT_RGBX_8888, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + COGL_PIXEL_FORMAT_BGRX_8888, + COGL_PIXEL_FORMAT_BGRA_8888_PRE, + COGL_PIXEL_FORMAT_XRGB_8888, + COGL_PIXEL_FORMAT_ARGB_8888_PRE, + COGL_PIXEL_FORMAT_XBGR_8888, + COGL_PIXEL_FORMAT_ABGR_8888_PRE, + }; + int i; + + cogl_color_init_from_4ub (&color, red, green, blue, alpha); + + for (i = 0; i < G_N_ELEMENTS (formats); i++) + { + CoglTexture2D *tex_src; + CoglOffscreen *offscreen_src; + GError *error = NULL; + int j; + + tex_src = cogl_texture_2d_new_with_format (test_ctx, 2, 2, formats[i]); + offscreen_src = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex_src)); + cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen_src), &error); + g_assert_no_error (error); + + for (j = 0; j < G_N_ELEMENTS (formats); j++) + { + CoglTexture2D *tex_dst; + CoglOffscreen *offscreen_dst; + CoglPipeline *pipeline; + uint8_t rgba_readback[4 * 4] = {}; + int k; + + tex_dst = cogl_texture_2d_new_with_format (test_ctx, 2, 2, formats[j]); + offscreen_dst = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex_dst)); + cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen_dst), &error); + g_assert_no_error (error); + + cogl_framebuffer_clear (COGL_FRAMEBUFFER (offscreen_src), + COGL_BUFFER_BIT_COLOR, + &color); + + cogl_framebuffer_clear4f (COGL_FRAMEBUFFER (offscreen_dst), + COGL_BUFFER_BIT_COLOR, + 0.0, 0.0, 0.0, 1.0); + + pipeline = cogl_pipeline_new (test_ctx); + cogl_pipeline_set_blend (pipeline, + "RGBA = ADD (SRC_COLOR, 0)", NULL); + cogl_pipeline_set_layer_texture (pipeline, 0, tex_src); + cogl_framebuffer_draw_rectangle (COGL_FRAMEBUFFER (offscreen_dst), + pipeline, + -1.0, -1.0, 1.0, 1.0); + cogl_object_unref (pipeline); + + cogl_framebuffer_read_pixels (COGL_FRAMEBUFFER (offscreen_dst), + 0, 0, 2, 2, formats[j], + (uint8_t *) &rgba_readback); + + for (k = 0; k < 4; k++) + { + int alpha_out; + + switch (formats[j]) + { + case COGL_PIXEL_FORMAT_RGBX_8888: + case COGL_PIXEL_FORMAT_RGBA_8888_PRE: + g_assert_cmpint (rgba_readback[k * 4 + 0], ==, red); + g_assert_cmpint (rgba_readback[k * 4 + 1], ==, green); + g_assert_cmpint (rgba_readback[k * 4 + 2], ==, blue); + alpha_out = rgba_readback[k * 4 + 3]; + break; + case COGL_PIXEL_FORMAT_XRGB_8888: + case COGL_PIXEL_FORMAT_ARGB_8888_PRE: + alpha_out = rgba_readback[k * 4 + 0]; + g_assert_cmpint (rgba_readback[k * 4 + 1], ==, red); + g_assert_cmpint (rgba_readback[k * 4 + 2], ==, green); + g_assert_cmpint (rgba_readback[k * 4 + 3], ==, blue); + break; + case COGL_PIXEL_FORMAT_BGRX_8888: + case COGL_PIXEL_FORMAT_BGRA_8888_PRE: + g_assert_cmpint (rgba_readback[k * 4 + 0], ==, blue); + g_assert_cmpint (rgba_readback[k * 4 + 1], ==, green); + g_assert_cmpint (rgba_readback[k * 4 + 2], ==, red); + alpha_out = rgba_readback[k * 4 + 3]; + break; + case COGL_PIXEL_FORMAT_XBGR_8888: + case COGL_PIXEL_FORMAT_ABGR_8888_PRE: + alpha_out = rgba_readback[k * 4 + 0]; + g_assert_cmpint (rgba_readback[k * 4 + 1], ==, blue); + g_assert_cmpint (rgba_readback[k * 4 + 2], ==, green); + g_assert_cmpint (rgba_readback[k * 4 + 3], ==, red); + break; + default: + g_assert_not_reached (); + } + + if ((formats[i] & COGL_A_BIT) && (formats[j] & COGL_A_BIT)) + g_assert_cmpint (alpha_out, ==, alpha); + else if (!(formats[i] & COGL_A_BIT) && !(formats[j] & COGL_A_BIT)) + g_assert_cmpint (alpha_out, ==, 0xff); + } + + g_object_unref (offscreen_dst); + cogl_object_unref (tex_dst); + } + + g_object_unref (offscreen_src); + cogl_object_unref (tex_src); + } } COGL_TEST_SUITE ( g_test_add_func ("/offscreen/texture-formats/store-rgb10", test_offscreen_texture_formats_store_rgb10); + g_test_add_func ("/offscreen/texture-formats/store-8", + test_offscreen_texture_formats_store_rgb8); g_test_add_func ("/offscreen/texture-formats/paint-rgb10", test_offscreen_texture_formats_paint_rgb10); + g_test_add_func ("/offscreen/texture-formats/paint-rgb8", + test_offscreen_texture_formats_paint_rgb8); ) diff --git a/src/tests/wayland-test-clients/color-representation.c b/src/tests/wayland-test-clients/color-representation.c new file mode 100644 index 0000000000000000000000000000000000000000..036f7c22b0c14bdac94c56b8c5cff6b0d4dfe48a --- /dev/null +++ b/src/tests/wayland-test-clients/color-representation.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * 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 . + */ + +#include "config.h" + +#include + +#include "wayland-test-client-utils.h" + +static WaylandDisplay *display; +static gboolean running; + +static struct wl_surface *surface; +static struct xdg_surface *xdg_surface; +static struct xdg_toplevel *xdg_toplevel; +static struct wp_color_representation_v1 *color_repr; + +static enum +{ + STATE_INIT, + STATE_PREMULT, +} state; + +static void +draw_main (void) +{ + draw_surface (display, surface, 700, 500, 0xff00ff00); +} + +static void +handle_xdg_toplevel_configure (void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array *state) +{ +} + +static void +handle_xdg_toplevel_close (void *data, + struct xdg_toplevel *xdg_toplevel) +{ + g_assert_not_reached (); +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + handle_xdg_toplevel_configure, + handle_xdg_toplevel_close, +}; + +static void +handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) +{ + xdg_surface_ack_configure (xdg_surface, serial); + wl_surface_commit (surface); + wl_display_flush (display->display); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + handle_xdg_surface_configure, +}; + +static void +on_sync_event (WaylandDisplay *display, + uint32_t serial) +{ + g_assert (serial == 0); + + running = FALSE; +} + +int +main (int argc, + const char **argv) +{ + display = wayland_display_new (WAYLAND_DISPLAY_CAPABILITY_TEST_DRIVER); + g_signal_connect (display, "sync-event", G_CALLBACK (on_sync_event), NULL); + state = STATE_INIT; + + surface = wl_compositor_create_surface (display->compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (display->xdg_wm_base, surface); + xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title (xdg_toplevel, "color-representation-test"); + draw_main (); + wl_surface_commit (surface); + wl_display_flush (display->display); + + test_driver_sync_point (display->test_driver, 0, NULL); + + color_repr = + wp_color_representation_manager_v1_create (display->color_representation, + surface); + + wp_color_representation_v1_set_alpha_mode ( + color_repr, + WP_COLOR_REPRESENTATION_V1_ALPHA_MODE_PREMULTIPLIED_OPTICAL); + wl_surface_commit (surface); + wl_display_flush (display->display); + + test_driver_sync_point (display->test_driver, 1, NULL); + + wp_color_representation_v1_destroy (color_repr); + wl_display_flush (display->display); + + test_driver_sync_point (display->test_driver, 2, NULL); + + wl_surface_commit (surface); + wl_display_flush (display->display); + + test_driver_sync_point (display->test_driver, 3, NULL); + + running = TRUE; + while (running) + { + if (wl_display_dispatch (display->display) == -1) + return EXIT_FAILURE; + } + + wl_display_roundtrip (display->display); + + return EXIT_SUCCESS; +} diff --git a/src/tests/wayland-test-clients/meson.build b/src/tests/wayland-test-clients/meson.build index da1fc65331275581758bcfc49333792c9a913b21..45c38a8f36ad644bdae0c6c831c99cb91694b933 100644 --- a/src/tests/wayland-test-clients/meson.build +++ b/src/tests/wayland-test-clients/meson.build @@ -18,6 +18,9 @@ wayland_test_clients = [ { 'name': 'buffer-transform', }, + { + 'name': 'color-representation', + }, { 'name': 'fractional-scale', }, diff --git a/src/tests/wayland-test-clients/wayland-test-client-utils.c b/src/tests/wayland-test-clients/wayland-test-client-utils.c index 97d28b8e18766f7039f75ab41dd3dda78c7e2e08..7775e6dfd0b43aff5957acb15b3603f78d512f2e 100644 --- a/src/tests/wayland-test-clients/wayland-test-client-utils.c +++ b/src/tests/wayland-test-clients/wayland-test-client-utils.c @@ -166,6 +166,12 @@ handle_registry_global (void *user_data, display->shm = wl_registry_bind (registry, id, &wl_shm_interface, 1); } + else if (strcmp (interface, wp_color_representation_manager_v1_interface.name) == 0) + { + display->color_representation = + wl_registry_bind (registry, id, + &wp_color_representation_manager_v1_interface, 1); + } else if (strcmp (interface, wp_fractional_scale_manager_v1_interface.name) == 0) { display->fractional_scale_mgr = diff --git a/src/tests/wayland-test-clients/wayland-test-client-utils.h b/src/tests/wayland-test-clients/wayland-test-client-utils.h index af5eb0e54e62b2eda5b3b15e600c62df1b32822b..b9f39131b27116a1fb4e771e3530aea988eed6d7 100644 --- a/src/tests/wayland-test-clients/wayland-test-client-utils.h +++ b/src/tests/wayland-test-clients/wayland-test-client-utils.h @@ -5,6 +5,7 @@ #include #include +#include "color-representation-v1-client-protocol.h" #include "fractional-scale-v1-client-protocol.h" #include "single-pixel-buffer-v1-client-protocol.h" #include "test-driver-client-protocol.h" @@ -29,6 +30,7 @@ typedef struct _WaylandDisplay struct wl_compositor *compositor; struct wl_subcompositor *subcompositor; struct wl_shm *shm; + struct wp_color_representation_manager_v1 *color_representation; struct wp_fractional_scale_manager_v1 *fractional_scale_mgr; struct wp_single_pixel_buffer_manager_v1 *single_pixel_mgr; struct wp_viewporter *viewporter; diff --git a/src/tests/wayland-unit-tests.c b/src/tests/wayland-unit-tests.c index ab5b8a54f658e1c42ea7f0e7e5f4fd27b2354596..986718a24af7239506579d2da1c8beded1840e86 100644 --- a/src/tests/wayland-unit-tests.c +++ b/src/tests/wayland-unit-tests.c @@ -839,6 +839,128 @@ wayland_registry_filter (void) g_assert_false (client3_saw_global); } +typedef struct _ColorReprData +{ + GMainLoop *loop; + MetaWaylandTestClient *wayland_test_client; + int sequence; +} ColorReprData; + +static void +on_color_repr_sync_point (MetaWaylandTestDriver *test_driver, + unsigned int sequence, + struct wl_resource *surface_resource, + struct wl_client *wl_client, + ColorReprData *data) +{ + MetaWindow *window; + MetaWaylandSurface *surface; + MetaSurfaceActor *surface_actor; + MetaShapedTexture *stex; + const MetaShapedTextureColorRepr *repr; + + window = find_client_window ("color-representation-test"); + + surface = meta_window_get_wayland_surface (window); + surface_actor = meta_wayland_surface_get_actor (surface); + stex = meta_surface_actor_get_texture (surface_actor); + repr = meta_shaped_texture_get_color_repr (stex); + + if (sequence == 0) + { + g_assert_cmpint (data->sequence, ==, 0); + + g_assert_cmpint (surface->color_representation.repr.premult, ==, + META_SHAPED_TEXTURE_PREMULT_ELECTRICAL); + g_assert_cmpint (surface->color_representation.repr.coeffs, ==, + META_SHAPED_TEXTURE_COEFFICIENTS_NONE); + g_assert_cmpint (surface->color_representation.repr.chroma_loc, ==, + META_SHAPED_TEXTURE_CHROMA_LOC_NONE); + + g_assert_cmpint (repr->premult, ==, + META_SHAPED_TEXTURE_PREMULT_ELECTRICAL); + g_assert_cmpint (repr->coeffs, ==, + META_SHAPED_TEXTURE_COEFFICIENTS_NONE); + g_assert_cmpint (repr->chroma_loc, ==, + META_SHAPED_TEXTURE_CHROMA_LOC_NONE); + + data->sequence++; + } + else if (sequence == 1) + { + g_assert_cmpint (data->sequence, ==, 1); + + g_assert_cmpint (surface->color_representation.repr.premult, ==, + META_SHAPED_TEXTURE_PREMULT_OPTICAL); + g_assert_cmpint (surface->color_representation.repr.coeffs, ==, + META_SHAPED_TEXTURE_COEFFICIENTS_NONE); + g_assert_cmpint (surface->color_representation.repr.chroma_loc, ==, + META_SHAPED_TEXTURE_CHROMA_LOC_NONE); + + g_assert_cmpint (repr->premult, ==, + META_SHAPED_TEXTURE_PREMULT_OPTICAL); + g_assert_cmpint (repr->coeffs, ==, + META_SHAPED_TEXTURE_COEFFICIENTS_NONE); + g_assert_cmpint (repr->chroma_loc, ==, + META_SHAPED_TEXTURE_CHROMA_LOC_NONE); + + data->sequence++; + g_main_loop_quit (data->loop); + } + else if (sequence == 2) + { + g_assert_cmpint (data->sequence, ==, 2); + + g_assert_cmpint (repr->premult, ==, + META_SHAPED_TEXTURE_PREMULT_OPTICAL); + g_assert_cmpint (repr->coeffs, ==, + META_SHAPED_TEXTURE_COEFFICIENTS_NONE); + g_assert_cmpint (repr->chroma_loc, ==, + META_SHAPED_TEXTURE_CHROMA_LOC_NONE); + + data->sequence++; + g_main_loop_quit (data->loop); + } + else if (sequence == 3) + { + g_assert_cmpint (data->sequence, ==, 3); + + g_assert_cmpint (repr->premult, ==, + META_SHAPED_TEXTURE_PREMULT_ELECTRICAL); + g_assert_cmpint (repr->coeffs, ==, + META_SHAPED_TEXTURE_COEFFICIENTS_NONE); + g_assert_cmpint (repr->chroma_loc, ==, + META_SHAPED_TEXTURE_CHROMA_LOC_NONE); + + data->sequence++; + g_main_loop_quit (data->loop); + } + else + { + g_assert_not_reached (); + } +} + +static void +color_representation_state (void) +{ + ColorReprData data = { 0 }; + gulong handler_id; + + data.loop = g_main_loop_new (NULL, FALSE); + data.wayland_test_client = + meta_wayland_test_client_new (test_context, "color-representation"); + handler_id = g_signal_connect (test_driver, "sync-point", + G_CALLBACK (on_color_repr_sync_point), + &data); + g_main_loop_run (data.loop); + g_assert_cmpint (data.sequence, ==, 4); + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (data.wayland_test_client); + g_test_assert_expected_messages (); + g_signal_handler_disconnect (test_driver, handler_id); +} + static void on_before_tests (void) { @@ -886,6 +1008,9 @@ init_tests (void) xdg_foreign_set_parent_of); g_test_add_func ("/wayland/registry/filter", wayland_registry_filter); + g_test_add_func ("/wayland/color-representation/state", + color_representation_state); + } int diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c index eb81d9e5f788de51a319f0bcf6747059bd6de467..b945ff9465f3fa19009a07b2536187e80302abcf 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -192,7 +192,7 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor { CoglSnippet *snippet; gboolean is_y_inverted; - CoglTexture *texture; + MetaMultiTexture *texture; snippet = meta_wayland_buffer_create_snippet (buffer); is_y_inverted = meta_wayland_buffer_is_y_inverted (buffer); @@ -202,6 +202,8 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor meta_shaped_texture_set_snippet (stex, snippet); meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted); meta_shaped_texture_set_buffer_scale (stex, surface->scale); + meta_shaped_texture_set_color_repr (stex, + &surface->color_representation.repr); cogl_clear_object (&snippet); } else diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c index b09a3c9afac33af5b699f49a2c2aa5e94182dd61..86f23e3b4b9f9d0974fc8588a1d5114f358344f8 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -66,10 +66,6 @@ #include "backends/native/meta-renderer-native.h" #endif -#ifndef DRM_FORMAT_MOD_INVALID -#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) -#endif - enum { RESOURCE_DESTROYED, @@ -161,7 +157,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 = meta_multi_texture_new_simple (COGL_TEXTURE (texture)); buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream); return TRUE; @@ -212,68 +208,62 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer) } static gboolean -shm_format_to_cogl_pixel_format (enum wl_shm_format shm_format, - CoglPixelFormat *format_out, - CoglTextureComponents *components_out) +shm_format_to_cogl_pixel_format (enum wl_shm_format shm_format, + CoglPixelFormat *format_out) { CoglPixelFormat format; - CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA; switch (shm_format) { #if G_BYTE_ORDER == G_BIG_ENDIAN + case WL_SHM_FORMAT_XRGB8888: + format = COGL_PIXEL_FORMAT_XRGB_8888; + break; case WL_SHM_FORMAT_ARGB8888: format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; break; - case WL_SHM_FORMAT_XRGB8888: - format = COGL_PIXEL_FORMAT_ARGB_8888; - components = COGL_TEXTURE_COMPONENTS_RGB; - break; case WL_SHM_FORMAT_XBGR8888: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; + format = COGL_PIXEL_FORMAT_XBGR_8888; case WL_SHM_FORMAT_ABGR8888: format = COGL_PIXEL_FORMAT_ABGR_8888_PRE; break; #elif G_BYTE_ORDER == G_LITTLE_ENDIAN case WL_SHM_FORMAT_RGB565: format = COGL_PIXEL_FORMAT_RGB_565; - components = COGL_TEXTURE_COMPONENTS_RGB; + break; + case WL_SHM_FORMAT_XRGB8888: + format = COGL_PIXEL_FORMAT_BGRX_8888; break; case WL_SHM_FORMAT_ARGB8888: format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; break; - case WL_SHM_FORMAT_XRGB8888: - format = COGL_PIXEL_FORMAT_BGRA_8888; - components = COGL_TEXTURE_COMPONENTS_RGB; - break; case WL_SHM_FORMAT_XBGR8888: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; + format = COGL_PIXEL_FORMAT_RGBX_8888; + break; case WL_SHM_FORMAT_ABGR8888: format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; break; case WL_SHM_FORMAT_XRGB2101010: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; + format = COGL_PIXEL_FORMAT_XRGB_2101010; + break; case WL_SHM_FORMAT_ARGB2101010: format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE; break; case WL_SHM_FORMAT_XBGR2101010: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; + format = COGL_PIXEL_FORMAT_XBGR_2101010; + break; case WL_SHM_FORMAT_ABGR2101010: format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE; break; case WL_SHM_FORMAT_XRGB16161616F: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; + format = COGL_PIXEL_FORMAT_BGRX_FP_16161616; + break; case WL_SHM_FORMAT_ARGB16161616F: format = COGL_PIXEL_FORMAT_BGRA_FP_16161616_PRE; break; case WL_SHM_FORMAT_XBGR16161616F: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; + format = COGL_PIXEL_FORMAT_RGBX_FP_16161616; + break; case WL_SHM_FORMAT_ABGR16161616F: format = COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE; break; @@ -284,17 +274,14 @@ shm_format_to_cogl_pixel_format (enum wl_shm_format shm_format, if (format_out) *format_out = format; - if (components_out) - *components_out = components; return TRUE; } static gboolean -shm_buffer_get_cogl_pixel_format (MetaWaylandBuffer *buffer, - struct wl_shm_buffer *shm_buffer, - CoglPixelFormat *format_out, - CoglTextureComponents *components_out) +shm_buffer_get_cogl_pixel_format (MetaWaylandBuffer *buffer, + struct wl_shm_buffer *shm_buffer, + CoglPixelFormat *format_out) { MetaContext *context = meta_wayland_compositor_get_context (buffer->compositor); @@ -303,11 +290,9 @@ shm_buffer_get_cogl_pixel_format (MetaWaylandBuffer *buffer, CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); CoglPixelFormat cogl_format; - CoglTextureComponents cogl_components; if (!shm_format_to_cogl_pixel_format (wl_shm_buffer_get_format (shm_buffer), - &cogl_format, - &cogl_components)) + &cogl_format)) return FALSE; if (!cogl_context_format_supports_upload (cogl_context, cogl_format)) @@ -315,8 +300,6 @@ shm_buffer_get_cogl_pixel_format (MetaWaylandBuffer *buffer, if (format_out) *format_out = cogl_format; - if (components_out) - *components_out = cogl_components; return TRUE; } @@ -345,7 +328,7 @@ shm_format_to_string (MetaDrmFormatBuf *format_buf, static gboolean shm_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error) { MetaContext *context = @@ -356,17 +339,15 @@ shm_buffer_attach (MetaWaylandBuffer *buffer, struct wl_shm_buffer *shm_buffer; int stride, width, height; CoglPixelFormat format; - CoglTextureComponents components; CoglBitmap *bitmap; - CoglTexture *new_texture; + CoglTexture *new_cogl_tex; MetaDrmFormatBuf format_buf; 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); - if (!shm_buffer_get_cogl_pixel_format (buffer, shm_buffer, - &format, &components)) + if (!shm_buffer_get_cogl_pixel_format (buffer, shm_buffer, &format)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid shm pixel format"); @@ -381,16 +362,19 @@ shm_buffer_attach (MetaWaylandBuffer *buffer, cogl_pixel_format_to_string (format)); 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) + meta_multi_texture_get_width (*texture) == width && + meta_multi_texture_get_height (*texture) == height) { - buffer->is_y_inverted = TRUE; - return TRUE; + CoglTexture *cogl_texture = meta_multi_texture_get_plane (*texture, 0); + + if (_cogl_texture_get_format (cogl_texture) == format) + { + buffer->is_y_inverted = TRUE; + return TRUE; + } } - cogl_clear_object (texture); + g_clear_object (texture); wl_shm_buffer_begin_access (shm_buffer); @@ -400,12 +384,11 @@ shm_buffer_attach (MetaWaylandBuffer *buffer, 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); + new_cogl_tex = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap)); - if (!cogl_texture_allocate (new_texture, error)) + if (!cogl_texture_allocate (new_cogl_tex, error)) { - g_clear_pointer (&new_texture, cogl_object_unref); + g_clear_pointer (&new_cogl_tex, cogl_object_unref); if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE)) { CoglTexture2DSliced *texture_sliced; @@ -415,11 +398,10 @@ shm_buffer_attach (MetaWaylandBuffer *buffer, texture_sliced = cogl_texture_2d_sliced_new_from_bitmap (bitmap, COGL_TEXTURE_MAX_WASTE); - new_texture = COGL_TEXTURE (texture_sliced); - cogl_texture_set_components (new_texture, components); + new_cogl_tex = COGL_TEXTURE (texture_sliced); - if (!cogl_texture_allocate (new_texture, error)) - g_clear_pointer (&new_texture, cogl_object_unref); + if (!cogl_texture_allocate (new_cogl_tex, error)) + g_clear_pointer (&new_cogl_tex, cogl_object_unref); } } @@ -427,10 +409,10 @@ shm_buffer_attach (MetaWaylandBuffer *buffer, wl_shm_buffer_end_access (shm_buffer); - if (!new_texture) + if (!new_cogl_tex) return FALSE; - *texture = new_texture; + *texture = meta_multi_texture_new_simple (new_cogl_tex); buffer->is_y_inverted = TRUE; return TRUE; @@ -438,7 +420,7 @@ shm_buffer_attach (MetaWaylandBuffer *buffer, static gboolean egl_image_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error) { MetaContext *context = @@ -456,8 +438,8 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, if (buffer->egl_image.texture) { - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->egl_image.texture); + g_clear_object (texture); + *texture = g_object_ref (buffer->egl_image.texture); return TRUE; } @@ -518,11 +500,11 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, if (!texture_2d) return FALSE; - buffer->egl_image.texture = COGL_TEXTURE (texture_2d); + buffer->egl_image.texture = meta_multi_texture_new_simple (COGL_TEXTURE (texture_2d)); buffer->is_y_inverted = !!y_inverted; - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->egl_image.texture); + g_clear_object (texture); + *texture = g_object_ref (buffer->egl_image.texture); return TRUE; } @@ -530,7 +512,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, #ifdef HAVE_WAYLAND_EGLSTREAM static gboolean egl_stream_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error) { MetaWaylandEglStream *stream = buffer->egl_stream.stream; @@ -540,8 +522,8 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer, if (!meta_wayland_egl_stream_attach (stream, error)) return FALSE; - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->egl_stream.texture); + g_clear_object (texture); + *texture = g_object_ref (buffer->egl_stream.texture); return TRUE; } @@ -587,8 +569,8 @@ clear_tainted_scanout_onscreens (MetaWaylandBuffer *buffer) /** * meta_wayland_buffer_attach: * @buffer: a pointer to a #MetaWaylandBuffer - * @texture: (inout) (transfer full): a #CoglTexture representing the surface - * content + * @texture: (inout) (transfer full): a #MetaMultiTexture representing the + * surface content * @error: return location for error or %NULL * * This function should be passed a pointer to the texture used to draw the @@ -605,7 +587,7 @@ clear_tainted_scanout_onscreens (MetaWaylandBuffer *buffer) */ gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error) { COGL_TRACE_BEGIN_SCOPED (MetaWaylandBufferAttach, "WaylandBuffer (attach)"); @@ -697,7 +679,7 @@ meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer) static gboolean process_shm_buffer_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, + MetaMultiTexture *texture, cairo_region_t *region, GError **error) { @@ -705,13 +687,15 @@ process_shm_buffer_damage (MetaWaylandBuffer *buffer, int i, n_rectangles; gboolean set_texture_failed = FALSE; CoglPixelFormat format; + CoglTexture *cogl_texture; n_rectangles = cairo_region_num_rectangles (region); shm_buffer = wl_shm_buffer_get (buffer->resource); - shm_buffer_get_cogl_pixel_format (buffer, shm_buffer, &format, NULL); + shm_buffer_get_cogl_pixel_format (buffer, shm_buffer, &format); g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, FALSE); + cogl_texture = meta_multi_texture_get_plane (texture, 0); wl_shm_buffer_begin_access (shm_buffer); @@ -725,7 +709,7 @@ process_shm_buffer_damage (MetaWaylandBuffer *buffer, bpp = cogl_pixel_format_get_bytes_per_pixel (format, 0); cairo_region_get_rectangle (region, i, &rect); - if (!_cogl_texture_set_region (texture, + if (!_cogl_texture_set_region (cogl_texture, rect.width, rect.height, format, stride, @@ -746,7 +730,7 @@ process_shm_buffer_damage (MetaWaylandBuffer *buffer, void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, + MetaMultiTexture *texture, cairo_region_t *region) { gboolean res = FALSE; @@ -894,16 +878,16 @@ meta_wayland_buffer_finalize (GObject *object) clear_tainted_scanout_onscreens (buffer); g_clear_pointer (&buffer->tainted_scanout_onscreens, g_hash_table_unref); - g_clear_pointer (&buffer->egl_image.texture, cogl_object_unref); + g_clear_object (&buffer->egl_image.texture); #ifdef HAVE_WAYLAND_EGLSTREAM - g_clear_pointer (&buffer->egl_stream.texture, cogl_object_unref); + g_clear_object (&buffer->egl_stream.texture); g_clear_object (&buffer->egl_stream.stream); #endif - g_clear_pointer (&buffer->dma_buf.texture, cogl_object_unref); + g_clear_object (&buffer->dma_buf.texture); g_clear_object (&buffer->dma_buf.dma_buf); g_clear_pointer (&buffer->single_pixel.single_pixel_buffer, meta_wayland_single_pixel_buffer_free); - cogl_clear_object (&buffer->single_pixel.texture); + g_clear_object (&buffer->single_pixel.texture); G_OBJECT_CLASS (meta_wayland_buffer_parent_class)->finalize (object); } @@ -965,9 +949,7 @@ meta_wayland_init_shm (MetaWaylandCompositor *compositor) { CoglPixelFormat cogl_format; - if (!shm_format_to_cogl_pixel_format (shm_formats[i], - &cogl_format, - NULL)) + if (!shm_format_to_cogl_pixel_format (shm_formats[i], &cogl_format)) continue; if (!cogl_context_format_supports_upload (cogl_context, cogl_format)) diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h index af70aa3bf125292f1ab4cd05dcf8d4549ed87f71..62459fd6085730d9588880739dd8a5c95d0aad14 100644 --- a/src/wayland/meta-wayland-buffer.h +++ b/src/wayland/meta-wayland-buffer.h @@ -29,6 +29,7 @@ #include #include "cogl/cogl.h" +#include "meta/meta-multi-texture.h" #include "wayland/meta-wayland-types.h" #include "wayland/meta-wayland-egl-stream.h" #include "wayland/meta-wayland-dma-buf.h" @@ -61,24 +62,24 @@ struct _MetaWaylandBuffer MetaWaylandBufferType type; struct { - CoglTexture *texture; + MetaMultiTexture *texture; } egl_image; #ifdef HAVE_WAYLAND_EGLSTREAM struct { MetaWaylandEglStream *stream; - CoglTexture *texture; + MetaMultiTexture *texture; } egl_stream; #endif struct { MetaWaylandDmaBufBuffer *dma_buf; - CoglTexture *texture; + MetaMultiTexture *texture; } dma_buf; struct { MetaWaylandSinglePixelBuffer *single_pixel_buffer; - CoglTexture *texture; + MetaMultiTexture *texture; } single_pixel; GHashTable *tainted_scanout_onscreens; @@ -94,14 +95,14 @@ struct wl_resource * meta_wayland_buffer_get_resource (MetaWaylandBuff gboolean meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error); CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer); void meta_wayland_buffer_inc_use_count (MetaWaylandBuffer *buffer); void meta_wayland_buffer_dec_use_count (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer); void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, + MetaMultiTexture *texture, cairo_region_t *region); CoglScanout * meta_wayland_buffer_try_acquire_scanout (MetaWaylandBuffer *buffer, CoglOnscreen *onscreen); diff --git a/src/wayland/meta-wayland-color-representation.c b/src/wayland/meta-wayland-color-representation.c new file mode 100644 index 0000000000000000000000000000000000000000..002715528a3d72c8aaa9eb97ae7750d05d271c9a --- /dev/null +++ b/src/wayland/meta-wayland-color-representation.c @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2023 Red Hat Inc. + * + * 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. + * + */ + +#include "config.h" + +#include "wayland/meta-wayland-color-representation.h" + +#include +#include "wayland/meta-wayland-private.h" +#include "compositor/meta-multi-texture-format-private.h" + +#include "color-representation-v1-server-protocol.h" + +static MetaShapedTextureCoefficients +code_point_to_coeffs (uint32_t code_point) +{ + switch (code_point) + { + case 0: + return META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_LIMITED; + case (1 << 8) | 0: + return META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_FULL; + case 1: + return META_SHAPED_TEXTURE_COEFFICIENTS_BT709_LIMITED; + case (1 << 8) | 1: + return META_SHAPED_TEXTURE_COEFFICIENTS_BT709_FULL; + default: + return META_SHAPED_TEXTURE_COEFFICIENTS_NONE; + } +} + +static uint32_t +coeffs_to_code_point (MetaShapedTextureCoefficients coeffs, + uint32_t *code_point_out) +{ + uint32_t code_point; + + switch (coeffs) + { + case META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_LIMITED: + code_point = 0; + break; + case META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_FULL: + code_point = (1 << 8) | 0; + break; + case META_SHAPED_TEXTURE_COEFFICIENTS_BT709_LIMITED: + code_point = 1; + break; + case META_SHAPED_TEXTURE_COEFFICIENTS_BT709_FULL: + code_point = (1 << 8) | 1; + break; + case META_SHAPED_TEXTURE_COEFFICIENTS_NONE: + return FALSE; + } + + if (code_point_out) + *code_point_out = code_point; + return TRUE; +} + +static MetaShapedTextureChromaLoc +code_point_to_chroma_loc (uint32_t code_point) +{ + switch (code_point) + { + case 2: + return META_SHAPED_TEXTURE_CHROMA_LOC_CENTER; + default: + return META_SHAPED_TEXTURE_CHROMA_LOC_NONE; + } +} + +static uint32_t +chroma_loc_to_code_point (MetaShapedTextureChromaLoc chroma_loc, + uint32_t *code_point_out) +{ + uint32_t code_point; + + switch (chroma_loc) + { + case META_SHAPED_TEXTURE_CHROMA_LOC_CENTER: + code_point = 2; + break; + case META_SHAPED_TEXTURE_CHROMA_LOC_NONE: + return FALSE; + } + + if (code_point_out) + *code_point_out = code_point; + return TRUE; +} + +void +meta_wayland_color_representation_commit_check (MetaWaylandSurface *surface) +{ + MetaWaylandSurfaceState *pending = surface->pending_state; + MetaMultiTexture *tex = pending->texture; + MetaShapedTextureColorRepr *repr = &pending->color_representation; + MetaMultiTextureFormat format; + int i; + int n_planes; + const uint8_t *subsampling_h; + const uint8_t *subsampling_v; + int hsub = 1; + int vsub = 1; + + format = meta_multi_texture_get_format (tex); + n_planes = meta_multi_texture_format_get_n_planes (format); + meta_multi_texture_format_get_subsampling_factors (format, + &subsampling_h, + &subsampling_v); + + /* we assume none of the formats have subsampled luma channels, so the + * chroma subsampling is just the max subsampling of all planes */ + for (i = 0; i < n_planes; i++) + { + hsub = MAX (hsub, subsampling_h[i]); + vsub = MAX (vsub, subsampling_v[i]); + } + + /* chroma subsampling location only meaningful on 4:2:0 subsampled textures. + * 4:2:0 means chroma is subsampled horizontally and vertically by a factor + * of 2. */ + if (repr->chroma_loc != META_SHAPED_TEXTURE_CHROMA_LOC_NONE && + (hsub != 2 || vsub != 2)) + { + wl_resource_post_error ( + surface->color_representation.resource, + WP_COLOR_REPRESENTATION_V1_ERROR_INCOMPATIBLE_PIXEL_FORMAT, + "commit contains a color representation with chroma location set and " + "a buffer with a pixel format which is not 4:2:0 subsampled"); + } + + switch (repr->coeffs) + { + case META_SHAPED_TEXTURE_COEFFICIENTS_NONE: + case META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_LIMITED: + case META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_FULL: + /* we assume all our MultiTextureFormats are either RGB or YCbCr + * and identity is supported for both*/ + break; + case META_SHAPED_TEXTURE_COEFFICIENTS_BT709_FULL: + case META_SHAPED_TEXTURE_COEFFICIENTS_BT709_LIMITED: + /* we assume all simple MultiTextures are RGB, everything else YCbCr + * and the formats here only support YCbCr */ + if (meta_multi_texture_is_simple (tex)) + { + wl_resource_post_error ( + surface->color_representation.resource, + WP_COLOR_REPRESENTATION_V1_ERROR_INCOMPATIBLE_PIXEL_FORMAT, + "commit contains a color representation with coefficiens for a " + "YCbCr pixel format and a buffer with an RGB pixel format"); + } + break; + } +} + +static void +unset_pending_color_representation (MetaWaylandSurface *surface) +{ + MetaWaylandSurfaceState *pending; + + g_return_if_fail (surface != NULL); + + pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + return; + + pending->color_representation.premult = + META_SHAPED_TEXTURE_PREMULT_ELECTRICAL; + pending->color_representation.coeffs = + META_SHAPED_TEXTURE_COEFFICIENTS_NONE; + pending->color_representation.chroma_loc = + META_SHAPED_TEXTURE_CHROMA_LOC_NONE; +} + +static void +on_surface_destroyed (MetaWaylandSurface *surface) +{ + wl_resource_set_user_data (surface->color_representation.resource, NULL); +} + +static void +color_representation_destructor (struct wl_resource *resource) +{ + MetaWaylandSurface *surface; + + surface = wl_resource_get_user_data (resource); + if (!surface) + return; + + unset_pending_color_representation (surface); + + g_clear_signal_handler (&surface->color_representation.destroy_handler_id, + surface); + surface->color_representation.resource = NULL; +} + +static void +color_representation_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static void +color_representation_set_alpha_mode (struct wl_client *client, + struct wl_resource *resource, + enum wp_color_representation_v1_alpha_mode alpha_mode) + +{ + MetaWaylandSurface *surface; + MetaWaylandSurfaceState *pending; + MetaShapedTexturePremult premult; + + surface = wl_resource_get_user_data (resource); + if (!surface) + return; + + pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + return; + + switch (alpha_mode) + { + case WP_COLOR_REPRESENTATION_V1_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL: + premult = META_SHAPED_TEXTURE_PREMULT_ELECTRICAL; + break; + case WP_COLOR_REPRESENTATION_V1_ALPHA_MODE_PREMULTIPLIED_OPTICAL: + premult = META_SHAPED_TEXTURE_PREMULT_OPTICAL; + break; + case WP_COLOR_REPRESENTATION_V1_ALPHA_MODE_STRAIGHT: + premult = META_SHAPED_TEXTURE_PREMULT_STRAIGHT; + break; + default: + premult = META_SHAPED_TEXTURE_PREMULT_ELECTRICAL; + wl_resource_post_error ( + resource, + WP_COLOR_REPRESENTATION_V1_ERROR_INVALID_ALPHA_MODE, + "invalid alpha mode"); + break; + } + + pending->color_representation.premult = premult; +} + +static void +color_representation_set_coefficients (struct wl_client *client, + struct wl_resource *resource, + uint32_t code_point) + +{ + MetaWaylandSurface *surface; + MetaWaylandSurfaceState *pending; + MetaShapedTextureCoefficients coeffs; + + surface = wl_resource_get_user_data (resource); + if (!surface) + return; + + pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + return; + + coeffs = code_point_to_coeffs (code_point); + if (coeffs == META_SHAPED_TEXTURE_COEFFICIENTS_NONE) + { + wl_resource_post_error ( + resource, + WP_COLOR_REPRESENTATION_V1_ERROR_UNSUPPORTED_COEFFICIENTS, + "unsupported coefficients"); + } + + pending->color_representation.coeffs = coeffs; +} + +static void +color_representation_set_chroma_location (struct wl_client *client, + struct wl_resource *resource, + uint32_t code_point) + +{ + MetaWaylandSurface *surface; + MetaWaylandSurfaceState *pending; + MetaShapedTextureChromaLoc chroma_loc; + + surface = wl_resource_get_user_data (resource); + if (!surface) + return; + + pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + return; + + chroma_loc = code_point_to_chroma_loc (code_point); + if (chroma_loc == META_SHAPED_TEXTURE_CHROMA_LOC_NONE) + { + wl_resource_post_error ( + resource, + WP_COLOR_REPRESENTATION_V1_ERROR_UNSUPPORTED_CHROMA_LOCATION, + "unsupported chroma location"); + } + + pending->color_representation.chroma_loc = chroma_loc; +} + +static const struct wp_color_representation_v1_interface + color_representation_implementation = +{ + color_representation_destroy, + color_representation_set_alpha_mode, + color_representation_set_coefficients, + color_representation_set_chroma_location, +}; + + + +static void +color_representation_manager_destroy (struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static void +color_representation_manager_create (struct wl_client *client, + struct wl_resource *resource, + uint32_t color_repr_id, + struct wl_resource *surface_resource) +{ + MetaWaylandSurface *surface; + struct wl_resource *color_repr_resource; + + surface = wl_resource_get_user_data (surface_resource); + if (surface->color_representation.resource) + { + wl_resource_post_error ( + resource, + WP_COLOR_REPRESENTATION_MANAGER_V1_ERROR_ALREADY_CONSTRUCTED, + "a wp_color_representation_v1 object already exists for this surface"); + return; + } + + color_repr_resource = + wl_resource_create (client, + &wp_color_representation_v1_interface, + wl_resource_get_version (resource), + color_repr_id); + + wl_resource_set_implementation (color_repr_resource, + &color_representation_implementation, + surface, + color_representation_destructor); + + surface->color_representation.resource = color_repr_resource; + surface->color_representation.destroy_handler_id = + g_signal_connect (surface, + "destroy", + G_CALLBACK (on_surface_destroyed), + NULL); +} + +static const struct wp_color_representation_manager_v1_interface + color_representation_manager_implementation = +{ + color_representation_manager_destroy, + color_representation_manager_create, +}; + +static void +send_supported_coeff (struct wl_resource *resource, + MetaShapedTextureCoefficients coeff) +{ + uint32_t code_point; + gboolean success; + + success = coeffs_to_code_point (coeff, &code_point); + g_assert (success); + wp_color_representation_manager_v1_send_coefficients (resource, + code_point); +} + +static void +send_supported_chroma_loc (struct wl_resource *resource, + MetaShapedTextureChromaLoc chroma_loc) +{ + uint32_t code_point; + gboolean success; + + success = chroma_loc_to_code_point (chroma_loc, &code_point); + g_assert (success); + wp_color_representation_manager_v1_send_chroma_location (resource, + code_point); +} + +static void +color_representation_manager_bind (struct wl_client *client, + void *data, + uint32_t version, + uint32_t id) +{ + struct wl_resource *resource; + + resource = wl_resource_create (client, + &wp_color_representation_manager_v1_interface, + version, id); + wl_resource_set_implementation (resource, + &color_representation_manager_implementation, + NULL, NULL); + + send_supported_coeff (resource, + META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_FULL); + send_supported_coeff (resource, + META_SHAPED_TEXTURE_COEFFICIENTS_IDENTITY_LIMITED); + send_supported_coeff (resource, + META_SHAPED_TEXTURE_COEFFICIENTS_BT709_FULL); + send_supported_coeff (resource, + META_SHAPED_TEXTURE_COEFFICIENTS_BT709_LIMITED); + + send_supported_chroma_loc (resource, + META_SHAPED_TEXTURE_CHROMA_LOC_CENTER); +} + +void +meta_wayland_color_representation_init (MetaWaylandCompositor *compositor) +{ + if (!wl_global_create (compositor->wayland_display, + &wp_color_representation_manager_v1_interface, + META_WP_COLOR_REPRESENTATION_VERSION, + compositor, + color_representation_manager_bind)) + g_warning ("Failed to create wp_color_representation_manager_v1 global"); +} diff --git a/src/backends/native/meta-cogl-utils.h b/src/wayland/meta-wayland-color-representation.h similarity index 58% rename from src/backends/native/meta-cogl-utils.h rename to src/wayland/meta-wayland-color-representation.h index b5fe6296f03ede4a19c5eb7c2b1099118f35a8b2..82b2eadb0710511d885805d087dddf416e30293e 100644 --- a/src/backends/native/meta-cogl-utils.h +++ b/src/wayland/meta-wayland-color-representation.h @@ -1,6 +1,5 @@ -/* meta-cogl-utils.h - * - * Copyright 2020 Georges Basile Stavracas Neto +/* + * Copyright (C) 2023 Red Hat Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -17,22 +16,16 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * - * SPDX-License-Identifier: GPL-2.0-or-later - * */ -#ifndef META_COGL_UTILS_H -#define META_COGL_UTILS_H - -#include "cogl/cogl.h" +#ifndef META_WAYLAND_COLOR_REPRESENTATION_H +#define META_WAYLAND_COLOR_REPRESENTATION_H -G_BEGIN_DECLS +#include "wayland/meta-wayland-types.h" +#include "compositor/meta-shaped-texture-private.h" -gboolean -meta_cogl_pixel_format_from_drm_format (uint32_t drm_format, - CoglPixelFormat *out_format, - CoglTextureComponents *out_components); +void meta_wayland_color_representation_commit_check (MetaWaylandSurface *surface); -G_END_DECLS +void meta_wayland_color_representation_init (MetaWaylandCompositor *compositor); -#endif /* META_COGL_UTILS_H */ +#endif /* META_WAYLAND_COLOR_REPRESENTATION_H */ diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c index 10f632eb36c3b5986dff4a859356bc4f07e1e88f..30a1e70a1e4f6a52807a837618e42be3246858ea 100644 --- a/src/wayland/meta-wayland-cursor-surface.c +++ b/src/wayland/meta-wayland-cursor-surface.c @@ -61,16 +61,17 @@ 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; + MetaMultiTexture *texture; if (!priv->cursor_renderer) return; texture = meta_wayland_surface_get_texture (surface); - if (texture) + + if (texture && meta_multi_texture_is_simple (texture)) { meta_cursor_sprite_set_texture (cursor_sprite, - texture, + meta_multi_texture_get_plane (texture, 0), priv->hot_x * surface->scale, priv->hot_y * surface->scale); } diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c index 7d96eb4a850cbcb5f0eb5be1e59ea854ad67f207..72b33a7ab477a7976bcd1b83d8986dda3caa76eb 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c @@ -46,10 +46,12 @@ #include #include "backends/meta-backend-private.h" +#include "backends/meta-cogl-utils.h" #include "backends/meta-egl-ext.h" #include "backends/meta-egl.h" #include "cogl/cogl-egl.h" #include "cogl/cogl.h" +#include "compositor/meta-multi-texture-format-private.h" #include "meta/meta-backend.h" #include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-private.h" @@ -65,10 +67,6 @@ #include "linux-dmabuf-unstable-v1-server-protocol.h" -#ifndef DRM_FORMAT_MOD_INVALID -#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) -#endif - #define META_WAYLAND_DMA_BUF_MAX_FDS 4 /* Compatible with zwp_linux_dmabuf_feedback_v1.tranche_flags */ @@ -346,12 +344,8 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf; - uint32_t n_planes; - uint64_t modifiers[META_WAYLAND_DMA_BUF_MAX_FDS]; + MetaMultiTextureFormat multi_format; CoglPixelFormat cogl_format; - EGLImageKHR egl_image; - CoglEglImageFlags flags; - CoglTexture2D *texture; #ifdef HAVE_NATIVE_BACKEND MetaDrmFormatBuf format_buf; #endif @@ -359,55 +353,10 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, if (buffer->dma_buf.texture) return TRUE; - switch (dma_buf->drm_format) + if (!meta_cogl_pixel_format_from_drm_format (dma_buf->drm_format, + &cogl_format, + &multi_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: - cogl_format = COGL_PIXEL_FORMAT_RGB_888; - break; - case DRM_FORMAT_XBGR8888: - cogl_format = COGL_PIXEL_FORMAT_BGR_888; - break; - case DRM_FORMAT_ARGB8888: - cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; - break; - case DRM_FORMAT_ABGR8888: - cogl_format = COGL_PIXEL_FORMAT_ABGR_8888_PRE; - break; - case DRM_FORMAT_XRGB2101010: - cogl_format = COGL_PIXEL_FORMAT_XRGB_2101010; - break; - case DRM_FORMAT_ARGB2101010: - cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE; - break; - case DRM_FORMAT_XBGR2101010: - cogl_format = COGL_PIXEL_FORMAT_XBGR_2101010; - break; - case DRM_FORMAT_ABGR2101010: - cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE; - break; - case DRM_FORMAT_RGB565: - cogl_format = COGL_PIXEL_FORMAT_RGB_565; - break; - case DRM_FORMAT_XBGR16161616F: - cogl_format = COGL_PIXEL_FORMAT_XBGR_FP_16161616; - break; - case DRM_FORMAT_ABGR16161616F: - cogl_format = COGL_PIXEL_FORMAT_ABGR_FP_16161616_PRE; - break; - case DRM_FORMAT_XRGB16161616F: - cogl_format = COGL_PIXEL_FORMAT_XRGB_FP_16161616; - break; - case DRM_FORMAT_ARGB16161616F: - cogl_format = COGL_PIXEL_FORMAT_ARGB_FP_16161616_PRE; - break; - default: g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unsupported buffer format %d", dma_buf->drm_format); @@ -416,49 +365,141 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, #ifdef HAVE_NATIVE_BACKEND meta_topic (META_DEBUG_WAYLAND, - "[dma-buf] wl_buffer@%u DRM format %s -> CoglPixelFormat %s", + "[dma-buf] wl_buffer@%u DRM format %s " + "-> MetaMultiTextureFormat %s / CoglPixelFormat %s", wl_resource_get_id (meta_wayland_buffer_get_resource (buffer)), meta_drm_format_to_string (&format_buf, dma_buf->drm_format), + meta_multi_texture_format_to_string (multi_format), cogl_pixel_format_to_string (cogl_format)); #endif - for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++) + if (multi_format == META_MULTI_TEXTURE_FORMAT_SIMPLE) { - if (dma_buf->fds[n_planes] < 0) - break; + EGLImageKHR egl_image; + CoglEglImageFlags flags; + CoglTexture2D *cogl_texture; + uint64_t modifiers[META_WAYLAND_DMA_BUF_MAX_FDS]; + uint32_t n_planes; - modifiers[n_planes] = dma_buf->drm_modifier; - } + for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++) + { + if (dma_buf->fds[n_planes] < 0) + break; - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - dma_buf->width, - dma_buf->height, - dma_buf->drm_format, - n_planes, - dma_buf->fds, - dma_buf->strides, - dma_buf->offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - return FALSE; + modifiers[n_planes] = dma_buf->drm_modifier; + } - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - texture = cogl_egl_texture_2d_new_from_image (cogl_context, + egl_image = meta_egl_create_dmabuf_image (egl, + egl_display, dma_buf->width, dma_buf->height, - cogl_format, - egl_image, - flags, + dma_buf->drm_format, + n_planes, + dma_buf->fds, + dma_buf->strides, + dma_buf->offsets, + modifiers, error); + if (egl_image == EGL_NO_IMAGE_KHR) + return FALSE; - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; + cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context, + dma_buf->width, + dma_buf->height, + cogl_format, + egl_image, + flags, + error); - if (!texture) - return FALSE; + meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - buffer->dma_buf.texture = COGL_TEXTURE (texture); + if (!cogl_texture) + return FALSE; + + buffer->dma_buf.texture = + meta_multi_texture_new_simple (COGL_TEXTURE (cogl_texture)); + } + else + { + CoglTexture **textures; + g_autoptr (GPtrArray) planes = NULL; + const CoglPixelFormat *subformats; + const uint8_t *horizontal_factors; + const uint8_t *vertical_factors; + const uint8_t *plane_indices; + int n_planes, i; + + n_planes = meta_multi_texture_format_get_n_planes (multi_format); + + /* Each EGLImage is a plane in the final CoglMultiPlaneTexture */ + planes = g_ptr_array_new_full (n_planes, cogl_object_unref); + meta_multi_texture_format_get_subformats (multi_format, &subformats); + meta_multi_texture_format_get_plane_indices (multi_format, &plane_indices); + meta_multi_texture_format_get_subsampling_factors (multi_format, + &horizontal_factors, + &vertical_factors); + + for (i = 0; i < n_planes; i++) + { + EGLImageKHR egl_image; + CoglEglImageFlags flags; + CoglTexture2D *cogl_texture; + uint32_t drm_format = 0; + int plane_index, j; + + for (j = 0; j < G_N_ELEMENTS (drm_format_to_cogl_pixel_format_map); j++) + { + if (drm_format_to_cogl_pixel_format_map[j].cogl_format == + subformats[i]) + { + drm_format = drm_format_to_cogl_pixel_format_map[j].drm_format; + break; + } + } + g_return_val_if_fail (drm_format != 0, FALSE); + + plane_index = plane_indices[i]; + + egl_image = meta_egl_create_dmabuf_image (egl, + egl_display, + dma_buf->width / + horizontal_factors[i], + dma_buf->height / + vertical_factors[i], + drm_format, + 1, + &dma_buf->fds[plane_index], + &dma_buf->strides[plane_index], + &dma_buf->offsets[plane_index], + &dma_buf->drm_modifier, + error); + if (egl_image == EGL_NO_IMAGE_KHR) + return FALSE; + + flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; + cogl_texture = cogl_egl_texture_2d_new_from_image (cogl_context, + dma_buf->width, + dma_buf->height, + subformats[i], + egl_image, + flags, + error); + + meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + + if (!cogl_texture) + return FALSE; + + g_ptr_array_add (planes, cogl_texture); + } + + textures = (CoglTexture**) g_ptr_array_free (g_steal_pointer (&planes), + FALSE); + buffer->dma_buf.texture = meta_multi_texture_new (multi_format, + textures, + n_planes); + } buffer->is_y_inverted = dma_buf->is_y_inverted; return TRUE; @@ -466,14 +507,14 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, gboolean meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error) { if (!meta_wayland_dma_buf_realize_texture (buffer, error)) return FALSE; - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->dma_buf.texture); + g_clear_object (texture); + *texture = g_object_ref (buffer->dma_buf.texture); return TRUE; } @@ -1576,22 +1617,6 @@ init_format_table (MetaWaylandDmaBufManager *dma_buf_manager) meta_anonymous_file_new (size, (uint8_t *) format_table); } -static EGLint supported_formats[] = { - DRM_FORMAT_ARGB8888, - DRM_FORMAT_ABGR8888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_XBGR8888, - DRM_FORMAT_ARGB2101010, - DRM_FORMAT_ABGR2101010, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_XBGR2101010, - DRM_FORMAT_RGB565, - DRM_FORMAT_ABGR16161616F, - DRM_FORMAT_XBGR16161616F, - DRM_FORMAT_XRGB16161616F, - DRM_FORMAT_ARGB16161616F -}; - static gboolean init_formats (MetaWaylandDmaBufManager *dma_buf_manager, EGLDisplay egl_display, @@ -1623,12 +1648,15 @@ init_formats (MetaWaylandDmaBufManager *dma_buf_manager, driver_formats, &num_formats, error)) return FALSE; - for (i = 0; i < G_N_ELEMENTS (supported_formats); i++) + for (i = 0; i < G_N_ELEMENTS (drm_format_to_cogl_pixel_format_map); i++) { for (j = 0; j < num_formats; j++) { - if (supported_formats[i] == driver_formats[j]) - add_format (dma_buf_manager, egl_display, supported_formats[i]); + if (drm_format_to_cogl_pixel_format_map[i].drm_format == + driver_formats[j] && + drm_format_to_cogl_pixel_format_map[i].multi_texture_format != + META_MULTI_TEXTURE_FORMAT_INVALID) + add_format (dma_buf_manager, egl_display, driver_formats[j]); } } diff --git a/src/wayland/meta-wayland-dma-buf.h b/src/wayland/meta-wayland-dma-buf.h index 716b8c778bcae368bb2de7c48ddf0d7ced4f8d70..3fdaf01589fb235d7d39f9d835289068e721ff95 100644 --- a/src/wayland/meta-wayland-dma-buf.h +++ b/src/wayland/meta-wayland-dma-buf.h @@ -31,6 +31,7 @@ #include #include "cogl/cogl.h" +#include "meta/meta-multi-texture.h" #include "wayland/meta-wayland-types.h" #define META_TYPE_WAYLAND_DMA_BUF_BUFFER (meta_wayland_dma_buf_buffer_get_type ()) @@ -48,7 +49,7 @@ MetaWaylandDmaBufManager * meta_wayland_dma_buf_manager_new (MetaWaylandComposit gboolean meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error); MetaWaylandDmaBufBuffer * diff --git a/src/wayland/meta-wayland-single-pixel-buffer.c b/src/wayland/meta-wayland-single-pixel-buffer.c index d327a8a97fad9e86bef3f18dedd9309d58f2a07d..7096a2dbc0506bd59719c6f8d3395a2bbf92317b 100644 --- a/src/wayland/meta-wayland-single-pixel-buffer.c +++ b/src/wayland/meta-wayland-single-pixel-buffer.c @@ -108,7 +108,7 @@ single_pixel_buffer_manager_bind (struct wl_client *client, gboolean meta_wayland_single_pixel_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error) { MetaContext *context = @@ -144,10 +144,11 @@ meta_wayland_single_pixel_buffer_attach (MetaWaylandBuffer *buffer, if (!tex_2d) return FALSE; - buffer->single_pixel.texture = COGL_TEXTURE (tex_2d); + buffer->single_pixel.texture = + meta_multi_texture_new_simple (COGL_TEXTURE (tex_2d)); - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->single_pixel.texture); + g_clear_object (texture); + *texture = g_object_ref (buffer->single_pixel.texture); return TRUE; } diff --git a/src/wayland/meta-wayland-single-pixel-buffer.h b/src/wayland/meta-wayland-single-pixel-buffer.h index 4b0deb9e6329e7a80e3c200c72610e9a31cebd46..28889809b1a363efff7ee3ba76d3f2ec1e28114d 100644 --- a/src/wayland/meta-wayland-single-pixel-buffer.h +++ b/src/wayland/meta-wayland-single-pixel-buffer.h @@ -24,12 +24,13 @@ #include #include "cogl/cogl.h" +#include "meta/meta-multi-texture.h" #include "wayland/meta-wayland-types.h" typedef struct _MetaWaylandSinglePixelBuffer MetaWaylandSinglePixelBuffer; gboolean meta_wayland_single_pixel_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, + MetaMultiTexture **texture, GError **error); MetaWaylandSinglePixelBuffer * meta_wayland_single_pixel_buffer_from_buffer (MetaWaylandBuffer *buffer); diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 611d3b32dbf69aedfac09eec77282e98aebe7cc4..5956bdb1a32edd52732904e37a5f558fe359fbb4 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -38,6 +38,7 @@ #include "core/window-private.h" #include "wayland/meta-wayland-actor-surface.h" #include "wayland/meta-wayland-buffer.h" +#include "wayland/meta-wayland-color-representation.h" #include "wayland/meta-wayland-data-device.h" #include "wayland/meta-wayland-fractional-scale.h" #include "wayland/meta-wayland-gtk-shell.h" @@ -440,7 +441,7 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state) { MetaWaylandFrameCallback *cb, *next; - cogl_clear_object (&state->texture); + g_clear_object (&state->texture); g_clear_pointer (&state->surface_damage, cairo_region_destroy); g_clear_pointer (&state->buffer_damage, cairo_region_destroy); @@ -490,7 +491,7 @@ meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from, to->newly_attached = TRUE; to->buffer = g_steal_pointer (&from->buffer); - cogl_clear_object (&to->texture); + g_clear_object (&to->texture); to->texture = g_steal_pointer (&from->texture); } @@ -731,7 +732,7 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, meta_wayland_buffer_dec_use_count (surface->buffer); g_set_object (&surface->buffer, state->buffer); - cogl_clear_object (&surface->output_state.texture); + g_clear_object (&surface->output_state.texture); surface->output_state.texture = g_steal_pointer (&state->texture); /* If the newly attached buffer is going to be accessed directly without @@ -745,6 +746,10 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, state->buffer->type != META_WAYLAND_BUFFER_TYPE_SINGLE_PIXEL)); } + // FIXME only copy if changed + meta_shaped_texture_color_repr_copy (&state->color_representation, + &surface->color_representation.repr); + if (state->scale > 0) surface->scale = state->scale; @@ -951,14 +956,16 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface) return; } - pending->texture = cogl_object_ref (surface->protocol_state.texture); + pending->texture = g_object_ref (surface->protocol_state.texture); g_object_ref (buffer); meta_wayland_buffer_inc_use_count (buffer); + + meta_wayland_color_representation_commit_check (surface); } else if (pending->newly_attached) { - cogl_clear_object (&surface->protocol_state.texture); + g_clear_object (&surface->protocol_state.texture); } if (meta_wayland_surface_is_synchronized (surface)) @@ -1466,7 +1473,7 @@ meta_wayland_surface_finalize (GObject *object) if (surface->buffer_held) meta_wayland_buffer_dec_use_count (surface->buffer); - g_clear_pointer (&surface->output_state.texture, cogl_object_unref); + g_clear_object (&surface->output_state.texture); g_clear_object (&surface->buffer); if (surface->opaque_region) @@ -1518,7 +1525,7 @@ wl_surface_destructor (struct wl_resource *resource) g_clear_pointer (&surface->wl_subsurface, wl_resource_destroy); g_clear_pointer (&surface->protocol_state.subsurface_branch_node, g_node_destroy); - cogl_clear_object (&surface->protocol_state.texture); + g_clear_object (&surface->protocol_state.texture); /* * Any transactions referencing this surface will keep it alive until they get @@ -2109,7 +2116,7 @@ meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, return g_hash_table_contains (surface->shortcut_inhibited_seats, seat); } -CoglTexture * +MetaMultiTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface) { return surface->output_state.texture; @@ -2184,7 +2191,7 @@ meta_wayland_surface_get_buffer_width (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); if (buffer) - return cogl_texture_get_width (surface->output_state.texture); + return meta_multi_texture_get_width (surface->output_state.texture); else return 0; } @@ -2195,7 +2202,7 @@ meta_wayland_surface_get_buffer_height (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); if (buffer) - return cogl_texture_get_height (surface->output_state.texture); + return meta_multi_texture_get_height (surface->output_state.texture); else return 0; } diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 71d623bde85606098d65fd92fccc7a701e27065e..ae6c7380d5ce42f34d010b0db01c38da5cbf9bba 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -83,7 +83,7 @@ struct _MetaWaylandSurfaceState /* wl_surface.attach */ gboolean newly_attached; MetaWaylandBuffer *buffer; - CoglTexture *texture; + MetaMultiTexture *texture; gulong buffer_destroy_handler_id; int32_t dx; int32_t dy; @@ -137,6 +137,9 @@ struct _MetaWaylandSurfaceState /* xdg_popup */ MetaWaylandXdgPositioner *xdg_positioner; uint32_t xdg_popup_reposition_token; + + /* color-representation */ + MetaShapedTextureColorRepr color_representation; }; struct _MetaWaylandDragDestFuncs @@ -193,7 +196,7 @@ struct _MetaWaylandSurface MetaWaylandSurface *parent; GNode *subsurface_branch_node; GNode *subsurface_leaf_node; - CoglTexture *texture; + MetaMultiTexture *texture; } output_state, protocol_state; /* Extension resources. */ @@ -269,6 +272,14 @@ struct _MetaWaylandSurface MetaWaylandTransaction *first_committed; MetaWaylandTransaction *last_committed; } transaction; + + /* color-representation */ + struct { + struct wl_resource *resource; + gulong destroy_handler_id; + + MetaShapedTextureColorRepr repr; + } color_representation; }; void meta_wayland_shell_init (MetaWaylandCompositor *compositor); @@ -371,7 +382,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); +MetaMultiTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface); META_EXPORT_TEST MetaSurfaceActor * meta_wayland_surface_get_actor (MetaWaylandSurface *surface); diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h index 2323d340761ff352d717a95ac74df88f0ea99aff..0034e3112b7fe242f0f2b2ef7ffd8cb6d0ec0c16 100644 --- a/src/wayland/meta-wayland-versions.h +++ b/src/wayland/meta-wayland-versions.h @@ -59,5 +59,6 @@ #define META_WP_SINGLE_PIXEL_BUFFER_V1_VERSION 1 #define META_MUTTER_X11_INTEROP_VERSION 1 #define META_WP_FRACTIONAL_SCALE_VERSION 1 +#define META_WP_COLOR_REPRESENTATION_VERSION 1 #endif diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index f485bdb3adef2663a0f17979e5022a09fb2d56e7..81ac893630d6064f12cd42a0ea78d3cb90c2f5ff 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -33,6 +33,7 @@ #include "compositor/meta-surface-actor-wayland.h" #include "core/events.h" #include "core/meta-context-private.h" +#include "wayland/meta-wayland-color-representation.h" #include "wayland/meta-wayland-activation.h" #include "wayland/meta-wayland-buffer.h" #include "wayland/meta-wayland-data-device.h" @@ -805,6 +806,7 @@ meta_wayland_compositor_new (MetaContext *context) meta_wayland_init_presentation_time (compositor); meta_wayland_activation_init (compositor); meta_wayland_transaction_init (compositor); + meta_wayland_color_representation_init (compositor); #ifdef HAVE_WAYLAND_EGLSTREAM {