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