[Piglit] [PATCH] polygon-mode: replace memcmp() with better pixel probing
Brian Paul
brian.e.paul at gmail.com
Wed Jan 25 06:03:13 PST 2012
Hi Jose,
I'm pretty sure I've got this right.
GL_QUADs drawn with polygon mode = GL_LINE should not render the
diagonal line. Similarly, GL_POLYGONs drawn in GL_LINE mode should
not draw any interior edges (that was broken in Gallium until I fixed
it last summer). I verified this w/ NVIDIA's driver too.
So the only case which should touch the center pixel in the quad
should be the GL_FILL case. If the driver mistakenly does draw the
diagonal in GL_LINE mode, we'll detect the primitive as being filled
and the test will fail. That's what we want.
-Brian
On Wed, Jan 25, 2012 at 4:54 AM, Jose Fonseca <jfonseca at vmware.com> wrote:
> 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
>>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit
More information about the Piglit
mailing list