~gnome3-team/mutter/trunk

« back to all changes in this revision

Viewing changes to cogl/tests/conform/test-sub-texture.c

  • Committer: Rui Matos
  • Date: 2016-04-27 16:36:25 UTC
  • mfrom: (0.87.3184)
  • Revision ID: git-v1:3fcbe1d3ec5c9208dde080f7e9dac24e4c379bc0
Merge cogl's cogl-1.22 branch into mutter

https://bugzilla.gnome.org/show_bug.cgi?id=760439

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <cogl/cogl.h>
 
2
#include <string.h>
 
3
 
 
4
#include "test-utils.h"
 
5
 
 
6
#define SOURCE_SIZE        32
 
7
#define SOURCE_DIVISIONS_X 2
 
8
#define SOURCE_DIVISIONS_Y 2
 
9
#define DIVISION_WIDTH     (SOURCE_SIZE / SOURCE_DIVISIONS_X)
 
10
#define DIVISION_HEIGHT    (SOURCE_SIZE / SOURCE_DIVISIONS_Y)
 
11
 
 
12
#define TEST_INSET         1
 
13
 
 
14
static const uint32_t
 
15
corner_colors[SOURCE_DIVISIONS_X * SOURCE_DIVISIONS_Y] =
 
16
  {
 
17
    0xff0000ff, /* red top left */
 
18
    0x00ff00ff, /* green top right */
 
19
    0x0000ffff, /* blue bottom left */
 
20
    0xff00ffff  /* purple bottom right */
 
21
  };
 
22
 
 
23
typedef struct _TestState
 
24
{
 
25
  CoglTexture2D *tex;
 
26
} TestState;
 
27
 
 
28
static CoglTexture2D *
 
29
create_source (TestState *state)
 
30
{
 
31
  int dx, dy;
 
32
  uint8_t *data = g_malloc (SOURCE_SIZE * SOURCE_SIZE * 4);
 
33
  CoglTexture2D *tex;
 
34
 
 
35
  /* Create a texture with a different coloured rectangle at each
 
36
     corner */
 
37
  for (dy = 0; dy < SOURCE_DIVISIONS_Y; dy++)
 
38
    for (dx = 0; dx < SOURCE_DIVISIONS_X; dx++)
 
39
      {
 
40
        uint8_t *p = (data + dy * DIVISION_HEIGHT * SOURCE_SIZE * 4 +
 
41
                     dx * DIVISION_WIDTH * 4);
 
42
        int x, y;
 
43
 
 
44
        for (y = 0; y < DIVISION_HEIGHT; y++)
 
45
          {
 
46
            for (x = 0; x < DIVISION_WIDTH; x++)
 
47
              {
 
48
                uint32_t color = GUINT32_FROM_BE (corner_colors[dx + dy * SOURCE_DIVISIONS_X]);
 
49
                memcpy (p, &color, 4);
 
50
                p += 4;
 
51
              }
 
52
 
 
53
            p += SOURCE_SIZE * 4 - DIVISION_WIDTH * 4;
 
54
          }
 
55
      }
 
56
 
 
57
  tex = cogl_texture_2d_new_from_data (test_ctx,
 
58
                                       SOURCE_SIZE, SOURCE_SIZE,
 
59
                                       COGL_PIXEL_FORMAT_RGBA_8888,
 
60
                                       SOURCE_SIZE * 4,
 
61
                                       data,
 
62
                                       NULL);
 
63
  return tex;
 
64
}
 
65
 
 
66
static CoglTexture2D *
 
67
create_test_texture (TestState *state)
 
68
{
 
69
  CoglTexture2D *tex;
 
70
  uint8_t *data = g_malloc (256 * 256 * 4), *p = data;
 
71
  int x, y;
 
72
 
 
73
  /* Create a texture that is 256x256 where the red component ranges
 
74
     from 0->255 along the x axis and the green component ranges from
 
75
     0->255 along the y axis. The blue and alpha components are all
 
76
     255 */
 
77
  for (y = 0; y < 256; y++)
 
78
    for (x = 0; x < 256; x++)
 
79
      {
 
80
        *(p++) = x;
 
81
        *(p++) = y;
 
82
        *(p++) = 255;
 
83
        *(p++) = 255;
 
84
      }
 
85
 
 
86
  tex = cogl_texture_2d_new_from_data (test_ctx,
 
87
                                       256, 256,
 
88
                                       COGL_PIXEL_FORMAT_RGBA_8888_PRE,
 
89
                                       256 * 4,
 
90
                                       data,
 
91
                                       NULL);
 
92
  g_free (data);
 
93
 
 
94
  return tex;
 
95
}
 
96
 
 
97
static void
 
98
paint (TestState *state)
 
