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

« back to all changes in this revision

Viewing changes to tests/conform/test-backface-culling.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
 
#ifdef CLUTTER_COGL_HAS_GL
11
 
 
12
 
/* Size the texture so that it is just off a power of two to enourage
13
 
   it so use software tiling when NPOTs aren't available */
14
 
#define TEXTURE_SIZE        257
15
 
 
16
 
#else /* CLUTTER_COGL_HAS_GL */
17
 
 
18
 
/* We can't use the funny-sized texture on GL ES because it will break
19
 
   cogl_texture_polygon. However there is only one code path for
20
 
   rendering quads so there is no need */
21
 
#define TEXTURE_SIZE        32
22
 
 
23
 
#endif /* CLUTTER_COGL_HAS_GL */
24
 
 
25
 
/* Amount of pixels to skip off the top, bottom, left and right of the
26
 
   texture when reading back the stage */
27
 
#define TEST_INSET          4
28
 
 
29
 
/* Size to actually render the texture at */
30
 
#define TEXTURE_RENDER_SIZE 32
31
 
 
32
 
typedef struct _TestState
33
 
{
34
 
  guint frame;
35
 
  CoglHandle texture;
36
 
} TestState;
37
 
 
38
 
static gboolean
39
 
validate_part (int xnum, int ynum, gboolean shown)
40
 
{
41
 
  guchar *pixels, *p;
42
 
  ClutterActor *stage = clutter_stage_get_default ();
43
 
  gboolean ret = TRUE;
44
 
 
45
 
  /* Read the appropriate part but skip out a few pixels around the
46
 
     edges */
47
 
  pixels = clutter_stage_read_pixels (CLUTTER_STAGE (stage),
48
 
                                      xnum * TEXTURE_RENDER_SIZE + TEST_INSET,
49
 
                                      ynum * TEXTURE_RENDER_SIZE + TEST_INSET,
50
 
                                      TEXTURE_RENDER_SIZE - TEST_INSET * 2,
51
 
                                      TEXTURE_RENDER_SIZE - TEST_INSET * 2);
52
 
 
53
 
  /* Make sure every pixels is the appropriate color */
54
 
  for (p = pixels;
55
 
       p < pixels + ((TEXTURE_RENDER_SIZE - TEST_INSET * 2)
56
 
                     * (TEXTURE_RENDER_SIZE - TEST_INSET * 2));
57
 
       p += 4)
58
 
    {
59
 
      if (p[0] != (shown ? 255 : 0))
60
 
        ret = FALSE;
61
 
      if (p[1] !=  0)
62
 
        ret = FALSE;
63
 
      if (p[2] != 0)
64
 
        ret = FALSE;
65
 
    }
66
 
 
67
 
  g_free (pixels);
68
 
 
69
 
  return ret;
70
 
}
71
 
 
72
 
static void
73
 
validate_result (TestState *state)
74
 
{
75
 
  /* Front-facing texture */
76
 
  g_assert (validate_part (0, 0, TRUE));
77
 
  /* Back-facing texture */
78
 
  g_assert (validate_part (1, 0, FALSE));
79
 
  /* Front-facing texture polygon */
80
 
  g_assert (validate_part (2, 0, TRUE));
81
 
  /* Back-facing texture polygon */
82
 
  g_assert (validate_part (3, 0, FALSE));
83
 
  /* Regular rectangle */
84
 
  g_assert (validate_part (4, 0, TRUE));
85
 
 
86
 
  /* Backface culling disabled - everything should be shown */
87
 
 
88
 
  /* Front-facing texture */
89
 
  g_assert (validate_part (0, 1, TRUE));
90
 
  /* Back-facing texture */
91
 
  g_assert (validate_part (1, 1, TRUE));
92
 
  /* Front-facing texture polygon */
93
 
  g_assert (validate_part (2, 1, TRUE));
94
 
  /* Back-facing texture polygon */
95
 
  g_assert (validate_part (3, 1, TRUE));
96
 
  /* Regular rectangle */
97
 
  g_assert (validate_part (4, 1, TRUE));
98
 
 
99
 
  /* Comment this out if you want visual feedback of what this test
100
 
   * paints.
101
 
   */
102
 
  clutter_main_quit ();
103
 
}
104
 
 
105
 
static void
106
 
on_paint (ClutterActor *actor, TestState *state)
107
 
