mirror of
https://github.com/brl/mutter.git
synced 2025-06-13 16:59:30 +00:00
tests/cogl: Migrate sub-texture test
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2555>
This commit is contained in:
@ -12,6 +12,7 @@ cogl_tests = [
|
||||
'test-premult',
|
||||
'test-snippets',
|
||||
'test-wrap-modes',
|
||||
'test-sub-texture',
|
||||
]
|
||||
|
||||
cogl_test_conformance_includes = [
|
||||
|
328
src/tests/cogl/conform/test-sub-texture.c
Normal file
328
src/tests/cogl/conform/test-sub-texture.c
Normal file
@ -0,0 +1,328 @@
|
||||
#include <cogl/cogl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tests/cogl-test-utils.h"
|
||||
|
||||
#define SOURCE_SIZE 32
|
||||
#define SOURCE_DIVISIONS_X 2
|
||||
#define SOURCE_DIVISIONS_Y 2
|
||||
#define DIVISION_WIDTH (SOURCE_SIZE / SOURCE_DIVISIONS_X)
|
||||
#define DIVISION_HEIGHT (SOURCE_SIZE / SOURCE_DIVISIONS_Y)
|
||||
|
||||
#define TEST_INSET 1
|
||||
|
||||
static const uint32_t
|
||||
corner_colors[SOURCE_DIVISIONS_X * SOURCE_DIVISIONS_Y] =
|
||||
{
|
||||
0xff0000ff, /* red top left */
|
||||
0x00ff00ff, /* green top right */
|
||||
0x0000ffff, /* blue bottom left */
|
||||
0xff00ffff /* purple bottom right */
|
||||
};
|
||||
|
||||
typedef struct _TestState
|
||||
{
|
||||
CoglTexture2D *tex;
|
||||
} TestState;
|
||||
|
||||
static CoglTexture2D *
|
||||
create_source (TestState *state)
|
||||
{
|
||||
int dx, dy;
|
||||
uint8_t *data = g_malloc (SOURCE_SIZE * SOURCE_SIZE * 4);
|
||||
CoglTexture2D *tex;
|
||||
|
||||
/* Create a texture with a different coloured rectangle at each
|
||||
corner */
|
||||
for (dy = 0; dy < SOURCE_DIVISIONS_Y; dy++)
|
||||
for (dx = 0; dx < SOURCE_DIVISIONS_X; dx++)
|
||||
{
|
||||
uint8_t *p = (data + dy * DIVISION_HEIGHT * SOURCE_SIZE * 4 +
|
||||
dx * DIVISION_WIDTH * 4);
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < DIVISION_HEIGHT; y++)
|
||||
{
|
||||
for (x = 0; x < DIVISION_WIDTH; x++)
|
||||
{
|
||||
uint32_t color = GUINT32_FROM_BE (corner_colors[dx + dy * SOURCE_DIVISIONS_X]);
|
||||
memcpy (p, &color, 4);
|
||||
p += 4;
|
||||
}
|
||||
|
||||
p += SOURCE_SIZE * 4 - DIVISION_WIDTH * 4;
|
||||
}
|
||||
}
|
||||
|
||||
tex = cogl_texture_2d_new_from_data (test_ctx,
|
||||
SOURCE_SIZE, SOURCE_SIZE,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
SOURCE_SIZE * 4,
|
||||
data,
|
||||
NULL);
|
||||
return tex;
|
||||
}
|
||||
|
||||
static CoglTexture2D *
|
||||
create_test_texture (TestState *state)
|
||||
{
|
||||
CoglTexture2D *tex;
|
||||
uint8_t *data = g_malloc (256 * 256 * 4), *p = data;
|
||||
int x, y;
|
||||
|
||||
/* Create a texture that is 256x256 where the red component ranges
|
||||
from 0->255 along the x axis and the green component ranges from
|
||||
0->255 along the y axis. The blue and alpha components are all
|
||||
255 */
|
||||
for (y = 0; y < 256; y++)
|
||||
for (x = 0; x < 256; x++)
|
||||
{
|
||||
*(p++) = x;
|
||||
*(p++) = y;
|
||||
*(p++) = 255;
|
||||
*(p++) = 255;
|
||||
}
|
||||
|
||||
tex = cogl_texture_2d_new_from_data (test_ctx,
|
||||
256, 256,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||
256 * 4,
|
||||
data,
|
||||
NULL);
|
||||
g_free (data);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
static void
|
||||
paint (TestState *state)
|
||||
{
|
||||
CoglTexture2D *full_texture;
|
||||
CoglSubTexture *sub_texture, *sub_sub_texture;
|
||||
CoglPipeline *pipeline = cogl_pipeline_new (test_ctx);
|
||||
|
||||
/* Create a sub texture of the bottom right quarter of the texture */
|
||||
sub_texture = cogl_sub_texture_new (test_ctx,
|
||||
state->tex,
|
||||
DIVISION_WIDTH,
|
||||
DIVISION_HEIGHT,
|
||||
DIVISION_WIDTH,
|
||||
DIVISION_HEIGHT);
|
||||
|
||||
/* Paint it */
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, sub_texture);
|
||||
cogl_object_unref (sub_texture);
|
||||
cogl_framebuffer_draw_rectangle (test_fb, pipeline,
|
||||
0.0f, 0.0f, DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||
|
||||
|
||||
/* Repeat a sub texture of the top half of the full texture. This is
|
||||
documented to be undefined so it doesn't technically have to work
|
||||
but it will with the current implementation */
|
||||
sub_texture = cogl_sub_texture_new (test_ctx,
|
||||
state->tex,
|
||||
0, 0,
|
||||
SOURCE_SIZE,
|
||||
DIVISION_HEIGHT);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, sub_texture);
|
||||
cogl_object_unref (sub_texture);
|
||||
cogl_framebuffer_draw_textured_rectangle (test_fb, pipeline,
|
||||
0.0f,
|
||||
SOURCE_SIZE,
|
||||
SOURCE_SIZE * 2.0f,
|
||||
SOURCE_SIZE * 1.5f,
|
||||
0.0f, 0.0f,
|
||||
2.0f, 1.0f);
|
||||
|
||||
/* Create a sub texture of a sub texture */
|
||||
full_texture = create_test_texture (state);
|
||||
sub_texture = cogl_sub_texture_new (test_ctx,
|
||||
full_texture,
|
||||
20, 10, 30, 20);
|
||||
cogl_object_unref (full_texture);
|
||||
sub_sub_texture = cogl_sub_texture_new (test_ctx,
|
||||
sub_texture,
|
||||
20, 10, 10, 10);
|
||||
cogl_object_unref (sub_texture);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, sub_sub_texture);
|
||||
cogl_object_unref (sub_sub_texture);
|
||||
cogl_framebuffer_draw_rectangle (test_fb, pipeline,
|
||||
0.0f, SOURCE_SIZE * 2.0f,
|
||||
10.0f, SOURCE_SIZE * 2.0f + 10.0f);
|
||||
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
validate_part (int xpos, int ypos,
|
||||
int width, int height,
|
||||
uint32_t color)
|
||||
{
|
||||
test_utils_check_region (test_fb,
|
||||
xpos + TEST_INSET,
|
||||
ypos + TEST_INSET,
|
||||
width - TEST_INSET - 2,
|
||||
height - TEST_INSET - 2,
|
||||
color);
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
create_update_data (void)
|
||||
{
|
||||
uint8_t *data = g_malloc (256 * 256 * 4), *p = data;
|
||||
int x, y;
|
||||
|
||||
/* Create some image data that is 256x256 where the blue component
|
||||
ranges from 0->255 along the x axis and the alpha component
|
||||
ranges from 0->255 along the y axis. The red and green components
|
||||
are all zero */
|
||||
for (y = 0; y < 256; y++)
|
||||
for (x = 0; x < 256; x++)
|
||||
{
|
||||
*(p++) = 0;
|
||||
*(p++) = 0;
|
||||
*(p++) = x;
|
||||
*(p++) = y;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
validate_result (TestState *state)
|
||||
{
|
||||
int i, division_num, x, y;
|
||||
CoglTexture2D *test_tex;
|
||||
CoglSubTexture *sub_texture;
|
||||
uint8_t *texture_data, *p;
|
||||
int tex_width, tex_height;
|
||||
|
||||
/* Sub texture of the bottom right corner of the texture */
|
||||
validate_part (0, 0, DIVISION_WIDTH, DIVISION_HEIGHT,
|
||||
corner_colors[
|
||||
(SOURCE_DIVISIONS_Y - 1) * SOURCE_DIVISIONS_X +
|
||||
SOURCE_DIVISIONS_X - 1]);
|
||||
|
||||
/* Sub texture of the top half repeated horizontally */
|
||||
for (i = 0; i < 2; i++)
|
||||
for (division_num = 0; division_num < SOURCE_DIVISIONS_X; division_num++)
|
||||
validate_part (i * SOURCE_SIZE + division_num * DIVISION_WIDTH,
|
||||
SOURCE_SIZE,
|
||||
DIVISION_WIDTH, DIVISION_HEIGHT,
|
||||
corner_colors[division_num]);
|
||||
|
||||
/* Sub sub texture */
|
||||
p = texture_data = g_malloc (10 * 10 * 4);
|
||||
cogl_flush ();
|
||||
cogl_framebuffer_read_pixels (test_fb,
|
||||
0, SOURCE_SIZE * 2, 10, 10,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
p);
|
||||
for (y = 0; y < 10; y++)
|
||||
for (x = 0; x < 10; x++)
|
||||
{
|
||||
g_assert (*(p++) == x + 40);
|
||||
g_assert (*(p++) == y + 20);
|
||||
p += 2;
|
||||
}
|
||||
g_free (texture_data);
|
||||
|
||||
/* Try reading back the texture data */
|
||||
sub_texture = cogl_sub_texture_new (test_ctx,
|
||||
state->tex,
|
||||
SOURCE_SIZE / 4,
|
||||
SOURCE_SIZE / 4,
|
||||
SOURCE_SIZE / 2,
|
||||
SOURCE_SIZE / 2);
|
||||
tex_width = cogl_texture_get_width (sub_texture);
|
||||
tex_height = cogl_texture_get_height (sub_texture);
|
||||
p = texture_data = g_malloc (tex_width * tex_height * 4);
|
||||
cogl_texture_get_data (sub_texture,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
tex_width * 4,
|
||||
texture_data);
|
||||
for (y = 0; y < tex_height; y++)
|
||||
for (x = 0; x < tex_width; x++)
|
||||
{
|
||||
int div_x = ((x * SOURCE_SIZE / 2 / tex_width + SOURCE_SIZE / 4) /
|
||||
DIVISION_WIDTH);
|
||||
int div_y = ((y * SOURCE_SIZE / 2 / tex_height + SOURCE_SIZE / 4) /
|
||||
DIVISION_HEIGHT);
|
||||
uint32_t reference = corner_colors[div_x + div_y * SOURCE_DIVISIONS_X] >> 8;
|
||||
uint32_t color = GUINT32_FROM_BE (*((uint32_t *)p)) >> 8;
|
||||
g_assert (color == reference);
|
||||
p += 4;
|
||||
}
|
||||
g_free (texture_data);
|
||||
cogl_object_unref (sub_texture);
|
||||
|
||||
/* Create a 256x256 test texture */
|
||||
test_tex = create_test_texture (state);
|
||||
/* Create a sub texture the views the center half of the texture */
|
||||
sub_texture = cogl_sub_texture_new (test_ctx,
|
||||
test_tex,
|
||||
64, 64, 128, 128);
|
||||
/* Update the center half of the sub texture */
|
||||
texture_data = create_update_data ();
|
||||
cogl_texture_set_region (sub_texture,
|
||||
0, 0, 32, 32, 64, 64, 256, 256,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE, 256 * 4,
|
||||
texture_data);
|
||||
g_free (texture_data);
|
||||
cogl_object_unref (sub_texture);
|
||||
/* Get the texture data */
|
||||
p = texture_data = g_malloc (256 * 256 * 4);
|
||||
cogl_texture_get_data (test_tex,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||
256 * 4, texture_data);
|
||||
|
||||
/* Verify the texture data */
|
||||
for (y = 0; y < 256; y++)
|
||||
for (x = 0; x < 256; x++)
|
||||
{
|
||||
/* If we're in the center quarter */
|
||||
if (x >= 96 && x < 160 && y >= 96 && y < 160)
|
||||
{
|
||||
g_assert ((*p++) == 0);
|
||||
g_assert ((*p++) == 0);
|
||||
g_assert ((*p++) == x - 96);
|
||||
g_assert ((*p++) == y - 96);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert ((*p++) == x);
|
||||
g_assert ((*p++) == y);
|
||||
g_assert ((*p++) == 255);
|
||||
g_assert ((*p++) == 255);
|
||||
}
|
||||
}
|
||||
g_free (texture_data);
|
||||
cogl_object_unref (test_tex);
|
||||
}
|
||||
|
||||
static void
|
||||
test_sub_texture (void)
|
||||
{
|
||||
TestState state;
|
||||
|
||||
state.tex = create_source (&state);
|
||||
|
||||
cogl_framebuffer_orthographic (test_fb,
|
||||
0, 0,
|
||||
cogl_framebuffer_get_width (test_fb),
|
||||
cogl_framebuffer_get_height (test_fb),
|
||||
-1,
|
||||
100);
|
||||
|
||||
paint (&state);
|
||||
validate_result (&state);
|
||||
|
||||
cogl_object_unref (state.tex);
|
||||
|
||||
if (cogl_test_verbose ())
|
||||
g_print ("OK\n");
|
||||
}
|
||||
|
||||
COGL_TEST_SUITE (
|
||||
g_test_add_func ("/sub-texture", test_sub_texture);
|
||||
)
|
Reference in New Issue
Block a user