99
{
 
100
  CoglTexture2D *full_texture;
 
101
  CoglSubTexture *sub_texture, *sub_sub_texture;
 
102
  CoglPipeline *pipeline = cogl_pipeline_new (test_ctx);
 
103
 
 
104
  /* Create a sub texture of the bottom right quarter of the texture */
 
105
  sub_texture = cogl_sub_texture_new (test_ctx,
 
106
                                      state->tex,
 
107
                                      DIVISION_WIDTH,
 
108
                                      DIVISION_HEIGHT,
 
109
                                      DIVISION_WIDTH,
 
110
                                      DIVISION_HEIGHT);
 
111
 
 
112
  /* Paint it */
 
113
  cogl_pipeline_set_layer_texture (pipeline, 0, sub_texture);
 
114
  cogl_object_unref (sub_texture);
 
115
  cogl_framebuffer_draw_rectangle (test_fb, pipeline,
 
116
                                   0.0f, 0.0f, DIVISION_WIDTH, DIVISION_HEIGHT);
 
117
 
 
118
 
 
119
  /* Repeat a sub texture of the top half of the full texture. This is
 
120
     documented to be undefined so it doesn't technically have to work
 
121
     but it will with the current implementation */
 
122
  sub_texture = cogl_sub_texture_new (test_ctx,
 
123
                                      state->tex,
 
124
                                      0, 0,
 
125
                                      SOURCE_SIZE,
 
126
                                      DIVISION_HEIGHT);
 
127
  cogl_pipeline_set_layer_texture (pipeline, 0, sub_texture);
 
128
  cogl_object_unref (sub_texture);
 
129
  cogl_framebuffer_draw_textured_rectangle (test_fb, pipeline,
 
130
                                            0.0f,
 
131
                                            SOURCE_SIZE,
 
132
                                            SOURCE_SIZE * 2.0f,
 
133
                                            SOURCE_SIZE * 1.5f,
 
134
                                            0.0f, 0.0f,
 
135
                                            2.0f, 1.0f);
 
136
 
 
137
  /* Create a sub texture of a sub texture */
 
138
  full_texture = create_test_texture (state);
 
139
  sub_texture = cogl_sub_texture_new (test_ctx,
 
140
                                      full_texture,
 
141
                                      20, 10, 30, 20);
 
142
  cogl_object_unref (full_texture);
 
143
  sub_sub_texture = cogl_sub_texture_new (test_ctx,
 
144
                                          sub_texture,
 
145
                                          20, 10, 10, 10);
 
146
  cogl_object_unref (sub_texture);
 
147
  cogl_pipeline_set_layer_texture (pipeline, 0, sub_sub_texture);
 
148
  cogl_object_unref (sub_sub_texture);
 
149
  cogl_framebuffer_draw_rectangle (test_fb, pipeline,
 
150
                                   0.0f, SOURCE_SIZE * 2.0f,
 
151
                                   10.0f, SOURCE_SIZE * 2.0f + 10.0f);
 
152
 
 
153
  cogl_object_unref (pipeline);
 
154
}
 
155
 
 
156
static void
 
157
validate_part (int xpos, int ypos,
 
158
               int width, int height,
 
159
               uint32_t color)
 
160
{
 
161
  test_utils_check_region (test_fb,
 
162
                           xpos + TEST_INSET,
 
163
                           ypos + TEST_INSET,
 
164
                           width - TEST_INSET - 2,
 
165
                           height - TEST_INSET - 2,
 
166
                           color);
 
167
}
 
168
 
 
169
static uint8_t *
 
170
create_update_data (void)
 
171
{
 
172
  uint8_t *data = g_malloc (256 * 256 * 4), *p = data;
 
173
  int x, y;
 
174
 
 
175
  /* Create some image data that is 256x256 where the blue component
 
176
     ranges from 0->255 along the x axis and the alpha component
 
177
     ranges from 0->255 along the y axis. The red and green components
 
178
     are all zero */
 
179
  for (y = 0; y < 256; y++)
 
180
    for (x = 0; x < 256; x++)
 
181
      {
 
182
        *(p++) = 0;
 
183
        *(p++) = 0;
 
184
        *(p++) = x;
 
185
        *(p++) = y;
 
186
      }
 
187
 
 
188
  return data;
 
189
}
 
190
 
 
191
static void
 
192
validate_result (TestState *state)
 