{
108
 
  int i;
109
 
  int frame_num;
110
 
  CoglHandle material = cogl_material_new ();
111
 
 
112
 
  cogl_material_set_layer_filters (material, 0,
113
 
                                   COGL_MATERIAL_FILTER_NEAREST,
114
 
                                   COGL_MATERIAL_FILTER_NEAREST);
115
 
 
116
 
  cogl_set_backface_culling_enabled (TRUE);
117
 
 
118
 
  cogl_push_matrix ();
119
 
 
120
 
  /* Render the scene twice - once with backface culling enabled and
121
 
     once without. The second time is translated so that it is below
122
 
     the first */
123
 
  for (i = 0; i < 2; i++)
124
 
    {
125
 
      float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE);
126
 
      CoglTextureVertex verts[4];
127
 
 
128
 
      cogl_set_source (material);
129
 
 
130
 
      memset (verts, 0, sizeof (verts));
131
 
 
132
 
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
133
 
 
134
 
      /* Draw a front-facing texture */
135
 
      cogl_material_set_layer (material, 0, state->texture);
136
 
      cogl_rectangle (x1, y1, x2, y2);
137
 
 
138
 
      x1 = x2;
139
 
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
140
 
 
141
 
      /* Draw a back-facing texture */
142
 
      cogl_material_set_layer (material, 0, state->texture);
143
 
      cogl_rectangle (x2, y1, x1, y2);
144
 
 
145
 
      x1 = x2;
146
 
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
147
 
 
148
 
      /* Draw a front-facing texture polygon */
149
 
      verts[0].x = x1;    verts[0].y = y2;
150
 
      verts[1].x = x2;    verts[1].y = y2;
151
 
      verts[2].x = x2;    verts[2].y = y1;
152
 
      verts[3].x = x1;    verts[3].y = y1;
153
 
      verts[0].tx = 0;    verts[0].ty = 0;
154
 
      verts[1].tx = 1.0;  verts[1].ty = 0;
155
 
      verts[2].tx = 1.0;  verts[2].ty = 1.0;
156
 
      verts[3].tx = 0;    verts[3].ty = 1.0;
157
 
      cogl_material_set_layer (material, 0, state->texture);
158
 
      cogl_polygon (verts, 4, FALSE);
159
 
 
160
 
      x1 = x2;
161
 
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
162
 
 
163
 
      /* Draw a back-facing texture polygon */
164
 
      verts[0].x = x1;    verts[0].y = y1;
165
 
      verts[1].x = x2;    verts[1].y = y1;
166
 
      verts[2].x = x2;    verts[2].y = y2;
167
 
      verts[3].x = x1;    verts[3].y = y2;
168
 
      verts[0].tx = 0;    verts[0].ty = 0;
169
 
      verts[1].tx = 1.0;  verts[1].ty = 0;
170
 
      verts[2].tx = 1.0;  verts[2].ty = 1.0;
171
 
      verts[3].tx = 0;    verts[3].ty = 1.0;
172
 
      cogl_material_set_layer (material, 0, state->texture);
173
 
      cogl_polygon (verts, 4, FALSE);
174
 
 
175
 
      x1 = x2;
176
 
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
177
 
 
178
 
      /* Draw a regular rectangle (this should always show) */
179
 
      cogl_set_source_color4f (1.0, 0, 0, 1.0);
180
 
      cogl_rectangle (x1, y1, x2, y2);
181
 
 
182
 
      /* The second time round draw beneath the first with backface
183
 
         culling disabled */
184
 
      cogl_translate (0, TEXTURE_RENDER_SIZE, 0);
185
 
      cogl_set_backface_culling_enabled (FALSE);
186
 
    }
187
 
 
188
 
  cogl_pop_matrix ();
189
 
 
190
 
  cogl_handle_unref (material);
191
 
 
192
 
  /* XXX: Experiments have shown that for some buggy drivers, when using
193
 
   * glReadPixels there is some kind of race, so we delay our test for a
194
 
   * few frames and a few seconds:
195
 
   */
196
 
  /* Need to increment frame first because clutter_stage_read_pixels
197
 
     fires a redraw */
198
 
  frame_num = state->frame++;
199
 
  if (frame_num == 2)
200
 
    validate_result (state);
201
 
  else if (frame_num < 2)
202
 
    g_usleep (G_USEC_PER_SEC);
203
 
}
204
 
 
205
 
static gboolean
206
 
queue_redraw (gpointer stage)
207
 
{
208
 
  clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
209
 
 
210
 
  return TRUE;
211
 
}
212
 
 
213
 
static CoglHandle
214
 
make_texture (void)
215
 
{
216
 
  guchar *tex_data, *p;
217
 
  CoglHandle tex;
218
 
 
219
 
  tex_data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4);
220
 
 
221
 
  for (p = tex_data + TEXTURE_SIZE * TEXTURE_SIZE * 4; p > tex_data;)
222
 
    {
223
 
      *(--p) = 255;
224
 
      *(--p) = 0;
225
 
      *(--p) = 0;
226
 
      *(--p) = 255;
227
 
    }
228
 
 
229
 
  tex = cogl_texture_new_from_data (TEXTURE_SIZE,
230
 
                                    TEXTURE_SIZE,
231
 
                                    COGL_TEXTURE_NONE,
232
 
                                    COGL_PIXEL_FORMAT_RGBA_8888,
233
 
                                    COGL_PIXEL_FORMAT_ANY,
234
 
                                    TEXTURE_SIZE * 4,
235
 
                                    tex_data);
236
 
 
237
 
  g_free (tex_data);
238
 
 
239
 
  return tex;
240
 
}
241
 
 
242
 
void
243
 
test_backface_culling (TestConformSimpleFixture *fixture,
244
 
                       gconstpointer data)
245
 
{
246
 
  TestState state;
247
 
  ClutterActor *stage;
248
 
  ClutterActor *group;
249
 
  guint idle_source;
250
 
 
251
 
  state.frame = 0;
252
 
 
253
 
  state.texture = make_texture ();
254
 
 
255
 
  stage = clutter_stage_get_default ();
256
 
 
257
 
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
258
 
 
259
 
  group = clutter_group_new ();
260
 
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
261
 
 
262
 
  /* We force continuous redrawing of the stage, since we need to skip
263
 
   * the first few frames, and we wont be doing anything else that
264
 
   * will trigger redrawing. */
265
 
  idle_source = g_idle_add (queue_redraw, stage);
266
 
 
267
 
  g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
268
 
 
269
 
  clutter_actor_show_all (stage);
270
 
 
271
 
  clutter_main ();
272
 
 
273
 
  g_source_remove (idle_source);
274
 
 
275
 
  cogl_handle_unref (state.texture);
276
 
 
277
 
  if (g_test_verbose ())
278
 
    g_print ("OK\n");
279
 
}
280