Skip to content

Implement scaled fullscreen #1821

@slipher

Description

@slipher

Rendering at a resolution lower than the screen resolution can be desirable if your hardware is too feeble to cope with so many pixels. With SDL2, under certain circumstances, you could pick a lower resolution, and have it automatically stretched to cover the whole screen. But with the SDL2 to SDL3 migration, we lost the ability to use true full-screen modes: SDL3 defaults to always using a full-screen window instead of true fullscreen. (True fullscreen is still supposed to be possible, but you have to use a different API which we don't do.) If you select a resolution lower than the display resolution in SDL3, no scaling is done, and the renderable area is anchored to the bottom left, which is just unusable. See Unvanquished/Unvanquished#2870 for some discussion of positioning the renderable area better, regardless of scaling.

That's not to say that the situation was great in SDL2. Only certain video backends and particular resolutions would produce a reasonable result. The resolution list that we show in the UI is ostensibly a list of fullscreen modes, but most of them produced bad results. Even some of the ones with an aspect matching the display still didn't work well. But with some resolutions having a matching aspect you could get a nice scaled result... if you were using Windows or an x11 compositor. If the underlying compositor was Wayland, it never worked regardless of x11 or Wayland protocol. For unsupported compositors or resolutions, a lot of times you just got the bottom-left anchoring, same as SDL3. Windows did some combination of scaling, letterboxing, and bottom-left anchoring. Hilariously, with certain resolutions you could get all 3 at once: some black bars were cleared on the left and right sides, and the output was scaled up somewhat, but it was still smaller than the remaining rectangle; the left side of the viewport was anchored to the left side's black bar.

Idea 1: reimplement full-screen modes

We could use SDL3's APIs to try to configure true fullscreen modes. A supposed advantage of this is improving performance by bypassing layers of compositing on certain systems. But this heavily depends on whether the fullscreen modes actually work. If support is as patchy as it was in SDL2, I consider this a waste of time.

Idea 2: 3D rendering resolution != final resolution

Make a cvar, say r_3dRenderingScale, to configure a scale factor for the 3D rendering FBOs relative to the final resolution. If you have 1920x1080 resolution and set r_3dRenderingScale 0.5 then 3D rendering would be done at 960x540. The cameraEffects shader would scale up the result as it is copied into the final framebuffer. Then 2D rendering would be done at the final resolution. Something cool with this is maybe we could use r_3dRenderingScale greater than 1 as a form of full screen supersampling antialiasing.

Other ideas:

  • Do all rendering including 2D at a reduced resolution, then scale it up as the very last step. But it's not appealing to have to copy everything yet again, since the point is to improve performance.
  • Try to get the OS's compositor to scale it up for us. Clearly this is a function they all have in some form, since each OS has some sort of "high DPI" upscaling mechanism. But I don't know whether there are APIs to control this.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions