"Initial commit to Gerrit"
[profile/ivi/cogl.git] / tests / conform / test-wrap-modes.c
1 #include <cogl/cogl.h>
2 #include <string.h>
3
4 #include "test-utils.h"
5
6 #define TEX_SIZE 4
7
8 typedef struct _TestState
9 {
10   int width;
11   int height;
12   CoglTexture *texture;
13 } TestState;
14
15 static CoglTexture *
16 create_texture (CoglTextureFlags flags)
17 {
18   guint8 *data = g_malloc (TEX_SIZE * TEX_SIZE * 4), *p = data;
19   CoglTexture *tex;
20   int x, y;
21
22   for (y = 0; y < TEX_SIZE; y++)
23     for (x = 0; x < TEX_SIZE; x++)
24       {
25         *(p++) = 0;
26         *(p++) = (x & 1) * 255;
27         *(p++) = (y & 1) * 255;
28         *(p++) = 255;
29       }
30
31   tex = cogl_texture_new_from_data (TEX_SIZE, TEX_SIZE, flags,
32                                     COGL_PIXEL_FORMAT_RGBA_8888_PRE,
33                                     COGL_PIXEL_FORMAT_ANY,
34                                     TEX_SIZE * 4,
35                                     data);
36   g_free (data);
37
38   return tex;
39 }
40
41 static CoglPipeline *
42 create_pipeline (TestState *state,
43                  CoglPipelineWrapMode wrap_mode_s,
44                  CoglPipelineWrapMode wrap_mode_t)
45 {
46   CoglPipeline *pipeline;
47
48   pipeline = cogl_pipeline_new (ctx);
49   cogl_pipeline_set_layer_texture (pipeline, 0, state->texture);
50   cogl_pipeline_set_layer_filters (pipeline, 0,
51                                    COGL_PIPELINE_FILTER_NEAREST,
52                                    COGL_PIPELINE_FILTER_NEAREST);
53   cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0, wrap_mode_s);
54   cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0, wrap_mode_t);
55
56   return pipeline;
57 }
58
59 static CoglPipelineWrapMode
60 wrap_modes[] =
61   {
62     COGL_PIPELINE_WRAP_MODE_REPEAT,
63     COGL_PIPELINE_WRAP_MODE_REPEAT,
64
65     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
66     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
67
68     COGL_PIPELINE_WRAP_MODE_REPEAT,
69     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
70
71     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
72     COGL_PIPELINE_WRAP_MODE_REPEAT,
73
74     COGL_PIPELINE_WRAP_MODE_AUTOMATIC,
75     COGL_PIPELINE_WRAP_MODE_AUTOMATIC,
76
77     COGL_PIPELINE_WRAP_MODE_AUTOMATIC,
78     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE
79   };
80
81 static void
82 draw_tests (TestState *state)
83 {
84   int i;
85
86   for (i = 0; i < G_N_ELEMENTS (wrap_modes); i += 2)
87     {
88       CoglPipelineWrapMode wrap_mode_s, wrap_mode_t;
89       CoglPipeline *pipeline;
90
91       /* Create a separate pipeline for each pair of wrap modes so
92          that we can verify whether the batch splitting works */
93       wrap_mode_s = wrap_modes[i];
94       wrap_mode_t = wrap_modes[i + 1];
95       pipeline = create_pipeline (state, wrap_mode_s, wrap_mode_t);
96       /* Render the pipeline at four times the size of the texture */
97       cogl_framebuffer_draw_textured_rectangle (fb,
98                                                 pipeline,
99                                                 i * TEX_SIZE,
100                                                 0,
101                                                 (i + 2) * TEX_SIZE,
102                                                 TEX_SIZE * 2,
103                                                 0, 0, 2, 2);
104       cogl_object_unref (pipeline);
105     }
106 }
107
108 static const CoglTextureVertex vertices[4] =
109   {
110     { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
111     { 0.0f, TEX_SIZE * 2, 0.0f, 0.0f, 2.0f },
112     { TEX_SIZE * 2, TEX_SIZE * 2, 0.0f, 2.0f, 2.0f },
113     { TEX_SIZE * 2, 0.0f, 0.0f, 2.0f, 0.0f }
114   };
115
116 static void
117 draw_tests_polygon (TestState *state)
118 {
119   int i;
120
121   for (i = 0; i < G_N_ELEMENTS (wrap_modes); i += 2)
122     {
123       CoglPipelineWrapMode wrap_mode_s, wrap_mode_t;
124       CoglPipeline *pipeline;
125
126       wrap_mode_s = wrap_modes[i];
127       wrap_mode_t = wrap_modes[i + 1];
128       pipeline = create_pipeline (state, wrap_mode_s, wrap_mode_t);
129       cogl_set_source (pipeline);
130       cogl_object_unref (pipeline);
131       cogl_push_matrix ();
132       cogl_translate (TEX_SIZE * i, 0.0f, 0.0f);
133       /* Render the pipeline at four times the size of the texture */
134       cogl_polygon (vertices, G_N_ELEMENTS (vertices), FALSE);
135       cogl_pop_matrix ();
136     }
137 }
138
139 static void
140 draw_tests_vbo (TestState *state)
141 {
142   CoglHandle vbo;
143   int i;
144
145   vbo = cogl_vertex_buffer_new (4);
146   cogl_vertex_buffer_add (vbo, "gl_Vertex", 3,
147                           COGL_ATTRIBUTE_TYPE_FLOAT, FALSE,
148                           sizeof (vertices[0]),
149                           &vertices[0].x);
150   cogl_vertex_buffer_add (vbo, "gl_MultiTexCoord0", 2,
151                           COGL_ATTRIBUTE_TYPE_FLOAT, FALSE,
152                           sizeof (vertices[0]),
153                           &vertices[0].tx);
154   cogl_vertex_buffer_submit (vbo);
155
156   for (i = 0; i < G_N_ELEMENTS (wrap_modes); i += 2)
157     {
158       CoglPipelineWrapMode wrap_mode_s, wrap_mode_t;
159       CoglPipeline *pipeline;
160
161       wrap_mode_s = wrap_modes[i];
162       wrap_mode_t = wrap_modes[i + 1];
163       pipeline = create_pipeline (state, wrap_mode_s, wrap_mode_t);
164       cogl_set_source (pipeline);
165       cogl_object_unref (pipeline);
166       cogl_push_matrix ();
167       cogl_translate (TEX_SIZE * i, 0.0f, 0.0f);
168       /* Render the pipeline at four times the size of the texture */
169       cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_TRIANGLE_FAN, 0, 4);
170       cogl_pop_matrix ();
171     }
172
173   cogl_handle_unref (vbo);
174 }
175
176 static void
177 validate_set (TestState *state, int offset)
178 {
179   guint8 data[TEX_SIZE * 2 * TEX_SIZE * 2 * 4], *p;
180   int x, y, i;
181
182   for (i = 0; i < G_N_ELEMENTS (wrap_modes); i += 2)
183     {
184       CoglPipelineWrapMode wrap_mode_s, wrap_mode_t;
185
186       wrap_mode_s = wrap_modes[i];
187       wrap_mode_t = wrap_modes[i + 1];
188
189       cogl_framebuffer_read_pixels (fb, i * TEX_SIZE, offset * TEX_SIZE * 2,
190                                     TEX_SIZE * 2, TEX_SIZE * 2,
191                                     COGL_PIXEL_FORMAT_RGBA_8888,
192                                     data);
193
194       p = data;
195
196       for (y = 0; y < TEX_SIZE * 2; y++)
197         for (x = 0; x < TEX_SIZE * 2; x++)
198           {
199             guint8 green, blue;
200
201             if (x < TEX_SIZE ||
202                 wrap_mode_s == COGL_PIPELINE_WRAP_MODE_REPEAT ||
203                 wrap_mode_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
204               green = (x & 1) * 255;
205             else
206               green = ((TEX_SIZE - 1) & 1) * 255;
207
208             if (y < TEX_SIZE ||
209                 wrap_mode_t == COGL_PIPELINE_WRAP_MODE_REPEAT ||
210                 wrap_mode_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
211               blue = (y & 1) * 255;
212             else
213               blue = ((TEX_SIZE - 1) & 1) * 255;
214
215             g_assert_cmpint (p[0], ==, 0);
216             g_assert_cmpint (p[1], ==, green);
217             g_assert_cmpint (p[2], ==, blue);
218
219             p += 4;
220           }
221     }
222 }
223
224 static void
225 validate_result (TestState *state)
226 {
227   validate_set (state, 0); /* non-atlased rectangle */
228 #if 0 /* this doesn't currently work */
229   validate_set (state, 1); /* atlased rectangle */
230 #endif
231   validate_set (state, 2); /* cogl_polygon */
232   validate_set (state, 3); /* vertex buffer */
233 }
234
235 static void
236 paint (TestState *state)
237 {
238   /* Draw the tests first with a non atlased texture */
239   state->texture = create_texture (COGL_TEXTURE_NO_ATLAS);
240   draw_tests (state);
241   cogl_object_unref (state->texture);
242
243   /* Draw the tests again with a possible atlased texture. This should
244      end up testing software repeats */
245   state->texture = create_texture (COGL_TEXTURE_NONE);
246   cogl_push_matrix ();
247   cogl_translate (0.0f, TEX_SIZE * 2.0f, 0.0f);
248   draw_tests (state);
249   cogl_pop_matrix ();
250   cogl_object_unref (state->texture);
251
252   /* Draw the tests using cogl_polygon */
253   state->texture = create_texture (COGL_TEXTURE_NO_ATLAS);
254   cogl_push_matrix ();
255   cogl_translate (0.0f, TEX_SIZE * 4.0f, 0.0f);
256   draw_tests_polygon (state);
257   cogl_pop_matrix ();
258   cogl_object_unref (state->texture);
259
260   /* Draw the tests using a vertex buffer */
261   state->texture = create_texture (COGL_TEXTURE_NO_ATLAS);
262   cogl_push_matrix ();
263   cogl_translate (0.0f, TEX_SIZE * 6.0f, 0.0f);
264   draw_tests_vbo (state);
265   cogl_pop_matrix ();
266   cogl_object_unref (state->texture);
267
268   validate_result (state);
269 }
270
271 void
272 test_wrap_modes (void)
273 {
274   TestState state;
275
276   state.width = cogl_framebuffer_get_width (fb);
277   state.height = cogl_framebuffer_get_height (fb);
278
279   cogl_framebuffer_orthographic (fb,
280                                  0, 0,
281                                  state.width,
282                                  state.height,
283                                  -1,
284                                  100);
285
286   /* XXX: we have to push/pop a framebuffer since this test currently
287    * uses the legacy cogl_vertex_buffer_draw() api. */
288   cogl_push_framebuffer (fb);
289   paint (&state);
290   cogl_pop_framebuffer ();
291
292   if (cogl_test_verbose ())
293     g_print ("OK\n");
294 }