mutter/tests/conform/test-sub-texture.c
Robert Bragg af7398788a remove internal_format and redundant error arguments
Texture allocation is now consistently handled lazily such that the
internal format can now be controlled using
cogl_texture_set_components() and cogl_texture_set_premultiplied()
before allocating the texture with cogl_texture_allocate(). This means
that the internal_format arguments to texture constructors are now
redundant and since most of the texture constructors now can't ever fail
the error arguments are also redundant. This now means we no longer
use CoglPixelFormat in the public api for describing the internal format
of textures which had been bad solution originally due to how specific
CoglPixelFormat is which is missleading when we don't support such
explicit control over the internal format.

Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 99a53c82e9ab0a1e5ee35941bf83dc334b1fbe87)

Note: there are numerous API changes for functions currently marked
as 'unstable' which we don't think are in use by anyone depending on
a stable 1.x api. Compared to the original patch though this avoids
changing the cogl_texture_rectangle_new_with_size() api which we know
is used by Mutter.
2014-01-09 15:49:47 +00:00

326 lines
10 KiB
C

#include <cogl/cogl.h>
#include <string.h>
#include "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);
}
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");
}