~oem-solutions-group/unity-2d/clutter-1.0

« back to all changes in this revision

Viewing changes to tests/conform/test-cogl-blend-strings.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-03-21 13:27:56 UTC
  • mto: (2.1.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20100321132756-nf8yd30yxo3zzwcm
Tags: upstream-1.2.2
ImportĀ upstreamĀ versionĀ 1.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include <clutter/clutter.h>
 
3
#include <cogl/cogl.h>
 
4
#include <string.h>
 
5
 
 
6
#include "test-conform-common.h"
 
7
 
 
8
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
 
9
 
 
10
#define QUAD_WIDTH 20
 
11
 
 
12
#define RED 0
 
13
#define GREEN 1
 
14
#define BLUE 2
 
15
#define ALPHA 3
 
16
 
 
17
#define MASK_RED(COLOR)   ((COLOR & 0xff000000) >> 24);
 
18
#define MASK_GREEN(COLOR) ((COLOR & 0xff0000) >> 16);
 
19
#define MASK_BLUE(COLOR)  ((COLOR & 0xff00) >> 8);
 
20
#define MASK_ALPHA(COLOR) (COLOR & 0xff);
 
21
 
 
22
#define BLEND_CONSTANT_UNUSED 0xDEADBEEF
 
23
#define TEX_CONSTANT_UNUSED   0xDEADBEEF
 
24
 
 
25
typedef struct _TestState
 
26
{
 
27
  guint frame;
 
28
  ClutterGeometry stage_geom;
 
29
} TestState;
 
30
 
 
31
 
 
32
static void
 
33
check_pixel (GLubyte *pixel, guint32 color)
 
34
{
 
35
  guint8 r = MASK_RED (color);
 
36
  guint8 g = MASK_GREEN (color);
 
37
  guint8 b = MASK_BLUE (color);
 
38
  guint8 a = MASK_ALPHA (color);
 
39
 
 
40
  if (g_test_verbose ())
 
41
    g_print ("  expected = %x, %x, %x, %x\n",
 
42
             r, g, b, a);
 
43
  /* FIXME - allow for hardware in-precision */
 
44
  g_assert_cmpint (pixel[RED], ==, r);
 
45
  g_assert_cmpint (pixel[GREEN], ==, g);
 
46
  g_assert_cmpint (pixel[BLUE], ==, b);
 
47
 
 
48
  /* FIXME
 
49
   * We ignore the alpha, since we don't know if our render target is
 
50
   * RGB or RGBA */
 
51
  /* g_assert (pixel[ALPHA] == a); */
 
52
}
 
53
 
 
54
static void
 
55
test_blend (TestState *state,
 
56
            int x,
 
57
            int y,
 
58
            guint32 src_color,
 
59
            guint32 dst_color,
 
60
            const char *blend_string,
 
61
            guint32 blend_constant,
 
62
            guint32 expected_result)
 
63
{
 
64
  /* src color */
 
65
  guint8 Sr = MASK_RED (src_color);
 
66
  guint8 Sg = MASK_GREEN (src_color);
 
67
  guint8 Sb = MASK_BLUE (src_color);
 
68
  guint8 Sa = MASK_ALPHA (src_color);
 
69
  /* dest color */
 
70
  guint8 Dr = MASK_RED (dst_color);
 
71
  guint8 Dg = MASK_GREEN (dst_color);
 
72
  guint8 Db = MASK_BLUE (dst_color);
 
73
  guint8 Da = MASK_ALPHA (dst_color);
 
74
  /* blend constant - when applicable */
 
75
  guint8 Br = MASK_RED (blend_constant);
 
76
  guint8 Bg = MASK_GREEN (blend_constant);
 
77
  guint8 Bb = MASK_BLUE (blend_constant);
 
78
  guint8 Ba = MASK_ALPHA (blend_constant);
 
79
  CoglColor blend_const_color;
 
80
 
 
81
  CoglHandle material;
 
82
  gboolean status;
 
83
  GError *error = NULL;
 
84
  GLubyte pixel[4];
 
85
  GLint y_off;
 
86
  GLint x_off;
 
87
 
 
88
  /* First write out the destination color without any blending... */
 
89
  material = cogl_material_new ();
 
90
  cogl_material_set_color4ub (material, Dr, Dg, Db, Da);
 
91
  cogl_material_set_blend (material, "RGBA = ADD (SRC_COLOR, 0)", NULL);
 
92
  cogl_set_source (material);
 
93
  cogl_rectangle (x * QUAD_WIDTH,
 
94
                  y * QUAD_WIDTH,
 
95
                  x * QUAD_WIDTH + QUAD_WIDTH,
 
96
                  y * QUAD_WIDTH + QUAD_WIDTH);
 
97
  cogl_handle_unref (material);
 
98
 
 
99
  /*
 
100
   * Now blend a rectangle over our well defined destination:
 
101
   */
 
102
 
 
103
  material = cogl_material_new ();
 
104
  cogl_material_set_color4ub (material, Sr, Sg, Sb, Sa);
 
105
 
 
106
  status = cogl_material_set_blend (material, blend_string, &error);
 
107
  if (!status)
 
108
    {
 
109
      /* It's not strictly a test failure; you need a more capable GPU or
 
110
       * driver to test this blend string. */
 
111
      g_debug ("Failed to test blend string %s: %s",
 
112
               blend_string, error->message);
 
113
    }
 
114
 
 
115
  cogl_color_set_from_4ub (&blend_const_color, Br, Bg, Bb, Ba);
 
116
  cogl_material_set_blend_constant (material, &blend_const_color);
 
117
 
 
118
  cogl_set_source (material);
 
119
  cogl_rectangle (x * QUAD_WIDTH,
 
120
                  y * QUAD_WIDTH,
 
121
                  x * QUAD_WIDTH + QUAD_WIDTH,
 
122
                  y * QUAD_WIDTH + QUAD_WIDTH);
 
123
  cogl_handle_unref (material);
 
124
 
 
125
  /* See what we got... */
 
126
 
 
127
  y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2);
 
128
  x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2);
 
