~gnome3-team/mutter/trunk

« back to all changes in this revision

Viewing changes to cogl/tests/conform/test-viewport.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
 
 
2
#include <clutter/clutter.h>
 
3
#include <cogl/cogl.h>
 
4
 
 
5
#include "test-conform-common.h"
 
6
 
 
7
#define RED 0
 
8
#define GREEN 1
 
9
#define BLUE 2
 
10
#define ALPHA 3
 
11
 
 
12
#define FRAMEBUFFER_WIDTH  640
 
13
#define FRAMEBUFFER_HEIGHT 480
 
14
 
 
15
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
 
16
 
 
17
static void
 
18
assert_region_color (int x,
 
19
                     int y,
 
20
                     int width,
 
21
                     int height,
 
22
                     uint8_t red,
 
23
                     uint8_t green,
 
24
                     uint8_t blue,
 
25
                     uint8_t alpha)
 
26
{
 
27
  uint8_t *data = g_malloc0 (width * height * 4);
 
28
  cogl_read_pixels (x, y, width, height,
 
29
                    COGL_READ_PIXELS_COLOR_BUFFER,
 
30
                    COGL_PIXEL_FORMAT_RGBA_8888_PRE,
 
31
                    data);
 
32
  for (y = 0; y < height; y++)
 
33
    for (x = 0; x < width; x++)
 
34
      {
 
35
        uint8_t *pixel = &data[y*width*4 + x*4];
 
36
#if 1
 
37
        g_assert (pixel[RED] == red &&
 
38
                  pixel[GREEN] == green &&
 
39
                  pixel[BLUE] == blue &&
 
40
                  pixel[ALPHA] == alpha);
 
41
#endif
 
42
      }
 
43
  g_free (data);
 
44
}
 
45
 
 
46
static void
 
47
assert_rectangle_color_and_black_border (int x,
 
48
                                         int y,
 
49
                                         int width,
 
50
                                         int height,
 
51
                                         uint8_t red,
 
52
                                         uint8_t green,
 
53
                                         uint8_t blue)
 
54
{
 
55
  /* check the rectangle itself... */
 
56
  assert_region_color (x, y, width, height, red, green, blue, 0xff);
 
57
  /* black to left of the rectangle */
 
58
  assert_region_color (x-10, y-10, 10, height+20, 0x00, 0x00, 0x00, 0xff);
 
59
  /* black to right of the rectangle */
 
60
  assert_region_color (x+width, y-10, 10, height+20, 0x00, 0x00, 0x00, 0xff);
 
61
  /* black above the rectangle */
 
62
  assert_region_color (x-10, y-10, width+20, 10, 0x00, 0x00, 0x00, 0xff);
 
63
  /* and black below the rectangle */
 
64
  assert_region_color (x-10, y+height, width+20, 10, 0x00, 0x00, 0x00, 0xff);
 
65
}
 
66
 
 
67
 
 
68
static void
 
69
on_paint (ClutterActor *actor, void *state)
 
