Added calibrate_rast.c program
authorBrian <brian.paul@tungstengraphics.com>
Fri, 29 Feb 2008 00:42:18 +0000 (17:42 -0700)
committerBrian <brian.paul@tungstengraphics.com>
Fri, 29 Feb 2008 00:55:26 +0000 (17:55 -0700)
Measures rasterization of points/lines/tris and suggests fixes/biases when
something doesn't meet spec.

progs/tests/Makefile
progs/tests/calibrate_rast.c [new file with mode: 0644]

index 8196c1b348f14abb2530af8ba62d6b5a720d0c74..7053ebc86aa6f3092dc7f0e8c9dc126fa6150f57 100644 (file)
@@ -30,6 +30,7 @@ SOURCES = \
        bug_3050.c \
        bug_3101.c \
        bug_3195.c \
+       calibrate_rast.c \
        copypixrate.c \
        crossbar.c \
        cva.c \
diff --git a/progs/tests/calibrate_rast.c b/progs/tests/calibrate_rast.c
new file mode 100644 (file)
index 0000000..37d8ac8
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * Automatic primitive rasterization precision test.
+ *
+ * Draw prims at various sub-pixel offsets and examine where the quad is
+ * actually drawn.
+ * Check if the range of offsets which paint the right pixels falls within
+ * OpenGL's specification.
+ * In case of failures, report the coordinate bias needed to fix the problem.
+ *
+ * Note that even Mesa/swrast fails some line tests.  This is because some
+ * window coordinates wind up as 53.9999 instead of 54, for example.  Enabling
+ * the small translation factor below fixes that.  Revisit someday...
+ *
+ * Brian Paul
+ * 28 Feb 2008
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/glut.h>
+
+
+static int Width = 100, Height = 100;
+static int Win;
+static float Step = 0.125;
+#if 0
+/* This tiny offset fixes errors in Mesa/Xlib */
+static float Xtrans = 0.5 * 0.125;
+static float Ytrans = 0.5 * 0.125;
+#else
+static float Xtrans = 0.0;
+static float Ytrans = 0.0;
+#endif
+
+
+static void
+PointCalibrate(int xpos, int ypos)
+{
+   GLfloat rgba[4];
+   float x, y;
+   float xmin, ymin, xmax, ymax;
+
+   xmin = ymin = 1000.0;
+   xmax = ymax = -1000.0;
+
+   for (y = -1.0; y <= 1.0; y += Step) {
+      for (x = -1.0; x <= 1.0; x += Step) {
+         glClear(GL_COLOR_BUFFER_BIT);
+         glBegin(GL_POINTS);
+         glVertex2f(xpos + x, ypos + y);
+         glEnd();
+         glReadPixels(xpos, ypos, 1, 1, GL_RGBA, GL_FLOAT, rgba);
+         if (rgba[0] == 1.0 && rgba[1] == 1.0 && rgba[2] == 1.0) {
+            /* hit */
+            if (x < xmin)
+               xmin = x;
+            if (y < ymin)
+               ymin = y;
+            if (x > xmax)
+               xmax = x;
+            if (y > ymax)
+               ymax = y;
+         }
+      }
+   }
+
+   printf("Point at (%2d, %2d) drawn for x in [%6.3f, %6.3f] and y in [%6.3f, %6.3f]\n",
+          xpos, ypos,
+          xpos + xmin, xpos + xmax,
+          ypos + ymin, ypos + ymax);
+
+   if (xmax - xmin != 1.0 - Step) {
+      printf("  => Inconsistant X-axis rasterization!\n");
+   }
+   if (ymax - ymin != 1.0 - Step) {
+      printf("  => Inconsistant Y-axis rasterization!\n");
+   }
+   if (xmin < 0.0) {
+      printf("  => Points should be X biased by about %f\n", xmin);
+   }
+   if (ymin < 0.0) {
+      printf("  => Points should be Y biased by about %f\n", ymin);
+   }
+   if (xmax > 1.0) {
+      printf("  => Points should be X biased by about %f\n", 1.0 - xmax);
+   }
+   if (ymax > 1.0) {
+      printf("  => Points should be Y biased by about %f\n", 1.0 - ymax);
+   }
+
+}
+
+
+/**
+ * XXX Implement VLineCalibrate() someday
+ */
+static void
+HLineCalibrate(int xpos, int ypos, int len)
+{
+   GLfloat rgba[2][4];
+   float x, y;
+   float ymin, ymax;
+   float xmin_left, xmax_left, xmin_right, xmax_right;
+
+   xmin_left = xmin_right = 1000.0;
+   xmax_left = xmax_right = -1000.0;
+   ymin = 1000;
+   ymax = -1000.0;
+
+   /*
+    * First, check vertical positioning of the horizontal line
+    */
+   for (y = -1.0; y <= 1.0; y += Step) {
+      glClear(GL_COLOR_BUFFER_BIT);
+      glBegin(GL_LINES);
+      glVertex2f(xpos,       ypos + y);
+      glVertex2f(xpos + len, ypos + y);
+      glEnd();
+
+      glReadPixels(xpos + len / 2, ypos, 1, 1, GL_RGBA, GL_FLOAT, rgba);
+      if (rgba[0][0] == 1.0) {
+         /* hit */
+         if (y < ymin)
+            ymin = y;
+         if (y > ymax)
+            ymax = y;
+      }
+   }
+
+   printf("H-line at Y=%2d drawn for y in [%6.3f, %6.3f]\n",
+          ypos,
+          ypos + ymin, ypos + ymax);
+
+   if (ymax - ymin != 1.0 - Step) {
+      printf("  => Inconsistant Y-axis rasterization!\n");
+   }
+
+   if (ymin > 0.5 ) {
+      printf("  => Lines should be Y biased by about %f\n", ymin - 0.5);
+   }
+
+   if (ymax < 0.5 ) {
+      printf("  => Lines should be Y biased by about %f\n", 0.5 - ymax);
+   }
+
+   /*
+    * Second, check endpoints  (for Y at 1/2 pixel)
+    */
+   for (x = -1.0; x <= 1.0; x += Step) {
+      glClear(GL_COLOR_BUFFER_BIT);
+      glBegin(GL_LINES);
+      glVertex2f(xpos + x,       ypos + 0.5f);
+      glVertex2f(xpos + x + len, ypos + 0.5f);
+      glEnd();
+
+      /* left end */
+      glReadPixels(xpos - 1, ypos, 2, 1, GL_RGBA, GL_FLOAT, rgba);
+      if (rgba[0][0] == 0.0 && rgba[1][0] == 1.0) {
+         /* hit */
+         if (x < xmin_left)
+            xmin_left = x;
+         if (x > xmax_left)
+            xmax_left = x;
+      }
+
+      /* right end */
+      glReadPixels(xpos + len - 1, ypos, 2, 1, GL_RGBA, GL_FLOAT, rgba);
+      if (rgba[0][0] == 1.0 && rgba[1][0] == 0.0) {
+         /* hit */
+         if (x < xmin_right)
+            xmin_right = x;
+         if (x > xmax_right)
+            xmax_right = x;
+      }
+   }
+
+   printf("H-line [%d..%d) hit left end for x in [%6.3f, %6.3f] "
+          "hit right end for x in [%6.3f, %6.3f]\n",
+          xpos, xpos + len,
+          xpos + xmin_left, xpos + xmax_left,
+          xpos + len + xmin_right, xpos + len + xmax_right);
+
+   if (xmax_left - xmin_left > 1.0 - Step) {
+      printf("  => Inconsistant left-end rasterization!\n");
+   }
+   if (xmax_right - xmin_right > 1.0 - Step) {
+      printf("  => Inconsistant right-end rasterization!\n");
+   }
+
+   if (xmin_left != xmin_right ||
+       xmax_left != xmax_right) {
+      printf("  => Inconsistant length!\n");
+   }
+
+   if (xmin_left < 0.0) {
+      printf("  => Coords should be X biased by about %f\n", xmin_left );
+   }
+   if (xmin_right < 0.0) {
+      printf("  => Coords should be X biased by about %f\n", xmin_right );
+   }
+   if (xmax_left >= 1.0) {
+      printf("  => Coords should be X biased by about %f\n", -xmax_right + 1.0);
+   }
+   if (xmax_right >= 1.0) {
+      printf("  => Coords should be X biased by about %f\n", -xmax_right + 1.0);
+   }
+
+}
+
+
+static void
+QuadCalibrate(int xpos, int ypos, int width, int height)
+{
+   GLfloat rgba1[2][4];
+   GLfloat rgba2[2][4];
+   float x, y;
+   float xmin, ymin, xmax, ymax;
+
+   xmin = ymin = 1000.0;
+   xmax = ymax = -1000.0;
+
+   for (y = -1.0; y <= 1.0; y += Step) {
+      for (x = -1.0; x <= 1.0; x += Step) {
+         glClear(GL_COLOR_BUFFER_BIT);
+         glBegin(GL_QUADS);
+         glVertex2f(xpos + x,         ypos + y);
+         glVertex2f(xpos + x + width, ypos + y);
+         glVertex2f(xpos + x + width, ypos + y + height);
+         glVertex2f(xpos + x,         ypos + y + height);
+         glEnd();
+
+         /* horizontal measurement */
+         glReadPixels(xpos - 1, ypos + 2, 2, 1, GL_RGBA, GL_FLOAT, rgba1);
+         glReadPixels(xpos + width - 1, ypos + 2, 2, 1, GL_RGBA, GL_FLOAT, rgba2);
+         if (rgba1[0][0] == 0.0 && rgba1[1][0] == 1.0 &&
+             rgba2[0][0] == 1.0 && rgba2[1][0] == 0.0) {
+            if (x < xmin)
+               xmin = x;
+            if (x > xmax)
+               xmax = x;
+         }
+
+         /* vertical measurement */
+         glReadPixels(xpos + 2, ypos - 1, 1, 2, GL_RGBA, GL_FLOAT, rgba1);
+         glReadPixels(xpos + 2, ypos + height - 1, 1, 2, GL_RGBA, GL_FLOAT, rgba2);
+         if (rgba1[0][0] == 0.0 && rgba1[1][0] == 1.0 &&
+             rgba2[0][0] == 1.0 && rgba2[1][0] == 0.0) {
+            if (y < ymin)
+               ymin = y;
+            if (y > ymax)
+               ymax = y;
+         }
+      }
+   }
+
+   printf("Quad at (%2d, %2d)..(%2d, %2d) drawn"
+          " for x in [%6.3f, %6.3f] and y in [%6.3f, %6.3f]\n",
+          xpos, ypos,
+          xpos + width, ypos + height,
+          xpos + xmin, xpos + xmax,
+          ypos + ymin, ypos + ymax);
+
+   if (xmax - xmin != 1.0 - Step) {
+      printf("  => Inconsistant X-axis rasterization/size!\n");
+   }
+   if (ymax - ymin != 1.0 - Step) {
+      printf("  => Inconsistant Y-axis rasterization/size!\n");
+   }
+
+   if (xmin < -0.5) {
+      printf("  => Coords should be X biased by about %f\n", 0.5 + xmin );
+   }
+   if (ymin < -0.5) {
+      printf("  => Coords should be Y biased by about %f\n", 0.5 + ymin);
+   }
+   if (xmax > 0.5) {
+      printf("  => Coords should be X biased by about %f\n", -xmax + 0.5);
+   }
+   if (ymax > 0.5) {
+      printf("  => Coords should be Y biased by about %f\n", -ymax + 0.5);
+   }
+}
+
+
+/**
+ * Misc/disabled code for debugging.
+ */
+static void
+DebugTest(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT);
+   glEnable(GL_BLEND);
+   glBlendFunc(GL_ONE, GL_ONE);
+
+   glColor3f(.5, .5, .5);
+
+   glBegin(GL_LINES);
+   glVertex2f(30, 35.5);
+   glVertex2f(54, 35.5);
+   glVertex2f(54, 35.5);
+   glVertex2f(66, 35.5);
+   glEnd();
+
+   glDisable(GL_BLEND);
+   glColor3f(1,1,1);
+}
+
+
+static void
+Draw(void)
+{
+   glClear(GL_COLOR_BUFFER_BIT);
+
+   glPushMatrix();
+   glTranslatef(Xtrans, Ytrans, 0);
+
+   PointCalibrate(1, 1);
+   PointCalibrate(50, 50);
+   PointCalibrate(28, 17);
+   PointCalibrate(17, 18);
+   printf("\n");
+
+   HLineCalibrate(5, 10, 10);
+   HLineCalibrate(25, 22, 12);
+   HLineCalibrate(54, 33, 12);
+   HLineCalibrate(54+12, 33, 12);
+   printf("\n");
+
+   QuadCalibrate(2, 2, 10, 10);
+   QuadCalibrate(50, 50, 10, 10);
+   QuadCalibrate(28, 17, 12, 12);
+   QuadCalibrate(17, 28, 12, 12);
+
+   (void) DebugTest;
+
+   glPopMatrix();
+
+   glutSwapBuffers();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+   Width = width;
+   Height = height;
+   glViewport(0, 0, width, height);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glOrtho(0, width, 0, height, -1, 1);
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+   (void) x;
+   (void) y;
+   switch (key) {
+   case 27:
+      glutDestroyWindow(Win);
+      exit(0);
+      break;
+   }
+   glutPostRedisplay();
+}
+
+
+static void
+Init(void)
+{
+   printf("Measurement/callibration for basic prim rasterization...\n");
+   printf("GL_RENDERER: %s\n", (char*) glGetString(GL_RENDERER));
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   glutInit(&argc, argv);
+   glutInitWindowPosition(0, 0);
+   glutInitWindowSize(Width, Height);
+   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+   Win = glutCreateWindow(argv[0]);
+   glutReshapeFunc(Reshape);
+   glutKeyboardFunc(Key);
+   glutDisplayFunc(Draw);
+   Init();
+   glutMainLoop();
+   return 0;
+}