129
 
 
130
  /* XXX:
 
131
   * We haven't always had good luck with GL drivers implementing glReadPixels
 
132
   * reliably and skipping the first two frames improves our chances... */
 
133
  if (state->frame <= 2)
 
134
    return;
 
135
 
 
136
  cogl_read_pixels (x_off, y_off, 1, 1,
 
137
                    COGL_READ_PIXELS_COLOR_BUFFER,
 
138
                    COGL_PIXEL_FORMAT_RGBA_8888_PRE,
 
139
                    pixel);
 
140
  if (g_test_verbose ())
 
141
    {
 
142
      g_print ("test_blend (%d, %d):\n%s\n", x, y, blend_string);
 
143
      g_print ("  src color = %02x, %02x, %02x, %02x\n", Sr, Sg, Sb, Sa);
 
144
      g_print ("  dst color = %02x, %02x, %02x, %02x\n", Dr, Dg, Db, Da);
 
145
      if (blend_constant != BLEND_CONSTANT_UNUSED)
 
146
        g_print ("  blend constant = %02x, %02x, %02x, %02x\n",
 
147
                 Br, Bg, Bb, Ba);
 
148
      else
 
149
        g_print ("  blend constant = UNUSED\n");
 
150
      g_print ("  result = %x, %x, %x, %x\n",
 
151
               pixel[RED], pixel[GREEN], pixel[BLUE], pixel[ALPHA]);
 
152
    }
 
153
 
 
154
  check_pixel (pixel, expected_result);
 
155
}
 
156
 
 
157
static CoglHandle
 
158
make_texture (guint32 color)
 
159
{
 
160
  guchar *tex_data, *p;
 
161
  guint8 r = MASK_RED (color);
 
162
  guint8 g = MASK_GREEN (color);
 
163
  guint8 b = MASK_BLUE (color);
 
164
  guint8 a = MASK_ALPHA (color);
 
165
  CoglHandle tex;
 
166
 
 
167
  tex_data = g_malloc (QUAD_WIDTH * QUAD_WIDTH * 4);
 
168
 
 
169
  for (p = tex_data + QUAD_WIDTH * QUAD_WIDTH * 4; p > tex_data;)
 
170
    {
 
171
      *(--p) = a;
 
172
      *(--p) = b;
 
173
      *(--p) = g;
 
174
      *(--p) = r;
 
175
    }
 
176
 
 
177
  /* Note: we don't use COGL_PIXEL_FORMAT_ANY for the internal format here
 
178
   * since we don't want to allow Cogl to premultiply our data. */
 
179
  tex = cogl_texture_new_from_data (QUAD_WIDTH,
 
180
                                    QUAD_WIDTH,
 
181
                                    COGL_TEXTURE_NONE,
 
182
                                    COGL_PIXEL_FORMAT_RGBA_8888,
 
183
                                    COGL_PIXEL_FORMAT_RGBA_8888,
 
184
                                    QUAD_WIDTH * 4,
 
185
                                    tex_data);
 
186
 
 
187
  g_free (tex_data);
 
188
 
 
189
  return tex;
 
190
}
 
