1 /*
2  * Copyright (c) 2014 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 
24 /** @file 3d.c
25  *
26  * A test of using glClearTexSubImage to clear sub-regions of a 3D
27  * texture. A 4x4x4 texture is created with all green data. The region
28  * 1x2x2+1+1+1 is cleared to zeroes by setting the data to NULL and
29  * the region 1x2x2+2+1+1 is cleared to red. All four 4x4 images are
30  * then drawn to the screen in left-to-right order.
31  */
32 
33 #define TEX_WIDTH 4
34 #define TEX_HEIGHT 4
35 #define TEX_DEPTH 4
36 
37 #include "piglit-util-gl.h"
38 
39 PIGLIT_GL_TEST_CONFIG_BEGIN
40 
41 	config.supports_gl_compat_version = 20;
42 
43 	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
44 
45 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
46 
47 PIGLIT_GL_TEST_CONFIG_END
48 
49 static const float green[3] = {0.0, 1.0, 0.0};
50 static const float red[3] = {1.0, 0.0, 0.0};
51 static const float black[3] = {0.0, 0.0, 0.0};
52 
53 static GLuint
create_texture(void)54 create_texture(void)
55 {
56 	GLubyte tex_data[TEX_WIDTH * TEX_HEIGHT * TEX_DEPTH * 3];
57 	static const GLubyte green_bytes[3] = { 0x00, 0xff, 0x00 };
58 	GLuint tex;
59 	int i;
60 
61 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
62 
63 	for (i = 0; i < TEX_WIDTH * TEX_HEIGHT * TEX_DEPTH; i++)
64 		memcpy(tex_data + i * 3, green_bytes, sizeof green_bytes);
65 
66 	glGenTextures(1, &tex);
67 	glBindTexture(GL_TEXTURE_3D, tex);
68 	glTexImage3D(GL_TEXTURE_3D,
69 		     0, /* level */
70 		     GL_RGB,
71 		     TEX_WIDTH, TEX_HEIGHT, TEX_DEPTH,
72 		     0, /* border */
73 		     GL_RGB,
74 		     GL_UNSIGNED_BYTE,
75 		     tex_data);
76 	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
77 	glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
78 
79 	if (!piglit_check_gl_error(GL_NO_ERROR))
80 		piglit_report_result(PIGLIT_FAIL);
81 
82 	return tex;
83 }
84 
85 static void
clear_texture(GLuint tex)86 clear_texture(GLuint tex)
87 {
88 	glClearTexSubImage(tex,
89 			   0, /* level */
90 			   1, 1, 1, /* x/y/z */
91 			   1, 2, 2, /* width/height/depth */
92 			   GL_RGB,
93 			   GL_UNSIGNED_BYTE,
94 			   NULL);
95 	glClearTexSubImage(tex,
96 			   0, /* level */
97 			   2, 1, 1, /* x/y/z */
98 			   1, 2, 2, /* width/height/depth */
99 			   GL_RGB,
100 			   GL_FLOAT,
101 			   red);
102 
103 	if (!piglit_check_gl_error(GL_NO_ERROR))
104 		piglit_report_result(PIGLIT_FAIL);
105 }
106 
107 static void
init_program(void)108 init_program(void)
109 {
110 	GLuint prog;
111 	GLuint uniform;
112 
113 	static const char vs_source[] =
114 		"attribute vec2 piglit_vertex;\n"
115 		"attribute vec3 piglit_texcoord;\n"
116 		"uniform vec2 fb_size;\n"
117 		"varying vec3 tex_coord;\n"
118 		"\n"
119 		"void main()\n"
120 		"{\n"
121 		"        gl_Position = vec4(piglit_vertex * 2.0 /\n"
122 		"                           fb_size - 1.0,\n"
123 		"                           0.0, 1.0);\n"
124 		"        tex_coord = piglit_texcoord;\n"
125 		"}\n";
126 	static const char fs_source[] =
127 		"uniform sampler3D tex;\n"
128 		"varying vec3 tex_coord;\n"
129 		"\n"
130 		"void main()\n"
131 		"{\n"
132 		"        gl_FragColor = texture3D(tex, tex_coord);\n"
133 		"}\n";
134 
135 	prog = piglit_build_simple_program(vs_source, fs_source);
136 
137 	glUseProgram(prog);
138 
139 	uniform = glGetUniformLocation(prog, "tex");
140 	glUniform1i(uniform, 0);
141 
142 	uniform = glGetUniformLocation(prog, "fb_size");
143 	glUniform2f(uniform, piglit_width, piglit_height);
144 }
145 
146 void
piglit_init(int argc,char ** argv)147 piglit_init(int argc, char **argv)
148 {
149 	/* glClearTexture is either in the GL_ARB_clear_texture
150 	 * extension or in core in GL 4.4
151 	 */
152 	if (piglit_get_gl_version() < 44 &&
153 	    !piglit_is_extension_supported("GL_ARB_clear_texture")) {
154 		printf("OpenGL 4.4 or GL_ARB_clear_texture is required.\n");
155 		piglit_report_result(PIGLIT_SKIP);
156 	}
157 
158 	init_program();
159 }
160 
161 static void
draw_rect(float x,float y,float width,float height,float tex_z)162 draw_rect(float x, float y, float width, float height, float tex_z)
163 {
164 	struct {
165 		float x, y;
166 		float tx, ty, tz;
167 	} attribs[] = {
168 		{ x, y, 0.0f, 0.0f, tex_z },
169 		{ x + width, y, 1.0f, 0.0f, tex_z },
170 		{ x, y + height, 0.0f, 1.0f, tex_z },
171 		{ x + width, y + height, 1.0f, 1.0f, tex_z },
172 	};
173 
174 	glEnableVertexAttribArray(PIGLIT_ATTRIB_POS);
175 	glVertexAttribPointer(PIGLIT_ATTRIB_POS,
176 			      2, /* size */
177 			      GL_FLOAT,
178 			      GL_FALSE, /* normalized */
179 			      sizeof attribs[0],
180 			      &attribs[0].x);
181 	glEnableVertexAttribArray(PIGLIT_ATTRIB_TEX);
182 	glVertexAttribPointer(PIGLIT_ATTRIB_TEX,
183 			      3, /* size */
184 			      GL_FLOAT,
185 			      GL_FALSE, /* normalized */
186 			      sizeof attribs[0],
187 			      &attribs[0].tx);
188 
189 	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
190 
191 	glDisableVertexAttribArray(PIGLIT_ATTRIB_POS);
192 	glDisableVertexAttribArray(PIGLIT_ATTRIB_TEX);
193 }
194 
195 enum piglit_result
piglit_display(void)196 piglit_display(void)
197 {
198 	bool pass = true;
199 	GLuint tex;
200 	int i;
201 
202 	tex = create_texture();
203 
204 	clear_texture(tex);
205 
206 	glBindTexture(GL_TEXTURE_3D, tex);
207 
208 	/* Render all of the images to the screen */
209 	for (i = 0; i < TEX_DEPTH; i++) {
210 		draw_rect(i * TEX_WIDTH, 0.0, /* x/y */
211 			  TEX_WIDTH, TEX_HEIGHT,
212 			  i / (TEX_DEPTH - 1.0f));
213 	}
214 
215 	glBindTexture(GL_TEXTURE_3D, 0);
216 
217 	glDeleteTextures(1, &tex);
218 
219 	/* First image is all green */
220 	pass &= piglit_probe_rect_rgb(0, 0, 4, 4, green);
221 
222 	/* Second image is green with with a short black and red bar
223 	 * in the middle */
224 	pass &= piglit_probe_rect_rgb(4, 0, 1, 4, green);
225 	pass &= piglit_probe_pixel_rgb(5, 0, green);
226 	pass &= piglit_probe_rect_rgb(5, 1, 1, 2, black);
227 	pass &= piglit_probe_pixel_rgb(5, 3, green);
228 	pass &= piglit_probe_pixel_rgb(6, 0, green);
229 	pass &= piglit_probe_rect_rgb(6, 1, 1, 2, red);
230 	pass &= piglit_probe_pixel_rgb(6, 3, green);
231 	pass &= piglit_probe_rect_rgb(7, 0, 1, 4, green);
232 	/* Third image is the same */
233 	pass &= piglit_probe_rect_rgb(8, 0, 1, 4, green);
234 	pass &= piglit_probe_pixel_rgb(9, 0, green);
235 	pass &= piglit_probe_rect_rgb(9, 1, 1, 2, black);
236 	pass &= piglit_probe_pixel_rgb(9, 3, green);
237 	pass &= piglit_probe_pixel_rgb(10, 0, green);
238 	pass &= piglit_probe_rect_rgb(10, 1, 1, 2, red);
239 	pass &= piglit_probe_pixel_rgb(10, 3, green);
240 	pass &= piglit_probe_rect_rgb(11, 0, 1, 4, green);
241 
242 	/* Fourth image is all green */
243 	pass &= piglit_probe_rect_rgb(12, 0, 4, 4, green);
244 
245 	piglit_present_results();
246 
247 	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
248 }
249