~ubuntu-branches/ubuntu/vivid/clutter-1.0/vivid-proposed

« back to all changes in this revision

Viewing changes to tests/conform/test-cogl-materials.c

  • Committer: Package Import Robot
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2014-03-26 11:51:28 UTC
  • mfrom: (1.5.1) (4.1.30 experimental)
  • Revision ID: package-import@ubuntu.com-20140326115128-timmbsde8734o6wz
Tags: 1.18.0-1
* New upstream release.
* debian/control.in:
  + Bump gtk-doc-tools build dependency.
  + Also break libcogl15.
  + Standards-Version is 3.9.5, no changes needed.
* debian/libclutter-1.0-0.symbols:
  + Drop a few symbols that were accidentally exported in the DSO because
    they had a clutter_ prefix but were not in the public headers.
  + Add one new symbol.
  + Drop unnecessary debian revisions from some symbols.
* debian/control.in,
  debian/rules,
  debian/libclutter-1.0-0.symbols:
  + Temporarily disable evdev input support. It was only enabled in 1.17.6-1
    in experimental and there is nothing using it yet, and I would like to
    wait a bit before uploading libinput to unstable as the ABI isn't stable
    yet.
* d/p/0001-wayland-Add-missing-CLUTTER_AVAILABLE-annotations.patch:
  + Add missing annotations so that a few symbols are exported in the DSO.

* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include "config.h"
2
 
 
3
 
/* XXX: we currently include config.h above as a hack so we can
4
 
 * determine if we are running with GLES2 or not but since Clutter
5
 
 * uses the experimental Cogl api that will also define
6
 
 * COGL_ENABLE_EXPERIMENTAL_2_0_API. The cogl_material_ api isn't
7
 
 * exposed if COGL_ENABLE_EXPERIMENTAL_2_0_API is defined though so we
8
 
 * undef it before cogl.h is included */
9
 
#undef COGL_ENABLE_EXPERIMENTAL_2_0_API
10
 
 
11
 
#include <clutter/clutter.h>
12
 
#include <cogl/cogl.h>
13
 
#include <string.h>
14
 
 
15
 
#include "test-conform-common.h"
16
 
 
17
 
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
18
 
 
19
 
static TestConformGLFunctions gl_functions;
20
 
 
21
 
#define QUAD_WIDTH 20
22
 
 
23
 
#define RED 0
24
 
#define GREEN 1
25
 
#define BLUE 2
26
 
#define ALPHA 3
27
 
 
28
 
#define MASK_RED(COLOR)   ((COLOR & 0xff000000) >> 24)
29
 
#define MASK_GREEN(COLOR) ((COLOR & 0xff0000) >> 16)
30
 
#define MASK_BLUE(COLOR)  ((COLOR & 0xff00) >> 8)
31
 
#define MASK_ALPHA(COLOR) (COLOR & 0xff)
32
 
 
33
 
#ifndef GL_VERSION
34
 
#define GL_VERSION 0x1F02
35
 
#endif
36
 
 
37
 
#ifndef GL_MAX_TEXTURE_IMAGE_UNITS
38
 
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
39
 
#endif
40
 
#ifndef GL_MAX_VERTEX_ATTRIBS
41
 
#define GL_MAX_VERTEX_ATTRIBS 0x8869
42
 
#endif
43
 
#ifndef GL_MAX_TEXTURE_UNITS
44
 
#define GL_MAX_TEXTURE_UNITS 0x84E2
45
 
#endif
46
 
 
47
 
typedef struct _TestState
48
 
{
49
 
  ClutterGeometry stage_geom;
50
 
} TestState;
51
 
 
52
 
 
53
 
static void
54
 
check_pixel (TestState *state, int x, int y, guint32 color)
55
 
{
56
 
  int y_off;
57
 
  int x_off;
58
 
  guint8 pixel[4];
59
 
  guint8 r = MASK_RED (color);
60
 
  guint8 g = MASK_GREEN (color);
61
 
  guint8 b = MASK_BLUE (color);
62
 
  guint8 a = MASK_ALPHA (color);
63
 
 
64
 
  /* See what we got... */
65
 
 
66
 
  y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2);
67
 
  x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2);
68
 
 
69
 
  cogl_read_pixels (x_off, y_off, 1, 1,
70
 
                    COGL_READ_PIXELS_COLOR_BUFFER,
71
 
                    COGL_PIXEL_FORMAT_RGBA_8888_PRE,
72
 
                    pixel);