191
 
 
192
static void
 
193
test_tex_combine (TestState *state,
 
194
                  int x,
 
195
                  int y,
 
196
                  guint32 tex0_color,
 
197
                  guint32 tex1_color,
 
198
                  guint32 combine_constant,
 
199
                  const char *combine_string,
 
200
                  guint32 expected_result)
 
201
{
 
202
  CoglHandle tex0, tex1;
 
203
 
 
204
  /* combine constant - when applicable */
 
205
  guint8 Cr = MASK_RED (combine_constant);
 
206
  guint8 Cg = MASK_GREEN (combine_constant);
 
207
  guint8 Cb = MASK_BLUE (combine_constant);
 
208
  guint8 Ca = MASK_ALPHA (combine_constant);
 
209
  CoglColor combine_const_color;
 
210
 
 
211
  CoglHandle material;
 
212
  gboolean status;
 
213
  GError *error = NULL;
 
214
  GLubyte pixel[4];
 
215
  GLint y_off;
 
216
  GLint x_off;
 
217
 
 
218
 
 
219
  tex0 = make_texture (tex0_color);
 
220
  tex1 = make_texture (tex1_color);
 
221
 
 
222
  material = cogl_material_new ();
 
223
 
 
224
  cogl_material_set_color4ub (material, 0x80, 0x80, 0x80, 0x80);
 
225
  cogl_material_set_blend (material, "RGBA = ADD (SRC_COLOR, 0)", NULL);
 
226
 
 
227
  cogl_material_set_layer (material, 0, tex0);
 
228
  cogl_material_set_layer_combine (material, 0,
 
229
                                   "RGBA = REPLACE (TEXTURE)", NULL);
 
230
 
 
231
  cogl_material_set_layer (material, 1, tex1);
 
232
  status = cogl_material_set_layer_combine (material, 1,
 
233
                                            combine_string, &error);
 
234
  if (!status)
 
235
    {
 
236
      /* It's not strictly a test failure; you need a more capable GPU or
 
237
       * driver to test this texture combine string. */
 
238
      g_debug ("Failed to test texture combine string %s: %s",
 
239
               combine_string, error->message);
 
240
    }
 
241
 
 
242
  cogl_color_set_from_4ub (&combine_const_color, Cr, Cg, Cb, Ca);
 
243
  cogl_material_set_layer_combine_constant (material, 1, &combine_const_color);
 
244
 
 
245
  cogl_set_source (material);
 
246
  cogl_rectangle (x * QUAD_WIDTH,
 
247
                  y * QUAD_WIDTH,
 
248
                  x * QUAD_WIDTH + QUAD_WIDTH,
 
249
                  y * QUAD_WIDTH + QUAD_WIDTH);
 
250
 
 
251
  cogl_handle_unref (material);
 
252
  cogl_handle_unref (tex0);
 
253
  cogl_handle_unref (tex1);
 
254
 
 
255
  /* See what we got... */
 
256
 
 
257
  y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2);
 
258
  x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2);
 
259
 
 
260
  /* XXX:
 
261
   * We haven't always had good luck with GL drivers implementing glReadPixels
 
262
   * reliably and skipping the first two frames improves our chances... */
 
263
  if (state->frame <= 2)
 
264
    return;
 
265
 
 
266
  cogl_read_pixels (x_off, y_off, 1, 1,
 
267
                    COGL_READ_PIXELS_COLOR_BUFFER,
 
268
                    COGL_PIXEL_FORMAT_RGBA_8888_PRE,
 
269
                    pixel);
 
270
  if (g_test_verbose ())
 
271
    {
 
272
      g_print ("test_tex_combine (%d, %d):\n%s\n", x, y, combine_string);
 
273
      g_print ("  texture 0 color = 0x%08lX\n", (unsigned long)tex0_color);
 
274
      g_print ("  texture 1 color = 0x%08lX\n", (unsigned long)tex1_color);
 
275
      if (combine_constant != TEX_CONSTANT_UNUSED)
 
276
        g_print ("  combine constant = %02x, %02x, %02x, %02x\n",
 
277
                 Cr, Cg, Cb, Ca);
 
278
      else
 
279
        g_print ("  combine constant = UNUSED\n");
 
280
      g_print ("  result = %02x, %02x, %02x, %02x\n",
 
281
               pixel[RED], pixel[GREEN], pixel[BLUE], pixel[ALPHA]);
 
282
    }
 
