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
11 #define FRAMEBUFFER_WIDTH 640
12 #define FRAMEBUFFER_HEIGHT 480
13
14 static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
15
16
17 static void
on_paint(ClutterActor * actor,void * state)18 on_paint (ClutterActor *actor, void *state)
19 {
20 float saved_viewport[4];
21 CoglMatrix saved_projection;
22 CoglMatrix projection;
23 CoglMatrix modelview;
24 guchar *data;
25 CoglHandle tex;
26 CoglHandle offscreen;
27 uint32_t *pixels;
28 uint8_t *pixelsc;
29
30 /* Save the Clutter viewport/matrices and load identity matrices */
31
32 cogl_get_viewport (saved_viewport);
33 cogl_get_projection_matrix (&saved_projection);
34 cogl_push_matrix ();
35
36 cogl_matrix_init_identity (&projection);
37 cogl_matrix_init_identity (&modelview);
38
39 cogl_set_projection_matrix (&projection);
40 cogl_set_modelview_matrix (&modelview);
41
42 /* All offscreen rendering is done upside down so the first thing we
43 * verify is reading back grid of colors from a CoglOffscreen framebuffer
44 */
45
46 data = malloc (FRAMEBUFFER_WIDTH * 4 * FRAMEBUFFER_HEIGHT);
47 tex = test_utils_texture_new_from_data (FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
48 TEST_UTILS_TEXTURE_NO_SLICING,
49 COGL_PIXEL_FORMAT_RGBA_8888, /* data fmt */
50 COGL_PIXEL_FORMAT_ANY, /* internal fmt */
51 FRAMEBUFFER_WIDTH * 4, /* rowstride */
52 data);
53 free (data);
54 offscreen = cogl_offscreen_new_with_texture (tex);
55
56 cogl_push_framebuffer (offscreen);
57
58 /* red, top left */
59 cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
60 cogl_rectangle (-1, 1, 0, 0);
61 /* green, top right */
62 cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
63 cogl_rectangle (0, 1, 1, 0);
64 /* blue, bottom left */
65 cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
66 cogl_rectangle (-1, 0, 0, -1);
67 /* white, bottom right */
68 cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff);
69 cogl_rectangle (0, 0, 1, -1);
70
71 pixels = calloc (1, FRAMEBUFFER_WIDTH * 4 * FRAMEBUFFER_HEIGHT);
72 cogl_read_pixels (0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
73 COGL_READ_PIXELS_COLOR_BUFFER,
74 COGL_PIXEL_FORMAT_RGBA_8888_PRE,
75 (guchar *)pixels);
76
77 g_assert_cmpint (pixels[0], ==, 0xff0000ff);
78 g_assert_cmpint (pixels[FRAMEBUFFER_WIDTH - 1], ==, 0xff00ff00);
79 g_assert_cmpint (pixels[(FRAMEBUFFER_HEIGHT - 1) * FRAMEBUFFER_WIDTH], ==, 0xffff0000);
80 g_assert_cmpint (pixels[(FRAMEBUFFER_HEIGHT - 1) * FRAMEBUFFER_WIDTH + FRAMEBUFFER_WIDTH - 1], ==, 0xffffffff);
81 free (pixels);
82
83 cogl_pop_framebuffer ();
84 cogl_handle_unref (offscreen);
85
86 /* Now verify reading back from an onscreen framebuffer...
87 */
88
89 cogl_set_source_texture (tex);
90 cogl_rectangle (-1, 1, 1, -1);
91
92 pixels = calloc (1, FRAMEBUFFER_WIDTH * 4 * FRAMEBUFFER_HEIGHT);
93 cogl_read_pixels (0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
94 COGL_READ_PIXELS_COLOR_BUFFER,
95 COGL_PIXEL_FORMAT_RGBA_8888_PRE,
96 (guchar *)pixels);
97
98 g_assert_cmpint (pixels[0], ==, 0xff0000ff);
99 g_assert_cmpint (pixels[FRAMEBUFFER_WIDTH - 1], ==, 0xff00ff00);
100 g_assert_cmpint (pixels[(FRAMEBUFFER_HEIGHT - 1) * FRAMEBUFFER_WIDTH], ==, 0xffff0000);
101 g_assert_cmpint (pixels[(FRAMEBUFFER_HEIGHT - 1) * FRAMEBUFFER_WIDTH + FRAMEBUFFER_WIDTH - 1], ==, 0xffffffff);
102 free (pixels);
103
104 /* Verify using BGR format */
105
106 cogl_set_source_texture (tex);
107 cogl_rectangle (-1, 1, 1, -1);
108
109 pixelsc = calloc (1, FRAMEBUFFER_WIDTH * 3 * FRAMEBUFFER_HEIGHT);
110 cogl_read_pixels (0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
111 COGL_READ_PIXELS_COLOR_BUFFER,
112 COGL_PIXEL_FORMAT_BGR_888,
113 (guchar *)pixelsc);
114
115 g_assert_cmpint (pixelsc[0], ==, 0x00);
116 g_assert_cmpint (pixelsc[1], ==, 0x00);
117 g_assert_cmpint (pixelsc[2], ==, 0xff);
118
119 g_assert_cmpint (pixelsc[(FRAMEBUFFER_WIDTH - 1) * 3 + 0], ==, 0x00);
120 g_assert_cmpint (pixelsc[(FRAMEBUFFER_WIDTH - 1) * 3 + 1], ==, 0xff);
121 g_assert_cmpint (pixelsc[(FRAMEBUFFER_WIDTH - 1) * 3 + 2], ==, 0x00);
122
123 free (pixelsc);
124
125 cogl_handle_unref (tex);
126
127 /* Restore the viewport and matrices state */
128 cogl_set_viewport (saved_viewport[0],
129 saved_viewport[1],
130 saved_viewport[2],
131 saved_viewport[3]);
132 cogl_set_projection_matrix (&saved_projection);
133 cogl_pop_matrix ();
134
135 /* Comment this out if you want visual feedback of what this test
136 * paints.
137 */
138 clutter_main_quit ();
139 }
140
141 static CoglBool
queue_redraw(void * stage)142 queue_redraw (void *stage)
143 {
144 clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
145
146 return TRUE;
147 }
148
149 void
test_readpixels(TestUtilsGTestFixture * fixture,void * data)150 test_readpixels (TestUtilsGTestFixture *fixture,
151 void *data)
152 {
153 unsigned int idle_source;
154 ClutterActor *stage;
155
156 stage = clutter_stage_get_default ();
157 clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
158
159 /* We force continuous redrawing of the stage, since we need to skip
160 * the first few frames, and we wont be doing anything else that
161 * will trigger redrawing. */
162 idle_source = g_idle_add (queue_redraw, stage);
163 g_signal_connect_after (stage, "paint", G_CALLBACK (on_paint), NULL);
164
165 clutter_actor_show (stage);
166 clutter_main ();
167
168 g_source_remove (idle_source);
169
170 /* Remove all of the actors from the stage */
171 clutter_container_foreach (CLUTTER_CONTAINER (stage),
172 (ClutterCallback) clutter_actor_destroy,
173 NULL);
174
175 if (cogl_test_verbose ())
176 g_print ("OK\n");
177 }
178
179