glsl: test loop unroll with uint overflow
[piglit.git] / tests / spec / ext_framebuffer_multisample / clip-and-scissor-blit.cpp
blobbe8687217c4d1583dddceeeea0b6ab78b293881e
1 /*
2 * Copyright © 2012 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 /**
25 * \file clip-and-scissor-blit.cpp
27 * Verify the accuracy of blits incolving MSAA buffers when the blit
28 * coordinates are clipped to the edges of the source or destination
29 * surface, or scissored.
31 * The test starts by creating a source framebuffer and populating it
32 * with a simple image. It also creates a destination framebuffer.
34 * Then, it executes the following sequence of steps several times in
35 * a loop:
37 * 1. Clear the destination framebuffer to gray.
39 * 2. Blit from the source framebuffer to the destination framebuffer,
40 * using clipping or scissoring to limit the amount of data that is
41 * blitted.
43 * 3. Do a simple (unclipped, unscissored) blit from the destination
44 * framebuffer to the screen. This produces a test image.
46 * 4. Clear the destination framebuffer to gray.
48 * 5. Blit from the source framebuffer to the destination framebuffer,
49 * this time adjusting the coordinates to limit the amount of data
50 * that is blitted.
52 * 6. Do a simple (unclipped, unscissored) blit from the destination
53 * framebuffer to the screen. This produces a reference image.
55 * 7. Verify that the test and reference images match.
57 #include "piglit-fbo.h"
58 using namespace piglit_util_fbo;
60 PIGLIT_GL_TEST_CONFIG_BEGIN
62 config.supports_gl_compat_version = 10;
64 config.window_width = 600;
65 config.window_height = 320;
66 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
67 config.khr_no_error_support = PIGLIT_NO_ERRORS;
69 PIGLIT_GL_TEST_CONFIG_END
71 namespace {
73 const int src_size[2] = { 30, 20 };
74 const int dst_size[2] = { 50, 40 };
75 const int cut_amount[2] = { 10, 7 };
77 enum test_type_enum
79 TEST_TYPE_SRC,
80 TEST_TYPE_DST,
81 TEST_TYPE_SCISSOR,
82 NUM_TEST_TYPES
85 Fbo src_fbo;
86 Fbo dst_fbo;
88 /**
89 * From the GL 3.3 spec (section 4.3.2 Copying Pixels):
91 * If SAMPLE_BUFFERS for either the read framebuffer or draw
92 * framebuffer is greater than zero, no copy is performed and an
93 * INVALID_OPERATION error is generated if the dimensions of the
94 * source and destination rectangles provided to BlitFramebuffer are
95 * not identical, if the formats of the read and draw framebuffers are
96 * not identical, or if the values of SAMPLES for the read and draw
97 * buffers are not identical.
99 * It is not 100% clear whether "the dimensions of the source and
100 * destination rectangles" are meant in a signed sense or an unsigned
101 * sense--in other words, if SAMPLE_BUFFERS is greater than zero for
102 * either the read or draw framebuffer, and abs(srcX0 - srcX1) ==
103 * abs(dstX0 - dstX1), but (srcX0 - srcX1) and (dstX0 - dstX1) have
104 * opposite signs (so that the image is being mirrored in the X
105 * direction), should an INVALID_OPERATION error be generated?
107 * Some implementations have interpreted the answer to be yes, so we
108 * only test clipping of mirrored blits when SAMPLE_BUFFERS is 0 for
109 * both the read and draw framebuffers.
111 * This boolean is true if we should test clipping of mirrored blits.
113 bool test_mirrored_blits = false;
115 void
116 draw_simple_src_image()
118 glColor4f(1.0, 0.0, 0.0, 0.0);
119 piglit_draw_rect(-1, -1, 1, 1);
121 glColor4f(0.0, 1.0, 0.0, 0.25);
122 piglit_draw_rect(0, -1, 1, 1);
124 glColor4f(0.0, 0.0, 1.0, 0.5);
125 piglit_draw_rect(-1, 0, 1, 1);
127 glColor4f(1.0, 1.0, 1.0, 1.0);
128 piglit_draw_rect(0, 0, 1, 1);
131 bool
132 do_test(int coord, bool clip_low, test_type_enum test_type,
133 bool flip_src, bool flip_dst)
135 /* If this test flips src but not dst (or vice versa), then it
136 * is unclear from the spec whether it should be allowed for
137 * multisampled blits, so skip it unless test_mirrored_blits
138 * is true.
140 if (flip_src != flip_dst && !test_mirrored_blits)
141 return true;
143 /* Figure out where to draw the images */
144 int display_x = (6 * coord + 2 * test_type) * dst_size[0];
145 int display_y = ((clip_low ? 4 : 0) + (flip_src ? 2 : 0) +
146 (flip_dst ? 1 : 0)) * dst_size[1];
148 static const char * const test_type_strings[] = {
149 "clip src",
150 "clip dst",
151 "scissor"
153 printf("Testing %s %s%s%s%s at (%d, %d)\n",
154 test_type_strings[test_type],
155 clip_low ? "-" : "+",
156 coord ? "y" : "x",
157 flip_src ? " (flip src)" : "",
158 flip_dst ? " (flip dst)" : "",
159 display_x, display_y);
161 /* Number of pixels we'll try to cut out of the blit by
162 * clipping or scissoring.
164 int cut = cut_amount[coord];
166 /* Amount by which the blits must be offset to produce an
167 * image in the center of the destination fbo.
169 int dx = (dst_size[0] - src_size[0]) / 2;
170 int dy = (dst_size[1] - src_size[1]) / 2;
172 /* Set up blit and scissor parameters for both the test and
173 * reference blits
175 int test_src[2][2] = { /* E.g. test_src[1][0] == srcY0 */
176 { 0, src_size[0] }, { 0, src_size[1] } };
177 int test_dst[2][2] = { /* E.g. test_dst[1][0] == dstY0 */
178 { dx, src_size[0] + dx }, { dy, src_size[1] + dy } };
179 int ref_src[2][2] = { /* E.g. test_src[1][0] == srcY0 */
180 { 0, src_size[0] }, { 0, src_size[1] } };
181 int ref_dst[2][2] = { /* E.g. test_dst[1][0] == dstY0 */
182 { dx, src_size[0] + dx }, { dy, src_size[1] + dy } };
183 int scissor[2][2] = { /* E.g. scissor[0] = { left, right } */
184 { 0, 0 }, { 0, 0 } };
185 switch (test_type) {
186 case TEST_TYPE_SRC:
187 if (clip_low) {
188 test_src[coord][0] += cut;
189 test_src[coord][1] += cut;
190 ref_src[coord][0] += cut;
191 ref_dst[coord][1] -= cut;
192 } else {
193 test_src[coord][0] -= cut;
194 test_src[coord][1] -= cut;
195 ref_src[coord][1] -= cut;
196 ref_dst[coord][0] += cut;
198 break;
199 case TEST_TYPE_DST:
200 if (clip_low) {
201 test_dst[coord][0] = -cut;
202 test_dst[coord][1] =
203 test_dst[coord][0] + src_size[coord];
204 ref_src[coord][0] = cut;
205 ref_dst[coord][0] = 0;
206 ref_dst[coord][1] = test_dst[coord][1];
207 } else {
208 test_dst[coord][1] = dst_size[coord] + cut;
209 test_dst[coord][0] =
210 test_dst[coord][1] - src_size[coord];
211 ref_src[coord][1] = src_size[coord] - cut;
212 ref_dst[coord][0] = test_dst[coord][0];
213 ref_dst[coord][1] = dst_size[coord];
215 break;
216 case TEST_TYPE_SCISSOR:
217 if (clip_low) {
218 scissor[coord][0] = test_dst[coord][0] + cut;
219 scissor[coord][1] = dst_size[coord];
220 ref_src[coord][0] += cut;
221 ref_dst[coord][0] += cut;
222 } else {
223 scissor[coord][0] = 0;
224 scissor[coord][1] = test_dst[coord][1] - cut;
225 ref_src[coord][1] -= cut;
226 ref_dst[coord][1] -= cut;
228 scissor[1-coord][0] = 0;
229 scissor[1-coord][1] = dst_size[1-coord];
230 break;
231 default:
232 printf("Unexpected test type\n");
233 piglit_report_result(PIGLIT_FAIL);
234 break;
237 /* Flip coordinates if requested */
238 if (flip_src) {
239 test_src[coord][0] = src_size[coord] - test_src[coord][0];
240 test_src[coord][1] = src_size[coord] - test_src[coord][1];
241 ref_src[coord][0] = src_size[coord] - ref_src[coord][0];
242 ref_src[coord][1] = src_size[coord] - ref_src[coord][1];
244 if (flip_dst) {
245 test_dst[coord][0] = dst_size[coord] - test_dst[coord][0];
246 test_dst[coord][1] = dst_size[coord] - test_dst[coord][1];
247 ref_dst[coord][0] = dst_size[coord] - ref_dst[coord][0];
248 ref_dst[coord][1] = dst_size[coord] - ref_dst[coord][1];
249 int tmp = scissor[coord][0];
250 scissor[coord][0] = dst_size[coord] - scissor[coord][1];
251 scissor[coord][1] = dst_size[coord] - tmp;
254 /* Clear the destination framebuffer to gray */
255 glBindFramebuffer(GL_READ_FRAMEBUFFER, src_fbo.handle);
256 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo.handle);
257 glClearColor(0.5, 0.5, 0.5, 0.5);
258 glClear(GL_COLOR_BUFFER_BIT);
260 /* Set up scissor */
261 glScissor(scissor[0][0],
262 scissor[1][0],
263 scissor[0][1] - scissor[0][0],
264 scissor[1][1] - scissor[1][0]);
265 if (test_type == TEST_TYPE_SCISSOR)
266 glEnable(GL_SCISSOR_TEST);
267 else
268 glDisable(GL_SCISSOR_TEST);
270 /* Do the test blit */
271 glBlitFramebuffer(test_src[0][0], test_src[1][0],
272 test_src[0][1], test_src[1][1],
273 test_dst[0][0], test_dst[1][0],
274 test_dst[0][1], test_dst[1][1],
275 GL_COLOR_BUFFER_BIT, GL_NEAREST);
277 /* Disable scissoring */
278 glDisable(GL_SCISSOR_TEST);
280 /* Transfer the test image to the screen */
281 glBindFramebuffer(GL_READ_FRAMEBUFFER, dst_fbo.handle);
282 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
283 glBlitFramebuffer(0, 0, dst_size[0], dst_size[1],
284 display_x, display_y,
285 display_x + dst_size[0], display_y + dst_size[1],
286 GL_COLOR_BUFFER_BIT, GL_NEAREST);
288 /* Clear the destination framebuffer to gray */
289 glBindFramebuffer(GL_READ_FRAMEBUFFER, src_fbo.handle);
290 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo.handle);
291 glClearColor(0.5, 0.5, 0.5, 0.5);
292 glClear(GL_COLOR_BUFFER_BIT);
294 /* Do the reference blit */
295 glBlitFramebuffer(ref_src[0][0], ref_src[1][0],
296 ref_src[0][1], ref_src[1][1],
297 ref_dst[0][0], ref_dst[1][0],
298 ref_dst[0][1], ref_dst[1][1],
299 GL_COLOR_BUFFER_BIT, GL_NEAREST);
301 /* Transfer the reference image to the screen */
302 glBindFramebuffer(GL_READ_FRAMEBUFFER, dst_fbo.handle);
303 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo);
304 glBlitFramebuffer(0, 0, dst_size[0], dst_size[1],
305 display_x + dst_size[0], display_y,
306 display_x + 2 * dst_size[0], display_y + dst_size[1],
307 GL_COLOR_BUFFER_BIT, GL_NEAREST);
309 /* Compare the test and reference images */
310 glBindFramebuffer(GL_READ_FRAMEBUFFER, piglit_winsys_fbo);
311 return piglit_probe_rect_halves_equal_rgba(display_x, display_y,
312 2 * dst_size[0],
313 dst_size[1]);
316 NORETURN void
317 print_usage_and_exit(char *prog_name)
319 printf("Usage: %s <num_samples> <blit_type>\n"
320 " where <blit_type> is one of:\n"
321 " msaa\n"
322 " upsample\n"
323 " downsample\n"
324 " normal\n",
325 prog_name);
326 piglit_report_result(PIGLIT_FAIL);
329 extern "C" void
330 piglit_init(int argc, char **argv)
332 piglit_require_gl_version(21);
333 piglit_require_extension("GL_ARB_framebuffer_object");
334 piglit_require_extension("GL_ARB_vertex_array_object");
336 if (argc < 3)
337 print_usage_and_exit(argv[0]);
339 int num_samples;
341 char *endptr = NULL;
342 num_samples = strtol(argv[1], &endptr, 0);
343 if (endptr != argv[1] + strlen(argv[1]))
344 print_usage_and_exit(argv[0]);
347 /* Skip the test if num_samples > GL_MAX_SAMPLES */
348 GLint max_samples;
349 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
350 if (num_samples > max_samples)
351 piglit_report_result(PIGLIT_SKIP);
353 int src_samples;
354 int dst_samples;
355 if (strcmp(argv[2], "msaa") == 0) {
356 src_samples = dst_samples = num_samples;
357 } else if (strcmp(argv[2], "upsample") == 0) {
358 src_samples = 0;
359 dst_samples = num_samples;
360 } else if (strcmp(argv[2], "downsample") == 0) {
361 src_samples = num_samples;
362 dst_samples = 0;
363 } else if (strcmp(argv[2], "normal") == 0) {
364 src_samples = dst_samples = 0;
365 test_mirrored_blits = true;
366 } else {
367 print_usage_and_exit(argv[0]);
370 src_fbo.setup(FboConfig(src_samples, src_size[0], src_size[1]));
371 dst_fbo.setup(FboConfig(dst_samples, dst_size[0], dst_size[1]));
374 extern "C" enum piglit_result
375 piglit_display()
377 /* Draw a simple image in the source buffer */
378 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, src_fbo.handle);
379 src_fbo.set_viewport();
380 draw_simple_src_image();
382 bool pass = true;
383 for (int coord = 0; coord < 2; ++coord) {
384 for (int clip_low = 0; clip_low < 2; ++clip_low) {
385 for (int test_type = 0; test_type < NUM_TEST_TYPES; ++test_type) {
386 for (int flip_src = 0; flip_src < 2; ++flip_src) {
387 for (int flip_dst = 0; flip_dst < 2; ++flip_dst) {
388 pass = do_test(coord, clip_low, test_type_enum(test_type),
389 flip_src, flip_dst) && pass;
396 piglit_present_results();
398 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
401 } /* anonymous namespace */