1
0
Fork 0
mutter-performance-source/cogl/tests/conform/test-atlas-migration.c
Simon McVittie a3cc62c285 cogl tests: Force defined behaviour for 24-bit left-shifts
When r is 128 or more, running tests compiled with the undefined behaviour
sanitizer (ubsan) reports:

test-utils.c:312:45: runtime error: left shift of 128 by 24 places cannot be represented in type 'int'

which indeed it cannot. Force the type to be unsigned 32-bit so that we
get defined behaviour.

Similarly, in test-atlas-migration, the left-shifted guint8 is promoted
to int, which again does not have enough non-sign bits available to
left-shift a value >= 128 by 24 bits. Again, force the shift to be done
in unsigned 32-bit space.

This was originally cogl!22, but applies equally to mutter's fork of cogl.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1271

Signed-off-by: Simon McVittie <smcv@debian.org>
2020-05-27 21:26:49 +00:00

146 lines
3.9 KiB
C

#include <cogl/cogl.h>
#include "test-declarations.h"
#include "test-utils.h"
#define N_TEXTURES 128
#define OPACITY_FOR_ROW(y) \
(0xff - ((y) & 0xf) * 0x10)
#define COLOR_FOR_SIZE(size) \
(colors + (size) % 3)
typedef struct
{
uint8_t red, green, blue, alpha;
} TestColor;
static const TestColor colors[] =
{ { 0xff, 0x00, 0x00, 0xff },
{ 0x00, 0xff, 0x00, 0xff },
{ 0x00, 0x00, 0xff, 0xff } };
static CoglTexture *
create_texture (int size)
{
CoglTexture *texture;
const TestColor *color;
uint8_t *data, *p;
int x, y;
/* Create a red, green or blue texture depending on the size */
color = COLOR_FOR_SIZE (size);
p = data = g_malloc (size * size * 4);
/* Fill the data with the color but fade the opacity out with
increasing y coordinates so that we can see the blending it the
atlas migration accidentally blends with garbage in the
texture */
for (y = 0; y < size; y++)
{
int opacity = OPACITY_FOR_ROW (y);
for (x = 0; x < size; x++)
{
/* Store the colors premultiplied */
p[0] = color->red * opacity / 255;
p[1] = color->green * opacity / 255;
p[2] = color->blue * opacity / 255;
p[3] = opacity;
p += 4;
}
}
texture = test_utils_texture_new_from_data (test_ctx,
size, /* width */
size, /* height */
TEST_UTILS_TEXTURE_NONE, /* flags */
/* format */
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
/* rowstride */
size * 4,
data);
g_free (data);
return texture;
}
static void
verify_texture (CoglTexture *texture, int size)
{
uint8_t *data, *p;
int x, y;
const TestColor *color;
color = COLOR_FOR_SIZE (size);
p = data = g_malloc (size * size * 4);
cogl_texture_get_data (texture,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
size * 4,
data);
for (y = 0; y < size; y++)
{
int opacity = OPACITY_FOR_ROW (y);
for (x = 0; x < size; x++)
{
TestColor real_color =
{
color->red * opacity / 255,
color->green * opacity / 255,
color->blue * opacity / 255
};
test_utils_compare_pixel (p,
(((guint32) real_color.red) << 24) |
(((guint32) real_color.green) << 16) |
(((guint32) real_color.blue) << 8) |
opacity);
g_assert_cmpint (p[3], ==, opacity);
p += 4;
}
}
g_free (data);
}
void
test_atlas_migration (void)
{
CoglTexture *textures[N_TEXTURES];
int i, tex_num;
/* Create and destroy all of the textures a few times to increase
the chances that we'll end up reusing the buffers for previously
discarded atlases */
for (i = 0; i < 5; i++)
{
for (tex_num = 0; tex_num < N_TEXTURES; tex_num++)
textures[tex_num] = create_texture (tex_num + 1);
for (tex_num = 0; tex_num < N_TEXTURES; tex_num++)
cogl_object_unref (textures[tex_num]);
}
/* Create all the textures again */
for (tex_num = 0; tex_num < N_TEXTURES; tex_num++)
textures[tex_num] = create_texture (tex_num + 1);
/* Verify that they all still have the right data */
for (tex_num = 0; tex_num < N_TEXTURES; tex_num++)
verify_texture (textures[tex_num], tex_num + 1);
/* Destroy them all */
for (tex_num = 0; tex_num < N_TEXTURES; tex_num++)
cogl_object_unref (textures[tex_num]);
if (cogl_test_verbose ())
g_print ("OK\n");
}