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