Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display scaling, live window resizing, and high-DPI support #113

Closed
wants to merge 6 commits into from

Conversation

Projects
None yet
6 participants
@past-due
Copy link
Contributor

commented Jan 27, 2018

Trac: #4720

Overview

  1. Internal enhancements to support screen / game / rendering scaling factors.
  2. Internal enhancements to support live window resizing / resolution changes.
  3. Internal enhancements to support UI layout recalculation.
  4. Support for live window resizing / resolution changes.[SDL backend]
  5. "Display Scale" option in the Video options menu, offering 100%+ display scaling options. [SDL backend]
  6. Automatic high-DPI ("retina") display support. [macOS-only]
  7. Better caching of text rasterization and reduction in unnecessary OpenGL state changes (required to support higher display scaling levels).
  8. Better clipping and other small tweaks (required to support higher display scaling levels).

General

These changes all essentially depend on each other, thus this is a single PR.

Additional Details

  1. Text and other rendering now supports scaling factors.
  2. New functions in all of the various UI-related components / files enable a call to a new parent gameScreenSizeDidChange function that distributes notifications of screen size changes.
  3. Several enhancements of note:
    • WIDGET now supports a new calcLayout callback function / lambda that is called when layout needs to be recalculated.
    • WIDGET now supports a new onDelete callback function / lambda that is called when the instance is about to be deleted.
    • W_INIT now supports a new initPUserDataFunc attribute which can be used to initialize the pUserData pointer per widget instance.
    • Parent WIDGETs automatically distribute screen size change notifications to all children.
    • Where needed, UI widgets have been migrated to setting a calcLayout lambda.
  4. Simply open the Video options and change the Resolution. Or resize the window at the corners / edges (as supported by your OS).

    Current Limitations:

    • Only live resolution changes in the current mode are supported. If you change the display mode (windowed / fullscreen), changes will be queued until Warzone is restarted (matching previous behavior). This is due to several current SDL quirks.
    • Live resizing is disabled while in a multiplayer game because pausing is disabled in multiplayer games (and with how the current event loop + SDL works, the game effectively pauses while the window is being actively resized).
    • Only the SDL backend currently supports live resizing. Compiling with the QT backend will revert to the prior behavior.
  5. Open the Video options and select from the new Display Scale percentages (100%+) available at the current window size. (Display scale options are limited by the window / screen size, as no combination can result in a logical screen size lower than the minimum supported by Warzone. Hence, only users with very large displays - and the Warzone window expanded on those displays - will see the highest display scaling options. Most users probably won't see over 250% available.)

    Current Limitations:

    • Only the SDL backend currently supports Display Scale options. Compiling with the QT backend will not currently show the Display Scale option in the menu.
  6. On macOS, automatic support for high-DPI ("retina") displays is enabled. Once a future version of SDL enables proper support for other OSes, they can be supported.
  7. Some highlights:
    • Switched over most text rendering to using the improved WzText, which caches and reduces text rasterization calls by over 99%, for a significant performance win. (Previously, most text was being re-rasterized on every frame, even if unchanged.)
    • A lot of time was previously being wasted disabling shaders... in loops that just kept enabling / disabling the same shader. New functions to batch calls and moving pie_DeactivateShader outside of loops yield a significant performance improvement (especially when running at higher display scaling modes that necessarily stress the engine more).
  8. Previously, the game engine spent a lot of time rendering things that were far off the visible screen. More accurate clipping techniques yield a large reduction in wasted non-visible drawing.
@Forgon2100

This comment has been minimized.

Copy link
Contributor

commented Jan 27, 2018

Performance must be significantly improved before this patch can be accepted.

This should be discussed in ticket #4720 and the forums, so more people can help.

@Chewbakka-Wakka

This comment has been minimized.

Copy link

commented Jan 27, 2018

@swiftlyfalling

This comment has been minimized.

Copy link

commented Jan 27, 2018

@Forgon2100: As mentioned on Trac, all my tests on several Windows and Mac machines showed improved performance, so we'll need to track down exactly what's happening on your system.

@perim

This comment has been minimized.

Copy link
Member

commented Jan 27, 2018

This functionality is really nice! Thanks.

  1. This patch adds requirement to SDL2 2.0.4+, since it uses SDL_GetDisplayDPI, which was only added in this version. Please change the version check in configure.ac to match.
  2. Gigantic commits are difficult to test and nearly always have bugs that are then difficult to bisect. Please at least split the last two points (general optimizations) into a separate commit.
  3. src/intdisplay.cpp:1228:18: error: variable ‘iDX’ set but not used

@past-due past-due force-pushed the past-due:resizing_high_dpi_work branch from 6561ec7 to 7821d5b Jan 27, 2018

@past-due

This comment has been minimized.

Copy link
Contributor Author

commented Jan 27, 2018

@perim:

  1. Made the SDL 2.0.4+ change to configure.ac
  2. Split into two commits, per your request.
  3. Fixed.

The revised patch should also fix the performance regression @Forgon2100 experienced.

past-due added some commits Jan 27, 2018

Fixes #4720: Display scaling, live window resizing, and high-DPI support
- Internal enhancements to support screen / game / rendering scaling factors.
- Internal enhancements to support live window resizing / resolution changes.
- Internal enhancements to support UI layout recalculation.
- [SDL backend] Support for live window resizing / resolution changes. (*Cannot currently change between Windowed / Fullscreen without restarting Warzone because of SDL quirks, but live resolution changes in the current mode are supported.)
- [SDL backend] New "displayScale" variable for config file (can also be set as "Display Scale" in video options), offering 100%-500%* display scaling options (*scaling options are limited by the window/screen size, as no combination can result in a logical screen size lower than the minimum supported by Warzone).
- [macOS] Automatic high-DPI ("retina") display support. (Currently limited to macOS because of SDL 2.0.x high-DPI support limitations.)
- Better caching of text rasterization (through judicious use of the improved WzText).
Performance improvements to support display scaling
- Reduction in unnecessary OpenGL state changes.
- More accurate clipping techniques yield a large reduction in wasted non-visible drawing.
- Other small performance enhancements (such as avoiding duplicated calculations of values).

@past-due past-due force-pushed the past-due:resizing_high_dpi_work branch from 7821d5b to dc69eb5 Jan 27, 2018

@past-due

This comment has been minimized.

Copy link
Contributor Author

commented Jan 27, 2018

@perim:

I force pushed a fix to the branch. configure.ac actually needs a minimum SDL version of 2.0.5 (because of SDL_SetWindowResizable).

Fixes for desktop window managers / OSes that yield differing SDL beh…
…avior

When changing resolution in windowed mode, use SDL_GetDisplayUsableBounds to obtain the usable display bounds.
Prevent endless loop on resolution change when only a single resolution is in the available list.
@past-due

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2018

@Forgon2100: The above (3rd) commit should fix the issue you encountered on ArchLinux. (I reproduced it on Ubuntu.)

An SDL quirk meant that SDL_GetWindowSize returned cached values (which do not match the adjusted window size that the desktop window manager adopts when attempting to set a window size greater than the usable screen space - i.e. the screen minus system reserved areas). This did not occur on macOS or Windows. To avoid this, the code now obtains the usable screen space with SDL_GetDisplayUsableBounds and rejects attempts to set the window size to something greater than the desktop window manager will allow.

EDIT: This fix is partial. Tiling window managers like i3 can yield a further issue. See the 4th commit below, which fixes this.

@past-due

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2018

@per: So I dug into this a bit more, and there's still an issue caused by a bug in SDL (not picking up "window manager resized the window" events) and attempting to set the windowed window size via the Video options menu. (Testing with i3 window manager on Ubuntu).

I'm not aware of an easy workaround for this SDL bug. Since this set of patches enables OS/window-manager provided window resizing (dragging by corners, etc), I'd like to suggest the following change we spoke briefly about on IRC:

  • Disabling the "Resolution" option from the Video options menu when in windowed mode.

It just isn't necessary anymore, and it apparently can't be made to work right in all circumstances because of SDL bugs / window manager or OS quirks. Users can just resize the window normally with these patches.

past-due and others added some commits Jan 28, 2018

Disable Video options menu `Resolution` option when in windowed mode
When live-resizing (i.e. using the OS / window-manager functionality to resize the window) is available, disable the Video options menu `Resolution` option in windowed mode.

(The option is still visible, to show the current windowed resolution.)

This is to avoid an issue caused by SDL & certain window managers (ex. i3), where SDL does not receive the actual window size after attempts to set the window size are rejected / reversed / altered by the window manager. The discrepancy between the actual window size and what SDL *thinks* the window size is causes issues.

The ability to change the windowed resolution from the menu isn't necessary when live resizing is available, so disabling the menu option is the simple solution.
@DroidSparks

This comment has been minimized.

Copy link

commented Feb 1, 2018

warzone2100\lib\widget\widget.cpp(223): fatal error C1017: invalid integer constant expression

Use #ifdef DEBUG to fix it.

@past-due

This comment has been minimized.

Copy link
Contributor Author

commented Feb 15, 2018

Merged in: 619e84d, 4d0dcae, e58b34a, 96b4866

@past-due past-due closed this Feb 15, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.