Fixed bug 2158 - Pixel missing in SDL_RenderDrawLines
authorSam Lantinga <slouken@libsdl.org>
Sun, 20 Oct 2013 10:10:14 -0700
changeset 78407e9cd472a889
parent 7839 d2804f8153fe
child 7841 b5d893a07471
Fixed bug 2158 - Pixel missing in SDL_RenderDrawLines

Sean McKean

I am running Ubuntu 12.04 (GL version 1.4 Mesa 8.0.4) , and on drawing a set of lines through the renderer through SDL_RenderDrawLines() (looped or not) or SDL_RenderDrawRect() I notice a pixel missing. For RenderDrawLines() it seems to be the second point in the sequence; for RenderDrawRect() it is the lower-right. This can be fixed by specifying SDL_RenderDrawPoint(s), but wouldn't it be easier to specify each pixel in a GL_POINTS glBegin/End loop in the OpenGL code, just to make sure?

I also ran the same program on Android; the rendering seemed to be correct, which uses glDrawArrays.
src/render/opengl/SDL_glfuncs.h
src/render/opengl/SDL_render_gl.c
     1.1 --- a/src/render/opengl/SDL_glfuncs.h	Sun Oct 20 09:58:37 2013 -0700
     1.2 +++ b/src/render/opengl/SDL_glfuncs.h	Sun Oct 20 10:10:14 2013 -0700
     1.3 @@ -89,8 +89,8 @@
     1.4  SDL_PROC_UNUSED(void, glDepthMask, (GLboolean flag))
     1.5  SDL_PROC_UNUSED(void, glDepthRange, (GLclampd zNear, GLclampd zFar))
     1.6  SDL_PROC(void, glDisable, (GLenum cap))
     1.7 -SDL_PROC_UNUSED(void, glDisableClientState, (GLenum array))
     1.8 -SDL_PROC_UNUSED(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count))
     1.9 +SDL_PROC(void, glDisableClientState, (GLenum array))
    1.10 +SDL_PROC(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count))
    1.11  SDL_PROC_UNUSED(void, glDrawBuffer, (GLenum mode))
    1.12  SDL_PROC_UNUSED(void, glDrawElements,
    1.13                  (GLenum mode, GLsizei count, GLenum type,
    1.14 @@ -103,7 +103,7 @@
    1.15                  (GLsizei stride, const GLvoid * pointer))
    1.16  SDL_PROC_UNUSED(void, glEdgeFlagv, (const GLboolean * flag))
    1.17  SDL_PROC(void, glEnable, (GLenum cap))
    1.18 -SDL_PROC_UNUSED(void, glEnableClientState, (GLenum array))
    1.19 +SDL_PROC(void, glEnableClientState, (GLenum array))
    1.20  SDL_PROC(void, glEnd, (void))
    1.21  SDL_PROC_UNUSED(void, glEndList, (void))
    1.22  SDL_PROC_UNUSED(void, glEvalCoord1d, (GLdouble u))
    1.23 @@ -448,7 +448,7 @@
    1.24  SDL_PROC_UNUSED(void, glVertex4s,
    1.25                  (GLshort x, GLshort y, GLshort z, GLshort w))
    1.26  SDL_PROC_UNUSED(void, glVertex4sv, (const GLshort * v))
    1.27 -SDL_PROC_UNUSED(void, glVertexPointer,
    1.28 +SDL_PROC(void, glVertexPointer,
    1.29                  (GLint size, GLenum type, GLsizei stride,
    1.30                   const GLvoid * pointer))
    1.31  SDL_PROC(void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height))
     2.1 --- a/src/render/opengl/SDL_render_gl.c	Sun Oct 20 09:58:37 2013 -0700
     2.2 +++ b/src/render/opengl/SDL_render_gl.c	Sun Oct 20 10:10:14 2013 -0700
     2.3 @@ -1066,61 +1066,28 @@
     2.4                     int count)
     2.5  {
     2.6      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
     2.7 -    int i;
     2.8  
     2.9      GL_SetDrawingState(renderer);
    2.10  
    2.11 +    data->glTranslatef(0.5f, 0.5f, 0.0f);
    2.12 +    data->glVertexPointer(2, GL_FLOAT, 0, points);
    2.13 +    data->glEnableClientState(GL_VERTEX_ARRAY);
    2.14 +
    2.15      if (count > 2 &&
    2.16          points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
    2.17 -        data->glBegin(GL_LINE_LOOP);
    2.18          /* GL_LINE_LOOP takes care of the final segment */
    2.19 -        --count;
    2.20 -        for (i = 0; i < count; ++i) {
    2.21 -            data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
    2.22 -        }
    2.23 -        data->glEnd();
    2.24 +        data->glDrawArrays(GL_LINE_LOOP, 0, count-1);
    2.25      } else {
    2.26 -#if defined(__APPLE__) || defined(__WIN32__)
    2.27 -#else
    2.28 -        int x1, y1, x2, y2;
    2.29 -#endif
    2.30 +        data->glDrawArrays(GL_LINE_STRIP, 0, count);
    2.31 +    }
    2.32 +    /* Make sure all the line endpoints are closed.
    2.33 +     * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
    2.34 +     * Which points need to be drawn varies by driver, so just draw all of them.
    2.35 +     */
    2.36 +    data->glDrawArrays(GL_POINTS, 0, count);
    2.37 +    data->glDisableClientState(GL_VERTEX_ARRAY);
    2.38 +    data->glTranslatef(-0.5f, -0.5f, 0.0f);
    2.39  
    2.40 -        data->glBegin(GL_LINE_STRIP);
    2.41 -        for (i = 0; i < count; ++i) {
    2.42 -            data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
    2.43 -        }
    2.44 -        data->glEnd();
    2.45 -
    2.46 -        /* The line is half open, so we need one more point to complete it.
    2.47 -         * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
    2.48 -         * If we have to, we can use vertical line and horizontal line textures
    2.49 -         * for vertical and horizontal lines, and then create custom textures
    2.50 -         * for diagonal lines and software render those.  It's terrible, but at
    2.51 -         * least it would be pixel perfect.
    2.52 -         */
    2.53 -        data->glBegin(GL_POINTS);
    2.54 -#if defined(__APPLE__) || defined(__WIN32__)
    2.55 -        /* Mac OS X and Windows seem to always leave the second point open */
    2.56 -        data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
    2.57 -#else
    2.58 -        /* Linux seems to leave the right-most or bottom-most point open */
    2.59 -        x1 = points[0].x;
    2.60 -        y1 = points[0].y;
    2.61 -        x2 = points[count-1].x;
    2.62 -        y2 = points[count-1].y;
    2.63 -
    2.64 -        if (x1 > x2) {
    2.65 -            data->glVertex2f(0.5f + x1, 0.5f + y1);
    2.66 -        } else if (x2 > x1) {
    2.67 -            data->glVertex2f(0.5f + x2, 0.5f + y2);
    2.68 -        } else if (y1 > y2) {
    2.69 -            data->glVertex2f(0.5f + x1, 0.5f + y1);
    2.70 -        } else if (y2 > y1) {
    2.71 -            data->glVertex2f(0.5f + x2, 0.5f + y2);
    2.72 -        }
    2.73 -#endif
    2.74 -        data->glEnd();
    2.75 -    }
    2.76      return GL_CheckError("", renderer);
    2.77  }
    2.78