70
{
 
71
  float saved_viewport[4];
 
72
  CoglMatrix saved_projection;
 
73
  CoglMatrix projection;
 
74
  CoglMatrix modelview;
 
75
  guchar *data;
 
76
  CoglHandle tex;
 
77
  CoglHandle offscreen;
 
78
  CoglColor black;
 
79
  float x0;
 
80
  float y0;
 
81
  float width;
 
82
  float height;
 
83
 
 
84
  /* for clearing the offscreen framebuffer to black... */
 
85
  cogl_color_init_from_4ub (&black, 0x00, 0x00, 0x00, 0xff);
 
86
 
 
87
  cogl_get_viewport (saved_viewport);
 
88
  cogl_get_projection_matrix (&saved_projection);
 
89
  cogl_push_matrix ();
 
90
 
 
91
  cogl_matrix_init_identity (&projection);
 
92
  cogl_matrix_init_identity (&modelview);
 
93
 
 
94
  cogl_set_projection_matrix (&projection);
 
95
  cogl_set_modelview_matrix (&modelview);
 
96
 
 
97
  /* - Create a 100x200 viewport (i.e. smaller than the onscreen framebuffer)
 
98
   *   and position it a (20, 10) inside the framebuffer.
 
99
   * - Fill the whole viewport with a purple rectangle
 
100
   * - Verify that the framebuffer is black with a 100x200 purple rectangle at
 
101
   *   (20, 10)
 
102
   */
 
103
  cogl_set_viewport (20, /* x */
 
104
                     10, /* y */
 
105
                     100, /* width */
 
106
                     200); /* height */
 
107
  /* clear everything... */
 
108
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
109
  /* fill the viewport with purple.. */
 
110
  cogl_set_source_color4ub (0xff, 0x00, 0xff, 0xff);
 
111
  cogl_rectangle (-1, 1, 1, -1);
 
112
  assert_rectangle_color_and_black_border (20, 10, 100, 200,
 
113
                                           0xff, 0x00, 0xff);
 
114
 
 
115
 
 
116
  /* - Create a viewport twice the size of the onscreen framebuffer with
 
117
   *   a negative offset positioning it at (-20, -10) relative to the
 
118
   *   buffer itself.
 
119
   * - Draw a 100x200 green rectangle at (40, 20) within the viewport (which
 
120
   *   is (20, 10) within the framebuffer)
 
121
   * - Verify that the framebuffer is black with a 100x200 green rectangle at
 
122
   *   (20, 10)
 
123
   */
 
124
  cogl_set_viewport (-20, /* x */
 
125
                     -10, /* y */
 
126
                     FRAMEBUFFER_WIDTH * 2, /* width */
 
127
                     FRAMEBUFFER_HEIGHT * 2); /* height */
 
128
  /* clear everything... */
 
129
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
130
  /* draw a 100x200 green rectangle offset into the viewport such that its
 
131
   * top left corner should be found at (20, 10) in the offscreen buffer */
 
132
  /* (offset 40 pixels right from the left of the viewport) */
 
133
  x0 = -1.0f + (1.0f / FRAMEBUFFER_WIDTH) * 40.f;
 
134
  /* (offset 20 pixels down from the top of the viewport) */
 
135
  y0 = 1.0f - (1.0f / FRAMEBUFFER_HEIGHT) * 20.0f;
 
136
  width = (1.0f / FRAMEBUFFER_WIDTH) * 100;
 
137
  height = (1.0f / FRAMEBUFFER_HEIGHT) * 200;
 
138
  cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
 
139
  cogl_rectangle (x0, y0, x0 + width, y0 - height);
 
140
  assert_rectangle_color_and_black_border (20, 10, 100, 200,
 
141
                                           0x00, 0xff, 0x00);
 
142
 
 
143
 
 
144
  /* - Create a 200x400 viewport and position it a (20, 10) inside the draw
 
145
   *   buffer.
 
146
   * - Push a 100x200 window space clip rectangle at (20, 10)
 
147
   * - Fill the whole viewport with a blue rectangle
 
148
   * - Verify that the framebuffer is black with a 100x200 blue rectangle at
 
149
   *   (20, 10)
 
150
   */
 
151
  cogl_set_viewport (20, /* x */
 
152
                     10, /* y */
 
153
                     200, /* width */
 
154
                     400); /* height */
 
155
  /* clear everything... */
 
156
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
157
  cogl_clip_push_window_rectangle (20, 10, 100, 200);
 
158
  /* fill the viewport with blue.. */
 
159
  cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
 
160
  cogl_rectangle (-1, 1, 1, -1);
 
161
  cogl_clip_pop ();
 
162
  assert_rectangle_color_and_black_border (20, 10, 100, 200,
 
163
                                           0x00, 0x00, 0xff);
 
164
 
 
165
 
 
166
  /* - Create a 200x400 viewport and position it a (20, 10) inside the draw
 
167
   *   buffer.
 
168
   * - Push a 100x200 model space clip rectangle at (20, 10) in the viewport
 
169
   *   (i.e. (40, 20) inside the framebuffer)
 
170
   * - Fill the whole viewport with a green rectangle
 
171
   * - Verify that the framebuffer is black with a 100x200 green rectangle at
 
172
   *   (40, 20)
 
173
   */
 
174
  cogl_set_viewport (20, /* x */
 
175
                     10, /* y */
 
176
                     200, /* width */
 
177
                     400); /* height */
 
178
  /* clear everything... */
 
179
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
180
  /* figure out where to position our clip rectangle in model space
 
181
   * coordinates... */
 
182
  /* (offset 40 pixels right from the left of the viewport) */
 
183
  x0 = -1.0f + (2.0f / 200) * 20.f;
 
184
  /* (offset 20 pixels down from the top of the viewport) */
 
185
  y0 = 1.0f - (2.0f / 400) * 10.0f;
 
186
  width = (2.0f / 200) * 100;
 
187
  height = (2.0f / 400) * 200;
 
188
  /* add the clip rectangle... */
 
189
  cogl_push_matrix ();
 
190
  cogl_translate (x0 + (width/2.0), y0 - (height/2.0), 0);
 
191
  /* XXX: Rotate just enough to stop Cogl from converting our model space
 
192
   * rectangle into a window space rectangle.. */
 
193
  cogl_rotate (0.1, 0, 0, 1);
 
194
  cogl_clip_push_rectangle (-(width/2.0), -(height/2.0),
 
195
                            width/2.0, height/2.0);
 
196
  cogl_pop_matrix ();
 
197
  /* fill the viewport with green.. */
 
198
  cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
 
199
  cogl_rectangle (-1, 1, 1, -1);
 
200
  cogl_clip_pop ();
 
201
  assert_rectangle_color_and_black_border (40, 20, 100, 200,
 
202
                                           0x00, 0xff, 0x00);
 
203
 
 
204
 
 
205
  /* Set the viewport to something specific so we can verify that it gets
 
206
   * restored after we are done testing with an offscreen framebuffer... */
 
207
  cogl_set_viewport (20, 10, 100, 200);
 
208
 
 
209
  /*
 
210
   * Next test offscreen drawing...
 
211
   */
 
212
  data = g_malloc (FRAMEBUFFER_WIDTH * 4 * FRAMEBUFFER_HEIGHT);
 
213
  tex = test_utils_texture_new_from_data (FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
 
214
                                    TEST_UTILS_TEXTURE_NO_SLICING,
 
215
                                    COGL_PIXEL_FORMAT_RGBA_8888, /* data fmt */
 
216
                                    COGL_PIXEL_FORMAT_ANY, /* internal fmt */
 
217
                                    FRAMEBUFFER_WIDTH * 4, /* rowstride */
 
218
                                    data);
 
219
  g_free (data);
 
220
  offscreen = cogl_offscreen_new_with_texture (tex);
 
221
 
 
222
  cogl_push_framebuffer (offscreen);
 
223
 
 
224
 
 
225
  /* - Create a 100x200 viewport (i.e. smaller than the offscreen framebuffer)
 
226
   *   and position it a (20, 10) inside the framebuffer.
 
227
   * - Fill the whole viewport with a blue rectangle
 
228
   * - Verify that the framebuffer is black with a 100x200 blue rectangle at
 
229
   *   (20, 10)
 
230
   */
 
231
  cogl_set_viewport (20, /* x */
 
232
                     10, /* y */
 
233
                     100, /* width */
 
234
                     200); /* height */
 
235
  /* clear everything... */
 
236
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
237
  /* fill the viewport with blue.. */
 
238
  cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
 
239
  cogl_rectangle (-1, 1, 1, -1);
 
240
  assert_rectangle_color_and_black_border (20, 10, 100, 200,
 
241
                                           0x00, 0x00, 0xff);
 
242
 
 
243
 
 
244
  /* - Create a viewport twice the size of the offscreen framebuffer with
 
245
   *   a negative offset positioning it at (-20, -10) relative to the
 
246
   *   buffer itself.
 
247
   * - Draw a 100x200 red rectangle at (40, 20) within the viewport (which
 
248
   *   is (20, 10) within the framebuffer)
 
249
   * - Verify that the framebuffer is black with a 100x200 red rectangle at
 
250
   *   (20, 10)
 
251
   */
 
252
  cogl_set_viewport (-20, /* x */
 
253
                     -10, /* y */
 
254
                     FRAMEBUFFER_WIDTH * 2, /* width */
 
255
                     FRAMEBUFFER_HEIGHT * 2); /* height */
 
256
  /* clear everything... */
 
257
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
258
  /* draw a 100x200 red rectangle offset into the viewport such that its
 
259
   * top left corner should be found at (20, 10) in the offscreen buffer */
 
260
  /* (offset 40 pixels right from the left of the viewport) */
 
261
  x0 = -1.0f + (1.0f / FRAMEBUFFER_WIDTH) * 40.f;
 
262
  /* (offset 20 pixels down from the top of the viewport) */
 
263
  y0 = 1.0f - (1.0f / FRAMEBUFFER_HEIGHT) * 20.0f;
 
264
  width = (1.0f / FRAMEBUFFER_WIDTH) * 100;
 
265
  height = (1.0f / FRAMEBUFFER_HEIGHT) * 200;
 
266
  cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
 
267
  cogl_rectangle (x0, y0, x0 + width, y0 - height);
 
268
  assert_rectangle_color_and_black_border (20, 10, 100, 200,
 
269
                                           0xff, 0x00, 0x00);
 
270
 
 
271
 
 
272
  /* - Create a 200x400 viewport and position it a (20, 10) inside the draw
 
273
   *   buffer.
 
274
   * - Push a 100x200 window space clip rectangle at (20, 10)
 
275
   * - Fill the whole viewport with a blue rectangle
 
276
   * - Verify that the framebuffer is black with a 100x200 blue rectangle at
 
277
   *   (20, 10)
 
278
   */
 
279
  cogl_set_viewport (20, /* x */
 
280
                     10, /* y */
 
281
                     200, /* width */
 
282
                     400); /* height */
 
283
  /* clear everything... */
 
284
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
285
  cogl_clip_push_window_rectangle (20, 10, 100, 200);
 
286
  /* fill the viewport with blue.. */
 
287
  cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
 
288
  cogl_rectangle (-1, 1, 1, -1);
 
289
  cogl_clip_pop ();
 
290
  assert_rectangle_color_and_black_border (20, 10, 100, 200,
 
291
                                           0x00, 0x00, 0xff);
 
292
 
 
293
 
 
294
  /* - Create a 200x400 viewport and position it a (20, 10) inside the draw
 
295
   *   buffer.
 
296
   * - Push a 100x200 model space clip rectangle at (20, 10) in the viewport
 
297
   *   (i.e. (40, 20) inside the framebuffer)
 
298
   * - Fill the whole viewport with a green rectangle
 
299
   * - Verify that the framebuffer is black with a 100x200 green rectangle at
 
300
   *   (40, 20)
 
301
   */
 
302
  cogl_set_viewport (20, /* x */
 
303
                     10, /* y */
 
304
                     200, /* width */
 
305
                     400); /* height */
 
306
  /* clear everything... */
 
307
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
308
  /* figure out where to position our clip rectangle in model space
 
309
   * coordinates... */
 
310
  /* (offset 40 pixels right from the left of the viewport) */
 
311
  x0 = -1.0f + (2.0f / 200) * 20.f;
 
312
  /* (offset 20 pixels down from the top of the viewport) */
 
313
  y0 = 1.0f - (2.0f / 400) * 10.0f;
 
314
  width = (2.0f / 200) * 100;
 
315
  height = (2.0f / 400) * 200;
 
316
  /* add the clip rectangle... */
 
317
  cogl_push_matrix ();
 
318
  cogl_translate (x0 + (width/2.0), y0 - (height/2.0), 0);
 
319
  /* XXX: Rotate just enough to stop Cogl from converting our model space
 
320
   * rectangle into a window space rectangle.. */
 
321
  cogl_rotate (0.1, 0, 0, 1);
 
322
  cogl_clip_push_rectangle (-(width/2.0), -(height/2.0),
 
323
                            width/2, height/2);
 
324
  cogl_pop_matrix ();
 
325
  /* fill the viewport with green.. */
 
326
  cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
 
327
  cogl_rectangle (-1, 1, 1, -1);
 
328
  cogl_clip_pop ();
 
329
  assert_rectangle_color_and_black_border (40, 20, 100, 200,
 
330
                                           0x00, 0xff, 0x00);
 
331
 
 
332
 
 
333
  /* Set the viewport to something obscure to verify that it gets
 
334
   * replace when we switch back to the onscreen framebuffer... */
 
335
  cogl_set_viewport (0, 0, 10, 10);
 
336
 
 
337
  cogl_pop_framebuffer ();
 
338
  cogl_handle_unref (offscreen);
 
339
 
 
340
  /*
 
341
   * Verify that the previous onscreen framebuffer's viewport was restored
 
342
   * by drawing a white rectangle across the whole viewport. This should
 
343
   * draw a 100x200 rectangle at (20,10) relative to the onscreen draw
 
344
   * buffer...
 
345
   */
 
346
  cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
347
  cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff);
 
