Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL_RenderDrawLine gives different results on different render backends #1626

Closed
SDLBugzilla opened this issue Feb 10, 2021 · 7 comments
Closed
Assignees
Milestone

Comments

@SDLBugzilla
Copy link
Collaborator

SDLBugzilla commented Feb 10, 2021

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: HG 2.0
Reported for operating system, platform: All, All

Comments on the original bug report:

On 2014-09-01 16:23:27 +0000, Nicolae Berendea wrote:

When I draw a blended line using SDL_RenderDrawLine, the last pixel gets drawn twice so it will not have the desired color.

SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(renderer, 0, 255, 255, 128);
SDL_RenderDrawLine(renderer, 100, 100, 100, 100+100);
SDL_RenderPresent(renderer);
SDL_Delay(1000);

On 2014-09-13 14:03:15 +0000, Nader Golbaz wrote:

What does this code do? It seems unnecessary.
from D3D_RenderDrawLines:

    /* DirectX 9 has the same line rasterization semantics as GDI,
       so we need to close the endpoint of the line */
    if (count == 2 ||
        points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
        vertices[0].x = points[count-1].x;
        vertices[0].y = points[count-1].y;
        result = IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, vertices, sizeof(*vertices));
    }

On 2014-09-15 07:27:36 +0000, Nicolae Berendea wrote:

Something similar is used to draw circles by the sdl_gfx library. So when I use aacircleRGBA (function that draws a blended circle), it has points with different color on its circumference.

On 2018-07-07 09:53:11 +0000, Björn Sundin wrote:

This bug still exists, please fix it.

On 2020-01-23 21:00:45 +0000, Nicolae Berendea wrote:

So, I looked into the implementation of SDL_RenderDrawLine. As Nader said, it draws the line from point a to b and then it draws another point at the end of the line (point b).
On both of my machines, the line is complete without drawing the last point - so the last point will be drawn twice thus changing color when using alpha channel.
On a virtual machine, the line is incomplete (it is missing point b) so it is necessary to draw an additional point as in the code.
Is it possible to differentiate between machines so the lines are drawn correctly in both environments?

The vm is running windows7x64. One of my machines has windows7x64; the other one windows10x64.

On 2020-02-10 18:06:37 +0000, Ryan C. Gordon wrote:

Nicolae, I don't know if the fix in Bug # 3182 will fix this too, but please test with the latest in revision control when you get a moment and let me know.

--ryan.

On 2020-02-11 17:11:29 +0000, Nicolae Berendea wrote:

Created attachment 4203
test.cpp

On 2020-02-11 17:24:03 +0000, Nicolae Berendea wrote:

Created attachment 4204
failed test picture

On 2020-02-11 17:48:50 +0000, Nicolae Berendea wrote:

I've tested again. Indeed the fix doesn't work for this issue.

The issue is in the direct3d renderers. There is a point added at the end of the line.
https://hg.libsdl.org/SDL/file/3d991f099f58/src/render/direct3d/SDL_render_d3d.c#l1367
https://hg.libsdl.org/SDL/file/3d991f099f58/src/render/direct3d11/SDL_render_d3d11.c#l2274

Sometimes that point is necessary (e.g. in my vm the line is drawn fine) but not always depending on the hardware (I think).

On 2020-02-12 07:32:15 +0000, Sam Lantinga wrote:

Ryan, I think your fix needs to be extended to the D3D renderers as well.

On 2020-02-12 20:14:56 +0000, Ryan C. Gordon wrote:

*** Bug 4976 has been marked as a duplicate of this bug. ***

On 2020-02-12 20:15:28 +0000, Ryan C. Gordon wrote:

*** Bug 3182 has been marked as a duplicate of this bug. ***

On 2020-02-17 21:17:29 +0000, Ryan C. Gordon wrote:

I've backed out the recent OpenGL fix with this commit:

https://hg.libsdl.org/SDL/rev/4ba421b1e88f

...and changed this bug to target-2.0.14. Once 2.0.12 ships, we'll re-merge this patch, decide what every renderer backend should do, and work on making them all work identically.

--ryan.

On 2020-10-26 03:18:55 +0000, Anthony @ POW Games wrote:

Created attachment 4485
GLES lines slightly off

Ryan, I've just tested the latest GLES line merge on my Windows 10 Intel HD Graphics system and the lines are slightly off. Software renderer is perfect. DX3D is OKish (it draws the last pixel twice - been that way for a while now), GL is perfect, but GLES the lines are off, being drawn 1 pixel too far forward, or too far back. Attached picture demonstrates a box being drawn using SDL_RenderDrawLinesF starting top-left and moving clockwise.

On 2020-10-27 00:28:08 +0000, Anthony @ POW Games wrote:

Also tested on Android and the same happens with GLES lines.

On 2020-11-14 02:55:40 +0000, Anthony @ POW Games wrote:

OpenGL and GLES lines now behave as expected (Tested on Windows & Android), thanks Ryan - I bet you'll be glad to see the back of this topic, lol.

