2 * Copyright © 2013 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
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
21 * DEALINGS IN THE SOFTWARE.
25 * \file read-after-clear.c
27 * Test that fast color clears of an off-screen buffer work properly
28 * when they are followed by various ways of reading from the buffer.
30 * There are four sub-tests (selectable by a command line parameter)
31 * for each of the following ways of reading from the texture buffer:
33 * - sample: read by sampling via a GLSL shader.
34 * - read_pixels: read using the glReadPixels() function.
35 * - blit: read by blitting from the texture to the windowsystem framebuffer.
36 * - copy: read by copying to a second texture using glCopyTexImage2D.
38 * In addition, each test can be qualified with "rb" or "tex" to
39 * choose whether the off-screen buffer is a texture or a
40 * renderbuffer. Note that the "rb" option is not allowed for the
43 * The test operates by creating an off-screen buffer, painting it red
44 * using a non-fast-clear technique (rendering a quad using a shader),
45 * and then clearing it to green using a fast clear. Then it reads
46 * from the buffer using the technique specified on the command line,
47 * to verify that the fast clear data got successfully written to the
51 #include "piglit-util-gl.h"
54 #define TEX_HEIGHT 512
56 PIGLIT_GL_TEST_CONFIG_BEGIN
57 config
.supports_gl_compat_version
= 11;
58 config
.window_width
= TEX_WIDTH
;
59 config
.window_height
= TEX_HEIGHT
;
60 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
61 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
62 PIGLIT_GL_TEST_CONFIG_END
65 static enum subtest_enum
{
72 static bool use_texture
;
75 static const char *vs_text
=
78 " gl_Position = gl_Vertex;\n"
79 " gl_TexCoord[0] = gl_MultiTexCoord0;\n"
82 static const char *fs_text_paint_red
=
85 " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
88 static const char *fs_text_sample
=
89 "uniform sampler2D samp;\n"
92 " gl_FragColor = texture2D(samp, gl_TexCoord[0].xy);\n"
95 static GLuint prog_paint_red
, prog_sample
, tex1
, tex2
, fb
;
99 print_usage_and_exit(const char *prog_name
)
101 printf("Usage: %s <subtest> <buffer_type>\n"
102 " where <subtest> is one of the following:\n"
103 " sample: read by sampling from the cleared buffer\n"
104 " read_pixels: read using glReadPixels()\n"
105 " blit: read by blitting from the cleared buffer\n"
106 " copy: read using glCopyTexImage2D()\n"
107 " and <buffer_type> is one of the following:\n"
108 " rb: off-screen buffer is a renderbuffer\n"
109 " tex: off-screen buffer is a texture\n", prog_name
);
110 piglit_report_result(PIGLIT_FAIL
);
114 static GLuint
allocate_texture()
117 glGenTextures(1, &tex
);
118 glBindTexture(GL_TEXTURE_2D
, tex
);
119 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
120 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
121 glTexImage2D(GL_TEXTURE_2D
,
123 GL_RGBA
/* internal format */,
124 TEX_WIDTH
, TEX_HEIGHT
,
126 GL_RGBA
/* format */,
134 piglit_init(int argc
, char **argv
)
136 GLuint vs
, fs_paint_red
, fs_sample
;
141 print_usage_and_exit(argv
[0]);
142 if (strcmp(argv
[1], "sample") == 0)
143 subtest
= SUBTEST_SAMPLE
;
144 else if (strcmp(argv
[1], "read_pixels") == 0)
145 subtest
= SUBTEST_READ_PIXELS
;
146 else if (strcmp(argv
[1], "blit") == 0)
147 subtest
= SUBTEST_BLIT
;
148 else if (strcmp(argv
[1], "copy") == 0)
149 subtest
= SUBTEST_COPY
;
151 print_usage_and_exit(argv
[0]);
152 if (strcmp(argv
[2], "rb") == 0)
154 else if (strcmp(argv
[2], "tex") == 0)
157 print_usage_and_exit(argv
[0]);
159 /* Detect parameter conflicts */
160 if (subtest
== SUBTEST_SAMPLE
&& !use_texture
) {
161 printf("Subtest 'sample' requires buffer_type 'tex'.\n");
162 piglit_report_result(PIGLIT_FAIL
);
166 piglit_require_vertex_shader();
167 piglit_require_fragment_shader();
168 piglit_require_extension("GL_ARB_framebuffer_object");
170 /* Compile shaders */
171 vs
= piglit_compile_shader_text(GL_VERTEX_SHADER
, vs_text
);
172 fs_paint_red
= piglit_compile_shader_text(GL_FRAGMENT_SHADER
,
174 prog_paint_red
= piglit_link_simple_program(vs
, fs_paint_red
);
176 piglit_report_result(PIGLIT_FAIL
);
177 fs_sample
= piglit_compile_shader_text(GL_FRAGMENT_SHADER
,
179 prog_sample
= piglit_link_simple_program(vs
, fs_sample
);
181 piglit_report_result(PIGLIT_FAIL
);
182 if (!piglit_check_gl_error(GL_NO_ERROR
))
183 piglit_report_result(PIGLIT_FAIL
);
185 /* Set up framebuffer */
186 glGenFramebuffers(1, &fb
);
187 glBindFramebuffer(GL_FRAMEBUFFER
, fb
);
189 tex1
= allocate_texture();
190 glFramebufferTexture2D(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
191 GL_TEXTURE_2D
, tex1
, 0 /* level */);
194 glGenRenderbuffers(1, &rb
);
195 glBindRenderbuffer(GL_RENDERBUFFER
, rb
);
196 glRenderbufferStorage(GL_RENDERBUFFER
, GL_RGBA
,
197 TEX_WIDTH
, TEX_HEIGHT
);
198 glFramebufferRenderbuffer(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
199 GL_RENDERBUFFER
, rb
);
201 if (!piglit_check_gl_error(GL_NO_ERROR
))
202 piglit_report_result(PIGLIT_FAIL
);
203 fb_status
= glCheckFramebufferStatus(GL_FRAMEBUFFER
);
204 if (fb_status
!= GL_FRAMEBUFFER_COMPLETE
) {
205 printf("Framebuffer status: %s\n",
206 piglit_get_gl_enum_name(fb_status
));
207 piglit_report_result(PIGLIT_FAIL
);
210 /* Set up second texture (used by "copy" test only) */
211 if (subtest
== SUBTEST_COPY
)
212 tex2
= allocate_texture();
213 if (!piglit_check_gl_error(GL_NO_ERROR
))
214 piglit_report_result(PIGLIT_FAIL
);
222 static const GLfloat green
[] = { 0.0, 1.0, 0.0, 1.0 };
224 /* Paint the texture red using a shader (not a fast clear). */
225 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, fb
);
226 glUseProgram(prog_paint_red
);
227 glViewport(0, 0, TEX_WIDTH
, TEX_HEIGHT
);
228 piglit_draw_rect(-1, -1, 2, 2);
230 /* Clear the texture to green; this will be optimized using
231 * a fast color clear if the hardware is capable of it.
233 glClearColor(0, 1, 0, 1);
234 glClear(GL_COLOR_BUFFER_BIT
);
238 /* Sample from the texture and draw to the window
239 * system framebuffer.
241 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, piglit_winsys_fbo
);
242 glViewport(0, 0, piglit_width
, piglit_height
);
243 glUseProgram(prog_sample
);
244 glUniform1i(glGetUniformLocation(prog_sample
, "samp"), 0);
245 glActiveTexture(GL_TEXTURE0
);
246 glBindTexture(GL_TEXTURE_2D
, tex1
);
247 piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);
248 glBindFramebuffer(GL_READ_FRAMEBUFFER
, piglit_winsys_fbo
);
249 pass
= piglit_probe_rect_rgba(0, 0, piglit_width
,
250 piglit_height
, green
) && pass
;
252 case SUBTEST_READ_PIXELS
:
253 /* Read directly from the texture using
256 glBindFramebuffer(GL_READ_FRAMEBUFFER
, fb
);
257 pass
= piglit_probe_rect_rgba(0, 0, TEX_WIDTH
, TEX_HEIGHT
,
259 /* And then clear the window system framebuffer to
260 * black since there is nothing to display in this
263 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, piglit_winsys_fbo
);
264 glClearColor(0, 0, 0, 1);
265 glClear(GL_COLOR_BUFFER_BIT
);
268 /* Blit from the texture to the window system
271 glBindFramebuffer(GL_READ_FRAMEBUFFER
, fb
);
272 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, piglit_winsys_fbo
);
273 glBlitFramebuffer(0, 0, TEX_WIDTH
, TEX_HEIGHT
,
274 0, 0, piglit_width
, piglit_height
,
275 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
276 glBindFramebuffer(GL_READ_FRAMEBUFFER
, piglit_winsys_fbo
);
277 pass
= piglit_probe_rect_rgba(0, 0, piglit_width
,
278 piglit_height
, green
) && pass
;
281 /* Copy to a second texture using glCopyTexImage2D(). */
282 glBindFramebuffer(GL_READ_FRAMEBUFFER
, fb
);
283 glBindTexture(GL_TEXTURE_2D
, tex2
);
284 glCopyTexImage2D(GL_TEXTURE_2D
,
287 0, 0, TEX_WIDTH
, TEX_HEIGHT
,
289 /* Sample from the second texture and draw to the
290 * window system framebuffer.
292 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, piglit_winsys_fbo
);
293 glViewport(0, 0, piglit_width
, piglit_height
);
294 glUseProgram(prog_sample
);
295 glUniform1i(glGetUniformLocation(prog_sample
, "samp"), 0);
296 glActiveTexture(GL_TEXTURE0
);
297 glBindTexture(GL_TEXTURE_2D
, tex2
);
298 piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);
299 glBindFramebuffer(GL_READ_FRAMEBUFFER
, piglit_winsys_fbo
);
300 pass
= piglit_probe_rect_rgba(0, 0, piglit_width
,
301 piglit_height
, green
) && pass
;
305 if (!piglit_check_gl_error(GL_NO_ERROR
))
308 piglit_present_results();
309 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;