[Piglit] [PATCH 5/6] Ported ortho positioning test from Glean to Piglit.

Laura Ekstrand laura at jlekstrand.net
Mon Oct 13 14:21:38 PDT 2014


---
 tests/spec/gl-1.0/CMakeLists.gl.txt |   1 +
 tests/spec/gl-1.0/orthpos.c         | 689 ++++++++++++++++++++++++++++++++++++
 2 files changed, 690 insertions(+)
 create mode 100644 tests/spec/gl-1.0/orthpos.c

diff --git a/tests/spec/gl-1.0/CMakeLists.gl.txt b/tests/spec/gl-1.0/CMakeLists.gl.txt
index 8726cf2..1ed735d 100644
--- a/tests/spec/gl-1.0/CMakeLists.gl.txt
+++ b/tests/spec/gl-1.0/CMakeLists.gl.txt
@@ -21,6 +21,7 @@ piglit_add_executable (gl-1.0-rendermode-feedback rendermode-feedback.c)
 piglit_add_executable (gl-1.0-swapbuffers-behavior swapbuffers-behavior.c)
 piglit_add_executable (gl-1.0-polygon-line-aa polygon-line-aa.c)
 piglit_add_executable (gl-1.0-blend-func blend.c)
+piglit_add_executable (gl-1.0-ortho-pos orthpos.c)
 piglit_add_executable (gl-1.0-fpexceptions fpexceptions.c)
 
 # vim: ft=cmake:
diff --git a/tests/spec/gl-1.0/orthpos.c b/tests/spec/gl-1.0/orthpos.c
new file mode 100644
index 0000000..9dcf750
--- /dev/null
+++ b/tests/spec/gl-1.0/orthpos.c
@@ -0,0 +1,689 @@
+/*
+ * BEGIN_COPYRIGHT -*- glean -*-
+ * 
+ * Copyright (C) 2000  Allen Akin   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL ALLEN AKIN BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ * 
+ * END_COPYRIGHT
+ */
+
+/*
+ * Copyright 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file orthopos.c
+ * 
+ *  Test positioning of primitives in orthographic projection.
+ *
+ *  Some applications use OpenGL extensively for 2D rendering:  portable
+ *  GUI toolkits, heads-up display generators, etc.  These apps require
+ *  primitives to be drawn with reliable position and size in orthographic
+ *  projections.  There are some potential pitfalls; for a good discussion,
+ *  see the OpenGL Programming Guide (the Red Book).  In the second edition,
+ *  see the OpenGL Correctness Tips on page 601.
+ */
+
+#include "piglit-util-gl.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#define window_size piglit_width
+#define drawing_size window_size - 2
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_compat_version = 13;
+
+	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+struct orthpos_result {
+	bool has_gaps, has_overlaps, has_bad_edges;
+};
+
+static int img_bytes;
+static GLubyte* img;
+
+void
+piglit_init(int argc, char **argv)
+{
+	srand(0);
+	img_bytes = window_size * window_size * 
+		piglit_num_components(GL_RGB) * sizeof(GLubyte);
+	img = malloc(img_bytes);
+
+	/* Common setup */
+	piglit_ortho_projection(window_size, window_size, GL_FALSE);
+	glTranslatef(0.375f, 0.375f, 0);
+
+	glFrontFace(GL_CCW);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glEnable(GL_BLEND);
+	glDisable(GL_DITHER);
+	glCullFace(GL_BACK);
+	glEnable(GL_CULL_FACE);
+	glShadeModel(GL_FLAT);
+}
+
+bool
+log_results(const char* title, struct orthpos_result* r) {
+	bool pass = true;
+	printf("\t%s: ", title);
+	if (r->has_gaps || r->has_overlaps || r->has_bad_edges) {
+		printf("%s %s %s\n", (r->has_gaps? "Gaps.": ""),
+			(r->has_overlaps? " Overlaps.": ""),
+			(r->has_bad_edges? " Incorrect edges.": ""));
+		pass = false;
+	} else {
+		printf(" No gaps, overlaps, or incorrect edges.\n");
+	}
+	return pass;
+} /* log_results */
+
+GLubyte
+logical_sum(GLubyte* start, int stride, int count) {
+	GLubyte* p = start;
+	GLubyte sum = 0;
+	int i;
+	for (i = 0; i < count; ++i) {
+		sum |= p[0];
+		sum |= p[1];
+		sum |= p[2];
+		p += stride;
+	}
+	return sum;
+}
+
+bool
+verify_orth_pos(const GLubyte* img, GLsizei img_row_size_in_bytes, 
+	const char* title) {
+
+	/*
+	 * All of the tests in this group are constructed so that the
+	 * "correct" image covers a square of exactly drawing_size by
+	 * drawing_size pixels, embedded in a window that's two pixels
+	 * larger in both dimensions.  The border consists of pixels
+	 * with all components set to zero.  Within the image, all
+	 * pixels should be either red (only the red component is
+	 * nonzero) or green (only the green component is nonzero).  If
+	 * any pixels with all zero components are found, that indicates
+	 * the presence of gaps.  If any pixels with both red and green
+	 * nonzero components are found, that indicates the presence of
+	 * overlaps.
+	 */
+
+	/* For logging results */
+	struct orthpos_result res;
+
+	/* For examining edges */
+	GLubyte* row0 = (GLubyte*) img;
+	GLubyte* row1 = row0 + img_row_size_in_bytes;
+	GLubyte* row_last = row0 + (window_size - 1) * img_row_size_in_bytes;
+	GLubyte* row_next_last = row_last - img_row_size_in_bytes;
+
+	/* For examining the drawing area */
+	int i, j, idx;
+	GLubyte red, green, blue;
+
+	/* Initialize results */
+	res.has_gaps = false;
+	res.has_overlaps = false;
+	res.has_bad_edges = false;
+
+	/* Check the bottom horizontal edge; it must be all zero. */
+	if (logical_sum(row0, 3, window_size)) {
+		printf("\t%s:  bottom border (at Y==0) was touched\n", title);
+		res.has_bad_edges = true;
+	}
+	/* Repeat the process for the top horizontal edge. */
+	if (logical_sum(row_last, 3, window_size)) {
+		printf("\t%s:  top border (at Y==%i) was touched\n",
+			title, window_size - 1);
+		res.has_bad_edges = true;
+	}
+	/*
+	 * Check the second row; there must be at least one nonzero
+	 * pixel in the "drawn" region (excluding the first and last
+	 * column).
+	 */
+	if (!logical_sum(row1 + 3/*skip first pixel's RGB*/, 3, drawing_size)) {
+		printf("\t%s:  first row (at Y==1) was not drawn\n", title);
+		res.has_bad_edges = true;
+	}
+	/* Repeat the process for the last row. */
+	if (!logical_sum(row_next_last + 3, 3, drawing_size)) {
+		printf("\t%s:  last row (at Y==%i) was not drawn\n",
+			title, window_size - 2);
+		res.has_bad_edges = true;
+	}
+
+	/* Check the left-hand vertical edge; it must be all zero. */
+	if (logical_sum(row0, img_row_size_in_bytes, window_size)) {
+		printf("\t%s:  left border (at X==0) was touched\n", title);
+		res.has_bad_edges = true;
+	}
+	/* Repeat for the right-hand vertical edge. */
+	if (logical_sum(row0 + 3 * (window_size - 1), img_row_size_in_bytes,
+	    window_size)) {
+		printf("\t%s:  right border (at X==%i) was touched\n",
+			title, window_size - 1);
+		res.has_bad_edges = true;
+	}
+	/* Check the left-hand column; something must be nonzero. */
+	if (!logical_sum(row1 + 3, img_row_size_in_bytes, drawing_size)) {
+		printf("\t%s:  first column (at X==1) was not drawn\n", title);
+		res.has_bad_edges = true;
+	}
+	/* And repeat for the right-hand column: */
+	if (!logical_sum(row1 + 3 * (drawing_size - 1), img_row_size_in_bytes,
+	    drawing_size)) {
+		printf("\t%s:  last column (at X==%i) was not drawn\n",
+			title, window_size - 2);
+		res.has_bad_edges = true;
+	}
+	
+	/*
+	 * Scan the drawing area.  Anytime we find a pixel with all zero
+	 * components, that's a gap.  Anytime we find a pixel with both
+	 * red and green components nonzero, that's an overlap.
+	 */
+	/* Not sure what was wrong with the original, but this works. */
+	for (i = 1; i < window_size - 1; ++i) {
+		for (j = 1; j < window_size - 1; ++j) {
+			idx = 3*(window_size*i + j);
+			red = img[idx + 0];
+			green = img[idx + 1];
+			blue = img[idx + 2];
+
+			if (!red && !green && !blue) {
+				if (!res.has_gaps) {
+					printf("\t%s:  found first gap at X==%i, Y==%i\n",
+						title, j, i);
+					res.has_gaps = true;
+				}
+			}
+			if (red && green) {
+				if (!res.has_overlaps) {
+					printf("\t%s:  found first overlap at X==%i, Y==%i\n",
+						title, j + 1, i + 1);
+					res.has_overlaps = true;
+				}
+			}
+		}
+	}
+
+	return log_results(title, &res);
+} /* verify_orth_pos */
+
+void
+subdivide_rects(int minx, int maxx, int miny, int maxy,
+    bool split_horiz, bool draw_in_red) {
+	/*
+	 * Basically we're just splitting the input rectangle
+	 * recursively.  At each step we alternate between splitting
+	 * horizontally (dividing along Y) or vertically (along X).  We
+	 * also toggle colors (between red and green) at various times,
+	 * in order to give us some adjacent edges of different colors
+	 * that we can check for overlaps.  Recursion bottoms out when
+	 * the axis of interest drops below 30 pixels in length.
+	 */
+	int split;
+
+	int min = split_horiz? miny: minx;
+	int max = split_horiz? maxy: maxx;
+	if (min + 30 > max) {
+		glColor4f(draw_in_red? 1.0: 0.0, draw_in_red? 0.0: 1.0,
+			0.0, 0.5);
+		glBegin(GL_QUADS);
+		glVertex2i(minx, miny);
+		glVertex2i(maxx, miny);
+		glVertex2i(maxx, maxy);
+		glVertex2i(minx, maxy);
+		glEnd();
+		return;
+	}
+
+	split = min + (int) ((max - min) * 
+		((float) rand() / RAND_MAX)); /* Float in range [0.0f, 1.0f] */
+	if (split_horiz) {
+		subdivide_rects(minx, maxx, miny, split,
+			!split_horiz, draw_in_red);
+		subdivide_rects(minx, maxx, split, maxy,
+			!split_horiz, !draw_in_red);
+	} else {
+		subdivide_rects(minx, split, miny, maxy,
+			!split_horiz, draw_in_red);
+		subdivide_rects(split, maxx, miny, maxy,
+			!split_horiz, !draw_in_red);
+	}
+}
+
+/**
+ * This test checks the positioning of unit-sized points under
+ * orthographic projection.  (This is important for apps that
+ * want to use OpenGL for precise 2D drawing.)  It fills in an
+ * entire rectangle one pixel at a time, drawing adjacent pixels
+ * with different colors and with blending enabled.  If there are
+ * gaps (pixels that are the background color, and thus haven't
+ * been filled), overlaps (pixels that show a blend of more than
+ * one color), or improper edges (pixels around the edge of the
+ * rectangle that haven't been filled, or pixels just outside the
+ * edge that have), then the test fails.
+ * 
+ * This test generally fails for one of several reasons.  First,
+ * the coordinate transformation process may have an incorrect bias;
+ * this usually will cause a bad edge.  Second, the coordinate
+ * transformation process may round pixel coordinates incorrectly;
+ * this will usually cause gaps and/or overlaps.  Third, the point
+ * rasterization process may not be filling the correct pixels;
+ * this can cause gaps, overlaps, or bad edges.
+ */
+
+bool
+ortho_pos_points() {
+	int x, y;
+
+	/* Draw the image */
+	glClear(GL_COLOR_BUFFER_BIT);
+	glBegin(GL_POINTS);
+	for (x = 1; x <= drawing_size; ++x) {
+		for (y = 1; y <= drawing_size; ++y) {
+			if ((x ^ y) & 1) {
+				glColor4f(0.0, 1.0, 0.0, 0.5);
+			}
+			else {
+				glColor4f(1.0, 0.0, 0.0, 0.5);
+			}
+			glVertex2i(x, y);
+		}
+	}
+	glEnd();
+
+	/* Read the image */
+	glReadPixels(0, 0, window_size, window_size, GL_RGB, GL_UNSIGNED_BYTE, img);
+
+	/* Show the image */
+	if (!piglit_automatic) {
+		piglit_present_results();
+	}
+
+	/* Check the results */
+	return verify_orth_pos(img, img_bytes/window_size, "Immediate-mode points");
+} /* ortho_pos_points */
+
+/**
+ * This test checks the positioning of unit-width vertical lines
+ * under orthographic projection.	(This is important for apps
+ * that want to use OpenGL for precise 2D drawing.)  It fills in
+ * an entire rectangle with a collection of vertical lines, drawing
+ * adjacent lines with different colors and with blending enabled.
+ * If there are gaps (pixels that are the background color, and
+ * thus haven't been filled), overlaps (pixels that show a blend
+ * of more than one color), or improper edges (pixels around the
+ * edge of the rectangle that haven't been filled, or pixels just
+ * outside the edge that have), then the test fails.
+ * 
+ * This test generally fails for one of several reasons.  First,
+ * the coordinate transformation process may have an incorrect bias;
+ * this usually will cause a bad edge.  Second, the coordinate
+ * transformation process may round pixel coordinates incorrectly;
+ * this will usually cause gaps and/or overlaps.  Third, the
+ * line rasterization process may not be filling the correct
+ * pixels; this can cause gaps, overlaps, or bad edges.  Fourth,
+ * the OpenGL implementation may not handle the diamond-exit rule
+ * (section 3.4.1 in version 1.2.1 of the OpenGL spec) correctly;
+ * this should cause a bad border or bad top edge.
+ * 
+ * It can be argued that this test is more strict that the OpenGL
+ * specification requires.  However, it is necessary to be this
+ * strict in order for the results to be useful to app developers
+ * using OpenGL for 2D drawing.
+ */
+bool
+ortho_pos_vlines() {
+	/*
+	 * Immediate-mode vertical lines
+	 * 	Note that these are a little tricky, because of
+	 * 	OpenGL's "diamond-exit rule" line semantics.  In
+	 * 	this case, we can safely treat them as half-open
+	 * 	lines, where the terminal point isn't drawn.  Thus
+	 * 	we need to specify a terminal coordinate one pixel
+	 * 	beyond the last pixel we wish to be drawn.
+	 */
+
+	int x;
+
+	/* Draw the image */
+	glClear(GL_COLOR_BUFFER_BIT);
+	glBegin(GL_LINES);
+	for (x = 1; x <= drawing_size; ++x) {
+		if (x & 1)
+			glColor4f(0.0, 1.0, 0.0, 0.5);
+		else
+			glColor4f(1.0, 0.0, 0.0, 0.5);
+		glVertex2i(x, 1);
+		glVertex2i(x, drawing_size + 1);
+	}
+	glEnd();
+
+	/* Read the image */
+	glReadPixels(0, 0, window_size, window_size, GL_RGB, GL_UNSIGNED_BYTE, img);
+
+	/* Show the image */
+	if (!piglit_automatic) {
+		piglit_present_results();
+	}
+
+	/* Check the results */
+	return verify_orth_pos(img, img_bytes/window_size, "Immediate-mode vertical lines");
+} /* ortho_pos_vlines */
+
+/**
+ * This test checks the positioning of unit-width horizontal lines
+ * under orthographic projection.	(This is important for apps
+ * that want to use OpenGL for precise 2D drawing.)  It fills in
+ * an entire rectangle with a stack of horizontal lines, drawing
+ * adjacent lines with different colors and with blending enabled.
+ * If there are gaps (pixels that are the background color, and
+ * thus haven't been filled), overlaps (pixels that show a blend
+ * of more than one color), or improper edges (pixels around the
+ * edge of the rectangle that haven't been filled, or pixels just
+ * outside the edge that have), then the test fails.
+ * 
+ * This test generally fails for one of several reasons.  First,
+ * the coordinate transformation process may have an incorrect bias;
+ * this usually will cause a bad edge.  Second, the coordinate
+ * transformation process may round pixel coordinates incorrectly;
+ * this will usually cause gaps and/or overlaps.  Third, the
+ * line rasterization process may not be filling the correct
+ * pixels; this can cause gaps, overlaps, or bad edges.  Fourth,
+ * the OpenGL implementation may not handle the diamond-exit rule
+ * (section 3.4.1 in version 1.2.1 of the OpenGL spec) correctly;
+ * this should cause a bad border or bad right edge.
+ * 
+ * It can be argued that this test is more strict that the OpenGL
+ * specification requires.  However, it is necessary to be this
+ * strict in order for the results to be useful to app developers
+ * using OpenGL for 2D drawing.
+ */
+bool
+ortho_pos_hlines() {
+	/*
+	 * Immediate-mode horizontal lines
+	 * See the comments in the vertical line case above.
+	 */
+	int y;
+	
+	/* Draw the image */
+	glClear(GL_COLOR_BUFFER_BIT);
+	glBegin(GL_LINES);
+	for (y = 1; y <= drawing_size; ++y) {
+		if (y & 1)
+			glColor4f(0.0, 1.0, 0.0, 0.5);
+		else
+			glColor4f(1.0, 0.0, 0.0, 0.5);
+		glVertex2i(1, y);
+		glVertex2i(drawing_size + 1, y);
+	}
+	glEnd();
+
+	/* Read the image */
+	glReadPixels(0, 0, window_size, window_size, GL_RGB, GL_UNSIGNED_BYTE, img);
+
+	/* Show the image */
+	if (!piglit_automatic) {
+		piglit_present_results();
+	}
+
+	/* Check the results */
+	return verify_orth_pos(img, img_bytes/window_size, "Immediate-mode horizontal lines");
+} /* ortho_pos_hlines */
+
+/**
+ * This test checks the positioning of 1x1-pixel quadrilaterals
+ * under orthographic projection.	(This is important for apps
+ * that want to use OpenGL for precise 2D drawing.)  It fills in
+ * an entire rectangle with an array of quadrilaterals, drawing
+ * adjacent quads with different colors and with blending enabled.
+ * If there are gaps (pixels that are the background color, and
+ * thus haven't been filled), overlaps (pixels that show a blend
+ * of more than one color), or improper edges (pixels around the
+ * edge of the rectangle that haven't been filled, or pixels just
+ * outside the edge that have), then the test fails.
+ * 
+ * This test generally fails for one of several reasons.  First,
+ * the coordinate transformation process may have an incorrect bias;
+ * this usually will cause a bad edge.  Second, the coordinate
+ * transformation process may round pixel coordinates incorrectly;
+ * this will usually cause gaps and/or overlaps.  Third, the
+ * quad rasterization process may not be filling the correct
+ * pixels; this can cause gaps, overlaps, or bad edges.
+ */
+bool
+ortho_pos_tiny_quads() {
+	/*
+	 * Immediate-mode 1x1-pixel quads
+	 */
+
+	int x, y;
+	
+	/* Draw the image */
+	glClear(GL_COLOR_BUFFER_BIT);
+	glBegin(GL_QUADS);
+	for (x = 1; x <= drawing_size; ++x)
+		for (y = 1; y <= drawing_size; ++y) {
+			if ((x ^ y) & 1)
+				glColor4f(0.0, 1.0, 0.0, 0.5);
+			else
+				glColor4f(1.0, 0.0, 0.0, 0.5);
+			glVertex2i(x, y);
+			glVertex2i(x + 1, y);
+			glVertex2i(x + 1, y + 1);
+			glVertex2i(x, y + 1);
+	}
+	glEnd();
+
+	/* Read the image */
+	glReadPixels(0, 0, window_size, window_size, GL_RGB, GL_UNSIGNED_BYTE, img);
+
+	/* Show the image */
+	if (!piglit_automatic) {
+		piglit_present_results();
+	}
+
+	/* Check the results */
+	return verify_orth_pos(img, img_bytes/window_size, "Immediate-mode 1x1 quads");
+} /* ortho_pos_tiny_quads */
+
+/**
+ * This test checks the positioning of axis-aligned rectangles
+ * under orthographic projection.	(This is important for apps
+ * that want to use OpenGL for precise 2D drawing.)  It fills in
+ * an entire rectangle with an array of smaller rects, drawing
+ * adjacent rects with different colors and with blending enabled.
+ * If there are gaps (pixels that are the background color, and
+ * thus haven't been filled), overlaps (pixels that show a blend
+ * of more than one color), or improper edges (pixels around the
+ * edge of the rectangle that haven't been filled, or pixels just
+ * outside the edge that have), then the test fails.
+ * 
+ * This test generally fails for one of several reasons.  First,
+ * the coordinate transformation process may have an incorrect bias;
+ * this usually will cause a bad edge.  Second, the coordinate
+ * transformation process may round pixel coordinates incorrectly;
+ * this will usually cause gaps and/or overlaps.  Third, the
+ * rectangle rasterization process may not be filling the correct
+ * pixels; this can cause gaps, overlaps, or bad edges.
+ */
+bool
+ortho_pos_rand_rects() {
+	/*
+	 * Immediate-mode random axis-aligned rectangles
+	 */
+
+	/* Draw the image */
+	glClear(GL_COLOR_BUFFER_BIT);
+	subdivide_rects(1, drawing_size + 1, 1, drawing_size + 1,
+		true, true);
+
+	/* Read the image */
+	glReadPixels(0, 0, window_size, window_size, GL_RGB, GL_UNSIGNED_BYTE, img);
+
+	/* Show the image */
+	if (!piglit_automatic) {
+		piglit_present_results();
+	}
+
+	/* Check the results */
+	return verify_orth_pos(img, img_bytes/window_size, 
+		"Immediate-mode random axis-aligned rectangles");
+} /* ortho_pos_rand_rects */
+
+/* Factory for generating random mesh just like Glean's RandomMesh2D class */
+float*
+random_mesh_2d(float minx, float maxx, int xpoints,
+	float miny, float maxy, int ypoints)
+{
+	int x, y, idx;
+	float* mesh = malloc(xpoints * ypoints * 2 * sizeof(float));
+	double deltax = 0.7 * (maxx - minx) / (xpoints - 1);
+	double deltay = 0.7 * (maxy - miny) / (ypoints - 1);
+	float rand_no;
+
+	for (y = 0; y < ypoints; ++y) {
+		for (x = 0; x < xpoints; ++x) {
+
+			idx = 2 * (xpoints * y + x);
+
+			/* Generate an unperturbed, uniform mesh */
+			mesh[idx + 0] = minx + (x * (maxx - minx)) / (xpoints - 1);
+			mesh[idx + 1] = miny + (y * (maxy - miny)) / (ypoints - 1);
+
+			/* Perturb the interior points of the mesh */
+			if ((x != 0) && (y != 0) && (x != xpoints - 1) && (y != ypoints - 1))
+			{
+				rand_no = (float) rand() / RAND_MAX; /* Float in range [0.0f, 1.0f] */
+				mesh[idx + 0] += deltax * (rand_no - 0.5);
+				rand_no = (float) rand() / RAND_MAX; 
+				mesh[idx + 1] += deltay * (rand_no - 0.5);
+			}
+		}
+	}
+
+	return mesh;
+} /* random_mesh_2d */
+
+/**
+ * This test checks the positioning of random triangles under
+ * orthographic projection.  (This is important for apps that
+ * want to use OpenGL for precise 2D drawing.)  It fills in an
+ * entire rectangle with an array of randomly-generated triangles,
+ * drawing adjacent triangles with different colors and with blending
+ * enabled.  If there are gaps (pixels that are the background color,
+ * and thus haven't been filled), overlaps (pixels that show a blend
+ * of more than one color), or improper edges (pixels around the
+ * edge of the rectangle that haven't been filled, or pixels just
+ * outside the edge that have), then the test fails.
+ * 
+ * This test generally fails for one of several reasons.  First,
+ * the coordinate transformation process may have an incorrect bias;
+ * this usually will cause a bad edge.  Second, the coordinate
+ * transformation process may round pixel coordinates incorrectly;
+ * this will usually cause gaps and/or overlaps.  Third, the
+ * triangle rasterization process may not be filling the correct
+ * pixels; this can cause gaps, overlaps, or bad edges.
+ */
+bool
+ortho_pos_rand_tris() {
+	/*
+	 * Immediate-mode random triangles
+	 */
+	int i, j;
+	int npoints = 10;
+	float* mesh;
+
+	/* Draw the image */
+	glClear(GL_COLOR_BUFFER_BIT);
+	mesh = random_mesh_2d(1, drawing_size + 1, npoints,
+		1, drawing_size + 1, npoints);
+	for (i = npoints - 1; i > 0; --i) {
+		glBegin(GL_TRIANGLE_STRIP);
+		for (j = 0; j < npoints; ++j) {
+			glColor4f(1.0, 0.0, 0.0, 0.5);
+			glVertex2fv(mesh + 2 * (npoints * i + j)); /* mesh[i, j] */
+			glColor4f(0.0, 1.0, 0.0, 0.5);
+			glVertex2fv(mesh + 2 * (npoints * (i - 1) + j)); /* mesh[i - 1, j] */
+		}
+		glEnd();
+	}
+	free(mesh);
+
+	/* Read the image */
+	glReadPixels(0, 0, window_size, window_size, GL_RGB, GL_UNSIGNED_BYTE, img);
+
+	/* Show the image */
+	if (!piglit_automatic) {
+		piglit_present_results();
+	}
+
+	/* Check the results */
+	return verify_orth_pos(img, img_bytes/window_size, 
+		"Immediate-mode random triangles");
+} /* ortho_pos_rand_tris */
+
+enum piglit_result
+piglit_display(void)
+{
+	bool pass = true;
+
+	pass &= ortho_pos_points();
+	pass &= ortho_pos_vlines();
+	pass &= ortho_pos_hlines();
+	pass &= ortho_pos_tiny_quads();
+	pass &= ortho_pos_rand_rects();
+	pass &= ortho_pos_rand_tris();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
-- 
2.1.0



More information about the Piglit mailing list