193
{
 
194
  int i, division_num, x, y;
 
195
  CoglTexture2D *test_tex;
 
196
  CoglSubTexture *sub_texture;
 
197
  uint8_t *texture_data, *p;
 
198
  int tex_width, tex_height;
 
199
 
 
200
  /* Sub texture of the bottom right corner of the texture */
 
201
  validate_part (0, 0, DIVISION_WIDTH, DIVISION_HEIGHT,
 
202
                 corner_colors[
 
203
                 (SOURCE_DIVISIONS_Y - 1) * SOURCE_DIVISIONS_X +
 
204
                 SOURCE_DIVISIONS_X - 1]);
 
205
 
 
206
  /* Sub texture of the top half repeated horizontally */
 
207
  for (i = 0; i < 2; i++)
 
208
    for (division_num = 0; division_num < SOURCE_DIVISIONS_X; division_num++)
 
209
      validate_part (i * SOURCE_SIZE + division_num * DIVISION_WIDTH,
 
210
                     SOURCE_SIZE,
 
211
                     DIVISION_WIDTH, DIVISION_HEIGHT,
 
212
                     corner_colors[division_num]);
 
213
 
 
214
  /* Sub sub texture */
 
215
  p = texture_data = g_malloc (10 * 10 * 4);
 
216
  cogl_flush ();
 
217
  cogl_framebuffer_read_pixels (test_fb,
 
218
                                0, SOURCE_SIZE * 2, 10, 10,
 
219
                                COGL_PIXEL_FORMAT_RGBA_8888,
 
220
                                p);
 
221
  for (y = 0; y < 10; y++)
 
222
    for (x = 0; x < 10; x++)
 
223
      {
 
224
        g_assert (*(p++) == x + 40);
 
225
        g_assert (*(p++) == y + 20);
 
226
        p += 2;
 
227
      }
 
228
  g_free (texture_data);
 
229
 
 
230
  /* Try reading back the texture data */
 
231
  sub_texture = cogl_sub_texture_new (test_ctx,
 
232
                                      state->tex,
 
233
                                      SOURCE_SIZE / 4,
 
234
                                      SOURCE_SIZE / 4,
 
235
                                      SOURCE_SIZE / 2,
 
236
                                      SOURCE_SIZE / 2);
 
237
  tex_width = cogl_texture_get_width (sub_texture);
 
238
  tex_height = cogl_texture_get_height (sub_texture);
 
239
  p = texture_data = g_malloc (tex_width * tex_height * 4);
 
240
  cogl_texture_get_data (sub_texture,
 
241
                         COGL_PIXEL_FORMAT_RGBA_8888,
 
242
                         tex_width * 4,
 
243
                         texture_data);
 
244
  for (y = 0; y < tex_height; y++)
 
245
    for (x = 0; x < tex_width; x++)
 
246
      {
 
247
        int div_x = ((x * SOURCE_SIZE / 2 / tex_width + SOURCE_SIZE / 4) /
 
248
                     DIVISION_WIDTH);
 
249
        int div_y = ((y * SOURCE_SIZE / 2 / tex_height + SOURCE_SIZE / 4) /
 
250
                     DIVISION_HEIGHT);
 
251
        uint32_t reference = corner_colors[div_x + div_y * SOURCE_DIVISIONS_X] >> 8;
 
252
        uint32_t color = GUINT32_FROM_BE (*((uint32_t *)p)) >> 8;
 
253
        g_assert (color == reference);
 
254
        p += 4;
 
255
      }
 
256
  g_free (texture_data);
 
257
  cogl_object_unref (sub_texture);
 
258
 
 
259
  /* Create a 256x256 test texture */
 
260
  test_tex = create_test_texture (state);
 
261
  /* Create a sub texture the views the center half of the texture */
 
262
  sub_texture = cogl_sub_texture_new (test_ctx,
 
263
                                      test_tex,
 
264
                                      64, 64, 128, 128);
 
265
  /* Update the center half of the sub texture */
 
266
  texture_data = create_update_data ();
 
267
  cogl_texture_set_region (sub_texture,
 
268
                           0, 0, 32, 32, 64, 64, 256, 256,
 
269
                           COGL_PIXEL_FORMAT_RGBA_8888_PRE, 256 * 4,
 
270
                           texture_data);
 
271
  g_free (texture_data);
 
272
  cogl_object_unref (sub_texture);
 
273
  /* Get the texture data */
 
274
  p = texture_data = g_malloc (256 * 256 * 4);
 
275
  cogl_texture_get_data (test_tex,
 
276
                         COGL_PIXEL_FORMAT_RGBA_8888_PRE,
 
277
                         256 * 4, texture_data);
 
278
 
 
279
  /* Verify the texture data */
 
280
  for (y = 0; y < 256; y++)
 
281
    for (x = 0; x < 256; x++)
 
282
      {
 
283
        /* If we're in the center quarter */
 
284
        if (x >= 96 && x < 160 && y >= 96 && y < 160)
 
285
          {
 
286
            g_assert ((*p++) == 0);
 
287
            g_assert ((*p++) == 0);
 
288
            g_assert ((*p++) == x - 96);
 
289
            g_assert ((*p++) == y - 96);
 
290
          }
 
291
        else
 
292
          {
 
293
            g_assert ((*p++) == x);
 
294
            g_assert ((*p++) == y);
 
295
            g_assert ((*p++) == 255);
 
296
            g_assert ((*p++) == 255);
 
297
          }
 
298
      }
 
299
  g_free (texture_data);
 
300
  cogl_object_unref (test_tex);
 
301
}
 
302
 
 
303
void
 
304
test_sub_texture (void)
 
305
{
 
306
  TestState state;
 
307
 
 
308
  state.tex = create_source (&state);
 
309
 
 
310
  cogl_framebuffer_orthographic (test_fb,
 
311
                                 0, 0,
 
312
                                 cogl_framebuffer_get_width (test_fb),
 
313
                                 cogl_framebuffer_get_height (test_fb),
 
314
                                 -1,
 
315
                                 100);
 
316
 
 
317
  paint (&state);
 
318
  validate_result (&state);
 
319
 
 
320
  cogl_object_unref (state.tex);
 
321
 
 
322
  if (cogl_test_verbose ())
 
323
    g_print ("OK\n");
 
324
}
 
325