283
 
 
284
  check_pixel (pixel, expected_result);
 
285
}
 
286
 
 
287
static void
 
288
on_paint (ClutterActor *actor, TestState *state)
 
289
{
 
290
  int frame_num;
 
291
 
 
292
  test_blend (state, 0, 0, /* position */
 
293
              0xff0000ff, /* src */
 
294
              0xffffffff, /* dst */
 
295
              "RGBA = ADD (SRC_COLOR, 0)",
 
296
              BLEND_CONSTANT_UNUSED,
 
297
              0xff0000ff); /* expected */
 
298
 
 
299
  test_blend (state, 1, 0, /* position */
 
300
              0x11223344, /* src */
 
301
              0x11223344, /* dst */
 
302
              "RGBA = ADD (SRC_COLOR, DST_COLOR)",
 
303
              BLEND_CONSTANT_UNUSED,
 
304
              0x22446688); /* expected */
 
305
 
 
306
  test_blend (state, 2, 0, /* position */
 
307
              0x80808080, /* src */
 
308
              0xffffffff, /* dst */
 
309
              "RGBA = ADD (SRC_COLOR * (CONSTANT), 0)",
 
310
              0x80808080, /* constant (RGBA all = 0.5 when normalized) */
 
311
              0x40404040); /* expected */
 
312
 
 
313
  test_blend (state, 3, 0, /* position */
 
314
              0x80000080, /* src (alpha = 0.5 when normalized) */
 
315
              0x40000000, /* dst */
 
316
              "RGBA = ADD (SRC_COLOR * (SRC_COLOR[A]),"
 
317
              "            DST_COLOR * (1-SRC_COLOR[A]))",
 
318
              BLEND_CONSTANT_UNUSED,
 
319
              0x60000040); /* expected */
 
320
 
 
321
  /* XXX:
 
322
   * For all texture combine tests tex0 will use a combine mode of
 
323
   * "RGBA = REPLACE (TEXTURE)"
 
324
   */
 
325
 
 
326
  test_tex_combine (state, 4, 0, /* position */
 
327
                    0x11111111, /* texture 0 color */
 
328
                    0x22222222, /* texture 1 color */
 
329
                    TEX_CONSTANT_UNUSED,
 
330
                    "RGBA = ADD (PREVIOUS, TEXTURE)", /* tex combine */
 
331
                    0x33333333); /* expected */
 
332
 
 
333
  test_tex_combine (state, 5, 0, /* position */
 
334
                    0x40404040, /* texture 0 color */
 
335
                    0x80808080, /* texture 1 color (RGBA all = 0.5) */
 
336
                    TEX_CONSTANT_UNUSED,
 
337
                    "RGBA = MODULATE (PREVIOUS, TEXTURE)", /* tex combine */
 
338
                    0x20202020); /* expected */
 
339
 
 
340
  test_tex_combine (state, 6, 0, /* position */
 
341
                    0xffffff80, /* texture 0 color (alpha = 0.5) */
 
342
                    0xDEADBE40, /* texture 1 color */
 
343
                    TEX_CONSTANT_UNUSED,
 
344
                    "RGB = REPLACE (PREVIOUS)"
 
345
                    "A = MODULATE (PREVIOUS, TEXTURE)", /* tex combine */
 
346
                    0xffffff20); /* expected */
 
347
 
 
348
  /* XXX: we are assuming test_tex_combine creates a material with
 
349
   * a color of 0x80808080 (i.e. the "PRIMARY" color) */
 
350
  test_tex_combine (state, 7, 0, /* position */
 
351
                    0xffffff80, /* texture 0 color (alpha = 0.5) */
 
352
                    0xDEADBE20, /* texture 1 color */
 
353
                    TEX_CONSTANT_UNUSED,
 
354
                    "RGB = REPLACE (PREVIOUS)"
 
355
                    "A = MODULATE (PRIMARY, TEXTURE)", /* tex combine */
 
356
                    0xffffff10); /* expected */
 
357
 
 
358
  test_tex_combine (state, 8, 0, /* position */
 
359
                    0x11111111, /* texture 0 color */
 
360
                    0x22222222, /* texture 1 color */
 
361
                    TEX_CONSTANT_UNUSED,
 
362
                    "RGBA = ADD (PREVIOUS, 1-TEXTURE)", /* tex combine */
 
363
                    0xeeeeeeee); /* expected */
 
364
 
 
365
  /* this is again assuming a primary color of 0x80808080 */
 
366
  test_tex_combine (state, 9, 0, /* position */
 
367
                    0x10101010, /* texture 0 color */
 
368
                    0x20202020, /* texture 1 color */
 
369
                    TEX_CONSTANT_UNUSED,
 
370
                    "RGBA = INTERPOLATE (PREVIOUS, TEXTURE, PRIMARY)",
 
371
                    0x18181818); /* expected */
 
372
 
 
373
#if 0 /* using TEXTURE_N appears to be broken in cogl-blend-string.c */
 
374
  test_tex_combine (state, 0, 1, /* position */
 
375
                    0xDEADBEEF, /* texture 0 color (not used) */
 
376
                    0x11223344, /* texture 1 color */
 
377
                    TEX_CONSTANT_UNUSED,
 
378
                    "RGBA = ADD (TEXTURE_1, TEXTURE)", /* tex combine */
 
379
                    0x22446688); /* expected */
 
380
#endif
 
381
 
 
382
  test_tex_combine (state, 1, 1, /* position */
 
383
                    0x21314151, /* texture 0 color */
 
384
                    0x99999999, /* texture 1 color */
 
385
                    TEX_CONSTANT_UNUSED,
 
386
                    "RGBA = ADD_SIGNED (PREVIOUS, TEXTURE)", /* tex combine */
 
387
                    0x3a4a5a6a); /* expected */
 
388
 
 
389
  test_tex_combine (state, 2, 1, /* position */
 
390
                    0xfedcba98, /* texture 0 color */
 
391
                    0x11111111, /* texture 1 color */
 
392
                    TEX_CONSTANT_UNUSED,
 
393
                    "RGBA = SUBTRACT (PREVIOUS, TEXTURE)", /* tex combine */
 
394
                    0xedcba987); /* expected */
 
395
 
 
396
  test_tex_combine (state, 3, 1, /* position */
 
397
                    0x8899aabb, /* texture 0 color */
 
398
                    0xbbaa9988, /* texture 1 color */
 
399
                    TEX_CONSTANT_UNUSED,
 
400
                    "RGB = DOT3_RGBA (PREVIOUS, TEXTURE)"
 
401
                    "A = REPLACE (PREVIOUS)",
 
402
                    0x2a2a2abb); /* expected */
 
403
 
 
404
  /* XXX: Experiments have shown that for some buggy drivers, when using
 
405
   * glReadPixels there is some kind of race, so we delay our test for a
 
406
   * few frames and a few seconds:
 
407
   */
 
408
  frame_num = state->frame++;
 
409
  if (frame_num < 2)
 
410
    g_usleep (G_USEC_PER_SEC);
 
411
 
 
412
  /* Comment this out if you want visual feedback for what this test paints */
 
413
#if 1
 
414
  if (frame_num == 3)
 
415
    clutter_main_quit ();
 
416
#endif
 
417
}
 