All that remains is what the OP posted: DX3D drawing the last pixel twice - it only affects the last line in an array of lines. It's not a deal breaker for me personally, but I can see how it can cause problems for some.

On 2020-11-18 16:06:05 +0000, Ryan C. Gordon wrote:

(In reply to Anthony @ POW Games from comment # 15)

All that remains is what the OP posted: DX3D drawing the last pixel twice -
it only affects the last line in an array of lines. It's not a deal breaker
for me personally, but I can see how it can cause problems for some.

Weird, I thought this was fixed, too. I'll check that again.

--ryan.

@icculus icculus added this to the 2.0.18 milestone Aug 11, 2021
icculus added a commit that referenced this issue Sep 19, 2021
…derer.

One place known to differ in a significant way is a single line segment that
starts and ends on the same point; the GL renderers will light up a single
pixel here, whereas the software renderer will not. My current belief is this
is a bug in the software renderer, based on the wording of the docs:

"SDL_RenderDrawLine() draws the line to include both end points."

You can see an example program that triggers that difference in Bug #2006.

As it stands, the GL renderers might _also_ render diagonal lines differently,
as the the Bresenham step might vary between implementations (one does three
pixels and then two, the other does two and then three, etc). But this patch
causes those lines to start and end on the correct pixel, and that's the best
we can do, and all anyone really needs here.

Not closing any bugs with this patch (yet!), but here are several that it
appears to fix. If no other corner cases pop up, we'll call this done.

Reference Bug #2006.
Reference Bug #1626.
Reference Bug #4001.
...and probably others...
@icculus
Copy link
Collaborator

icculus commented Sep 19, 2021

OpenGL and GLES renderers should be improved here, in the latest in revision control. Any corner cases that remain (or are caused by this patch), PLEASE report them asap, as we would like this to be solid and never thought about again by the time 2.0.18 ships.

Thanks!

@icculus icculus self-assigned this Sep 23, 2021
@LoneFox78
Copy link

The GL renderer still draws lines one pixel shorter than the software one, missing the end point.

Relevant specs: Ryzen 2400G built-in GPU, Linux, X11, Mesa 21.2.2, SDL latest git snapshot (commit ce66051b0a).

@icculus
Copy link
Collaborator

icculus commented Sep 24, 2021

It's definitely not doing it here...

software:
software

opengl:
opengl

Are we really just going to have to draw a block of GL_POINTS to make this work everywhere?

@icculus
Copy link
Collaborator

icculus commented Sep 24, 2021

The modified test program I'm using, which dumps out the render to a .bmp for each render driver:

#include <SDL.h>

int main(int argc, char* argv[])
{
	int posX = 100, posY = 100, width = 320, height = 240;

    SDL_Init(SDL_INIT_VIDEO);
   int num = SDL_GetNumRenderDrivers();
    for (int i = 0; i < num; i++) {
    	SDL_Window* win = SDL_CreateWindow("Hello World", posX, posY, width, height, 0);
	    SDL_Renderer* renderer = SDL_CreateRenderer(win, i, 0);

        SDL_RendererInfo info;
             SDL_GetRendererInfo(renderer, &info);
             SDL_Log("renderer[%d] %s", i, info.name);

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

    	SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
    	SDL_SetRenderDrawColor(renderer, 0, 255, 255, 128);
    	SDL_RenderDrawLine(renderer, 100, 100, 100, 100 + 100);

        SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, 800, 800, 32, SDL_PIXELFORMAT_RGB888);
          SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_RGB888, surface->pixels, 800 * 4);
          char fname[32];
          SDL_snprintf(fname, sizeof (fname), "%s.bmp", info.name);
          SDL_SaveBMP(surface, fname);
          SDL_FreeSurface(surface);

    	SDL_RenderPresent(renderer);
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(win);
    }

	//SDL_Delay(10000);
    SDL_Quit();

	return 0;
}

You'll have an "opengl.bmp", "opengles2.bmp", "software.bmp" etc when it finishes running.

@LoneFox78
Copy link

On my desktop, the GL renderers draw the line one pixel shorter than the software one.

On my laptop, which has an older AMD APU that uses the r600 Mesa driver instead of radeonsi, the line is always the same length, but there is a lot of random junk around it. I guess the test program should call SDL_RenderClear(renderer) before drawing the line.

So, does this mean the bug is actually in the radeonsi Mesa driver?

@icculus
Copy link
Collaborator

icculus commented Sep 30, 2021

I guess the test program should call SDL_RenderClear(renderer) before drawing the line.

Yeah, that's a bug in the test program. I'm going to edit the comment to add it to the source code.

So, does this mean the bug is actually in the radeonsi Mesa driver?

Possibly. Might just be a rounding error working out in one place and not another. I'll check my math again.

@icculus
Copy link
Collaborator

icculus commented Nov 27, 2021

Okay, closing this with several other bugs.

@icculus icculus closed this as completed Nov 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants