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

Jose Fonseca jfonseca at vmware.com
Wed Jan 25 03:54:57 PST 2012


Brian,

I think the center probe is unreliable: imagine we request a filled rectangle, the implementation draws two triangles in wireframe mode as

  +-----+
  +    /|
  +   / |
  +  /  |
  + /   |
  +/    |
  +-----+

IIUC, the 

  probe_region(cx, cy, expectedColor)

call will incorrectly interpret the colored center point (due to the diagonal) as a filled rectangle.

Jose


----- Original Message -----
> 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
> 
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit
> 


More information about the Piglit mailing list