[Piglit] [PATCH] polygon-mode: replace memcmp() with better pixel probing

Brian Paul brianp at vmware.com
Tue Jan 24 13:54:13 PST 2012


Previously, we compared the reference image and the test image with
memcmp().  That failed when the driver used different drawing paths
for glPolygonMode() vs. regular filled/line/point drawing.

The new test examines the rendering with 3x3-pixel probes to determine if
a polygon was drawn filled, outlined or as points.
---
 tests/general/polygon-mode.c |  162 ++++++++++++++++++++++++++++++++++++------
 1 files changed, 140 insertions(+), 22 deletions(-)

diff --git a/tests/general/polygon-mode.c b/tests/general/polygon-mode.c
index 217ff2b..fdd95cc 100644
--- a/tests/general/polygon-mode.c
+++ b/tests/general/polygon-mode.c
@@ -34,6 +34,8 @@
 int piglit_width = 500, piglit_height = 100;
 int piglit_window_mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE;
 
+static float ortho_left = -1, ortho_right = 8, ortho_bottom = -2, ortho_top = 2;
+
 static const char *TestName = "polygon-mode";
 
 #define VERTS 16
@@ -119,16 +121,117 @@ get_prim_mode(GLenum mode)
 }
 
 
+static void
+obj_pos_to_win_pos(float x, float y, int *wx, int *wy)
+{
+   float ortho_width = ortho_right - ortho_left;
+   float ortho_height = ortho_top - ortho_bottom;
+   *wx = (int) ((x - ortho_left) / ortho_width * piglit_width);
+   *wy = (int) ((y - ortho_bottom) / ortho_height * piglit_height);
+}
+
+
+/**
+ * Probe a 3x3 pixel region to see if any of the pixels matches the
+ * expected color.
+ */
+static GLboolean
+probe_region(float px, float py, const GLfloat expectedColor[4])
+{
+   GLfloat img[3][3][4];
+   int i, j;
+   int wx, wy;
+
+   obj_pos_to_win_pos(px, py, &wx, &wy);
+
+   glReadPixels(wx-1, wy-1, 3, 3, GL_RGBA, GL_FLOAT, img);
+
+   /* see if any of the pixels matches the expected color */
+   for (i = 0; i < 3; i++) {
+      for (j = 0; j < 3; j++) {
+         if (img[i][j][0] == expectedColor[0] &&
+             img[i][j][1] == expectedColor[1] &&
+             img[i][j][2] == expectedColor[2] &&
+             img[i][j][3] == expectedColor[3]) {
+            return GL_TRUE;
+         }
+      }
+   }
+
+   return GL_FALSE;
+}
+
+
+/**
+ * Examine the pixels drawn by a rect using the four vertex positions
+ * and determine if it was drawn filled, outlined, or as four points.
+ * \return GL_FILL, GL_LINE, GL_POINT or GL_NONE
+ */
+static GLenum
+identify_primitive(const GLfloat positions[4][2],
+                   const GLfloat expectedColor[4])
+{
+   /* center */
+   float cx = (positions[0][0] + positions[2][0]) / 2.0;
+   float cy = (positions[0][1] + positions[2][1]) / 2.0;
+   /* left edge */
+   float lx = positions[0][0];
+   float ly = cy;
+   /* right edge */
+   float rx = positions[2][0];
+   float ry = cy;
+   /* bottom edge */
+   float bx = cx;
+   float by = positions[0][1];
+   /* bottom edge */
+   float tx = cx;
+   float ty = positions[2][1];
+
+   /* probe center */
+   if (probe_region(cx, cy, expectedColor))
+      return GL_FILL;
+
+   /* probe left edge */
+   if (probe_region(lx, ly, expectedColor)) {
+      /* and bottom edge */
+      if (probe_region(bx, by, expectedColor)) {
+         /* and right edge */
+         if (probe_region(rx, ry, expectedColor)) {
+            /* and top edge */
+            if (probe_region(tx, ty, expectedColor)) {
+               return GL_LINE;
+            }
+         }
+      }
+   }
+
+   /* probe lower-left corner */
+   if (probe_region(lx, by, expectedColor)) {
+      /* probe lower-right corner */
+      if (probe_region(rx, by, expectedColor)) {
+         /* probe top-left corner */
+         if (probe_region(lx, ty, expectedColor)) {
+            /* probe top-right corner */
+            if (probe_region(rx, ty, expectedColor)) {
+               return GL_POINT;
+            }
+         }
+      }
+   }
+
+   return GL_NONE;
+}
+
+
+
 static GLboolean
 test_combo(GLenum frontMode, GLenum backMode)
 {
    GLenum frontPrim = get_prim_mode(frontMode);
    GLenum backPrim = get_prim_mode(backMode);
-   GLubyte *ref, *test;
    GLboolean pass = GL_TRUE;
-
-   ref = malloc(piglit_width * piglit_height * 4);
-   test = malloc(piglit_width * piglit_height * 4);
+   GLenum expectedPrims[4];
+   int i;
 
    /* Draw reference image */
    glClear(GL_COLOR_BUFFER_BIT);
@@ -137,33 +240,48 @@ test_combo(GLenum frontMode, GLenum backMode)
    glDrawArrays(backPrim, 4, 4);
    glDrawArrays(frontPrim, 8, 4);
    glDrawArrays(backPrim, 12, 4);
-   glReadPixels(0, 0, piglit_width, piglit_height,
-                GL_RGBA, GL_UNSIGNED_BYTE, ref);
+
+   /* determine what kind of primitives were drawn */
+   for (i = 0; i < 4; i++) {
+      bool err = false;
+      expectedPrims[i] = identify_primitive(&Positions[4 * i], Colors[4 * i]);
+      if (i & 1) {
+         if (expectedPrims[i] != backMode) {
+            err = true;
+         }
+      }
+      else {
+         if (expectedPrims[i] != frontMode) {
+            err = true;
+         }
+      }
+      if (err) {
+         /* we didn't get the expected reference primitive */
+         fprintf(stderr,
+                 "%s: reference drawing failed for frontPrim=%s, backPrim=%s\n",
+                 TestName, get_mode_str(frontMode), get_mode_str(backMode));
+         return GL_FALSE;
+      }
+   }
 
    /* Draw test image */
    glClear(GL_COLOR_BUFFER_BIT);
    glPolygonMode(GL_FRONT, frontMode);
    glPolygonMode(GL_BACK, backMode);
    glDrawArrays(GL_QUADS, 0, 16);
-   glReadPixels(0, 0, piglit_width, piglit_height,
-                GL_RGBA, GL_UNSIGNED_BYTE, test);
-
-   /*
-    * This assumes that there are generally no rasterization differences
-    * between the normal rendering paths vs. when glPolygonMode is in effect.
-    * If that's not true, we'll need a different comparision method.
-    */
-   if (memcmp(ref, test, piglit_width * piglit_height * 4)) {
-      fprintf(stderr, "%s: glPolygonMode(front=%s, back=%s) failed\n",
-              TestName, get_mode_str(frontMode), get_mode_str(backMode));
-      pass = GL_FALSE;
+
+   /* check that these prims match the reference prims */
+   for (i = 0; i < 4; i++) {
+      GLenum prim = identify_primitive(&Positions[4 * i], Colors[4 * i]);
+      if (prim != expectedPrims[i]) {
+         fprintf(stderr, "%s: glPolygonMode(front=%s, back=%s) failed\n",
+                 TestName, get_mode_str(frontMode), get_mode_str(backMode));
+         pass = GL_FALSE;
+      }
    }
 
    glutSwapBuffers();
 
-   free(ref);
-   free(test);
-
    return pass;
 }
 
@@ -222,7 +340,7 @@ piglit_init(int argc, char **argv)
 {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
-   glOrtho(-1, 8, -2, 2, -1, 1);
+   glOrtho(ortho_left, ortho_right, ortho_bottom, ortho_top, -1, 1);
 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
-- 
1.7.1



More information about the Piglit mailing list