348
  cogl_rectangle (-1, 1, 1, -1);
 
349
  assert_rectangle_color_and_black_border (20, 10, 100, 200,
 
350
                                           0xff, 0xff, 0xff);
 
351
 
 
352
 
 
353
  /* Uncomment to display the last contents of the offscreen framebuffer */
 
354
#if 1
 
355
  cogl_matrix_init_identity (&projection);
 
356
  cogl_matrix_init_identity (&modelview);
 
357
  cogl_set_viewport (0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
 
358
  cogl_set_projection_matrix (&projection);
 
359
  cogl_set_modelview_matrix (&modelview);
 
360
  cogl_set_source_texture (tex);
 
361
  cogl_rectangle (-1, 1, 1, -1);
 
362
#endif
 
363
 
 
364
  cogl_handle_unref (tex);
 
365
 
 
366
  /* Finally restore the stage's original state... */
 
367
  cogl_pop_matrix ();
 
368
  cogl_set_projection_matrix (&saved_projection);
 
369
  cogl_set_viewport (saved_viewport[0], saved_viewport[1],
 
370
                     saved_viewport[2], saved_viewport[3]);
 
371
 
 
372
 
 
373
  /* Comment this out if you want visual feedback of what this test
 
374
   * paints.
 
375
   */
 
376
  clutter_main_quit ();
 
377
}
 
