opengl: Backed out hg changeset 0c915d307499
authorRyan C. Gordon
Mon, 17 Feb 2020 16:15:04 -0500
changeset 135364ba421b1e88f
parent 13535 dbcccb065928
child 13537 97d093e10ac7
opengl: Backed out hg changeset 0c915d307499

This is the OpenGL line drawing fix for Bugzilla #3182, but there's some
disagreement about what the renderers should do here, so I'm backing this out
until after 2.0.12 ships, and then we'll reevaluate all the renderer backends
to decide what's correct, and make them all work the same.
src/render/opengl/SDL_render_gl.c
src/render/opengles/SDL_render_gles.c
src/render/opengles2/SDL_render_gles2.c
     1.1 --- a/src/render/opengl/SDL_render_gl.c	Mon Feb 17 16:11:18 2020 -0500
     1.2 +++ b/src/render/opengl/SDL_render_gl.c	Mon Feb 17 16:15:04 2020 -0500
     1.3 @@ -866,60 +866,6 @@
     1.4  }
     1.5  
     1.6  static int
     1.7 -GL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
     1.8 -{
     1.9 -    GLfloat *verts;
    1.10 -    int i;
    1.11 -
    1.12 -    SDL_assert(count >= 2);  /* should have been checked at the higher level. */
    1.13 -
    1.14 -    verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, (count-1) * 4 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    1.15 -    if (!verts) {
    1.16 -        return -1;
    1.17 -    }
    1.18 -
    1.19 -    cmd->data.draw.count = count;
    1.20 -
    1.21 -    /* GL_LINE_STRIP seems to be unreliable on various drivers, so try
    1.22 -       to build out our own GL_LINES.  :(
    1.23 -       If the line segment is completely horizontal or vertical,
    1.24 -       make it one pixel longer, to satisfy the diamond-exit rule.
    1.25 -       We should probably do this for diagonal lines too, but we'd have to
    1.26 -       do some trigonometry to figure out the correct pixel and generally
    1.27 -       when we have problems with pixel perfection, it's for straight lines
    1.28 -       that are missing a pixel that frames something and not arbitrary
    1.29 -       angles. Maybe !!! FIXME for later, though. */
    1.30 -
    1.31 -    for (i = 0; i < count-1; i++, points++) {
    1.32 -        GLfloat xstart = 0.5f + points[0].x;   /* 0.5f to get to the center of the pixel. */
    1.33 -        GLfloat ystart = 0.5f + points[0].y;
    1.34 -        GLfloat xend = 0.5f + points[1].x;
    1.35 -        GLfloat yend = 0.5f + points[1].y;
    1.36 -
    1.37 -        if (xstart == xend) {  /* vertical line */
    1.38 -            if (yend > ystart) {
    1.39 -                yend += 1.0f;
    1.40 -            } else {
    1.41 -                ystart += 1.0f;
    1.42 -            }
    1.43 -        } else if (ystart == yend) {  /* horizontal line */
    1.44 -            if (xend > xstart) {
    1.45 -                xend += 1.0f;
    1.46 -            } else {
    1.47 -                xstart += 1.0f;
    1.48 -            }
    1.49 -        }
    1.50 -
    1.51 -        *(verts++) = xstart;
    1.52 -        *(verts++) = ystart;
    1.53 -        *(verts++) = xend;
    1.54 -        *(verts++) = yend;
    1.55 -    }
    1.56 -
    1.57 -    return 0;
    1.58 -}
    1.59 -
    1.60 -static int
    1.61  GL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
    1.62  {
    1.63      GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    1.64 @@ -1282,14 +1228,59 @@
    1.65              case SDL_RENDERCMD_DRAW_LINES: {
    1.66                  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
    1.67                  const size_t count = cmd->data.draw.count;
    1.68 -                SDL_assert(count >= 2);
    1.69                  SetDrawState(data, cmd, SHADER_SOLID);
    1.70 -                data->glBegin(GL_LINES);
    1.71 -                for (i = 0; i < count-1; ++i, verts += 4) {
    1.72 -                    data->glVertex2f(verts[0], verts[1]);
    1.73 -                    data->glVertex2f(verts[2], verts[3]);
    1.74 +                if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
    1.75 +                    data->glBegin(GL_LINE_LOOP);
    1.76 +                    /* GL_LINE_LOOP takes care of the final segment */
    1.77 +                    for (i = 1; i < count; ++i, verts += 2) {
    1.78 +                        data->glVertex2f(verts[0], verts[1]);
    1.79 +                    }
    1.80 +                    data->glEnd();
    1.81 +                } else {
    1.82 +                    #if defined(__MACOSX__) || defined(__WIN32__)
    1.83 +                    #else
    1.84 +                    int x1, y1, x2, y2;
    1.85 +                    #endif
    1.86 +
    1.87 +                    data->glBegin(GL_LINE_STRIP);
    1.88 +                    for (i = 0; i < count; ++i, verts += 2) {
    1.89 +                        data->glVertex2f(verts[0], verts[1]);
    1.90 +                    }
    1.91 +                    data->glEnd();
    1.92 +                    verts -= 2 * count;
    1.93 +
    1.94 +                    /* The line is half open, so we need one more point to complete it.
    1.95 +                     * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
    1.96 +                     * If we have to, we can use vertical line and horizontal line textures
    1.97 +                     * for vertical and horizontal lines, and then create custom textures
    1.98 +                     * for diagonal lines and software render those.  It's terrible, but at
    1.99 +                     * least it would be pixel perfect.
   1.100 +                     */
   1.101 +
   1.102 +                    data->glBegin(GL_POINTS);
   1.103 +                    #if defined(__MACOSX__) || defined(__WIN32__)
   1.104 +                    /* Mac OS X and Windows seem to always leave the last point open */
   1.105 +                    data->glVertex2f(verts[(count-1)*2], verts[(count*2)-1]);
   1.106 +                    #else
   1.107 +                    /* Linux seems to leave the right-most or bottom-most point open */
   1.108 +                    x1 = verts[0];
   1.109 +                    y1 = verts[1];
   1.110 +                    x2 = verts[(count-1)*2];
   1.111 +                    y2 = verts[(count*2)-1];
   1.112 +
   1.113 +                    if (x1 > x2) {
   1.114 +                        data->glVertex2f(x1, y1);
   1.115 +                    } else if (x2 > x1) {
   1.116 +                        data->glVertex2f(x2, y2);
   1.117 +                    }
   1.118 +                    if (y1 > y2) {
   1.119 +                        data->glVertex2f(x1, y1);
   1.120 +                    } else if (y2 > y1) {
   1.121 +                        data->glVertex2f(x2, y2);
   1.122 +                    }
   1.123 +                    #endif
   1.124 +                    data->glEnd();
   1.125                  }
   1.126 -                data->glEnd();
   1.127                  break;
   1.128              }
   1.129  
   1.130 @@ -1628,7 +1619,7 @@
   1.131      renderer->QueueSetViewport = GL_QueueSetViewport;
   1.132      renderer->QueueSetDrawColor = GL_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
   1.133      renderer->QueueDrawPoints = GL_QueueDrawPoints;
   1.134 -    renderer->QueueDrawLines = GL_QueueDrawLines;
   1.135 +    renderer->QueueDrawLines = GL_QueueDrawPoints;  /* lines and points queue vertices the same way. */
   1.136      renderer->QueueFillRects = GL_QueueFillRects;
   1.137      renderer->QueueCopy = GL_QueueCopy;
   1.138      renderer->QueueCopyEx = GL_QueueCopyEx;
     2.1 --- a/src/render/opengles/SDL_render_gles.c	Mon Feb 17 16:11:18 2020 -0500
     2.2 +++ b/src/render/opengles/SDL_render_gles.c	Mon Feb 17 16:15:04 2020 -0500
     2.3 @@ -562,60 +562,6 @@
     2.4  }
     2.5  
     2.6  static int
     2.7 -GLES_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
     2.8 -{
     2.9 -    GLfloat *verts;
    2.10 -    int i;
    2.11 -
    2.12 -    SDL_assert(count >= 2);  /* should have been checked at the higher level. */
    2.13 -
    2.14 -    verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, (count-1) * 4 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    2.15 -    if (!verts) {
    2.16 -        return -1;
    2.17 -    }
    2.18 -
    2.19 -    cmd->data.draw.count = count;
    2.20 -
    2.21 -    /* GL_LINE_STRIP seems to be unreliable on various drivers, so try
    2.22 -       to build out our own GL_LINES.  :(
    2.23 -       If the line segment is completely horizontal or vertical,
    2.24 -       make it one pixel longer, to satisfy the diamond-exit rule.
    2.25 -       We should probably do this for diagonal lines too, but we'd have to
    2.26 -       do some trigonometry to figure out the correct pixel and generally
    2.27 -       when we have problems with pixel perfection, it's for straight lines
    2.28 -       that are missing a pixel that frames something and not arbitrary
    2.29 -       angles. Maybe !!! FIXME for later, though. */
    2.30 -
    2.31 -    for (i = 0; i < count-1; i++, points++) {
    2.32 -        GLfloat xstart = 0.5f + points[0].x;   /* 0.5f to get to the center of the pixel. */
    2.33 -        GLfloat ystart = 0.5f + points[0].y;
    2.34 -        GLfloat xend = 0.5f + points[1].x;
    2.35 -        GLfloat yend = 0.5f + points[1].y;
    2.36 -
    2.37 -        if (xstart == xend) {  /* vertical line */
    2.38 -            if (yend > ystart) {
    2.39 -                yend += 1.0f;
    2.40 -            } else {
    2.41 -                ystart += 1.0f;
    2.42 -            }
    2.43 -        } else if (ystart == yend) {  /* horizontal line */
    2.44 -            if (xend > xstart) {
    2.45 -                xend += 1.0f;
    2.46 -            } else {
    2.47 -                xstart += 1.0f;
    2.48 -            }
    2.49 -        }
    2.50 -
    2.51 -        *(verts++) = xstart;
    2.52 -        *(verts++) = ystart;
    2.53 -        *(verts++) = xend;
    2.54 -        *(verts++) = yend;
    2.55 -    }
    2.56 -
    2.57 -    return 0;
    2.58 -}
    2.59 -
    2.60 -static int
    2.61  GLES_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
    2.62  {
    2.63      GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    2.64 @@ -955,10 +901,16 @@
    2.65              case SDL_RENDERCMD_DRAW_LINES: {
    2.66                  const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
    2.67                  const size_t count = cmd->data.draw.count;
    2.68 -                SDL_assert(count >= 2);
    2.69                  SetDrawState(data, cmd);
    2.70                  data->glVertexPointer(2, GL_FLOAT, 0, verts);
    2.71 -                data->glDrawArrays(GL_LINES, 0, (GLsizei) ((count-1) * 2));
    2.72 +                if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
    2.73 +                    /* GL_LINE_LOOP takes care of the final segment */
    2.74 +                    data->glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) (count - 1));
    2.75 +                } else {
    2.76 +                    data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
    2.77 +                    /* We need to close the endpoint of the line */
    2.78 +                    data->glDrawArrays(GL_POINTS, (GLsizei) (count - 1), 1);
    2.79 +                }
    2.80                  break;
    2.81              }
    2.82  
    2.83 @@ -1207,7 +1159,7 @@
    2.84      renderer->QueueSetViewport = GLES_QueueSetViewport;
    2.85      renderer->QueueSetDrawColor = GLES_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
    2.86      renderer->QueueDrawPoints = GLES_QueueDrawPoints;
    2.87 -    renderer->QueueDrawLines = GLES_QueueDrawLines;
    2.88 +    renderer->QueueDrawLines = GLES_QueueDrawPoints;  /* lines and points queue vertices the same way. */
    2.89      renderer->QueueFillRects = GLES_QueueFillRects;
    2.90      renderer->QueueCopy = GLES_QueueCopy;
    2.91      renderer->QueueCopyEx = GLES_QueueCopyEx;
     3.1 --- a/src/render/opengles2/SDL_render_gles2.c	Mon Feb 17 16:11:18 2020 -0500
     3.2 +++ b/src/render/opengles2/SDL_render_gles2.c	Mon Feb 17 16:15:04 2020 -0500
     3.3 @@ -784,60 +784,6 @@
     3.4  }
     3.5  
     3.6  static int
     3.7 -GLES2_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
     3.8 -{
     3.9 -    GLfloat *verts;
    3.10 -    int i;
    3.11 -
    3.12 -    SDL_assert(count >= 2);  /* should have been checked at the higher level. */
    3.13 -
    3.14 -    verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, (count-1) * 4 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    3.15 -    if (!verts) {
    3.16 -        return -1;
    3.17 -    }
    3.18 -
    3.19 -    cmd->data.draw.count = count;
    3.20 -
    3.21 -    /* GL_LINE_STRIP seems to be unreliable on various drivers, so try
    3.22 -       to build out our own GL_LINES.  :(
    3.23 -       If the line segment is completely horizontal or vertical,
    3.24 -       make it one pixel longer, to satisfy the diamond-exit rule.
    3.25 -       We should probably do this for diagonal lines too, but we'd have to
    3.26 -       do some trigonometry to figure out the correct pixel and generally
    3.27 -       when we have problems with pixel perfection, it's for straight lines
    3.28 -       that are missing a pixel that frames something and not arbitrary
    3.29 -       angles. Maybe !!! FIXME for later, though. */
    3.30 -
    3.31 -    for (i = 0; i < count-1; i++, points++) {
    3.32 -        GLfloat xstart = 0.5f + points[0].x;   /* 0.5f to get to the center of the pixel. */
    3.33 -        GLfloat ystart = 0.5f + points[0].y;
    3.34 -        GLfloat xend = 0.5f + points[1].x;
    3.35 -        GLfloat yend = 0.5f + points[1].y;
    3.36 -
    3.37 -        if (xstart == xend) {  /* vertical line */
    3.38 -            if (yend > ystart) {
    3.39 -                yend += 1.0f;
    3.40 -            } else {
    3.41 -                ystart += 1.0f;
    3.42 -            }
    3.43 -        } else if (ystart == yend) {  /* horizontal line */
    3.44 -            if (xend > xstart) {
    3.45 -                xend += 1.0f;
    3.46 -            } else {
    3.47 -                xstart += 1.0f;
    3.48 -            }
    3.49 -        }
    3.50 -
    3.51 -        *(verts++) = xstart;
    3.52 -        *(verts++) = ystart;
    3.53 -        *(verts++) = xend;
    3.54 -        *(verts++) = yend;
    3.55 -    }
    3.56 -
    3.57 -    return 0;
    3.58 -}
    3.59 -
    3.60 -static int
    3.61  GLES2_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
    3.62  {
    3.63      GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    3.64 @@ -1348,10 +1294,17 @@
    3.65              }
    3.66  
    3.67              case SDL_RENDERCMD_DRAW_LINES: {
    3.68 +                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
    3.69                  const size_t count = cmd->data.draw.count;
    3.70 -                SDL_assert(count >= 2);
    3.71                  if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
    3.72 -                    data->glDrawArrays(GL_LINES, 0, (GLsizei) ((count-1) * 2));
    3.73 +                    if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
    3.74 +                        /* GL_LINE_LOOP takes care of the final segment */
    3.75 +                        data->glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) (count - 1));
    3.76 +                    } else {
    3.77 +                        data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
    3.78 +                        /* We need to close the endpoint of the line */
    3.79 +                        data->glDrawArrays(GL_POINTS, (GLsizei) (count - 1), 1);
    3.80 +                    }
    3.81                  }
    3.82                  break;
    3.83              }
    3.84 @@ -2146,7 +2099,7 @@
    3.85      renderer->QueueSetViewport    = GLES2_QueueSetViewport;
    3.86      renderer->QueueSetDrawColor   = GLES2_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
    3.87      renderer->QueueDrawPoints     = GLES2_QueueDrawPoints;
    3.88 -    renderer->QueueDrawLines      = GLES2_QueueDrawLines;
    3.89 +    renderer->QueueDrawLines      = GLES2_QueueDrawPoints;  /* lines and points queue vertices the same way. */
    3.90      renderer->QueueFillRects      = GLES2_QueueFillRects;
    3.91      renderer->QueueCopy           = GLES2_QueueCopy;
    3.92      renderer->QueueCopyEx         = GLES2_QueueCopyEx;