SDL_RenderDrawLine endpoint inconsistency

SDL_RenderDrawLine is documented as drawing the line “to include both end points” and that’s exactly what I find it does when running on Windows (OpenGL renderer), Mac OS and Android. But on Linux (specifically Ubuntu because I haven’t had a chance to try it on anything else) it appears to draw the line exclusive of the end point, indeed if you specify the same coordinates for both the start point and the end point it draws nothing at all!

The same thing happens on two different PCs: one running 32-bit Ubuntu 16.04 and the other running 64-bit Ubuntu 16.04 in VirtualBox under Windows, so I’m assuming the graphics card is not to blame. The version of SDL is whatever is currently available from the Ubuntu repository.

I’m rather mystified by this inconsistency. Any thoughts as to the possible cause?

Richard.

Here’s a test case to demonstrate the issue. It should draw a white square on a blue background, with all four corner pixels drawn, and this is what happens in Windows and Mac OS. But in Linux (Ubuntu 16.04, SDL 2.0.4) it draws only two horizontal lines. Can somebody confirm this, or if they find it is working correctly report on what version of Linux/OpenGL/SDL they are using:

Code:
// Demo of SDL_RenderDrawLine endpoint behavior, R.T.Russell http://www.rtrussell.co.uk/

#include <stdio.h>
#include “SDL2_gfxPrimitives.h”

#define WIDTH 640
#define HEIGHT 480

int main(int argc, char* argv[])
{

if (SDL_Init(SDL_INIT_VIDEO)) 
{ 
    printf ("SDL_Init Error: %s", SDL_GetError()); 
    return 1; 
} 

SDL_SetHint (SDL_HINT_RENDER_DRIVER, "opengl") ;

SDL_Window *window = SDL_CreateWindow("SDL_RenderDrawLine test", 100, 100, WIDTH, HEIGHT, SDL_WINDOW_OPENGL); 
if (window == NULL) 
{ 
    printf ("SDL_CreateWindow Error: %s", SDL_GetError()); 
    SDL_Quit(); 
    return 2; 
} 

SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); 
if (renderer == NULL) 
{ 
    SDL_DestroyWindow(window); 
    printf ("SDL_CreateRenderer Error: %s", SDL_GetError()); 
    SDL_Quit(); 
    return 3; 
} 

SDL_Event e; 

int quit = 0; 
while (!quit) 
{
int i;
int w = WIDTH / 4;
int h = w;
int x = (WIDTH - w) / 2;
int y = (HEIGHT - h) / 2;

    if (SDL_PollEvent(&e)) 
    { 
        if (e.type == SDL_QUIT) 
            quit = 1; 
    } 
    SDL_SetRenderDrawColor(renderer, 0, 0, 0xFF, 0xFF); 
    SDL_RenderClear(renderer); 

    SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); 
SDL_RenderDrawLine(renderer, x, y, x + w, y);
SDL_RenderDrawLine(renderer, x, y + h, x + w, y + h);
for (i = y + 1; i < y + h; i++)
{
    SDL_RenderDrawLine(renderer, x, i, x, i) ;
    SDL_RenderDrawLine(renderer, x + w, i, x + w, i);
}    

    SDL_RenderPresent(renderer); 
    SDL_Delay(10); 
} 

SDL_DestroyRenderer(renderer); 
SDL_DestroyWindow(window); 
SDL_Quit(); 
return 0; 

}

Richard.

Since nobody has ventured an opinion I’ve looked at the source and there seems to be code specifically to make Linux behave differently; the trouble is, according to my tests, it makes Linux behave wrongly:

sdl_render_gl.c:
Code:
#if defined(MACOSX) || defined(WIN32)
/* Mac OS X and Windows seem to always leave the last point open /
data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
#else
/
Linux seems to leave the right-most or bottom-most point open */
x1 = points[0].x;
y1 = points[0].y;
x2 = points[count-1].x;
y2 = points[count-1].y;

    if (x1 > x2) {
        data->glVertex2f(0.5f + x1, 0.5f + y1);
    } else if (x2 > x1) {
        data->glVertex2f(0.5f + x2, 0.5f + y2);
    }
    if (y1 > y2) {
        data->glVertex2f(0.5f + x1, 0.5f + y1);
    } else if (y2 > y1) {
        data->glVertex2f(0.5f + x2, 0.5f + y2);
    }

#endif

It seems unlikely that OpenGL works differently on Linux by design so should this code still be in SDL?

Richard.

This dodgy code is still in SDL 2.0.10 and causes SDL_RenderDrawLine() to misbehave on every Linux platform I have tested. Checking bugzilla, there are several outstanding bugs affecting SDL_RenderDrawLine() but this doesn’t seem to be one of them. Should I add yet another bug report, or is there a likelihood that because of the number of issues it will be completely recoded in a future release?

