Fixed bug 2421 - SDL_RenderCopyEx off by one when rotating by 90 and -90
authorSam Lantinga <slouken@libsdl.org>
Mon, 07 Jul 2014 23:26:34 -0700
changeset 8993bc47cf4c679d
parent 8992 6d5b8a8752ce
child 8994 b80b0595975c
Fixed bug 2421 - SDL_RenderCopyEx off by one when rotating by 90 and -90

chasesan

When using SDL_RenderCopyEx, I get a problem on some platforms where the output is offset by +/-1 on other platforms and not on others. I tried it with a center of both 0,0 (and offsetting by width/height) and NULL (for centered).

The rotation involved is 90, and/or -90 rotation. The rotation was a constant, no arithmetic was involved when inputting it into SDL_RenderCopyEx.

This occurred with 32x32, 24x24, and 16x16 texture sizes. I apologize that I don't have more precise information, as I received the information as a bug report myself. But I have tracked the problem down to here.

My program requires pixel perfect alignment on several different platforms, so this is something of a showstopper for me.

--

Sylvain

It appears the RenderCopyEx is done as expected,
this is the red rectangle which is not correctly positionned !

So, here's patch with a 0.5 float increment, like for opengles2, for DrawLines, and also Draw Points.
src/render/opengles/SDL_render_gles.c
     1.1 --- a/src/render/opengles/SDL_render_gles.c	Mon Jul 07 21:34:04 2014 -0700
     1.2 +++ b/src/render/opengles/SDL_render_gles.c	Mon Jul 07 23:26:34 2014 -0700
     1.3 @@ -814,12 +814,24 @@
     1.4                        int count)
     1.5  {
     1.6      GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
     1.7 +    GLfloat *vertices;
     1.8 +    int idx;
     1.9  
    1.10      GLES_SetDrawingState(renderer);
    1.11  
    1.12 -    data->glVertexPointer(2, GL_FLOAT, 0, points);
    1.13 +    /* Emit the specified vertices as points */
    1.14 +    vertices = SDL_stack_alloc(GLfloat, count * 2);
    1.15 +    for (idx = 0; idx < count; ++idx) {
    1.16 +        GLfloat x = points[idx].x + 0.5f;
    1.17 +        GLfloat y = points[idx].y + 0.5f;
    1.18 +
    1.19 +        vertices[idx * 2] = x;
    1.20 +        vertices[(idx * 2) + 1] = y;
    1.21 +    }
    1.22 +
    1.23 +    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
    1.24      data->glDrawArrays(GL_POINTS, 0, count);
    1.25 -
    1.26 +    SDL_stack_free(vertices);
    1.27      return 0;
    1.28  }
    1.29  
    1.30 @@ -828,10 +840,22 @@
    1.31                       int count)
    1.32  {
    1.33      GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
    1.34 +    GLfloat *vertices;
    1.35 +    int idx;
    1.36  
    1.37      GLES_SetDrawingState(renderer);
    1.38  
    1.39 -    data->glVertexPointer(2, GL_FLOAT, 0, points);
    1.40 +    /* Emit a line strip including the specified vertices */
    1.41 +    vertices = SDL_stack_alloc(GLfloat, count * 2);
    1.42 +    for (idx = 0; idx < count; ++idx) {
    1.43 +        GLfloat x = points[idx].x + 0.5f;
    1.44 +        GLfloat y = points[idx].y + 0.5f;
    1.45 +
    1.46 +        vertices[idx * 2] = x;
    1.47 +        vertices[(idx * 2) + 1] = y;
    1.48 +    }
    1.49 +
    1.50 +    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
    1.51      if (count > 2 &&
    1.52          points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
    1.53          /* GL_LINE_LOOP takes care of the final segment */
    1.54 @@ -842,6 +866,7 @@
    1.55          /* We need to close the endpoint of the line */
    1.56          data->glDrawArrays(GL_POINTS, count-1, 1);
    1.57      }
    1.58 +    SDL_stack_free(vertices);
    1.59  
    1.60      return 0;
    1.61  }