arb_copy_image: test copying of different mipmap levels of a texture
[piglit.git] / tests / fbo / fbo-depth-array.c
blobf57532932793267938c758290bbf2e7ae364372c
1 /*
2 * Copyright © 2009 Intel Corporation
3 * Copyright (c) 2010 VMware, Inc.
4 * Copyright © 2011 Red Hat Inc.
5 * Copyright © 2014 Advanced Micro Devices, Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
26 * Authors:
27 * Dave Airlie
28 * Christoph Bumiller
29 * Marek Olšák <maraeo@gmail.com>
32 /** @file fbo-depth-array.c
34 * Tests that drawing to or clearing each layer of a depth-stencil array
35 * texture FBO and then drawing views of those individual layers
36 * to the window system framebuffer succeeds.
37 * based on fbo-array.c
40 #include "piglit-util-gl.h"
42 /* GL3 requirement. */
43 #define MAX_DIM 8192
44 #define MAX_MEM (2048*1024)
46 enum {
47 CLEAR,
48 LAYERED_CLEAR,
49 DRAW,
50 FS_WRITES_VALUE,
53 static bool test_stencil;
54 static bool test_single_size;
55 static unsigned width = 32, height = 32, layers = 6;
56 static unsigned test;
58 static void parse_args(int argc, char **argv);
60 PIGLIT_GL_TEST_CONFIG_BEGIN
62 piglit_gl_process_args(&argc, argv, &config);
63 parse_args(argc, argv);
65 config.supports_gl_compat_version = 33;
66 config.supports_gl_core_version = 33;
68 if (!piglit_use_fbo || test_single_size) {
69 config.window_width = (width + 2) * MIN2(layers, 4);
70 config.window_height = (height + 2) * ((layers + 2) / 3);
72 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
73 config.khr_no_error_support = PIGLIT_NO_ERRORS;
75 PIGLIT_GL_TEST_CONFIG_END
77 static const char *vs_text =
78 "#version 330 \n"
79 "layout(location = 0) in vec4 piglit_vertex; \n"
80 "layout(location = 1) in vec4 piglit_texcoord; \n"
81 "out vec4 texcoord; \n"
82 "void main() { \n"
83 " gl_Position = piglit_vertex; \n"
84 " texcoord = piglit_texcoord; \n"
85 "}\n";
87 static const char *frag_shader_empty_text =
88 "#version 330 \n"
89 "void main() {} \n";
91 static const char *fs_depth_output_text =
92 "#version 330 \n"
93 "uniform float z; \n"
94 "void main() \n"
95 "{ \n"
96 " gl_FragDepth = z; \n"
97 "} \n";
99 static const char *fs_stencil_output_text =
100 "#version 330 \n"
101 "#extension GL_ARB_shader_stencil_export : require \n"
102 "uniform int ref; \n"
103 "void main() \n"
104 "{ \n"
105 " gl_FragStencilRefARB = ref; \n"
106 "} \n";
109 static const char *fs_texdepth_text =
110 "#version 330 \n"
111 "uniform sampler2DArray tex; \n"
112 "uniform float z; \n"
113 "in vec4 texcoord; \n"
114 "void main() \n"
115 "{ \n"
116 " gl_FragColor = texture(tex, vec3(texcoord.xy, z)).xxxx; \n"
117 "} \n";
119 static const char *fs_texstencil_text =
120 "#version 330 \n"
121 "uniform usampler2DArray tex; \n"
122 "uniform float z; \n"
123 "in vec4 texcoord; \n"
124 "void main() \n"
125 "{ \n"
126 " gl_FragColor = vec4(float(texture(tex, vec3(texcoord.xy, z)))) / 255.0; \n"
127 "} \n";
129 static GLuint program_fs_empty;
130 static GLuint program_depth_output;
131 static GLuint program_stencil_output;
132 static GLuint program_texdepth;
133 static GLuint program_texstencil;
136 static float
137 get_depth_value(unsigned layer)
139 if (test == LAYERED_CLEAR)
140 return 0.4; /* constant */
141 else
142 return (double)(layer+1) / (layers+1);
145 static unsigned
146 get_stencil_value(unsigned layer) {
147 if (test == LAYERED_CLEAR)
148 return 0x53;
149 else
150 return (layer+1) * 255 / (layers+1);
153 static float
154 get_stencil_value_float(unsigned layer)
156 return get_stencil_value(layer) / 255.0;
159 static void
160 parse_args(int argc, char **argv)
162 unsigned lwidth, lheight, llayers;
163 int i;
165 for (i = 1; i < argc; i++) {
166 if (sscanf(argv[i], "%ux%ux%u", &lwidth, &lheight, &llayers) == 3 &&
167 lwidth && lheight && llayers) {
168 width = lwidth;
169 height = lheight;
170 layers = llayers;
171 test_single_size = true;
173 else if (!strcmp(argv[i], "depth-clear")) {
174 test = CLEAR;
175 puts("Testing glClear");
177 else if (!strcmp(argv[i], "depth-layered-clear")) {
178 test = LAYERED_CLEAR;
179 puts("Testing layered glClear");
181 else if (!strcmp(argv[i], "depth-draw")) {
182 test = DRAW;
183 puts("Testing drawing");
185 else if (!strcmp(argv[i], "fs-writes-depth")) {
186 test = FS_WRITES_VALUE;
187 puts("Testing gl_FragDepth");
189 else if (!strcmp(argv[i], "stencil-clear")) {
190 test = CLEAR;
191 test_stencil = true;
192 puts("Testing stencil glClear");
194 else if (!strcmp(argv[i], "stencil-layered-clear")) {
195 test = LAYERED_CLEAR;
196 test_stencil = true;
197 puts("Testing stencil layered glClear");
199 else if (!strcmp(argv[i], "stencil-draw")) {
200 test = DRAW;
201 test_stencil = true;
202 puts("Testing stencil drawing");
204 else if (!strcmp(argv[i], "fs-writes-stencil")) {
205 test = FS_WRITES_VALUE;
206 test_stencil = true;
207 puts("Testing gl_FragStencilRef");
209 else {
210 puts("Invalid parameter.");
211 piglit_report_result(PIGLIT_FAIL);
216 static GLuint
217 create_array_fbo(void)
219 GLuint tex, fb, z, ref;
220 GLenum status;
221 int layer;
223 glGenTextures(1, &tex);
224 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
225 if (!piglit_check_gl_error(GL_NO_ERROR))
226 piglit_report_result(PIGLIT_FAIL);
228 /* allocate empty array texture */
229 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8,
230 width, height, layers, 0,
231 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
232 if (!piglit_check_gl_error(GL_NO_ERROR))
233 piglit_report_result(PIGLIT_FAIL);
235 glGenFramebuffers(1, &fb);
236 glBindFramebuffer(GL_FRAMEBUFFER, fb);
238 glDrawBuffer(GL_NONE);
239 glReadBuffer(GL_NONE);
241 /* draw something into each layer of the array texture */
242 for (layer = 0; layer < layers; layer++) {
243 if (test == LAYERED_CLEAR) {
244 glFramebufferTexture(GL_FRAMEBUFFER,
245 test_stencil ? GL_STENCIL_ATTACHMENT :
246 GL_DEPTH_ATTACHMENT,
247 tex, 0);
249 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
250 if (status != GL_FRAMEBUFFER_COMPLETE) {
251 fprintf(stderr, "FBO incomplete\n");
252 goto done;
255 glViewport(0, 0, width, height);
256 if (test_stencil) {
257 glClearStencil(get_stencil_value(0));
258 glClear(GL_STENCIL_BUFFER_BIT);
260 else {
261 glClearDepth(get_depth_value(0));
262 glClear(GL_DEPTH_BUFFER_BIT);
264 break;
266 glFramebufferTextureLayer(GL_FRAMEBUFFER,
267 test_stencil ? GL_STENCIL_ATTACHMENT :
268 GL_DEPTH_ATTACHMENT,
269 tex,
271 layer);
273 if (!piglit_check_gl_error(GL_NO_ERROR))
274 piglit_report_result(PIGLIT_FAIL);
276 status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
277 if (status != GL_FRAMEBUFFER_COMPLETE) {
278 fprintf(stderr, "FBO incomplete\n");
279 goto done;
282 glViewport(0, 0, width, height);
284 switch (test) {
285 case CLEAR:
286 if (test_stencil) {
287 glClearStencil(get_stencil_value(layer));
288 glClear(GL_STENCIL_BUFFER_BIT);
290 else {
291 glClearDepth(get_depth_value(layer));
292 glClear(GL_DEPTH_BUFFER_BIT);
294 break;
295 case DRAW:
296 glUseProgram(program_fs_empty);
297 if (test_stencil) {
298 glEnable(GL_STENCIL_TEST);
299 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
300 glStencilFunc(GL_ALWAYS, get_stencil_value(layer), 0xff);
302 piglit_draw_rect(-1, -1, 2, 2);
304 glDisable(GL_STENCIL_TEST);
306 else {
307 glEnable(GL_DEPTH_TEST);
308 glDepthFunc(GL_ALWAYS);
310 piglit_draw_rect_z(get_depth_value(layer) * 2 - 1,
311 -1, -1, 2, 2);
313 glDisable(GL_DEPTH_TEST);
315 glUseProgram(0);
316 break;
317 case FS_WRITES_VALUE:
318 if (test_stencil) {
319 glUseProgram(program_stencil_output);
320 ref = glGetUniformLocation(program_stencil_output, "ref");
321 glUniform1i(ref, get_stencil_value(layer));
323 glEnable(GL_STENCIL_TEST);
324 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
325 glStencilFunc(GL_ALWAYS, 0, 0xff);
327 piglit_draw_rect(-1, -1, 2, 2);
329 glDisable(GL_STENCIL_TEST);
331 else {
332 glUseProgram(program_depth_output);
333 z = glGetUniformLocation(program_depth_output, "z");
334 glUniform1f(z, get_depth_value(layer));
336 glEnable(GL_DEPTH_TEST);
337 glDepthFunc(GL_ALWAYS);
339 piglit_draw_rect(-1, -1, 2, 2);
341 glDisable(GL_DEPTH_TEST);
343 glUseProgram(0);
344 break;
348 done:
349 glDeleteFramebuffers(1, &fb);
350 if (!piglit_check_gl_error(GL_NO_ERROR))
351 piglit_report_result(PIGLIT_FAIL);
352 return tex;
355 /* Draw a textured quad, sampling only the given layer of the
356 * array texture.
358 static void
359 draw_layer(int x, int y,
360 int tx, int ty,
361 int tw, int th,
362 int depth)
364 GLfloat depth_coord = (GLfloat)depth;
365 GLuint prog = test_stencil ? program_texstencil : program_texdepth;
366 GLint loc, z;
368 glUseProgram(prog);
369 loc = glGetUniformLocation(prog, "tex");
370 z = glGetUniformLocation(prog, "z");
371 glUniform1i(loc, 0); /* texture unit p */
372 glUniform1f(z, depth_coord);
374 glViewport(0, 0, piglit_width, piglit_height);
375 glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo);
377 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
378 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
379 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
380 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
381 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
382 if (test_stencil)
383 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_DEPTH_STENCIL_TEXTURE_MODE,
384 GL_STENCIL_INDEX);
386 piglit_draw_rect_tex((double)x / piglit_width * 2 - 1,
387 (double)y / piglit_height * 2 - 1,
388 (double)tw / piglit_width * 2,
389 (double)th / piglit_height * 2,
390 tx / (float) width, ty / (float) height,
391 tw / (float) width, th / (float) height);
392 glUseProgram(0);
393 if (!piglit_check_gl_error(GL_NO_ERROR))
394 piglit_report_result(PIGLIT_FAIL);
397 static GLboolean draw_and_test_layer(int start_x, int start_y,
398 int layer)
400 float expected = (test_stencil ?
401 get_stencil_value_float(layer) :
402 get_depth_value(layer));
403 int tx, ty, tw, th;
404 GLboolean pass = GL_TRUE;
406 for (ty = 0; ty < height; ty += piglit_height - start_y) {
407 for (tx = 0; tx < width; tx += piglit_width - start_x) {
408 tw = MIN2(piglit_width - start_x, width - tx);
409 th = MIN2(piglit_height - start_y, height - ty);
410 draw_layer(start_x, start_y,
411 tx, ty,
412 tw, th,
413 layer);
415 pass = piglit_probe_rect_r_ubyte(start_x, start_y,
416 tw, th,
417 expected * 255.0) &&
418 pass;
422 return pass;
425 static bool
426 test_once(void)
428 bool pass = true;
429 int layer;
430 GLuint tex;
432 printf("Testing %ix%ix%i\n", width, height, layers);
434 glClearColor(0.2, 0.1, 0.1, 1.0);
435 glClear(GL_COLOR_BUFFER_BIT);
437 tex = create_array_fbo();
439 for (layer = 0; layer < layers; layer++) {
440 int x,y;
442 if (piglit_use_fbo && !test_single_size) {
443 x = 0;
444 y = 0;
446 else {
447 x = 1 + (layer % 3) * (width + 1);
448 y = 1 + (layer / 3) * (height + 1);
450 pass = draw_and_test_layer(x, y, layer) && pass;
452 if (piglit_use_fbo && !test_single_size && layer < layers-1) {
453 glClearColor(0.2, 0.1, 0.1, 1.0);
454 glClear(GL_COLOR_BUFFER_BIT);
458 glDeleteTextures(1, &tex);
459 if (!piglit_check_gl_error(GL_NO_ERROR))
460 piglit_report_result(PIGLIT_FAIL);
461 return pass;
464 enum piglit_result
465 piglit_display(void)
467 bool pass = true;
468 int i,j;
470 if (piglit_use_fbo && !test_single_size) {
471 static int dims[] = {1, 4, 16, 64, 256, 1024, 4096, MAX_DIM};
473 for (i = 0; i < ARRAY_SIZE(dims); i++) {
474 for (j = 0; j < ARRAY_SIZE(dims); j++) {
475 width = dims[i];
476 height = dims[j];
478 /* Don't allocate too much texture memory. */
479 if (width*height > MAX_MEM) {
480 if (width > height && height/2 > dims[j-1])
481 height /= 2;
482 else if (height > width && width/2 > dims[i-1])
483 width /= 2;
485 if (width*height > MAX_MEM)
486 continue;
489 pass = test_once() && pass;
493 else {
494 pass = test_once() && pass;
497 piglit_present_results();
499 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
502 void piglit_init(int argc, char **argv)
504 if (piglit_get_gl_version() < 33) {
505 piglit_report_result(PIGLIT_SKIP);
508 if (test_stencil) {
509 piglit_require_extension("GL_ARB_stencil_texturing");
510 if (test == FS_WRITES_VALUE)
511 piglit_require_extension("GL_ARB_shader_stencil_export");
514 if (test_stencil) {
515 program_texstencil = piglit_build_simple_program(vs_text,
516 fs_texstencil_text);
518 if (test == FS_WRITES_VALUE)
519 program_stencil_output = piglit_build_simple_program(vs_text,
520 fs_stencil_output_text);
522 else {
523 program_texdepth = piglit_build_simple_program(vs_text,
524 fs_texdepth_text);
526 if (test == FS_WRITES_VALUE)
527 program_depth_output = piglit_build_simple_program(vs_text,
528 fs_depth_output_text);
531 program_fs_empty = piglit_build_simple_program(vs_text,
532 frag_shader_empty_text);
533 if (!piglit_check_gl_error(GL_NO_ERROR))
534 piglit_report_result(PIGLIT_FAIL);