418
 
 
419
static gboolean
 
420
queue_redraw (gpointer stage)
 
421
{
 
422
  clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
 
423
 
 
424
  return TRUE;
 
425
}
 
426
 
 
427
void
 
428
test_cogl_blend_strings (TestConformSimpleFixture *fixture,
 
429
                         gconstpointer data)
 
430
{
 
431
  TestState state;
 
432
  ClutterActor *stage;
 
433
  ClutterActor *group;
 
434
  guint idle_source;
 
435
 
 
436
  state.frame = 0;
 
437
 
 
438
  stage = clutter_stage_get_default ();
 
439
 
 
440
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
 
441
  clutter_actor_get_geometry (stage, &state.stage_geom);
 
442
 
 
443
  group = clutter_group_new ();
 
444
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
 
445
 
 
446
  /* We force continuous redrawing of the stage, since we need to skip
 
447
   * the first few frames, and we wont be doing anything else that
 
448
   * will trigger redrawing. */
 
449
  idle_source = g_idle_add (queue_redraw, stage);
 
450
 
 
451
  g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
 
452
 
 
453
  clutter_actor_show_all (stage);
 
454
 
 
455
  clutter_main ();
 
456
 
 
457
  g_source_remove (idle_source);
 
458
 
 
459
  if (g_test_verbose ())
 
460
    g_print ("OK\n");
 
461
}
 
462