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

GL_RenderDrawLines drops pixels on Linux/Unix #1700

Closed
SDLBugzilla opened this issue Feb 10, 2021 · 3 comments
Closed

GL_RenderDrawLines drops pixels on Linux/Unix #1700

SDLBugzilla opened this issue Feb 10, 2021 · 3 comments
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: Linux, x86_64

Comments on the original bug report:

On 2014-12-01 05:55:24 +0000, Andreas Schiffler wrote:

GL_RenderDrawLines (and similar functions) has custom code that handles the "open point" case differently depending on platform. This seems to cause issues on newer versions of Linux (in my case: Linux Mint 17.1 on x86 with radeon rendered, see version info below).

Detection is easy with the testautomation render suite:

./testautomation --info render --seed 02BZFAAR8A8MQAHA --filter render_testPrimitives
...
Current renderer:
Renderer opengl:
Flags: 0x0000000A (Accelerated | 0x00000008)
Texture formats (5): ARGB8888, YV12, IYUV, NV12, NV21
Max Texture Size: 2048x2048
INFO: 11/30/14 20:11:17: ::::: Test Run /w seed '02BZFAAR8A8MQAHA' started
INFO: 11/30/14 20:11:17: Filtering: running only test 'render_testPrimitives' in suite 'Render'
...
ERROR: 11/30/14 20:11:18: Comparison of pixels with allowable error of 0 failed 1 times.
ERROR: 11/30/14 20:11:18: First detected occurrence at position 50,30 with a squared RGB-difference of 33550.
ERROR: 11/30/14 20:11:18: Surfaces from failed comparison saved as 'CompareSurfaces0001_TestOutput.bmp' and 'CompareSurfaces0001_Reference.bmp'
...

When analyzing the images, the difference is a missing pixel for the last line rendered in the sequence:

test/testautomation_render.c
...

   ret = SDL_RenderDrawLine(renderer, 79, 0, 50, 29 );
   SDLTest_AssertCheck(ret == 0, "Validate result from SDL_RenderDrawLine, expected: 0, got: %i", ret);

   ret = SDL_RenderDrawLine(renderer, 79, 59, 50, 30 );
   SDLTest_AssertCheck(ret == 0, "Validate result from SDL_RenderDrawLine, expected: 0, got: %i", ret);

   /* Make current */
   SDL_RenderPresent(renderer);

   /* See if it's the same. */
   referenceSurface = SDLTest_ImagePrimitives();
   _compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE );

...

The cause is the following code (with the invalid code on this platform commented out) in src/render/opengl/SDL_render_gl.c:

        data->glBegin(GL_POINTS);
#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
/* Standard code fixes test case */
        data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);

        /* Linux seems to leave the right-most or bottom-most point open */
/* Original code breaks test case
        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
        data->glEnd();

Other rendering platforms were also affected in the same way on this platform.
Linux shuttlebox 3.13.0-37-generic # 64-Ubuntu SMP Mon Sep 22 21:30:01 UTC 2014 i686 i686 i686 GNU/Linux
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
OpenGL vendor string: X.Org R300 Project
OpenGL renderer string: Gallium 0.4 on ATI RV350
OpenGL version string: 2.1 Mesa 10.1.3
OpenGL shading language version string: 1.20

On 2014-12-01 05:57:32 +0000, Andreas Schiffler wrote:

Created attachment 1948
Reference image

On 2014-12-01 05:58:00 +0000, Andreas Schiffler wrote:

Created attachment 1949
Test output image

On 2020-02-24 00:18:59 +0000, Juan wrote:

The same here, February 2020.

In Arch Linux with Qt Creator, I followed a tutorial from the LazyFoo site and also encountered this problem.

A pixel appears after drawing a line and that loose pixel is the same color as the last line drawn.


OS: Arch Linux x86_64
Kernel: 5.5.5-zen1-1-zen
Resolution: 1280x1024
WM: i3
CPU: Intel Celeron G1610 (2) @ 2.600GHz
GPU: Intel HD Graphics
Memory: 4895MiB

Vendor: Intel Open Source Technology Center (0x8086)
Device: Mesa DRI Intel(R) Ivybridge Desktop (0x152)
Version: 19.3.4
Accelerated: yes
Video memory: 1536MB
Unified memory: yes
Preferred profile: core (0x1)
Max core profile version: 4.2
Max compat profile version: 3.0
Max GLES1 profile version: 1.1
Max GLES[23] profile version: 3.0

gcc versión 9.2.1 20200130 (Arch Linux 9.2.1+20200130-2)

Qt Creator 4.11.1 - Based on Qt 5.14.1 (GCC 9.2.0, 64 bit)


Makefile, for the command line:

#OBJS specifies which files to compile as part of the project
OBJS = main.cpp

#CC specifies which compiler we're using
CC = g++

#COMPILER_FLAGS specifies the additional compilation options we're using
# -w suppresses all warnings
COMPILER_FLAGS = -w

#LINKER_FLAGS specifies the libraries we're linking against
LINKER_FLAGS = -lSDL2 -lSDL2_image

#OBJ_NAME specifies the name of our exectuable
OBJ_NAME = executable

#This is the target that compiles our executable
all : $(OBJS)
	$(CC) $(OBJS) $(COMPILER_FLAGS) $(LINKER_FLAGS) -o $(OBJ_NAME)

Configuration in the .pro file of Qt Creator:

TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += \
        main.cpp

LIBS += `sdl2-config --cflags --libs`

Example used:

/*This source code copyrighted by Lazy Foo' Productions (2004-2020)
and may not be redistributed without written permission.*/


