We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2207

Summary: SDL_RenderSetViewport behavior is different/incorrect on OpenGL renderer vs DirectX renderer
Product: SDL Reporter: Andreas Schiffler <aschiffler>
Component: renderAssignee: Ryan C. Gordon <icculus>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2    
Version: 2.0.1   
Hardware: x86_64   
OS: Windows 7   
Attachments: OpenGL renderer screenshot
DirectX renderer screenshot
testviewport.c
Simplified test program

Description Andreas Schiffler 2013-11-03 18:30:12 UTC
Created attachment 1403 [details]
OpenGL renderer screenshot

SDL2_gfx's test program "testgfx" checks clipping and viewport setup by making calls to SDL_RenderSetViewport() for 4 different screen areas. 

/* viewport border */
#define BORDER	10
...
/* Set a viewport based on a rect with a border */
void SetViewport(SDL_Renderer *renderer, int x1, int y1, int x2, int y2)
{ 
	SDL_Rect clip;
	clip.x = x1+BORDER;
	clip.y = y1+BORDER;
	clip.w = x2-x1-2*BORDER;
	clip.h = y2-y1-2*BORDER;
	SDL_RenderSetViewport(renderer, &clip);
}

When using the DirectX renderer this results in correct behavior (similar to SDL_gfx surface based implementatin). When switching to the OpenGL renderer, the behavior is not correct anymore as the pixels seem to be offset (incorrect location). 

Screenshots of both cases are attached.

Repro procedure in Win7 box: 
- Build and install SDL
- Build and install SDL2_gfx
- Build SDL2_gfx\test
- Run testgfx.exe
- Run testgfx.exe --renderer OpenGL
Comment 1 Andreas Schiffler 2013-11-03 18:30:39 UTC
Created attachment 1404 [details]
DirectX renderer screenshot
Comment 2 Andreas Schiffler 2013-11-13 04:18:54 UTC
Created attachment 1425 [details]
testviewport.c

Test program showing the behavior of Viewport.
$ gcc -o testviewport.exe testviewport.c -g -O2 -I/usr/local/include/SDL2 -I/usr/include/mingw -Dmain=SDL_main -DHAVE_OPENGL -g -lSDL2_test -L/usr/local/lib -lcygwin -lSDL2main -lSDL2 -mwindows

Run for example with:
 ./testviewport.exe --renderer direct3d
 ./testviewport.exe --renderer software
 ./testviewport.exe --renderer opengl

Recommend to add this to the set of included test programs for future verification.
Comment 3 Andreas Schiffler 2013-11-13 04:25:19 UTC
I think that I found the issue: when a viewport is applied against the OpenGL renderer, the origin and orientation is OpenGL-style (i.e. 0,0 is bottom left screen pixel) vs. DirectX/Software style (i.e. 0,0 is top left pixel). This flip causes the rendering differences seen in my screenshots.

The attached test programs shows it even more clearly.

GL_UpdateViewport() seems to have some code that tries to flip the y-coordinate:

        if (renderer->target) {
            data->glOrtho((GLdouble) 0,
                          (GLdouble) renderer->viewport.w,
                          (GLdouble) 0,
                          (GLdouble) renderer->viewport.h,
                           0.0, 1.0);
        } else {
            data->glOrtho((GLdouble) 0,
                          (GLdouble) renderer->viewport.w,
                          (GLdouble) renderer->viewport.h,
                          (GLdouble) 0,
                           0.0, 1.0);
        }

but in either code path, the output is the same (manually tested) and incorrect. Presumably glOrtho's matrix setup is not doing the flip (could it even?).
Comment 4 Sam Lantinga 2013-11-15 06:31:31 UTC
Hey Ryan, can you take a look at this? I thought I did the right thing here when I originally implemented it. Is there a bug, or did I just totally miss it somehow?
Comment 5 Ryan C. Gordon 2013-11-15 15:17:46 UTC
Created attachment 1447 [details]
Simplified test program

(In reply to Sam Lantinga from comment #4)
> Hey Ryan, can you take a look at this? I thought I did the right thing here
> when I originally implemented it. Is there a bug, or did I just totally miss
> it somehow?

Just for the sake of simplification, here's a modified test program that alternates between drawing a box at the top of the screen and then at the bottom.

This appears to do the right thing on Mac OS X between the GL and software renderer...Did I simplify the problem out?

--ryan.
Comment 6 Ryan C. Gordon 2013-11-15 15:19:20 UTC
(In reply to Ryan C. Gordon from comment #5)
> This appears to do the right thing on Mac OS X between the GL and software
> renderer...Did I simplify the problem out?

Oh, wait, this is totally upside down in the original test program...what the heck?

Checking.

--ryan.
Comment 7 Ryan C. Gordon 2013-11-16 04:25:14 UTC
(In reply to Andreas Schiffler from comment #3)
> GL_UpdateViewport() seems to have some code that tries to flip the
> y-coordinate:

Yeah, I think this got specified backwards when render targets were added, or something like that.

Fixed in https://hg.libsdl.org/SDL/rev/6558e2b68c03

--ryan.
Comment 8 Sam Lantinga 2013-11-16 06:23:24 UTC
Fixed more in this changeset:
https://hg.libsdl.org/SDL/rev/0eed14683885