mirror of
https://github.com/open-goal/jak-project
synced 2026-06-29 11:41:11 -04:00
2d64108af5
Some monitors are very specific about their reported refresh rates: ``` [54:37] [debug] [DISPLAY]: Skipping 640x480 as it requires 360.11hz but the monitor is currently set to 360hz ``` The current code truncated the display mode, but would compare against the reported refresh rate. As per the log, they are obviously not equal. - Retain the float component and only round it off when sending the value to GOAL - Make the comparison more generous, +/- 1.0hz
145 lines
4.9 KiB
C++
145 lines
4.9 KiB
C++
#pragma once
|
|
|
|
#include <mutex>
|
|
#include <optional>
|
|
#include <queue>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <variant>
|
|
|
|
#include "game/settings/settings.h"
|
|
#include "game/system/hid/input_manager.h"
|
|
|
|
#include "third-party/SDL/include/SDL3/SDL.h"
|
|
|
|
/*
|
|
TODO:
|
|
- hiDPI support, see https://wiki.libsdl.org/SDL2/SDL_GetRendererOutputSize
|
|
*/
|
|
|
|
enum class WindowState { Minimized, Maximized, Restored };
|
|
|
|
enum class Orientation { Landscape, LandscapeFlipped, Portrait, PortraitFlipped, Unknown };
|
|
|
|
/// https://wiki.libsdl.org/SDL3/SDL_DisplayMode
|
|
struct DisplayMode {
|
|
SDL_DisplayID sdl_display_id;
|
|
std::string display_name;
|
|
/// https://wiki.libsdl.org/SDL3/SDL_PixelFormat
|
|
uint32_t sdl_pixel_format;
|
|
int screen_width;
|
|
int screen_height;
|
|
/// refresh rate (in Hz), or 0 for unspecified
|
|
float refresh_rate;
|
|
Orientation orientation;
|
|
};
|
|
|
|
// Describes an available resolution
|
|
struct Resolution {
|
|
int width;
|
|
int height;
|
|
float aspect_ratio;
|
|
};
|
|
|
|
/// Monitors and handles all SDL events related to monitors and the window position
|
|
/// Stores related info for other parts of the application to use
|
|
/// Manages display related operations and querying
|
|
class DisplayManager {
|
|
private:
|
|
enum class EEDisplayEventType { SET_WINDOW_SIZE, SET_DISPLAY_MODE, SET_DISPLAY_ID };
|
|
game_settings::DisplaySettings::DisplayMode m_previous_fullscreen_display_mode =
|
|
game_settings::DisplaySettings::DisplayMode::Fullscreen;
|
|
struct EEDisplayEvent {
|
|
EEDisplayEventType type;
|
|
std::variant<bool, int, game_settings::DisplaySettings::DisplayMode> param1;
|
|
std::variant<bool, int> param2;
|
|
std::variant<int> param3;
|
|
};
|
|
|
|
public:
|
|
DisplayManager(SDL_Window* window);
|
|
~DisplayManager();
|
|
|
|
/// Propagate and handle the SDL event, ignoring it if it's not relevant
|
|
void process_sdl_event(const SDL_Event& event);
|
|
/// Any event coming from the EE thread that interacts directly with SDL should be enqueued as an
|
|
/// event so it can be ran from the proper thread context (the graphics thread)
|
|
void process_ee_events();
|
|
|
|
int get_active_display_index() { return m_display_settings.display_id; }
|
|
bool is_window_active() { return m_window != nullptr; }
|
|
bool is_minimized() { return m_window_state == WindowState::Minimized; }
|
|
int get_window_width() { return m_window_width; }
|
|
int get_window_height() { return m_window_height; }
|
|
int get_window_game_width() { return m_window_game_width; }
|
|
int get_window_game_height() { return m_window_game_height; }
|
|
float get_window_scale_x() { return m_window_scale_x; }
|
|
float get_window_scale_y() { return m_window_scale_y; }
|
|
int num_connected_displays() { return m_current_display_modes.size(); }
|
|
std::string get_connected_display_name(int id);
|
|
int get_active_display_refresh_rate();
|
|
int get_screen_width();
|
|
int get_screen_height();
|
|
game_settings::DisplaySettings::DisplayMode get_display_mode() {
|
|
return m_display_settings.display_mode;
|
|
}
|
|
int get_num_resolutions(bool for_window_size);
|
|
Resolution get_resolution(int id, bool for_window_size);
|
|
bool is_supported_resolution(int width, int height);
|
|
|
|
// Mutators
|
|
void enqueue_set_window_size(int width, int height);
|
|
void enqueue_set_window_display_mode(game_settings::DisplaySettings::DisplayMode mode,
|
|
const int window_width,
|
|
const int window_height);
|
|
void toggle_display_mode();
|
|
void enqueue_set_display_id(int display_id);
|
|
|
|
void set_game_size(int width, int height) {
|
|
m_window_game_width = width;
|
|
m_window_game_height = height;
|
|
}
|
|
|
|
void set_input_manager(std::shared_ptr<InputManager> input_manager) {
|
|
m_input_manager = input_manager;
|
|
}
|
|
|
|
private:
|
|
SDL_Window* m_window;
|
|
game_settings::DisplaySettings m_display_settings;
|
|
std::optional<std::shared_ptr<InputManager>> m_input_manager;
|
|
|
|
std::mutex event_queue_mtx;
|
|
std::queue<EEDisplayEvent> ee_event_queue;
|
|
|
|
int m_window_xpos = 0;
|
|
int m_window_ypos = 0;
|
|
int m_window_width = 0;
|
|
int m_window_height = 0;
|
|
int m_window_game_width = 0;
|
|
int m_window_game_height = 0;
|
|
float m_window_scale_x = 1.0;
|
|
float m_window_scale_y = 1.0;
|
|
WindowState m_window_state = WindowState::Restored;
|
|
|
|
// The currently set display mode for each display
|
|
// There is no reason to keep track of all display modes for all monitors
|
|
// the only one that matters is the one the user _currently_ has configured
|
|
//
|
|
// ie. allowing someone to set 150fps on a monitor set to 60hz is not correct
|
|
std::vector<DisplayMode> m_current_display_modes;
|
|
std::vector<Resolution> m_available_resolutions;
|
|
std::vector<Resolution> m_available_window_sizes;
|
|
|
|
void initialize_window_position_from_settings();
|
|
void update_curr_display_info();
|
|
void update_video_modes();
|
|
void update_resolutions();
|
|
|
|
void set_window_size(int width, int height);
|
|
void set_display_mode(game_settings::DisplaySettings::DisplayMode mode,
|
|
const int window_width,
|
|
const int window_height);
|
|
void set_display_id(int display_id);
|
|
};
|