378
 
 
379
static CoglBool
 
380
queue_redraw (void *stage)
 
381
{
 
382
  clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
 
383
 
 
384
  return TRUE;
 
385
}
 
386
 
 
387
void
 
388
test_viewport (TestUtilsGTestFixture *fixture,
 
389
                    void *data)
 
390
{
 
391
  unsigned int idle_source;
 
392
  ClutterActor *stage;
 
393
 
 
394
  stage = clutter_stage_get_default ();
 
395
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
 
396
 
 
397
  /* We force continuous redrawing of the stage, since we need to skip
 
398
   * the first few frames, and we wont be doing anything else that
 
399
   * will trigger redrawing. */
 
400
  idle_source = g_idle_add (queue_redraw, stage);
 
401
  g_signal_connect_after (stage, "paint", G_CALLBACK (on_paint), NULL);
 
402
 
 
403
  clutter_actor_show (stage);
 
404
  clutter_main ();
 
405
 
 
406
  g_source_remove (idle_source);
 
407
 
 
408
  /* Remove all of the actors from the stage */
 
409
  clutter_container_foreach (CLUTTER_CONTAINER (stage),
 
410
                             (ClutterCallback) clutter_actor_destroy,
 
411
                             NULL);
 
412
 
 
413
  if (cogl_test_verbose ())
 
414
    g_print ("OK\n");
 
415
}
 
416