1 /*
2 * Copyright © 2010 Intel Corporation
3 *
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:
10 *
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.
14 *
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.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 * Brian Paul
26 */
27
28 /** @file fbo-readdrawpix.c
29 *
30 * Test glReadPixels / glDrawPixels between FBO and window.
31 * See also fbo-blit.c and fbo-copypix.c
32 */
33
34 #include "piglit-util-gl.h"
35
36 PIGLIT_GL_TEST_CONFIG_BEGIN
37
38 config.supports_gl_compat_version = 10;
39
40 config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
41 config.khr_no_error_support = PIGLIT_NO_ERRORS;
42
43 PIGLIT_GL_TEST_CONFIG_END
44
45 #define PAD 10
46 #define SIZE 20
47
48 /* size of texture/renderbuffer (power of two) */
49 #define FBO_SIZE 64
50
51
52 static GLuint
make_fbo(int w,int h)53 make_fbo(int w, int h)
54 {
55 GLuint tex;
56 GLuint fb;
57 GLenum status;
58
59 glGenFramebuffersEXT(1, &fb);
60 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
61
62 glGenTextures(1, &tex);
63 glBindTexture(GL_TEXTURE_2D, tex);
64 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
65 w, h, 0,
66 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
67
68 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
69 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
70
71 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
72 GL_COLOR_ATTACHMENT0_EXT,
73 GL_TEXTURE_2D,
74 tex,
75 0);
76 if (!piglit_check_gl_error(GL_NO_ERROR))
77 piglit_report_result(PIGLIT_FAIL);
78
79 status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
80 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
81 fprintf(stderr, "fbo incomplete (status = 0x%04x)\n", status);
82 piglit_report_result(PIGLIT_SKIP);
83 }
84
85 return fb;
86 }
87
88 static void
draw_color_rect(int x,int y,int w,int h)89 draw_color_rect(int x, int y, int w, int h)
90 {
91 int x1 = x;
92 int x2 = x + w / 2;
93 int y1 = y;
94 int y2 = y + h / 2;
95
96 glColor4f(1.0, 0.0, 0.0, 0.0);
97 piglit_draw_rect(x1, y1, w / 2, h / 2);
98 glColor4f(0.0, 1.0, 0.0, 0.0);
99 piglit_draw_rect(x2, y1, w / 2, h / 2);
100 glColor4f(0.0, 0.0, 1.0, 0.0);
101 piglit_draw_rect(x1, y2, w / 2, h / 2);
102 glColor4f(1.0, 1.0, 1.0, 0.0);
103 piglit_draw_rect(x2, y2, w / 2, h / 2);
104 }
105
106 static GLboolean
verify_color_rect(int start_x,int start_y,int w,int h)107 verify_color_rect(int start_x, int start_y, int w, int h)
108 {
109 float red[] = {1, 0, 0, 0};
110 float green[] = {0, 1, 0, 0};
111 float blue[] = {0, 0, 1, 0};
112 float white[] = {1, 1, 1, 0};
113
114 if (!piglit_probe_rect_rgb(start_x, start_y, w / 2, h / 2, red))
115 return GL_FALSE;
116 if (!piglit_probe_rect_rgb(start_x + w/2, start_y, w/2, h/2, green))
117 return GL_FALSE;
118 if (!piglit_probe_rect_rgb(start_x, start_y + h/2, w/2, h/2, blue))
119 return GL_FALSE;
120 if (!piglit_probe_rect_rgb(start_x + w/2, start_y + h/2, w/2, h/2, white))
121 return GL_FALSE;
122
123 return GL_TRUE;
124 }
125
126
127 static void
copy(GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1)128 copy(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
129 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
130 {
131 GLsizei srcW = srcX1 - srcX0, srcH = srcY1 - srcY0;
132 GLsizei dstW = dstX1 - dstX0, dstH = dstY1 - dstY0;
133 void *buf = malloc(srcW * srcH * 4);
134 glReadPixels(srcX0, srcY0, srcW, srcH,
135 GL_RGBA, GL_UNSIGNED_BYTE, buf);
136 glPixelZoom((float) dstW / (float) srcW,
137 (float) dstH / (float) srcH);
138 glWindowPos2i(dstX0, dstY0);
139 glDrawPixels(srcW, srcH, GL_RGBA, GL_UNSIGNED_BYTE, buf);
140 free(buf);
141 }
142
143
144 static GLboolean
run_test(void)145 run_test(void)
146 {
147 GLboolean pass = GL_TRUE;
148 GLuint fbo;
149 int fbo_width = FBO_SIZE;
150 int fbo_height = FBO_SIZE;
151 int x0 = PAD;
152 int y0 = PAD;
153 int y1 = PAD * 2 + SIZE;
154 int y2 = PAD * 3 + SIZE * 2;
155
156 glViewport(0, 0, piglit_width, piglit_height);
157 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
158
159 glClearColor(0.5, 0.5, 0.5, 0.5);
160 glClear(GL_COLOR_BUFFER_BIT);
161
162 /* Draw the color rect in the window system window */
163 draw_color_rect(x0, y0, SIZE, SIZE);
164
165 fbo = make_fbo(fbo_width, fbo_height);
166
167 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo);
168 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, piglit_winsys_fbo);
169 glViewport(0, 0, fbo_width, fbo_height);
170 piglit_ortho_projection(fbo_width, fbo_height, GL_FALSE);
171 glClearColor(1.0, 0.0, 1.0, 0.0);
172 glClear(GL_COLOR_BUFFER_BIT);
173
174 /* Draw the color rect in the FBO */
175 draw_color_rect(x0, y0, SIZE, SIZE);
176
177 /* Now that we have correct samples, blit things around.
178 * FBO(bottom) -> WIN(middle)
179 */
180 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, piglit_winsys_fbo);
181 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo);
182 copy(x0, y0, x0 + SIZE, y0 + SIZE,
183 x0, y1, x0 + SIZE, y1 + SIZE);
184
185 /* WIN(bottom) -> FBO(middle) */
186 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo);
187 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, piglit_winsys_fbo);
188 copy(x0, y0, x0 + SIZE, y0 + SIZE,
189 x0, y1, x0 + SIZE, y1 + SIZE);
190
191 /* FBO(middle) -> WIN(top) back to verify WIN -> FBO */
192 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, piglit_winsys_fbo);
193 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo);
194 copy(x0, y1, x0 + SIZE, y1 + SIZE,
195 x0, y2, x0 + SIZE, y2 + SIZE);
196
197 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, piglit_winsys_fbo);
198 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, piglit_winsys_fbo);
199
200 pass = verify_color_rect(PAD, y0, SIZE, SIZE) && pass;
201 pass = verify_color_rect(PAD, y1, SIZE, SIZE) && pass;
202 pass = verify_color_rect(PAD, y2, SIZE, SIZE) && pass;
203
204 piglit_present_results();
205
206 return pass;
207 }
208
209
210 enum piglit_result
piglit_display(void)211 piglit_display(void)
212 {
213 GLboolean pass = run_test();
214
215 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
216 }
217
218
219 void
piglit_init(int argc,char ** argv)220 piglit_init(int argc, char **argv)
221 {
222 piglit_require_gl_version(14);
223
224 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
225
226 piglit_require_extension("GL_EXT_framebuffer_object");
227 piglit_require_extension("GL_EXT_framebuffer_blit");
228 }
229