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