| Summary: | New support for controlling the scaling policy/mode of SDL_RenderSetLogicalSize for both letterbox and overscan | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Eric wing <ewmailing> |
| Component: | render | Assignee: | Ryan C. Gordon <icculus> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | dm2, icculus |
| Version: | 2.0.3 | ||
| Hardware: | All | ||
| OS: | All | ||
|
Description
Eric wing
2014-12-03 12:56:48 UTC
Hello Eric, First of all, thanks you very much for your patch, it is quite useful for people that wanted to use the overscan method over the default and unique letterboxing method. I have tried your patch in current SDL2 code (as of 31-March-2016) and it worked fine for: - Software - Direct3D 11 - OpenGL but with standard Direct3D, all I got is a black screen. I have tested it on Windows 10 and 7, 32 and 64 bits modes and with AMD/Nvidia cards just for discarding a configuration issue, but the same issue on all configuration. I know a lot of time since your post but if by any chance you can help with this issue, it will be great!! Thanks! Roberto Hi again, Well, after checking the code it seems that the guilty is Direct3D 9 as the view port is using unsigned int so no negative values can be passed to it the changes made for the "overscan" method used negative values... OpenGL and Direct3D 11 allow the viewport to be negative... Cheers Roberto Thank you for discovering and isolating this problem. I admit I'm not a Direct3D guru, so I was wondering if you had any ideas on how we can workaround this problem for D3D9. I would like to fix this if possible. Also, how do you force select D3D9 vs. D3D11? Hi Eric,
As you are modifying the viewport for performing the overscan method, I think it can not be implemented on Direct3D 9:
typedef struct _D3DVIEWPORT9 {
DWORD X;
DWORD Y; /* Viewport Top left */
DWORD Width;
DWORD Height; /* Viewport Dimensions */
float MinZ; /* Min/max of clip Volume */
float MaxZ;
} D3DVIEWPORT9;
Being DWORD=unsigned int
Unless you find a workaround for doing the same without using the viewport, it wont work on Direct3D 9. I spent some time "googling" but didnt find anything that could help.
For using Direct3D 11, you have to enable this flag on SDL_config_windows.h:
SDL_VIDEO_RENDER_D3D11 1
and SDL2 will be using it as a renderer. Then, in your code, when creating the renderer:
SDL_CreateRenderer(windows, 1, 0);
Usually, the order is 0 for d3d9, 1 for d3d11, 2 for opengl.
This renderer only works on Windows 8+, I have an article on my blog explaining why (http://www.megastormsystems.com/sdl/sdl2-direct3d11-renderer-and-windows-7).
Hope you can find an alternative way of doing it without using viewports or someone else with more knowledge of Direct3D can show us how to "emulate" a viewport with negative values..
Cheers
Roberto
Thank you for investigating all this. This is really good information. So here are my thoughts, though as I said, I am not a D3D guru, so if you know how to actually implement this or see a problem with this idea, I'd like your help. 1) We add a runtime check for Direct3D inside SDL when the overscan hint is requested. If it is D3D 11 or more, we allow the overscan hint to work as before. (I'm not sure how to do a runtime check on this since you are setting a compile flag.) 2) If we detect D3D 9 (or less?), then we can either: 2a) ignore the hint and say it is not supported or 2b) We try to do something with the projection matrix. I found this function via Google: D3DXMatrixOrthoOffCenterLH. I'm thinking we can leave the viewport alone, and zoom in the orthographic projection. The major downside I see to this (besides the extra complexity of figuring out how to actually do this), is that I think we can only do this for the SDL 2D renderer. We must not interfere with anybody who is directly requesting a D3D context and using it directly. Presumably this call would screw up their own projection matrix. (I don't know offhand if it is actually possible to screw up somebody else's D3D context in SDL since they are probably separate instances and set active at different times, but I want to be confident we don't create some weird/broken subtle interaction bug between the two systems.) What do you think? Do you have any expertise on the right incantations to do this? First, I pushed a fix to my original overscan repo/patch that checks for Direct3D 9 and ignores the overscan hint/mode for that case. This will avoid the black screen problem. The request that this be accepted into mainline continues. https://bitbucket.org/ewing/sdl_overscan Second, I tried some experiments to implement overscan for D3D9, but it hasn't worked so well. I tried two different techniques, 1) setting the orthographic projection matrix to zoom in to the correct area (adjusting for aspect ratio) 2) setting a modelview matrix basically to scale everything In the first case, I thought this idea would be easy...just set the orthographic rect to the region you want to look at and I thought things would just workout, but it's not working out that way. You can kind of see the idea, but the specifics are wonky. Shrinking the window works better than growing it. But in my tests, not everything seems to be centered around the same origin. Some things are centered, but I see other things misaligned sometimes. In the second case, I tried to change a modelview matrix and basically just scale everything. Since overscan basically just scales until everything fits the screen, I thought this might be an alternative path. This one works a little bit better, however I think this approach is actually less sound than the projection matrix. One problem is that there is no global modelview matrix and seems to be on a per-RenderCopyEx basis. (I hacked RenderCopy to go to RenderCopyEx in the D3D version.) So each object gets transformed separately. I noticed for large window sizes, some of my objects felt like they were bunching up. Also, I was having trouble keeping the screen centered. I kind of got that working in the shrink case, but it breaks on the grow case. In both cases, there are some other problems. First culling/clipping seems to be happening, and in a different coordinate system than what I'm showing. So for example, if you make the window small, things on the edge of the screen seem to get prematurely culled. Additionally, both of these cases do not affect the mouse coordinates. So if you are trying to click some object, the coordinates are not lining up. I'm not sure where this code is. But since I didn't need to muck with it before, I assume it is tied with the viewport settings. So I feel stuck at the moment. I'm posting my (hacky) changes in another repo if you or anybody else wants to play with this. hg push ssh://hg@bitbucket.org/ewing/sdl_overscan_d3d9_experiments There are two Mercurial bookmarks "overscan_d3d9_projection" and "overscan_d3d9_modelview" I picked the wrong link to copy. This is a better link to find my experiments repo. https://bitbucket.org/ewing/sdl_overscan_d3d9_experiments Hi Eric, The way I am using SDL2 is through a high-level library which wrap and extend the functionality. As the D3D9 code path for the overscan is not working, I am just disabling it when the user asked for it. In my case, it does not hurt to much as for Windows 8+, I am using D3D11 and for Android/Linux/MacOS X, OpenGL code path is used. As you see, in my case at least, no real rush for having a functional D3D9 code. I now it is a pity not having it using a clean way but is the D3D9 which imposes the restriction of not having negative values on the viewport. Hacking too much around the SDL2 source code for getting it, IMHO does not worth it. Unfortunately, my D3D knowledge is very limited so I could not help you. I really appreciate your efforts for trying to fix it and probably your 2 alternatives solution could help someone else. For me, your patches were really important and they will use for sure :) Thanks you very much Eric! Cheers Roberto This patch is now https://hg.libsdl.org/SDL/rev/8a29b371e2db, thanks! --ryan. |