From f04209dcbffe05e3d4679b9685db4a4e1d9fe1de Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Fri, 9 Jun 2023 11:52:37 +0200 Subject: [PATCH] cogl: Add RGB8888 opaque format variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So we can properly handle matching DRM and WL_SHM formats in a unified manner. Add extensive testing between these and existing pre-multiplied alpha formats, i.e. all formats we support on Wayland. Note that unfortunately for some format combinations the value in the alpha channel is not cleared as expected, likely because of fast-paths in Cogl. If both source and destination format is opaque, it always works, however. This thereby includes all cases where they are the same. Co-Authored-By: Jonas Ã…dahl Part-of: --- cogl/cogl/cogl-bitmap-conversion.c | 4 + cogl/cogl/cogl-bitmap-packing.h | 152 ++++++++++++ cogl/cogl/cogl-pixel-format.c | 28 +++ cogl/cogl/cogl-pixel-format.h | 8 + cogl/cogl/driver/gl/gl/cogl-driver-gl.c | 28 +++ .../driver/gl/gl/cogl-texture-driver-gl.c | 4 + cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 11 + .../driver/gl/gles/cogl-texture-driver-gles.c | 4 + .../conform/test-offscreen-texture-formats.c | 217 ++++++++++++++++++ 9 files changed, 456 insertions(+) diff --git a/cogl/cogl/cogl-bitmap-conversion.c b/cogl/cogl/cogl-bitmap-conversion.c index b97f90e7d..d48c51bd2 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: diff --git a/cogl/cogl/cogl-bitmap-packing.h b/cogl/cogl/cogl-bitmap-packing.h index 9448e57ad..cc2ec3e40 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, @@ -361,18 +425,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); @@ -516,6 +592,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 +624,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 +656,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 +688,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, @@ -744,18 +884,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); diff --git a/cogl/cogl/cogl-pixel-format.c b/cogl/cogl/cogl-pixel-format.c index 0210af046..682bbf8f2 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", diff --git a/cogl/cogl/cogl-pixel-format.h b/cogl/cogl/cogl-pixel-format.h index 8a21371a8..55deeb437 100644 --- a/cogl/cogl/cogl-pixel-format.h +++ b/cogl/cogl/cogl-pixel-format.h @@ -150,9 +150,13 @@ 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 @@ -212,9 +216,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), diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c index 7843921fa..d74ffb823 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; 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 6c59e2471..a1b4cadc2 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: diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c index 7e3a29b82..08920f53d 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: 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 978ffeb8b..4d9519a3b 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: diff --git a/src/tests/cogl/conform/test-offscreen-texture-formats.c b/src/tests/cogl/conform/test-offscreen-texture-formats.c index 7b6e61ec7..a77bdfbcb 100644 --- a/src/tests/cogl/conform/test-offscreen-texture-formats.c +++ b/src/tests/cogl/conform/test-offscreen-texture-formats.c @@ -169,6 +169,104 @@ test_offscreen_texture_formats_store_rgb10 (void) } } +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); + } +} + static void test_offscreen_texture_formats_paint_rgb10 (void) { @@ -229,9 +327,128 @@ test_offscreen_texture_formats_paint_rgb10 (void) g_assert_cmpint (get_bits (rgb10_readback[0], 9, 0), ==, rgb10_red); } +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); + + 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, 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); )