1 /*
2  * Copyright © 2013 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 /**
25  * \file piglit-test-pattern.cpp
26  *
27  * This file defines the functions which can be utilized to draw test patterns
28  * in to color, depth or stencil buffers.
29  *
30  */
31 #include "piglit-test-pattern.h"
32 using namespace piglit_util_test_pattern;
33 
34 const float TestPattern::no_projection[4][4] = {
35 	{ 1, 0, 0, 0 },
36 	{ 0, 1, 0, 0 },
37 	{ 0, 0, 1, 0 },
38 	{ 0, 0, 0, 1 }
39 };
40 
41 
compile()42 void Triangles::compile()
43 {
44 	/* Triangle coords within (-1,-1) to (1,1) rect */
45 	static const float pos_within_tri[][2] = {
46 		{ -0.5, -1.0 },
47 		{  0.0,  1.0 },
48 		{  0.5, -1.0 }
49 	};
50 
51 	/* Number of triangle instances across (and down) */
52 	int tris_across = 8;
53 
54 	/* Total number of triangles drawn */
55 	num_tris = tris_across * tris_across;
56 
57 	/* Scaling factor uniformly applied to triangle coords */
58 	float tri_scale = 0.8 / tris_across;
59 
60 	/* Amount each triangle should be rotated compared to prev */
61 	float rotation_delta = M_PI * 2.0 / num_tris;
62 
63 	/* Final scaling factor */
64 	float final_scale = 0.95;
65 
66 	static const char *vert =
67 		"#version 120\n"
68 		"attribute vec2 pos_within_tri;\n"
69 		"uniform float tri_scale;\n"
70 		"uniform float rotation_delta;\n"
71 		"uniform int tris_across;\n"
72 		"uniform float final_scale;\n"
73 		"uniform mat4 proj;\n"
74 		"uniform int tri_num; /* [0, num_tris) */\n"
75 		"\n"
76 		"void main()\n"
77 		"{\n"
78 		"  vec2 pos = tri_scale * pos_within_tri;\n"
79 		"  float rotation = rotation_delta * tri_num;\n"
80 		"  pos = mat2(cos(rotation), sin(rotation),\n"
81 		"             -sin(rotation), cos(rotation)) * pos;\n"
82 		"  int i = int(mod(float(tri_num), float(tris_across)));\n"
83 		"  int j = tris_across - 1 - tri_num / tris_across;\n"
84 		"  pos += (vec2(i, j) * 2.0 + 1.0) / tris_across - 1.0;\n"
85 		"  pos *= final_scale;\n"
86 		"  gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
87 		"}\n";
88 
89 	static const char *frag =
90 		"#version 120\n"
91 		"void main()\n"
92 		"{\n"
93 		"  gl_FragColor = vec4(1.0);\n"
94 		"}\n";
95 
96 	/* Compile program */
97 	prog = glCreateProgram();
98 	GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
99 	glAttachShader(prog, vs);
100 	GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
101 	glAttachShader(prog, fs);
102 	glBindAttribLocation(prog, 0, "pos_within_tri");
103 	glLinkProgram(prog);
104 	if (!piglit_link_check_status(prog)) {
105 		piglit_report_result(PIGLIT_FAIL);
106 	}
107 
108 	/* Set up uniforms */
109 	glUseProgram(prog);
110 	glUniform1f(glGetUniformLocation(prog, "tri_scale"), tri_scale);
111 	glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
112 		    rotation_delta);
113 	glUniform1i(glGetUniformLocation(prog, "tris_across"), tris_across);
114 	glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
115 	proj_loc = glGetUniformLocation(prog, "proj");
116 	tri_num_loc = glGetUniformLocation(prog, "tri_num");
117 
118 	/* Set up vertex array object */
119 	glGenVertexArrays(1, &vao);
120 	glBindVertexArray(vao);
121 
122 	/* Set up vertex input buffer */
123 	glGenBuffers(1, &vertex_buf);
124 	glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
125 	glBufferData(GL_ARRAY_BUFFER, sizeof(pos_within_tri), pos_within_tri,
126 		     GL_STATIC_DRAW);
127 	glEnableVertexAttribArray(0);
128 	glVertexAttribPointer(0, ARRAY_SIZE(pos_within_tri[0]), GL_FLOAT,
129 			      GL_FALSE, sizeof(pos_within_tri[0]), (void *) 0);
130 }
131 
draw(const float (* proj)[4])132 void Triangles::draw(const float (*proj)[4])
133 {
134 	glClear(GL_COLOR_BUFFER_BIT);
135 
136 	glUseProgram(prog);
137 	glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
138 	glBindVertexArray(vao);
139 	for (int tri_num = 0; tri_num < num_tris; ++tri_num) {
140 		glUniform1i(tri_num_loc, tri_num);
141 		glDrawArrays(GL_TRIANGLES, 0, 3);
142 	}
143 }
144 
145 
InterpolationTestPattern(const char * frag)146 InterpolationTestPattern::InterpolationTestPattern(const char *frag)
147 	: frag(frag), viewport_size_loc(0)
148 {
149 }
150 
151 
152 void
compile()153 InterpolationTestPattern::compile()
154 {
155 	static struct vertex_attributes {
156 		float pos_within_tri[2];
157 		float barycentric_coords[3];
158 	} vertex_data[] = {
159 		{ { -0.5, -1.0 }, { 1, 0, 0 } },
160 		{ {  0.0,  1.0 }, { 0, 1, 0 } },
161 		{ {  0.5, -1.0 }, { 0, 0, 1 } }
162 	};
163 
164 	/* Number of triangle instances across (and down) */
165 	int tris_across = 8;
166 
167 	/* Total number of triangles drawn */
168 	num_tris = tris_across * tris_across;
169 
170 	/* Scaling factor uniformly applied to triangle coords */
171 	float tri_scale = 0.8 / tris_across;
172 
173 	/* Amount each triangle should be rotated compared to prev */
174 	float rotation_delta = M_PI * 2.0 / num_tris;
175 
176 	/* Final scaling factor */
177 	float final_scale = 0.95;
178 
179 	static const char *vert =
180 		"#version 120\n"
181 		"attribute vec2 pos_within_tri;\n"
182 		"attribute vec3 in_barycentric_coords;\n"
183 		"varying vec3 barycentric_coords;\n"
184 		"centroid varying vec3 barycentric_coords_centroid;\n"
185 		"varying vec2 pixel_pos;\n"
186 		"centroid varying vec2 pixel_pos_centroid;\n"
187 		"uniform float tri_scale;\n"
188 		"uniform float rotation_delta;\n"
189 		"uniform int tris_across;\n"
190 		"uniform float final_scale;\n"
191 		"uniform mat4 proj;\n"
192 		"uniform int tri_num; /* [0, num_tris) */\n"
193 		"uniform ivec2 viewport_size;\n"
194 		"\n"
195 		"void main()\n"
196 		"{\n"
197 		"  vec2 pos = tri_scale * pos_within_tri;\n"
198 		"  float rotation = rotation_delta * tri_num;\n"
199 		"  pos = mat2(cos(rotation), sin(rotation),\n"
200 		"             -sin(rotation), cos(rotation)) * pos;\n"
201 		"  int i = int(mod(float(tri_num), float(tris_across)));\n"
202 		"  int j = tris_across - 1 - tri_num / tris_across;\n"
203 		"  pos += (vec2(i, j) * 2.0 + 1.0) / tris_across - 1.0;\n"
204 		"  pos *= final_scale;\n"
205 		"  gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
206 		"  barycentric_coords = barycentric_coords_centroid =\n"
207 		"    in_barycentric_coords;\n"
208 		"  pixel_pos = pixel_pos_centroid =\n"
209 		"    vec2(viewport_size) * (pos + 1.0) / 2.0;\n"
210 		"}\n";
211 
212 	/* Compile program */
213 	prog = glCreateProgram();
214 	GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
215 	glAttachShader(prog, vs);
216 	GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
217 	glAttachShader(prog, fs);
218 	glBindAttribLocation(prog, 0, "pos_within_tri");
219 	glBindAttribLocation(prog, 1, "in_barycentric_coords");
220 	glLinkProgram(prog);
221 	if (!piglit_link_check_status(prog)) {
222 		piglit_report_result(PIGLIT_FAIL);
223 	}
224 
225 	/* Set up uniforms */
226 	glUseProgram(prog);
227 	glUniform1f(glGetUniformLocation(prog, "tri_scale"), tri_scale);
228 	glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
229 		    rotation_delta);
230 	glUniform1i(glGetUniformLocation(prog, "tris_across"), tris_across);
231 	glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
232 	proj_loc = glGetUniformLocation(prog, "proj");
233 	tri_num_loc = glGetUniformLocation(prog, "tri_num");
234 	viewport_size_loc = glGetUniformLocation(prog, "viewport_size");
235 
236 	/* Set up vertex array object */
237 	glGenVertexArrays(1, &vao);
238 	glBindVertexArray(vao);
239 
240 	/* Set up vertex input buffer */
241 	glGenBuffers(1, &vertex_buf);
242 	glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
243 	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
244 		     GL_STATIC_DRAW);
245 	glEnableVertexAttribArray(0);
246 	glVertexAttribPointer(0, ARRAY_SIZE(vertex_data[0].pos_within_tri),
247 			      GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
248 			      (void *) offsetof(vertex_attributes,
249 						pos_within_tri));
250 	glEnableVertexAttribArray(1);
251 	glVertexAttribPointer(1, ARRAY_SIZE(vertex_data[0].barycentric_coords),
252 			      GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
253 			      (void *) offsetof(vertex_attributes,
254 						barycentric_coords));
255 }
256 
257 
258 void
draw(const float (* proj)[4])259 InterpolationTestPattern::draw(const float (*proj)[4])
260 {
261 	glUseProgram(prog);
262 
263 	/* Depending what the fragment shader does, it's possible that
264 	 * viewport_size might get optimized away.  Only set it if it
265 	 * didn't.
266 	 */
267 	if (viewport_size_loc != -1) {
268 		GLint viewport_dims[4];
269 		glGetIntegerv(GL_VIEWPORT, viewport_dims);
270 		glUniform2i(viewport_size_loc, viewport_dims[2], viewport_dims[3]);
271 	}
272 
273 	Triangles::draw(proj);
274 }
275 
276 
compile()277 void Lines::compile()
278 {
279 	/* Line coords within (-1,-1) to (1,1) rect */
280 	static const float pos_line[][2] = {
281 		{ -0.8, -0.5 },
282 		{  0.8, -0.5 }
283 	};
284 
285 	/* Number of line instances across (and down) */
286 	int lines_across = 4;
287 
288 	/* Total number of lines drawn */
289 	num_lines = lines_across * lines_across;
290 
291 	/* Amount each line should be rotated compared to prev */
292 	float rotation_delta = M_PI * 2.0 / num_lines;
293 
294 	/* Scaling factor uniformly applied to line coords */
295 	float line_scale = 0.8 / lines_across;
296 
297 	/* Final scaling factor */
298 	float final_scale = 0.95;
299 
300 	static const char *vert =
301 		"#version 120\n"
302 		"attribute vec2 pos_line;\n"
303 		"uniform float line_scale;\n"
304 		"uniform float rotation_delta;\n"
305 		"uniform int lines_across;\n"
306 		"uniform float final_scale;\n"
307 		"uniform mat4 proj;\n"
308 		"uniform int line_num;\n"
309 		"\n"
310 		"void main()\n"
311 		"{\n"
312 		"  vec2 pos = line_scale * pos_line;\n"
313 		"  float rotation = rotation_delta * line_num;\n"
314 		"  pos = mat2(cos(rotation), sin(rotation),\n"
315 		"             -sin(rotation), cos(rotation)) * pos;\n"
316 		"  int i = int(mod(float(line_num), float(lines_across)));\n"
317 		"  int j = lines_across - 1 - line_num / lines_across;\n"
318 		"  pos += (vec2(i, j) * 2.0 + 1.0) / lines_across - 1.0;\n"
319 		"  pos *= final_scale;\n"
320 		"  gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
321 		"}\n";
322 
323 	static const char *frag =
324 		"#version 120\n"
325 		"void main()\n"
326 		"{\n"
327 		"  gl_FragColor = vec4(1.0);\n"
328 		"}\n";
329 
330 	/* Compile program */
331 	prog = glCreateProgram();
332 	GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
333 	glAttachShader(prog, vs);
334 	GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
335 	glAttachShader(prog, fs);
336 	glBindAttribLocation(prog, 0, "pos_line");
337 	glLinkProgram(prog);
338 	if (!piglit_link_check_status(prog)) {
339 		piglit_report_result(PIGLIT_FAIL);
340 	}
341 
342 	/* Set up uniforms */
343 	glUseProgram(prog);
344 	glUniform1f(glGetUniformLocation(prog, "line_scale"), line_scale);
345 	glUniform1f(glGetUniformLocation(prog, "rotation_delta"),
346 		    rotation_delta);
347 	glUniform1i(glGetUniformLocation(prog, "lines_across"), lines_across);
348 	glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
349 	proj_loc = glGetUniformLocation(prog, "proj");
350 	line_num_loc = glGetUniformLocation(prog, "line_num");
351 
352 	/* Set up vertex array object */
353 	glGenVertexArrays(1, &vao);
354 	glBindVertexArray(vao);
355 
356 	/* Set up vertex input buffer */
357 	glGenBuffers(1, &vertex_buf);
358 	glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
359 	glBufferData(GL_ARRAY_BUFFER, sizeof(pos_line), pos_line,
360 		     GL_STATIC_DRAW);
361 	glEnableVertexAttribArray(0);
362 	glVertexAttribPointer(0, ARRAY_SIZE(pos_line[0]), GL_FLOAT,
363 			      GL_FALSE, sizeof(pos_line[0]), (void *) 0);
364 }
365 
draw(const float (* proj)[4])366 void Lines::draw(const float (*proj)[4])
367 {
368 	glClear(GL_COLOR_BUFFER_BIT);
369 	glUseProgram(prog);
370 	glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
371 	glBindVertexArray(vao);
372 	for (int line_num = 0; line_num < num_lines; ++line_num) {
373 		/* Draws with line width = 0.25, 0.75, 1.25,
374 		 * 1.75, 2.25, 2.75, 3.25, 3.75
375 		 */
376 		glLineWidth((1 + 2 * line_num) / 4.0);
377 		glUniform1i(line_num_loc, line_num);
378 		glDrawArrays(GL_LINES, 0, 2);
379 	}
380 }
381 
compile()382 void Points::compile()
383 {
384 	/* Point coords within (-1,-1) to (1,1) rect */
385 	static const float pos_point[2] = { -0.5, -0.5 };
386 
387 	/* Number of point instances across (and down) */
388 	int points_across = 4;
389 
390 	/* Total number of points drawn */
391 	num_points = points_across * points_across;
392 
393 	/* Scaling factor uniformly applied to point coords */
394 	float point_scale = 0.8 / points_across;
395 
396 	/* Final scaling factor */
397 	float final_scale = 0.95;
398 
399 	static const char *vert =
400 		"#version 120\n"
401 		"attribute vec2 pos_point;\n"
402 		"uniform float point_scale;\n"
403 		"uniform int points_across;\n"
404 		"uniform float final_scale;\n"
405 		"uniform mat4 proj;\n"
406 		"uniform int point_num;\n"
407 		"uniform float depth;\n"
408 		"\n"
409 		"void main()\n"
410 		"{\n"
411 		"  vec2 pos = point_scale * pos_point;\n"
412 		"  int i = int(mod(float(point_num), float(points_across)));\n"
413 		"  int j = points_across - 1 - point_num / points_across;\n"
414 		"  pos += (vec2(i, j) * 2.0 + 1.0) / points_across - 1.0;\n"
415 		"  pos *= final_scale;\n"
416 		"  gl_Position = proj * vec4(pos, depth, 1.0);\n"
417 		"}\n";
418 
419 	static const char *frag =
420 		"#version 120\n"
421 		"void main()\n"
422 		"{\n"
423 		"  gl_FragColor = vec4(1.0);\n"
424 		"}\n";
425 
426 	/* Compile program */
427 	prog = glCreateProgram();
428 	GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
429 	glAttachShader(prog, vs);
430 	GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
431 	glAttachShader(prog, fs);
432 	glBindAttribLocation(prog, 0, "pos_point");
433 	glLinkProgram(prog);
434 	if (!piglit_link_check_status(prog)) {
435 		piglit_report_result(PIGLIT_FAIL);
436 	}
437 
438 	/* Set up uniforms */
439 	glUseProgram(prog);
440 	glUniform1f(glGetUniformLocation(prog, "point_scale"), point_scale);
441 	glUniform1i(glGetUniformLocation(prog, "points_across"), points_across);
442 	glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale);
443 	proj_loc = glGetUniformLocation(prog, "proj");
444 	point_num_loc = glGetUniformLocation(prog, "point_num");
445 	depth_loc = glGetUniformLocation(prog, "depth");
446 
447 	/* Set up vertex array object */
448 	glGenVertexArrays(1, &vao);
449 	glBindVertexArray(vao);
450 
451 	/* Set up vertex input buffer */
452 	glGenBuffers(1, &vertex_buf);
453 	glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
454 	glBufferData(GL_ARRAY_BUFFER, sizeof(pos_point), pos_point,
455 		     GL_STATIC_DRAW);
456 	glEnableVertexAttribArray(0);
457 	glVertexAttribPointer(0, ARRAY_SIZE(pos_point), GL_FLOAT,
458 			      GL_FALSE, 0, (void *) 0);
459 }
460 
draw(const float (* proj)[4])461 void Points::draw(const float (*proj)[4])
462 {
463 	glClear(GL_COLOR_BUFFER_BIT);
464 	glUseProgram(prog);
465 	glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
466 	glBindVertexArray(vao);
467 	glUniform1f(depth_loc, 0.0);
468 	for (int point_num = 0; point_num < num_points; ++point_num) {
469 		glPointSize((1.0 + 4 * point_num) / 4.0);
470 		glUniform1i(point_num_loc, point_num);
471 		glDrawArrays(GL_POINTS, 0, 1);
472 	}
473 }
474 
Sunburst()475 Sunburst::Sunburst()
476 	: out_type(GL_UNSIGNED_NORMALIZED),
477 	  compute_depth(false),
478 	  prog(0),
479 	  rotation_loc(0),
480 	  vert_depth_loc(0),
481 	  frag_depth_loc(0),
482 	  proj_loc(0),
483 	  draw_colors_loc(0),
484 	  vao(0),
485 	  num_tris(0),
486 	  vertex_buf(0)
487 {
488 }
489 
490 
491 /**
492  * Determine the GLSL type that should be used for rendering, based on
493  * out_type.
494  */
495 const char *
get_out_type_glsl() const496 Sunburst::get_out_type_glsl() const
497 {
498 	switch(out_type) {
499 	case GL_INT:
500 		return "ivec4";
501 	case GL_UNSIGNED_INT:
502 		return "uvec4";
503 	case GL_UNSIGNED_NORMALIZED:
504 	case GL_FLOAT:
505 		return "vec4";
506 	default:
507 		printf("Unrecognized out_type: %s\n",
508 		       piglit_get_gl_enum_name(out_type));
509 		piglit_report_result(PIGLIT_FAIL);
510 		return "UNKNOWN";
511 	}
512 }
513 
514 
compile()515 void Sunburst::compile()
516 {
517 	static struct vertex_attributes {
518 		float pos_within_tri[2];
519 		float barycentric_coords[3];
520 	} vertex_data[] = {
521 		{ { -0.3, -0.8 }, { 1, 0, 0 } },
522 		{ {  0.0,  1.0 }, { 0, 1, 0 } },
523 		{ {  0.3, -0.8 }, { 0, 0, 1 } }
524 	};
525         bool need_glsl130 = out_type == GL_INT || out_type == GL_UNSIGNED_INT;
526 
527 	if (need_glsl130) {
528 		piglit_require_gl_version(30);
529 	}
530 
531 	/* Total number of triangles drawn */
532 	num_tris = 7;
533 
534 	static const char *vert_template =
535 		"#version %s\n"
536 		"attribute vec2 pos_within_tri;\n"
537 		"attribute vec3 in_barycentric_coords;\n"
538 		"varying vec3 barycentric_coords;\n"
539 		"uniform float rotation;\n"
540 		"uniform float vert_depth;\n"
541 		"uniform mat4 proj;\n"
542 		"\n"
543 		"void main()\n"
544 		"{\n"
545 		"  vec2 pos = pos_within_tri;\n"
546 		"  pos = mat2(cos(rotation), sin(rotation),\n"
547 		"             -sin(rotation), cos(rotation)) * pos;\n"
548 		"  gl_Position = proj * vec4(pos, vert_depth, 1.0);\n"
549 		"  barycentric_coords = in_barycentric_coords;\n"
550 		"}\n";
551 
552 	static const char *frag_template =
553 		"#version %s\n"
554 		"#define OUT_TYPE %s\n"
555 		"#define COMPUTE_DEPTH %s\n"
556 		"uniform float frag_depth;\n"
557 		"varying vec3 barycentric_coords;\n"
558 		"uniform mat3x4 draw_colors;\n"
559 		"#if __VERSION__ == 130\n"
560 		"  out OUT_TYPE frag_out;\n"
561 		"#endif\n"
562 		"\n"
563 		"void main()\n"
564 		"{\n"
565 		"#if __VERSION__ == 130\n"
566 		"  frag_out = OUT_TYPE(draw_colors * barycentric_coords);\n"
567 		"#else\n"
568 		"  gl_FragColor = draw_colors * barycentric_coords;\n"
569 		"#endif\n"
570 		"#if COMPUTE_DEPTH\n"
571 		"  gl_FragDepth = (frag_depth + 1.0) / 2.0;\n"
572 		"#endif\n"
573 		"}\n";
574 
575 	/* Compile program */
576 	prog = glCreateProgram();
577 	unsigned vert_alloc_len =
578 		strlen(vert_template) + 4;
579 	char *vert = (char *) malloc(vert_alloc_len);
580 	sprintf(vert, vert_template, need_glsl130 ? "130" : "120");
581 	GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
582 	free(vert);
583 	glAttachShader(prog, vs);
584 
585 	const char *out_type_glsl = get_out_type_glsl();
586 	unsigned frag_alloc_len =
587 		strlen(frag_template) + strlen(out_type_glsl) + 4;
588 	char *frag = (char *) malloc(frag_alloc_len);
589 	sprintf(frag, frag_template, need_glsl130 ? "130" : "120",
590 		out_type_glsl,
591 		compute_depth ? "1" : "0");
592 	GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
593 	free(frag);
594 	glAttachShader(prog, fs);
595 
596 	glBindAttribLocation(prog, 0, "pos_within_tri");
597 	glBindAttribLocation(prog, 1, "in_barycentric_coords");
598 	if (need_glsl130) {
599 		glBindFragDataLocation(prog, 0, "frag_out");
600 	}
601 	glLinkProgram(prog);
602 	if (!piglit_link_check_status(prog)) {
603 		piglit_report_result(PIGLIT_FAIL);
604 	}
605 
606 	/* Set up uniforms */
607 	glUseProgram(prog);
608 	rotation_loc = glGetUniformLocation(prog, "rotation");
609 	vert_depth_loc = glGetUniformLocation(prog, "vert_depth");
610 	frag_depth_loc = glGetUniformLocation(prog, "frag_depth");
611 	glUniform1f(vert_depth_loc, 0.0);
612 	glUniform1f(frag_depth_loc, 0.0);
613 	proj_loc = glGetUniformLocation(prog, "proj");
614 	draw_colors_loc = glGetUniformLocation(prog, "draw_colors");
615 
616 	/* Set up vertex array object */
617 	glGenVertexArrays(1, &vao);
618 	glBindVertexArray(vao);
619 
620 	/* Set up vertex input buffer */
621 	glGenBuffers(1, &vertex_buf);
622 	glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
623 	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
624 		     GL_STATIC_DRAW);
625 	glEnableVertexAttribArray(0);
626 	glVertexAttribPointer(0, ARRAY_SIZE(vertex_data[0].pos_within_tri),
627 			      GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
628 			      (void *) 0);
629 	glEnableVertexAttribArray(1);
630 	glVertexAttribPointer(1, ARRAY_SIZE(vertex_data[0].barycentric_coords),
631 			      GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
632 			      (void *) offsetof(vertex_attributes,
633 						barycentric_coords));
634 }
635 
636 
ColorGradientSunburst(GLenum out_type)637 ColorGradientSunburst::ColorGradientSunburst(GLenum out_type)
638 {
639 	this->out_type = out_type;
640 }
641 
642 
643 /**
644  * Draw the color gradient sunburst, but instead of using color
645  * components that range from 0.0 to 1.0, apply the given scaling
646  * factor and offset to each color component.
647  *
648  * The offset is also applied when clearing the color buffer.
649  */
650 void
draw_with_scale_and_offset(const float (* proj)[4],float scale,float offset)651 ColorGradientSunburst::draw_with_scale_and_offset(const float (*proj)[4],
652 						  float scale, float offset)
653 {
654 	switch (out_type) {
655 	case GL_INT: {
656 		int clear_color[4] = { offset, offset, offset, offset };
657 		glClearBufferiv(GL_COLOR, 0, clear_color);
658 		break;
659 	}
660 	case GL_UNSIGNED_INT: {
661 		unsigned clear_color[4] = { offset, offset, offset, offset };
662 		glClearBufferuiv(GL_COLOR, 0, clear_color);
663 		break;
664 	}
665 	case GL_UNSIGNED_NORMALIZED:
666 	case GL_FLOAT: {
667 		glClearColor(offset, offset, offset, offset);
668 		glClear(GL_COLOR_BUFFER_BIT);
669 		break;
670 	}
671 	default:
672 		printf("Unrecognized out_type: %s\n",
673 		       piglit_get_gl_enum_name(out_type));
674 		piglit_report_result(PIGLIT_FAIL);
675 		break;
676 	}
677 
678 	glUseProgram(prog);
679 	glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
680 	float draw_colors[3][4] =
681 		{ { 1, 0, 0, 1.0 }, { 0, 1, 0, 0.5 }, { 0, 0, 1, 1.0 } };
682 	for (int i = 0; i < 3; ++i) {
683 		for (int j = 0; j < 4; ++j) {
684 			draw_colors[i][j] = scale * draw_colors[i][j] + offset;
685 		}
686 	}
687 	glUniformMatrix3x4fv(draw_colors_loc, 1, GL_FALSE,
688 			     &draw_colors[0][0]);
689 	glBindVertexArray(vao);
690 	for (int i = 0; i < num_tris; ++i) {
691 		glUniform1f(rotation_loc, M_PI * 2.0 * i / num_tris);
692 		glDrawArrays(GL_TRIANGLES, 0, 3);
693 	}
694 }
695 
696 
697 void
draw(const float (* proj)[4])698 ColorGradientSunburst::draw(const float (*proj)[4])
699 {
700 	draw_with_scale_and_offset(proj, 1.0, 0.0);
701 }
702 
703 
704 void
draw(const float (* proj)[4])705 StencilSunburst::draw(const float (*proj)[4])
706 {
707 	glEnable(GL_STENCIL_TEST);
708 	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
709 
710 	glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
711 
712 	glUseProgram(prog);
713 	glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
714 	glBindVertexArray(vao);
715 	for (int i = 0; i < num_tris; ++i) {
716 		glStencilFunc(GL_ALWAYS, i+1, 0xff);
717 		glUniform1f(rotation_loc, M_PI * 2.0 * i / num_tris);
718 		glDrawArrays(GL_TRIANGLES, 0, 3);
719 	}
720 
721 	glDisable(GL_STENCIL_TEST);
722 }
723 
724 
DepthSunburst(bool compute_depth)725 DepthSunburst::DepthSunburst(bool compute_depth)
726 {
727 	this->compute_depth = compute_depth;
728 }
729 
730 
731 void
draw(const float (* proj)[4])732 DepthSunburst::draw(const float (*proj)[4])
733 {
734 	glEnable(GL_DEPTH_TEST);
735 	glDepthFunc(GL_LESS);
736 
737 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
738 
739 	glUseProgram(prog);
740 	glUniformMatrix4fv(proj_loc, 1, GL_TRUE, &proj[0][0]);
741 	glBindVertexArray(vao);
742 	for (int i = 0; i < num_tris; ++i) {
743 		/* Draw triangles in a haphazard order so we can
744 		 * verify that depth comparisons sort them out
745 		 * properly.
746 		 */
747 		int triangle_to_draw = (i * 3) % num_tris;
748 
749 		/* Note: with num_tris == 7, this causes us to draw
750 		 * triangles at depths of 3/4, 1/2, -1/4, 0, 1/4, 1/2,
751 		 * and 3/4.
752 		 */
753 		glUniform1f(compute_depth ? frag_depth_loc : vert_depth_loc,
754 			    float(num_tris - triangle_to_draw * 2 - 1)
755 			    / (num_tris + 1));
756 
757 		glUniform1f(rotation_loc,
758 			    M_PI * 2.0 * triangle_to_draw / num_tris);
759 		glDrawArrays(GL_TRIANGLES, 0, 3);
760 	}
761 
762 	glDisable(GL_DEPTH_TEST);
763 }
764 
765 
766 void
compile()767 ManifestStencil::compile()
768 {
769 	static const char *vert =
770 		"#version 120\n"
771 		"attribute vec2 pos;\n"
772 		"void main()\n"
773 		"{\n"
774 		"  gl_Position = vec4(pos, 0.0, 1.0);\n"
775 		"}\n";
776 
777 	static const char *frag =
778 		"#version 120\n"
779 		"uniform vec4 color;\n"
780 		"void main()\n"
781 		"{\n"
782 		"  gl_FragColor = color;\n"
783 		"}\n";
784 
785 	/* Compile program */
786 	prog = glCreateProgram();
787 	GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
788 	glAttachShader(prog, vs);
789 	GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
790 	glAttachShader(prog, fs);
791 	glBindAttribLocation(prog, 0, "pos");
792 	glLinkProgram(prog);
793 	if (!piglit_link_check_status(prog)) {
794 		piglit_report_result(PIGLIT_FAIL);
795 	}
796 
797 	/* Set up uniforms */
798 	glUseProgram(prog);
799 	color_loc = glGetUniformLocation(prog, "color");
800 
801 	/* Set up vertex array object */
802 	glGenVertexArrays(1, &vao);
803 	glBindVertexArray(vao);
804 
805 	/* Set up vertex input buffer */
806 	float vertex_data[4][2] = {
807 		{ -1, -1 },
808 		{ -1,  1 },
809 		{  1, -1 },
810 		{  1,  1 }
811 	};
812 	glGenBuffers(1, &vertex_buf);
813 	glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
814 	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
815 		     GL_STATIC_DRAW);
816 	glEnableVertexAttribArray(0);
817 	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
818 			      (void *) 0);
819 }
820 
821 void
run()822 ManifestStencil::run()
823 {
824 	static float colors[8][4] = {
825 		{ 0.0, 0.0, 0.0, 1.0 },
826 		{ 0.0, 0.0, 1.0, 1.0 },
827 		{ 0.0, 1.0, 0.0, 1.0 },
828 		{ 0.0, 1.0, 1.0, 1.0 },
829 		{ 1.0, 0.0, 0.0, 1.0 },
830 		{ 1.0, 0.0, 1.0, 1.0 },
831 		{ 1.0, 1.0, 0.0, 1.0 },
832 		{ 1.0, 1.0, 1.0, 1.0 }
833 	};
834 
835 	glUseProgram(prog);
836 	glBindVertexArray(vao);
837 
838 	glEnable(GL_STENCIL_TEST);
839 	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
840 
841 	/* Clear the color buffer to 0, in case the stencil buffer
842 	 * contains any values outside the range 0..7
843 	 */
844 	glClear(GL_COLOR_BUFFER_BIT);
845 
846 	for (int i = 0; i < 8; ++i) {
847 		glStencilFunc(GL_EQUAL, i, 0xff);
848 		glUniform4fv(color_loc, 1, colors[i]);
849 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
850 	}
851 
852 	glDisable(GL_STENCIL_TEST);
853 }
854 
855 void
compile()856 ManifestDepth::compile()
857 {
858 	static const char *vert =
859 		"#version 120\n"
860 		"attribute vec2 pos;\n"
861 		"uniform float depth;\n"
862 		"void main()\n"
863 		"{\n"
864 		"  gl_Position = vec4(pos, depth, 1.0);\n"
865 		"}\n";
866 
867 	static const char *frag =
868 		"#version 120\n"
869 		"uniform vec4 color;\n"
870 		"void main()\n"
871 		"{\n"
872 		"  gl_FragColor = color;\n"
873 		"}\n";
874 
875 	/* Compile program */
876 	prog = glCreateProgram();
877 	GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
878 	glAttachShader(prog, vs);
879 	GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
880 	glAttachShader(prog, fs);
881 	glBindAttribLocation(prog, 0, "pos");
882 	glLinkProgram(prog);
883 	if (!piglit_link_check_status(prog)) {
884 		piglit_report_result(PIGLIT_FAIL);
885 	}
886 
887 	/* Set up uniforms */
888 	glUseProgram(prog);
889 	color_loc = glGetUniformLocation(prog, "color");
890 	depth_loc = glGetUniformLocation(prog, "depth");
891 
892 	/* Set up vertex array object */
893 	glGenVertexArrays(1, &vao);
894 	glBindVertexArray(vao);
895 
896 	/* Set up vertex input buffer */
897 	float vertex_data[4][2] = {
898 		{ -1, -1 },
899 		{ -1,  1 },
900 		{  1, -1 },
901 		{  1,  1 }
902 	};
903 	glGenBuffers(1, &vertex_buf);
904 	glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
905 	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
906 		     GL_STATIC_DRAW);
907 	glEnableVertexAttribArray(0);
908 	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]),
909 			      (void *) 0);
910 }
911 
912 void
run()913 ManifestDepth::run()
914 {
915 	static float colors[8][4] = {
916 		{ 0.0, 0.0, 0.0, 1.0 },
917 		{ 0.0, 0.0, 1.0, 1.0 },
918 		{ 0.0, 1.0, 0.0, 1.0 },
919 		{ 0.0, 1.0, 1.0, 1.0 },
920 		{ 1.0, 0.0, 0.0, 1.0 },
921 		{ 1.0, 0.0, 1.0, 1.0 },
922 		{ 1.0, 1.0, 0.0, 1.0 },
923 		{ 1.0, 1.0, 1.0, 1.0 }
924 	};
925 
926 	glUseProgram(prog);
927 	glBindVertexArray(vao);
928 
929 	glEnable(GL_DEPTH_TEST);
930 	glDepthFunc(GL_LESS);
931 	glEnable(GL_STENCIL_TEST);
932 	glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
933 	glStencilFunc(GL_EQUAL, 0, 0xff);
934 
935 	/* Clear the stencil buffer to 0, leaving depth and color
936 	 * buffers unchanged.
937 	 */
938 	glClear(GL_STENCIL_BUFFER_BIT);
939 
940 	for (int i = 0; i < 8; ++i) {
941 		glUniform4fv(color_loc, 1, colors[i]);
942 		glUniform1f(depth_loc, float(7 - 2*i)/8);
943 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
944 	}
945 
946 	glDisable(GL_STENCIL_TEST);
947 	glDisable(GL_DEPTH_TEST);
948 }
949