Skip to content
This repository has been archived by the owner on Jun 8, 2022. It is now read-only.

RFC: Fullscreen rendering with configurable aspect ratio #1080

Closed
wants to merge 22 commits into from

Conversation

Botje
Copy link
Member

@Botje Botje commented Aug 29, 2014

This is my proposal to enable ResidualVM to work on monitors/drivers/OSes that no longer allow switching to 640x480.
In the shader-based renderer (and only there, for now), the game is first rendered to a framebuffer and later pushed to the screen.
You can configure how this is done using the fullscreen_mode parameter per-game.

There are four options.
Assuming your desktop resolution is 1920x1080, and the game wants a 640x480 window, these are:

  • native: This is the current way of rendering, 640x480 resolution, no framebuffer.
  • center: The game is rendered as a 640x480 rectangle in the center of your 1920x1080 display.
  • scale: The game is rendered to 640x480 and scaled up to an integer multiple that still fits. For the given resolutions, a 1280x960 rectangle in the center of your 1920x1080 display.
  • stretch: The game is rendered at 640x480 and stretched to fill your 1920x1080 display.

If you think this approach could work, I'll look into expanding it to use GL_EXT_framebuffer_object for OpenGL 1.4.

@aquadran
Copy link
Member

I don't know why you called configurable aspect ratio since you don't do that, at least I don't see it in the code, I would call it fullscreen scaler modes.

I like "modes" idea instead resolutions, however not all from it.
"stretch" mode is ok and no comments are needed here.
"center" mode is also ok, but rather minor in usage, but still option for some.
"native" mode should be removed, it's not controllable result. This path might be internally in generic fallback, but not an option for user.
"scale" mode most important I would expect actually scale not something between "center" and scale to fullscreen.
I would expect scale to width or height of native/desktop resolution which is closer.
Of course this could be additional mode, but lack of this make not sense for me as whole.

Please explore rendering using this extension which might be solution for us.

Rendering to texture in OpenGLS I guess is fine.

About whole framework I know it's just make some solution for fullscreen issues, but you should know that is not direction I would see here. Might be solution for time being to get proper framework.

And TinyGL also need support this.

This PR is about fullscreen, but what about window mode ?
it should be together with that changes.
All modes for fullscreen mode will work here too.

On another topic, but related to this changes, I don't like idea moving more and more OpenGL/GLS code there, why not use similar approach with code in "graphics/opengles2" and make "graphics/opengl" for helper functions. Also move some existed parts from SDL surface file if possible to that dirs. also probably from android backend too.

@somaen
Copy link
Member

somaen commented Aug 30, 2014

IMHO, TinyGL internally doesn't need to support scaling (internally), as long as we allow for some scaling (where possible) of the final frame buffer atleast (which is similar to rendering to an FBO anyhow).

return 1;
--k;

