1 /*
2  * Copyright © 2015 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  *    Neil Roberts <neil@linux.intel.com>
25  *
26  */
27 
28 /** @file zero-tex-coord.c
29  *
30  * Tests various texture sampling functions using constant 0 values
31  * for the arguments. The i965 driver has optimisations for trailing 0
32  * arguments to sampler messages so the intention is to test these
33  * code paths.
34  */
35 
36 #include "piglit-util-gl.h"
37 
38 PIGLIT_GL_TEST_CONFIG_BEGIN
39 
40 	config.supports_gl_compat_version = 10;
41 	config.supports_gl_core_version = 31;
42 
43 	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
44 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
45 
46 PIGLIT_GL_TEST_CONFIG_END
47 
48 struct sample_function {
49 	const char *name;
50 	const char *snippet;
51 	int glsl_version;
52 	const char *extension;
53 };
54 
55 static const struct sample_function
56 sample_functions[] = {
57 	{ "texture2D", "texture2D(tex, vec2(0.0))", 0 },
58 	{ "bias", "texture2D(tex, vec2(0.0), 0.0)", 0 },
59 	{ "textureGrad",
60 	  "textureGrad(tex, vec2(0.0), vec2(0.0), vec2(0.0))",
61 	  130 },
62 	{ "texelFetch", "texelFetch(tex, ivec2(0), 0)", 130 },
63 	{ "textureLod",
64 	  "textureLod(tex, vec2(0.0), 0.0)",
65 	  130 },
66 	{ "textureSize",
67 	  "textureSize(tex, 0) == ivec2(4) ? "
68 	  "vec4(0.0, 1.0, 0.0, 1.0) : "
69 	  "vec4(1.0, 0.0, 0.0, 1.0)",
70 	  130 },
71 	{ "textureQueryLOD",
72 	  "textureQueryLOD(tex, vec2(0.0)).x == 0.0 ? "
73 	  "vec4(0.0, 1.0, 0.0, 1.0) : "
74 	  "vec4(1.0, 0.0, 0.0, 1.0)",
75 	  0, "GL_ARB_texture_query_lod" },
76 	{ "textureGather",
77 	  "textureGather(tex, vec2(0.0), 0) == vec4(0.0) ? "
78 	  "vec4(0.0, 1.0, 0.0, 1.0) : "
79 	  "vec4(1.0, 0.0, 0.0, 1.0)",
80 	  130, "GL_ARB_gpu_shader5" },
81 };
82 
83 static const char
84 vertex_source[] =
85 	"attribute vec2 piglit_vertex;\n"
86 	"\n"
87 	"void\n"
88 	"main()\n"
89 	"{\n"
90 	"        gl_Position = vec4(piglit_vertex, 0.0, 1.0);\n"
91 	"}\n";
92 
93 static const char
94 fragment_source[] =
95 	"uniform sampler2D tex;\n"
96 	"\n"
97 	"void\n"
98 	"main()\n"
99 	"{\n"
100 	"        gl_FragColor = SNIPPET;\n"
101 	"}\n";
102 
103 const struct sample_function *
104 sample_function = sample_functions;
105 
106 static const GLfloat
107 green[] = { 0.0f, 1.0f, 0.0f, 1.0f };
108 
109 static GLuint
make_tex(void)110 make_tex(void)
111 {
112 	/* Make a fully mipmapped texture with a green texel on at the
113 	 * 0,0 position on the largest mip image and a red texel for
114 	 * all of the other positions */
115 
116 	GLuint tex;
117 	int size = 4;
118 	int level = 0;
119 	GLubyte *image, *p;
120 	int y, x;
121 
122 	glGenTextures(1, &tex);
123 	glBindTexture(GL_TEXTURE_2D, tex);
124 	glTexParameteri(GL_TEXTURE_2D,
125 			GL_TEXTURE_MIN_FILTER,
126 			GL_NEAREST_MIPMAP_NEAREST);
127 	glTexParameteri(GL_TEXTURE_2D,
128 			GL_TEXTURE_MAG_FILTER,
129 			GL_NEAREST);
130 	glTexParameteri(GL_TEXTURE_2D,
131 			GL_TEXTURE_WRAP_S,
132 			GL_CLAMP_TO_EDGE);
133 	glTexParameteri(GL_TEXTURE_2D,
134 			GL_TEXTURE_WRAP_T,
135 			GL_CLAMP_TO_EDGE);
136 
137 	while (size >= 1) {
138 		p = image = malloc(size * size * 4);
139 
140 		for (y = 0; y < size; y++) {
141 			for (x = 0; x < size; x++) {
142 				if (level == 0 && y == 0 && x == 0) {
143 					*(p++) = 0x00;
144 					*(p++) = 0xff;
145 				} else {
146 					*(p++) = 0xff;
147 					*(p++) = 0x00;
148 				}
149 				*(p++) = 0x00;
150 				*(p++) = 0x00;
151 			}
152 		}
153 
154 		glTexImage2D(GL_TEXTURE_2D,
155 			     level,
156 			     GL_RGBA,
157 			     size, size,
158 			     0, /* border */
159 			     GL_RGBA, GL_UNSIGNED_BYTE,
160 			     image);
161 
162 		free(image);
163 
164 		size /= 2;
165 		level++;
166 	}
167 
168 	return tex;
169 }
170 
171 static GLuint
make_program(void)172 make_program(void)
173 {
174 	const char *snippet = sample_function->snippet;
175 	int glsl_version = sample_function->glsl_version;
176 	int snippet_length = strlen(snippet);
177 	int snippet_pos = strstr(fragment_source, "SNIPPET") - fragment_source;
178 	GLuint program;
179 	char source[1000], *p = source;
180 
181 	if (glsl_version > 0) {
182 		p += sprintf(p, "#version %i\n", glsl_version);
183 		piglit_require_GLSL_version(glsl_version);
184 	}
185 
186 	if (sample_function->extension) {
187 		p += sprintf(p,
188 			     "#extension %s : require\n",
189 			     sample_function->extension);
190 		piglit_require_extension(sample_function->extension);
191 	}
192 
193 	memcpy(p, fragment_source, snippet_pos);
194 	p += snippet_pos;
195 	memcpy(p, snippet, snippet_length);
196 	p += snippet_length;
197 	memcpy(p,
198 	       fragment_source + snippet_pos + 7,
199 	       sizeof fragment_source - snippet_pos - 7);
200 
201 	program = piglit_build_simple_program(vertex_source, source);
202 
203 	return program;
204 }
205 
206 enum piglit_result
piglit_display(void)207 piglit_display(void)
208 {
209 	GLboolean pass = GL_TRUE;
210 	GLuint program, tex;
211 	GLint tex_location;
212 
213 	tex = make_tex();
214 	program = make_program();
215 
216 	glUseProgram(program);
217 	tex_location = glGetUniformLocation(program, "tex");
218 	glUniform1i(tex_location, 0);
219 
220 	piglit_draw_rect(-1.0f, -1.0f, 2.0f, 2.0f);
221 
222 	glUseProgram(0);
223 
224 	glDeleteTextures(1, &tex);
225 	glDeleteProgram(program);
226 
227 	pass = piglit_probe_rect_rgb(0, 0,
228 				     piglit_width, piglit_height,
229 				     green) && pass;
230 
231 	piglit_present_results();
232 
233 	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
234 }
235 
236 void
piglit_init(int argc,char ** argv)237 piglit_init(int argc, char **argv)
238 {
239 	int i;
240 
241 	if (argc > 1) {
242 		for (i = 0; i < ARRAY_SIZE(sample_functions); i++) {
243 			if (!strcmp(sample_functions[i].name, argv[1])) {
244 				sample_function = sample_functions + i;
245 				goto found;
246 			}
247 		}
248 
249 		fprintf(stderr, "Unknown function: %s\n", argv[1]);
250 		piglit_report_result(PIGLIT_FAIL);
251 
252 	found:
253 		(void) 0;
254 	}
255 
256 	piglit_require_GLSL();
257 }
258