73
 
  if (g_test_verbose ())
74
 
    g_print ("  result = %02x, %02x, %02x, %02x\n",
75
 
             pixel[RED], pixel[GREEN], pixel[BLUE], pixel[ALPHA]);
76
 
 
77
 
  if (g_test_verbose ())
78
 
    g_print ("  expected = %x, %x, %x, %x\n",
79
 
             r, g, b, a);
80
 
  /* FIXME - allow for hardware in-precision */
81
 
  g_assert (pixel[RED] == r);
82
 
  g_assert (pixel[GREEN] == g);
83
 
  g_assert (pixel[BLUE] == b);
84
 
 
85
 
  /* FIXME
86
 
   * We ignore the alpha, since we don't know if our render target is
87
 
   * RGB or RGBA */
88
 
  /* g_assert (pixel[ALPHA] == a); */
89
 
}
90
 
 
91
 
static void
92
 
test_material_with_primitives (TestState *state,
93
 
                               int x, int y,
94
 
                               guint32 color)
95
 
{
96
 
  CoglTextureVertex verts[4];
97
 
  CoglHandle vbo;
98
 
 
99
 
  verts[0].x = 0;
100
 
  verts[0].y = 0;
101
 
  verts[0].z = 0;
102
 
  verts[1].x = 0;
103
 
  verts[1].y = QUAD_WIDTH;
104
 
  verts[1].z = 0;
105
 
  verts[2].x = QUAD_WIDTH;
106
 
  verts[2].y = QUAD_WIDTH;
107
 
  verts[2].z = 0;
108
 
  verts[3].x = QUAD_WIDTH;
109
 
  verts[3].y = 0;
110
 
  verts[3].z = 0;
111
 
 
112
 
  cogl_push_matrix ();
113
 
 
114
 
  cogl_translate (x * QUAD_WIDTH, y * QUAD_WIDTH, 0);
115
 
 
116
 
  cogl_rectangle (0, 0, QUAD_WIDTH, QUAD_WIDTH);
117
 
 
118
 
  cogl_translate (0, QUAD_WIDTH, 0);
119
 
  cogl_polygon (verts, 4, FALSE);
120
 
 
121
 
  cogl_translate (0, QUAD_WIDTH, 0);
122
 
  vbo = cogl_vertex_buffer_new (4);
123
 
  cogl_vertex_buffer_add (vbo,
124
 
                          "gl_Vertex",
125
 
                          2, /* n components */
126
 
                          COGL_ATTRIBUTE_TYPE_FLOAT,
127
 
                          FALSE, /* normalized */
128
 
                          sizeof (CoglTextureVertex), /* stride */
129
 
                          verts);
130
 
  cogl_vertex_buffer_draw (vbo,
131
 
                           COGL_VERTICES_MODE_TRIANGLE_FAN,
132
 
                           0, /* first */
133
 
                           4); /* count */
134
 
  cogl_handle_unref (vbo);
135
 
 
136
 
  cogl_pop_matrix ();
137
 
 
138
 
  check_pixel (state, x, y,   color);
139
 
  check_pixel (state, x, y+1, color);
140
 
  check_pixel (state, x, y+2, color);
141
 
}
142
 
 
143
 
static void
144
 
test_invalid_texture_layers (TestState *state, int x, int y)
145
 
{
146
 
  CoglHandle        material = cogl_material_new ();
147
 
 
148
 
  /* explicitly create a layer with an invalid handle. This may be desireable
149
 
   * if the user also sets a texture combine string that e.g. refers to a
150
 
   * constant color. */
151
 
  cogl_material_set_layer (material, 0, COGL_INVALID_HANDLE);
152
 
 
153
 
  cogl_set_source (material);
154
 
 
155
 
  cogl_handle_unref (material);
156
 
 
157
 
  /* We expect a white fallback material to be used */
158
 
  test_material_with_primitives (state, x, y, 0xffffffff);
159
 
}
160
 
 
161
 
#ifdef COGL_HAS_GLES2
162
 
static gboolean
163
 
using_gles2_driver (void)
164
 
{
165
 
  /* FIXME: This should probably be replaced with some way to query
166
 
     the driver from Cogl */
167
 
  return g_str_has_prefix ((const char *) gl_functions.glGetString (GL_VERSION),
168
 
                           "OpenGL ES 2");
169
 
}
170
 
#endif
171
 
 
172
 
static void
173
 
test_using_all_layers (TestState *state, int x, int y)
174
 
{
175
 
  CoglHandle material = cogl_material_new ();
176
 
  guint8 white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
177
 
  guint8 red_pixel[] = { 0xff, 0x00, 0x00, 0xff };
178
 
  CoglHandle white_texture;
179
 
  CoglHandle red_texture;
180
 
  int n_layers;
181
 
  int i;
182
 
 
183
 
  /* Create a material that uses the maximum number of layers. All but
184
 
     the last layer will use a solid white texture. The last layer
185
 
     will use a red texture. The layers will all be modulated together
186
 
     so the final fragment should be red. */
187
 
 
188
 
  white_texture = cogl_texture_new_from_data (1, 1, COGL_TEXTURE_NONE,
189
 
                                              COGL_PIXEL_FORMAT_RGBA_8888_PRE,
190
 
                                              COGL_PIXEL_FORMAT_ANY,
191
 
                                              4, white_pixel);
192
 
  red_texture = cogl_texture_new_from_data (1, 1, COGL_TEXTURE_NONE,
193
 
                                            COGL_PIXEL_FORMAT_RGBA_8888_PRE,
194
 
                                            COGL_PIXEL_FORMAT_ANY,
195
 
                                            4, red_pixel);
196
 
 
197
 
  /* FIXME: Cogl doesn't provide a way to query the maximum number of
198
 
     texture layers so for now we'll just ask GL directly. */
199
 
#ifdef COGL_HAS_GLES2
200
 
  if (using_gles2_driver ())
201
 
    {
202
 
      int n_image_units, n_attribs;
203
 
      /* GLES 2 doesn't have GL_MAX_TEXTURE_UNITS and it uses
204
 
         GL_MAX_TEXTURE_IMAGE_UNITS instead */
205
 
      gl_functions.glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &n_image_units);
206
 
      /* Cogl needs a vertex attrib for each layer to upload the texture
207
 
         coordinates */
208
 
      gl_functions.glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, &n_attribs);
209
 
      /* We can't use two of the attribs because they are used by the
210
 
         position and color */
211
 
      n_attribs -= 2;
212
 
      n_layers = MIN (n_attribs, n_image_units);
213
 
    }
214
 
  else
215
 
#endif
216
 
    {
217
 
#if defined(COGL_HAS_GLES1) || defined(COGL_HAS_GL)
218
 
      gl_functions.glGetIntegerv (GL_MAX_TEXTURE_UNITS, &n_layers);
219
 
#endif
220
 
    }
221
 
 
222
 
  /* FIXME: is this still true? */
223
 
  /* Cogl currently can't cope with more than 32 layers so we'll also
224
 
     limit the maximum to that. */
225
 
  if (n_layers > 32)
226
 
    n_layers = 32;
227
 
 
228
 
  for (i = 0; i < n_layers; i++)
229
 
    {
230
 
      cogl_material_set_layer_filters (material, i,
231
 
                                       COGL_MATERIAL_FILTER_NEAREST,
232
 
                                       COGL_MATERIAL_FILTER_NEAREST);
233
 
      cogl_material_set_layer (material, i,
234
 
                               i == n_layers - 1 ? red_texture : white_texture);
235
 
    }
236
 
 
237
 
  cogl_set_source (material);
238
 
 
239
 
  cogl_handle_unref (material);
240
 
  cogl_handle_unref (white_texture);
241
 
  cogl_handle_unref (red_texture);
242
 
 
243
 
  /* We expect the final fragment to be red */
244
 
  test_material_with_primitives (state, x, y, 0xff0000ff);
245
 
}
246
 
 
247
 
static void
248
 
test_invalid_texture_layers_with_constant_colors (TestState *state,
249
 
                                                  int x, int y)
250
 
{
251
 
  CoglHandle material = cogl_material_new ();
252
 
  CoglColor constant_color;
253
 
 
254
 
  /* explicitly create a layer with an invalid handle */
255
 
  cogl_material_set_layer (material, 0, COGL_INVALID_HANDLE);
256
 
 
257
 
  /* ignore the fallback texture on the layer and use a constant color
258
 
     instead */
259
 
  cogl_color_init_from_4ub (&constant_color, 0, 0, 255, 255);
260
 
  cogl_material_set_layer_combine (material, 0,
261
 
                                   "RGBA=REPLACE(CONSTANT)",
262
 
                                   NULL);
263
 
  cogl_material_set_layer_combine_constant (material, 0, &constant_color);
264
 
 
265
 
  cogl_set_source (material);
266
 
 
267
 
  cogl_handle_unref (material);
268
 
 
269
 
  /* We expect the final fragments to be green */
270
 
  test_material_with_primitives (state, x, y, 0x0000ffff);
271
 
}
272
 
 
273
 
static void
274
 
basic_ref_counting_destroy_cb (void *user_data)
275
 
{
276
 
  gboolean *destroyed_flag = user_data;
277
 
 
278
 
  g_assert (*destroyed_flag == FALSE);
279
 
 
280
 
  *destroyed_flag = TRUE;
281
 
}
282
 
 
283
 
static void
284
 
test_basic_ref_counting (void)
285
 
{
286
 
  CoglMaterial *material_parent;
287
 
  gboolean parent_destroyed = FALSE;
288
 
  CoglMaterial *material_child;
289
 
  gboolean child_destroyed = FALSE;
290
 
  static CoglUserDataKey user_data_key;
291
 
 
292
 
  /* This creates a material with a copy and then just unrefs them
293
 
     both without setting them as a source. They should immediately be
294
 
     freed. We can test whether they were freed or not by registering
295
 
     a destroy callback with some user data */
296
 
 
297
 
  material_parent = cogl_material_new ();
298
 
  /* Set some user data so we can detect when the material is
299
 
     destroyed */
300
 
  cogl_object_set_user_data (COGL_OBJECT (material_parent),
301
 
                             &user_data_key,
302
 
                             &parent_destroyed,
303
 
                             basic_ref_counting_destroy_cb);
304
 
 
305
 
  material_child = cogl_material_copy (material_parent);
306
 
  cogl_object_set_user_data (COGL_OBJECT (material_child),
307
 
                             &user_data_key,
308
 
                             &child_destroyed,
309
 
                             basic_ref_counting_destroy_cb);
310
 
 
311
 
  cogl_object_unref (material_child);
312
 
  cogl_object_unref (material_parent);
313
 
 
314
 
  g_assert (parent_destroyed);
315
 
  g_assert (child_destroyed);
316
 
}
317
 
 
318
 
static void
319
 
on_paint (ClutterActor *actor, TestState *state)
320
 
{
321
 
  test_invalid_texture_layers (state,
322
 
                               0, 0 /* position */
323
 
                               );
324
 
  test_invalid_texture_layers_with_constant_colors (state,
325
 
                                                    1, 0 /* position */
326
 
                                                    );
327
 
  test_using_all_layers (state,
328
 
                         2, 0 /* position */
329
 
                         );
330
 
 
331
 
  test_basic_ref_counting ();
332
 
 
333
 
  /* Comment this out if you want visual feedback for what this test paints */
334
 
#if 1
335
 
  clutter_main_quit ();
336
 
#endif
337
 
}
338
 
 
339
 
static gboolean
340
 
queue_redraw (gpointer stage)
341
 
{
342
 
  clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
343
 
 
344
 
  return G_SOURCE_CONTINUE;
345
 
}
346
 
 
347
 
void
348
 
test_cogl_materials (TestConformSimpleFixture *fixture,
349
 
                     gconstpointer data)
350
 
{
351
 
  TestState state;
352
 
  ClutterActor *stage;
353
 
  ClutterActor *group;
354
 
  guint idle_source;
355
 
 
356
 
  test_conform_get_gl_functions (&gl_functions);
357
 
 
358
 
  stage = clutter_stage_new ();
359
 
 
360
 
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
361
 
  clutter_actor_get_geometry (stage, &state.stage_geom);
362
 
 
363
 
  group = clutter_group_new ();
364
 
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
365
 
 
366
 
  /* We force continuous redrawing of the stage, since we need to skip
367
 
   * the first few frames, and we wont be doing anything else that
368
 
   * will trigger redrawing. */
369
 
  idle_source = clutter_threads_add_idle (queue_redraw, stage);
370
 
 
371
 
  g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
372
 
 
373
 
  clutter_actor_show_all (stage);
374
 
 
375
 
  clutter_main ();
376
 
 
377
 
  g_source_remove (idle_source);
378
 
 
379
 
  clutter_actor_destroy (stage);
380
 
 
381
 
  if (g_test_verbose ())
382
 
    g_print ("OK\n");
383
 
}