for (uint i = 1; i < sizeof(T) * 8; i <<= 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, loops should always have braces.

@FabioPedretti
Copy link

Can we render at native or arbitrary resolution? IIRC it was possible manually changing variables currently set to 640 and 480.

@Botje
Copy link
Member Author

Botje commented Aug 30, 2014

@FabioPedretti:
This PR always renders the game to a texture at its native resolution (640x480) and then renders that texture to screen. The focus here is on keeping the native monitor resolution (1920x1080). Arbitrary resolutions are out of the scope for now.

@aquadran:
I made scale use an integer scale because I was not sure what it would look like. Going to full-width or full-height is a one-line change.
I'll give the OpenGL framebuffer extension a shot.
As for your other points: I haven't considered TinyGL at all.
For windowed mode you either need a target resolution or a scaling factor, which could be the input to the framebuffer, but that's a different PR.

@@ -40,26 +53,53 @@ static bool usePackedBuffer() {
return true;
}

FrameBuffer::FrameBuffer(GLuint texture_name, uint width, uint height, uint texture_width, uint texture_height) : _colorTexture(texture_name), _width(width), _height(height) {
FrameBuffer::FrameBuffer(uint width, uint height)
: _managedTexture(true), _width(width), _height(height),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatting: initializers should not be at same level as code

@aquadran
Copy link
Member

"For windowed mode you either need a target resolution or a scaling factor, which could be the input to the frame buffer" this statement is in conflict with this PR where the same thing can work too.
That would also confusing with mixed options.

This could be:
"your scale"/"max scale factor" to find integer scale factor, the same as for fullscreen.
"full scale" full-width/height,
"no scale" renamed from "center", to just place in center in fullscreen and nothing in window mode
"scale2x", "scale3x" for integer 2x,3x scaler factors, they can works with fullscreen and window mode.
maybe even dynamically created list of scale factors based on desktop resulution.
"stretch" just the same as fullscreen.

Still not sure about your case "native", it doesn't make much sense for HW accelarated scaling, but in case software, turn off for some might be an option because of speed, like speed issues in AmigaOS4 port.
It could be exception in code for "no scale" mode and use native (640x480) fullscreen or even for all software rendered not just Amiga case, since rendering small bitmap in center of screen make no sense for me at all.

I see this PR only with included window mode too.
And TinyGL must be too.

@bgK
Copy link
Member

bgK commented Aug 31, 2014

Excellent idea. I would keep it as is, with:

  • "scale" changed to extend to the max screen width or height, whatever comes first
  • "scale" as the default mode
  • Maybe with an added option to disable bilinear filtering for the FBO texture. This added to the game textures filtering makes Myst III very blurry.

Regarding the current implementation, I am experiencing the following issues (mesa/r600g):

  • The first image of the game is rendered (say the menu for Myst III), but does not update ...
  • ... unless I trigger the debug console
  • The overlay is rendered below the game screen
  • OSystem::getHeight and OSystem::getWidth return the actual fullscreen resolution. I wonder if this is correct. At least it confuses the mouse coordinates scaling code in Myst III that was designed to support arbitrary resolutions.

APITrace does not show any error.

@aquadran
Copy link
Member

@bgK option for filtering might be indeed needed even for TinyGL case.
And remember it's temporary solution and also one step forward, our target is to make engines works with any resolutions.

@somaen
Copy link
Member

somaen commented Aug 31, 2014

Doesn't this, for the fullscreen case atleast, boil down to:

  • Whether or not any scaling should happen (if no, that's what center does)
  • Whether or not the aspect should be respected (scale vs stretch).

For windowed mode, I can see having other settings (like integer multiple), but for fullscreen?

@aquadran
Copy link
Member

different options for fullscreen and for window make mess in config and handling switching fullscreen<->window mode. That require two sets of configs, two sets of defaults, two ways GUI options handle. Unified options which works for both make more sense for me. I'm pointing cases when for us something make not much sense, but for users it is. Like stretch mode which some prefer. All options can work for both if we allow it.

@somaen
Copy link
Member

somaen commented Aug 31, 2014

Yes, it boils down to how to layout this in configuration. Stretch is basically a question of "maintain aspect ratio", which could easily be a checkbox setting (and thus make sense both for windowed and fullscreen with the same setting). The bigger question is how we would allow users to select scale factor for windowed, while having a sensible possibility of "fill the screen (possibly with pillboxes)" for fullscreen.

Since the resolution necessary to do so depends on the desktop resolution (or our ability to change it in the case of fullscreen), and that scaling anywhere between 640x480 and filling the screen is a use case that is useless for fullscreen, I'd suggest this:

  • Setting to enable/disable "maintain aspect ratio".
  • Setting to enable/disable "scaling"
  • Setting to set scale factor.

In fullscreen, if scaling is enabled, then the scale factor should be ignored, and filling the screen is the behavior that should happen (possibly stretching). If maintain aspect is also enabled, then we should only scale by the same factor in both directions, and the factor should be the one that (as bgk says) fills whichever comes first of height/width, but no more.

If however we are in windowed mode, then the user selected scale factor takes precedence.

Another alternative, would be to expose actual resolutions to the user, as well as the maintain aspect setting. (Which we will want anyhow, to allow the users to override any problematic screen setups, so that they ALWAYS have the possibility of getting pillarboxes, as that aspect is how the game was designed to be played).

@Botje Botje changed the title RFC: Fullscreen rendering with configuratioble aspect ratio RFC: Fullscreen rendering with configurable aspect ratio Sep 3, 2014
@Botje
Copy link
Member Author

Botje commented Sep 11, 2014

These patches make it work on OpenGL as well, and make scaling take up all of the smallest dimension, leading to pillarboxing.
I did not have time to look at the other issues you brought up, but I agree with hiding native, and making scale the default.

@Botje
Copy link
Member Author

Botje commented Sep 19, 2014

I think this is the behavior @somaen and @bgK suggested.
It only uses one parameter aspect_ratio that determines whether to scale or stretch in fullscreen.
The scale used in windowed mode should be determined by the engine, then.

This does leave the comments about OSystem::{getWidth,getHeight}, not sure what to do about these ..

@bgK
Copy link
Member

bgK commented Sep 20, 2014

Regarding OSystem::{getWidth,getHeight}, the actual resolution makes no sense from the perspective of an engine. Therefore IMO we should return the game screen resolution.

I've pushed some changes building upon this PR to this branch:

@Botje, you may or may not want to include some of these commits here.

Together @Botje's changes, merging would be fine with me once falling back to mode setting is implemented.

@@ -260,17 +296,17 @@ Graphics::PixelBuffer SurfaceSdlGraphicsManager::setupScreen(uint screenW, uint
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &glflag);
debug("INFO: OpenGL Stencil buffer bits: %d", glflag);

#ifdef USE_OPENGL_SHADERS
debug("INFO: GLSL version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why you moved out USE_OPENGL_SHADERS out of include GLEW code ?

@Botje
Copy link
Member Author

Botje commented Oct 15, 2014

If there are no more comments I'll do a final round of testing with all variations I can think of, push my aspect-ratio-rebased branch, and close this issue.

@aquadran
Copy link
Member

this is not full functional implementation, it lacks of tinygl support

@aquadran
Copy link
Member

is aspect ratio button disabled for non fullscreen mode ?

@giucam
Copy link
Contributor

giucam commented Oct 15, 2014

this is not full functional implementation, it lacks of tinygl support

I think that can be done in a separate PR, the OpenGL implementation can be introduced without breaking TinyGL, as long as TinyGL is still doing something sane and not crashing or whatever.
If Botje is not willing to implement this feature in TinyGL it doesn't make sense imho to withdraw the OpenGL implementation because of that. Him or someone else can implement it later.

@aquadran
Copy link
Member

I don't agree. if this will not be implemented this stay open at it is, until missing feature is implemented on separated PR

@giucam
Copy link
Contributor

giucam commented Oct 15, 2014

Why? Are you willing to implement it?
Users are asking for configurable aspect ratio, this PR implements that for a very high percentage of them. What's the point in not merging it because there are still some users who will not be able to use it (provided they actually need it, which i'm not so sure)?

@aquadran
Copy link
Member

"Why? Are you willing to implement it?" please don't start with that, I didn't started this PR. This PR not describe only OpenGL/ES2. I'm not accepting this as only because "don't know" or "willing not do that". This is not impossible or hard. It's not even showing try implementing.
For second this project is not about support only support high percentage users from some area.
I would not block it if I saw some interest of implementing it, but so far I don't see any.

@giucam
Copy link
Contributor

giucam commented Oct 15, 2014

You are throwing away good code and a working feature. The "Are you willing to implement it?" was an honest question. Botje has all the rights to not wanting to write that, on the other hand this PR works. If you keep this line this feature may never come to ResidualVM, for any renderer.

@aquadran
Copy link
Member

I'm not throwing any code but holding it until this feature will be fully workable. I'm not telling him write any code. But I can block any code if this doesn't fit proper quality/functionality. I prefer something finished not half done imported into main code.

@giucam
Copy link
Contributor

giucam commented Oct 15, 2014

What makes you think there will ever be a TinyGL implementation? It may even be impossible or require changes too massive to be worth it.
This problem has been known for years, it's pretty clear nobody is willing to implement it. Botje has been working hard on this, let's not demoralize him by being overly strict.
Assuming a miracle happens and someone in the future wants to implement it for TinyGL, merging this now will not require him to rebase it on top of the future master, with who knows how many conflicts and additional work.

@aquadran
Copy link
Member

"What makes you think there will ever be a TinyGL implementation? It may even be impossible or require changes too massive to be worth it." Why so negative statements? "ever", "not possible", "not worth it".
Yes, I'm gonna be strict on this. And it's not really overly strict as you see, it's typical thing when adding core features in mature projects. I'm not ignoring his work on this PR, I think PR turn out to be something good, but not fully completed as I see due lack of TinyGL support.

@Botje
Copy link
Member Author

Botje commented Oct 15, 2014

Look, I agree with striving for feature parity when it comes to engines and renderers.
But who in 2014 is losing out due to not being able to run the software renderer fullscreen on a monitor that no longer supports 640x480?

@aquadran
Copy link
Member

@Botje So, in that kind of thinking why keep TinyGL because small range of people use it? We could also remove classic OpenGL renderer, why we bother use version below 3.0. we could also drop SDL1 for SDL2, Why we bother about amigos4 users? Due percentage we could also drop OS X and linux, since mostly are Windows users. in that kind of thinking why RE EMI, since it works on windows.

@Botje
Copy link
Member Author

Botje commented Oct 15, 2014

I'm not advocating the removal of TinyGL. I just don't see the point in holding back something that people on the forum have asked about several times because it does not improve the experience for a completely hypothetic situation.

@somaen
Copy link
Member

somaen commented Oct 15, 2014

To be completely fair, full feature parity with regards to scaling will NEVER happen at all, for TinyGL the only thing that might make sense, without slowing everything down quite a bit, would perhaps be a nearest neighbour 2x/3x-solution.

Overall, I personally think that allowing scaling in TinyGL is a bit separate from allowing it in OpenGL, especially if we have any kind of requirement of speed on it. (For instance, accelerated scaled blitting on platforms that allow it, is ENTIRELY out of scope for this discussion). At some points, TinyGL simply can't keep up successfully with OpenGL, which is quite clear, HOWEVER, in this case, I'd say this:

The major issue is that we have:

  • Users that don't have OpenGL
  • A need for testing when users have broken OpenGL.
  • Users that don't have 640x480-support, but still would like to get a bit more than a letter AND pillarboxed window.

The solution to this, might be to simply have a different mode where the TinyGL buffer is scaled by SDL, allowing for it to fill the screen. We might even be able to speed this up a tad by leveraging the Dirty-rect-rect when talking to SDL, so that SDL doesn't need to do a full blit every time it updates.

So, if we're not doing any sort of scaling, same thing as now, if TinyGL needs to be scaled, we handle it SDL-side?

Other than that, I can see the that TinyGL-scaling could be handled as a separate issue from this PR in itself, as the code doesn't touch at all. ScummVM has different degrees of scaling available depending on renderer too (OpenGL allows arbitrary window-sizes, the various software-scalers allow only 2/3/4(?)x, where some only allow 2x).

@aquadran
Copy link
Member

"people on the forum have asked about several times " I don't want answer for that here on public channel. I have always simple answer for that.

@aquadran
Copy link
Member

@somaen in my case OpenGL drivers are broken, lighting is wrong, so for proper draw I need use software renderer, fortunately OS make aspect ratio on system in fullscreen.
I don't require make this PR. But I'm not happy about lack of interest implement things fully. If this will be merged, then even more lack of interest after.
Scaler is not really difficult, but rather speed, which is hardly to predict, and it also relative, but CPUs are faster every day.

@somaen
Copy link
Member

somaen commented Oct 15, 2014

Well, the speed vs CPU-developments question is a bit problematic, most of the platforms where OpenGL isn't working, are also platforms where the CPUs are in the slower end of the scale. For platforms with faster CPUs, there is likely to be decent OpenGL-support too (and thus more relevant to fix the issues with the drivers in OpenGL).

Overall, this boils down to whether anyone wants to fix the TinyGL-case to allow for consistent scaling. (Speed is atleast completely out of scope for THIS discussion).

So, if this is merged without TinyGL changes, then we have a system where we get:

  • Scaling on OpenGL user-configurable
  • TinyGL filling the screen IF the operating system happens to allow for (faking) 640x480, where it will completely ignore any aspect-ratio setting.

I can understand that that is a bit partial, but consider the current scenario, where ALL renderers end up doing what TinyGL does now (leaving it up to the OS). Thus, this PR is an improvement, without moving TinyGL backwards in any other way than adding an option it ignores.

I suggest the following compromise: We merge this, thus allowing for it to be fully tested before any release. Then we can perhaps discuss what is enabled in the release, depending on whether we can make TinyGL decently consistent with the options.

@Botje
Copy link
Member Author

Botje commented Oct 15, 2014

There. It compiles and runs.

@somaen
Copy link
Member

somaen commented Oct 15, 2014

I just compiled and tested with EMI:

OpenGL: alt-enter switches mode, and does fill the screen, but switching back to window, I get a buggy window with the font data displayed all over the screen, instead of the game window (it's also problematic that the enter-call gets passed through to the game).

This might stem from issues with how the engine SWITCHES between fullscreen and windowed.

TinyGL: Switching to fullscreen, I get a tiny window, then nothing ever gets updated when I switch back.

@aquadran
Copy link
Member

@somaen "most of the platforms where OpenGL isn't working, are also platforms where the CPUs are in the slower end of the scale" this is wrong statement, GPU and CPU are not correlated. you can have decent platform with strong CPU but broken or lack proper driver.

@Botje
Copy link
Member Author

Botje commented Oct 15, 2014

I have no idea which path the code takes when you hit alt-enter or why it's behaving so weird.
Anyway, my aspect-ratio-rebased branch is updated again.

@Botje
Copy link
Member Author

Botje commented Oct 17, 2014

That should fix switching between windowed and full screen.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants