| Summary: | SDL_RenderSetViewport behavior is different/incorrect on OpenGL renderer vs DirectX renderer | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Andreas Schiffler <aschiffler> |
| Component: | render | Assignee: | 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 |
||
Created attachment 1404 [details]
DirectX renderer screenshot
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.
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?).
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? 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. (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. (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. Fixed more in this changeset: https://hg.libsdl.org/SDL/rev/0eed14683885 |
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