2020-01-01 21:29:24 +01:00
|
|
|
#ifndef SCREEN_H
|
|
|
|
#define SCREEN_H
|
|
|
|
|
|
|
|
#include <SDL.h>
|
|
|
|
|
2020-11-13 01:29:11 +01:00
|
|
|
#include "ScreenSettings.h"
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
class Screen
|
|
|
|
{
|
|
|
|
public:
|
2021-12-25 09:18:51 +01:00
|
|
|
void init(const struct ScreenSettings* settings);
|
2021-09-07 03:56:39 +02:00
|
|
|
void destroy(void);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2021-12-25 09:18:51 +01:00
|
|
|
void GetSettings(struct ScreenSettings* settings);
|
2020-12-22 01:34:16 +01:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
void LoadIcon(void);
|
2020-11-01 04:25:27 +01:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
void ResizeScreen(int x, int y);
|
|
|
|
void ResizeToNearestMultiple(void);
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
void GetScreenSize(int* x, int* y);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
Always update scaling before rendering
This fixes the following bug that only occurs on Wayland: If the game is
configured to be fullscreened and in stretch mode, on startup, it won't
be in stretch mode. It will appear to be in letterbox mode, but the game
still thinks it's in stretch mode.
This is because during the ResizeScreen() call on startup, for whatever
reason, the window size will be reported to be the default size (640 by
480) instead of the screen resolution of the monitor, as one would
expect from being in fullscreen. It seems like when the game queries the
window size, the window isn't actually in fullscreen at that time, even
though this is after fullscreen has been set to true.
To fix this, I decided to always update the logical size before
SDL_RenderPresent() is called. To make this neater, I put the scaling
code in its own function named UpdateScaling().
This bug has existed since 2.3 and does not occur on X11. I tested this
on GNOME Wayland, and for testing it on X11, I used Openbox in a Xephyr
session while running VVVVVV with SDL_VIDEODRIVER=x11.
2023-03-21 04:31:31 +01:00
|
|
|
void UpdateScaling(void);
|
2023-03-18 23:24:14 +01:00
|
|
|
void RenderPresent(void);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
void toggleFullScreen(void);
|
2021-12-23 04:54:59 +01:00
|
|
|
void toggleScalingMode(void);
|
2021-09-07 03:56:39 +02:00
|
|
|
void toggleLinearFilter(void);
|
2021-09-15 05:23:22 +02:00
|
|
|
void toggleVSync(void);
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2023-01-07 19:28:07 +01:00
|
|
|
void recacheTextures(void);
|
|
|
|
|
2021-12-26 07:55:55 +01:00
|
|
|
bool isForcedFullscreen(void);
|
|
|
|
|
Store display index of window to settings
I have this annoying issue where the game will open on the wrong monitor
in fullscreen mode, because that monitor is considered to be display 0,
whereas the primary monitor I want is display 1.
To mitigate this somewhat, the game now stores the display index that it
was closed on, and will save it to settings. Then the next time the game
opens, it will open on that display index. This should work pretty well
as long as you aren't changing your monitor setup constantly.
Of course, none of this applies if your window manager is busted. For
example, on GNOME Wayland, which is what I use, in windowed mode the
game will always open on the monitor the cursor is on, and it won't even
be centered in the monitor. But it works fine if I use XWayland via
SDL_VIDEODRIVER=x11.
2023-03-21 08:23:42 +01:00
|
|
|
int windowDisplay;
|
Persist windowed mode size through fullscreen mode
Previously, the game would not store the size of the window itself, and
would always call SDL_GetRendererOutputSize() (via
Screen::GetWindowSize()) to figure out the size of the window. The only
problem is, this would return the size of the whole monitor if the game
was in fullscreen mode. And the only place where the original windowed
mode size was stored would be in SDL itself, but that wouldn't persist
after the game was closed.
So, if you exited the game while in fullscreen mode, then your window
size would get set to the size of your monitor (1920 by 1080 in my
case). Then when you opened the game and toggled fullscreen off, it
would go back to the default window size, which is 640 by 480.
This is made worse, however, if you were in forced fullscreen mode when
you previously exited the game in windowed mode. In that case, the game
saves the size of 1920 by 1080, but doesn't save that you were in
fullscreen mode, so opening the game not in forced fullscreen mode would
result in you having a 1920 by 1080 window, but in windowed mode.
Meaning that not even fullscreening and unfullscreening would put the
game window back to normal size.
The solution, of course, is to just store the window size ourselves,
like any other screen setting, and only use GetWindowSize() if needed.
And just to make things clear, I've also renamed the GetWindowSize()
function to GetScreenSize(), because if it was named "window" it could
lead one to think that it would always return the size of the screen in
windowed mode, when in fact it returns the size of the screen whatever
mode it is in - fullscreen size if in fullscreen mode and window size if
in windowed mode.
And doing this also fixes the FIXME above Screen::isForcedFullscreen().
2023-03-21 04:59:37 +01:00
|
|
|
int windowWidth;
|
|
|
|
int windowHeight;
|
2021-09-07 03:56:39 +02:00
|
|
|
bool isWindowed;
|
|
|
|
bool isFiltered;
|
|
|
|
bool badSignalEffect;
|
2021-12-23 04:54:59 +01:00
|
|
|
int scalingMode;
|
2021-09-07 03:56:39 +02:00
|
|
|
bool vsync;
|
2020-01-01 21:29:24 +01:00
|
|
|
|
2021-09-07 03:56:39 +02:00
|
|
|
SDL_Window *m_window;
|
|
|
|
SDL_Renderer *m_renderer;
|
2020-01-01 21:29:24 +01:00
|
|
|
};
|
|
|
|
|
Extern `gameScreen`, remove `screenbuffer`
I know earlier I removed the gameScreen extern in favor of using
screenbuffer, but that was only to be consistent. After further
consideration, I have found that it's actually really stupid.
There's no reason to be accessing it through screenbuffer, and it's
probably an artifact of 2.0-2.2 passing stack-allocated otherwise-global
classes everywhere through function arguments. Also, it leads to stupid
bugs where screenbuffer could potentially be NULL, which has already
resulted in various annoying crashes in the past. Although those could
be fixed by simply initializing screenbuffer at the very top of main(),
but, why not just scrap the whole thing anyway?
So that's what I'm doing.
As a nice side effect, I've removed the transitive include of Screen.h
from Graphics.h. This could've been done already since it only includes
it for the pointer anyway, but it's still good to do it now.
2021-12-25 08:56:47 +01:00
|
|
|
#ifndef GAMESCREEN_DEFINITION
|
|
|
|
extern Screen gameScreen;
|
|
|
|
#endif
|
|
|
|
|
2020-01-01 21:29:24 +01:00
|
|
|
#endif /* SCREEN_H */
|