//Using SDL, SDL_image, standard IO, math, and strings
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#include <string>
#include <cmath>


//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;


//Starts up SDL and creates window
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
//Loads individual image as texture
SDL_Texture* loadTexture( std::string path );


//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;


bool init()
{
	//Initialization flag
	bool success = true;

	//Initialize SDL
	if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
	{
		printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
		success = false;
	}
	else
	{
		//Set texture filtering to linear
		if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
		{
			printf( "Warning: Linear texture filtering not enabled!" );
		}

		//Create window
		gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
		if( gWindow == NULL )
		{
			printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
			success = false;
		}
		else
		{
			//Create renderer for window
			gRenderer = SDL_CreateRenderer( gWindow, -1, SDL_RENDERER_ACCELERATED );
			if( gRenderer == NULL )
			{
				printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
				success = false;
			}
			else
			{
				//Initialize renderer color
				SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );

				//Initialize PNG loading
				int imgFlags = IMG_INIT_PNG;
				if( !( IMG_Init( imgFlags ) & imgFlags ) )
				{
					printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
					success = false;
				}
			}
		}
	}

	return success;
}


bool loadMedia()
{
	//Loading success flag
	bool success = true;

	//Nothing to load
	return success;
}


void close()
{
	//Destroy window	
	SDL_DestroyRenderer( gRenderer );
	SDL_DestroyWindow( gWindow );
	gWindow = NULL;
	gRenderer = NULL;

	//Quit SDL subsystems
	IMG_Quit();
	SDL_Quit();
}


SDL_Texture* loadTexture( std::string path )
{
	//The final texture
	SDL_Texture* newTexture = NULL;

	//Load image at specified path
	SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
	if( loadedSurface == NULL )
	{
		printf( "Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError() );
	}
	else
	{
		//Create texture from surface pixels
        newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface );
		if( newTexture == NULL )
		{
			printf( "Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
		}

		//Get rid of old loaded surface
		SDL_FreeSurface( loadedSurface );
	}

	return newTexture;
}


int main( int argc, char* args[] )
{
	//Start up SDL and create window
	if( !init() )
	{
		printf( "Failed to initialize!\n" );
	}
	else
	{
		//Load media
		if( !loadMedia() )
		{
			printf( "Failed to load media!\n" );
		}
		else
		{	
			//Main loop flag
			bool quit = false;

			//Event handler
			SDL_Event e;

			//While application is running
			while( !quit )
			{
				//Handle events on queue
				while( SDL_PollEvent( &e ) != 0 )
				{
					//User requests quit
					if( e.type == SDL_QUIT )
					{
						quit = true;
					}
				}

				//Clear screen
				SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
				SDL_RenderClear( gRenderer );

				//Render red filled quad
				SDL_Rect fillRect = { SCREEN_WIDTH / 4, SCREEN_HEIGHT / 4, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 };
				SDL_SetRenderDrawColor( gRenderer, 0xFF, 0x00, 0x00, 0xFF );		
				SDL_RenderFillRect( gRenderer, &fillRect );

				//Render green outlined quad
				SDL_Rect outlineRect = { SCREEN_WIDTH / 6, SCREEN_HEIGHT / 6, SCREEN_WIDTH * 2 / 3, SCREEN_HEIGHT * 2 / 3 };
				SDL_SetRenderDrawColor( gRenderer, 0x00, 0xFF, 0x00, 0xFF );		
				SDL_RenderDrawRect( gRenderer, &outlineRect );
				
				//Draw blue horizontal line
				SDL_SetRenderDrawColor( gRenderer, 0x00, 0x00, 0xFF, 0xFF );		
				SDL_RenderDrawLine( gRenderer, 0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT / 2 );

				//Draw vertical line of yellow dots
				SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0x00, 0xFF );
				for( int i = 0; i < SCREEN_HEIGHT; i += 4 )
				{
					SDL_RenderDrawPoint( gRenderer, SCREEN_WIDTH / 2, i );
				}

				//Update screen
				SDL_RenderPresent( gRenderer );
			}
		}
	}

	//Free resources and close SDL
	close();

	return 0;
}

On 2020-02-24 00:26:00 +0000, Juan wrote:

I sorry, the configuration of the .pro file of Qt Creator is this.


TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += \
        main.cpp

LIBS += -lSDL2_image `sdl2-config --cflags --libs`

On 2020-04-15 22:11:04 +0000, Florian D wrote:

(In reply to Juan from comment # 3)

The same here, February 2020.

Like you I see the last pixel not aligned with the line. Using SDL 2.0.8 on ubuntu 18.04, I will try with the latest sdl and see if it remains the same.

On 2020-04-15 22:13:18 +0000, Florian D wrote:

Created attachment 4308
Scrrenshot of the bug, the last pixel appears shifted

On 2020-04-16 21:25:46 +0000, Juan wrote:

(In reply to Florian D from comment # 6)

Created attachment 4308 [details]
Scrrenshot of the bug, the last pixel appears shifted

I used SDL 2.0.12-1 on Arch Linux. But yes. It is the same behavior.

@icculus icculus added this to the 2.0.18 milestone Aug 11, 2021
@icculus
Copy link
Collaborator

icculus commented Aug 11, 2021

Another one of these. Gonna close a bunch of these as dupes.

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

icculus commented Sep 23, 2021

This is confirmed fixed with the latest in revision control, but I'm leaving this open and in my test suite until we decide we're solid everywhere.

@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

2 participants