Can I just say that it’s frustrating that this issue gets no attention. I’ve received a report today that small filled circles drawn by SDL2_gfx are the wrong shape on Linux, and I suspect this bug is directly responsible (filled circles and ellipses are drawn using a series of parallel lines).

I would expect that simply deleting the Linux special-case code would at least result in all platforms behaving consistenty if the same rendering back end is used (in my case OpenGL) .

You should report that to Bugzilla. had a similar issue that got no attention in the forums, but was fixed in a week once I created a bug. It’s even better for the devs if you can submit a patch.

Thanks for the suggestion, but I believe bug 2796 describes exactly the same issue, and that has not been addressed since being reported in 2014. There are other bugs related to SDL_RenderDrawLine() (2711 and 3162) and they too have not been fixed. So I’m not sure that adding what would probably be a duplicate report would be helpful.

Unfortunately I don’t know how to.

I have a similar king of bug. I’m using sdl 2.0.8 on ubuntu 18.04.
When drawing line with either RenderDrawLine (or RenderDrawLines), the last pixel at the end of the line is not aligned.

I have not yet tried to upgrade to the latest version of SDL, nor tried on Windows.

I have the exact same problem. I found that the software renderer draws the line correctly SDL_RENDERER_SOFTWARE:

drawline-results

For straight lines I’ve resorted to SDL_RenderDrawPoint.

2 Likes

Thanks ! I’ll try that =)

I’m using 2.0.10 on ubuntu 20.04, and having the same issue. Does anyone know if this was corrected in recent SDL versions?

The relevant bug at Bugzilla says “target-2.0.16” so I assume this means it won’t be fixed until that release at the earliest. I don’t know why it is proving such a difficult nut to crack, but it may be that the various rendering backends simply aren’t consistent in their behavior.

My workaround has been to use SDL_RenderDrawPoints() which whilst not ideal is faster than calling SDL_RenderDrawPoint() multiple times.

yes, this is what I did, too. (using SDL_RenderDrawPoints())
I agree with you that this bug should have high priority.

1 Like

It was originally reported in December 2014. Perhaps they are trying to set a record for the longest time to fix a bug (six years and counting…) :grinning:

Here is my own test. Interestingly, the color of the non-aligned pixel is from the previous line, not the current one. The whole width of the line (including the non-aligned pixel) is correct (here 51px)

Zoom:
lines

Code:
#include <SDL2/SDL.h>

int main()
{
 
    SDL_Init(SDL_INIT_VIDEO);

    SDL_Window * window = SDL_CreateWindow("SDL2 Line Drawing",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 500, 500, 0);

    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_SetRenderDrawBlendMode (renderer, SDL_BLENDMODE_BLEND);

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderClear(renderer);

    SDL_SetRenderDrawColor(renderer, 10, 10, 255, 255);
    SDL_RenderDrawLine(renderer, 200, 200, 250, 200); // OK
    SDL_RenderDrawLine(renderer, 250, 210, 200, 210); // NOT OK
    SDL_RenderDrawLine(renderer, 200, 180, 200, 150); // OK
    SDL_RenderDrawLine(renderer, 250, 150, 250, 180); // OK

    SDL_SetRenderDrawColor(renderer, 255, 10, 10, 255);
    SDL_RenderDrawLine(renderer, 200, 300, 250, 300); // NOT OK
    SDL_RenderDrawLine(renderer, 250, 310, 200, 310); // NOT OK

    SDL_SetRenderDrawColor(renderer, 10, 255, 10, 255);
    SDL_RenderDrawLine(renderer, 200, 400, 250, 400); // NOT OK
    SDL_RenderDrawLine(renderer, 250, 410, 200, 410); // NOT OK

    SDL_RenderPresent(renderer);

    SDL_Delay(10000);

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}


/*
gcc line.c -lSDL2 -lSDL2main -o line
*/

The relevant bug at Bugzilla says “target-2.0.16”

Sorry, this was fixed for 2.0.14, but the bug report got forgotten (rather, there were several duplicates, and we missed one that got sorted into target-2.0.16).

The new 2.0.14 release has this fixed across all render backends.

(sorry in my previous post was still linking with an old SDL version.)
So I have dowloaded the current version, and indeed the mis-aligned point has disappeared, but there is still a problem. When the lines are drawn from right to left, they are not the same as when they’re drawn from left to right: namely they are shifted 1 pixel to the left.

Ouch, that’s actually worse: a fault at both ends rather than just one. :frowning_face:
Although I suppose if the workaround is to reverse the drawing direction, that’s not so bad.

Well, that’s infuriating. I’ll take a look.