From eec66c585e882db4ce0dcde8d79f7575e4eee70e Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 16 Oct 2023 16:10:56 +0200 Subject: [PATCH] display: Add method for querying current display mode index Note that it doesn't work on macOS with high-DPI displays, this requires #1308 (which is on master), otherwise it will just report -1 for now Fixes #1550 --- panda/src/cocoadisplay/cocoaGraphicsPipe.mm | 16 ++++++++++++++++ panda/src/display/displayInformation.cxx | 14 +++++++++++--- panda/src/display/displayInformation.h | 4 +++- panda/src/windisplay/winDetectDx.h | 15 ++++++++++++--- panda/src/windisplay/winGraphicsPipe.cxx | 16 ++++++++++++++++ panda/src/x11display/x11GraphicsPipe.cxx | 14 ++++++++++++++ 6 files changed, 72 insertions(+), 7 deletions(-) diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm index 91bd0fbbb9..3ad9099545 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm @@ -69,11 +69,19 @@ load_display_information() { // Display modes size_t num_modes = 0; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 + int32_t current_mode_id = -1; CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, NULL); if (modes != NULL) { num_modes = CFArrayGetCount(modes); _display_information->_total_display_modes = num_modes; _display_information->_display_mode_array = new DisplayMode[num_modes]; + + // Get information about the current mode. + CGDisplayModeRef mode = CGDisplayCopyDisplayMode(_display); + if (mode) { + current_mode_id = CGDisplayModeGetIODisplayModeID(mode); + CGDisplayModeRelease(mode); + } } for (size_t i = 0; i < num_modes; ++i) { @@ -109,6 +117,14 @@ load_display_information() { // pixel can be deduced from the string length. Nifty! _display_information->_display_mode_array[i].bits_per_pixel = CFStringGetLength(encoding); } + + if (current_mode_id >= 0 && current_mode_id == CGDisplayModeGetIODisplayModeID(mode)) { + _display_information->_current_display_mode_index = i; + + // Stop checking + current_mode_id = -1; + } + CFRelease(encoding); } if (modes != NULL) { diff --git a/panda/src/display/displayInformation.cxx b/panda/src/display/displayInformation.cxx index 337da59699..a51c39ffa9 100644 --- a/panda/src/display/displayInformation.cxx +++ b/panda/src/display/displayInformation.cxx @@ -75,7 +75,6 @@ DisplayInformation:: DisplayInformation:: DisplayInformation() { DisplayInformation::DetectionState state; - int get_adapter_display_mode_state; int get_device_caps_state; int window_width; int window_height; @@ -88,7 +87,6 @@ DisplayInformation() { uint64_t available_physical_memory; state = DisplayInformation::DS_unknown; - get_adapter_display_mode_state = false; get_device_caps_state = false; window_width = 0; window_height = 0; @@ -101,7 +99,7 @@ DisplayInformation() { available_physical_memory = 0; _state = state; - _get_adapter_display_mode_state = get_adapter_display_mode_state; + _current_display_mode_index = -1; _get_device_caps_state = get_device_caps_state; _maximum_window_width = window_width; _maximum_window_height = window_height; @@ -209,6 +207,16 @@ get_display_mode(int display_index) { return _display_mode_array[display_index]; } +/** + * Returns the index of the current display mode (determined at the time of + * application start) in the display mode array, or -1 if this could not be + * determined. + */ +int DisplayInformation:: +get_current_display_mode_index() const { + return _current_display_mode_index; +} + /** * */ diff --git a/panda/src/display/displayInformation.h b/panda/src/display/displayInformation.h index 2869c8320a..9cb4c8d6ea 100644 --- a/panda/src/display/displayInformation.h +++ b/panda/src/display/displayInformation.h @@ -57,6 +57,8 @@ PUBLISHED: const DisplayMode &get_display_mode(int display_index); MAKE_SEQ(get_display_modes, get_total_display_modes, get_display_mode); + int get_current_display_mode_index() const; + // Older interface for display modes. int get_display_mode_width(int display_index); int get_display_mode_height(int display_index); @@ -116,7 +118,7 @@ PUBLISHED: public: DetectionState _state; - int _get_adapter_display_mode_state; + int _current_display_mode_index; int _get_device_caps_state; int _maximum_window_width; int _maximum_window_height; diff --git a/panda/src/windisplay/winDetectDx.h b/panda/src/windisplay/winDetectDx.h index 4b979de6f0..68645b196e 100644 --- a/panda/src/windisplay/winDetectDx.h +++ b/panda/src/windisplay/winDetectDx.h @@ -101,7 +101,6 @@ static int get_display_information (DisplaySearchParameters &display_search_para int success; DisplayInformation::DetectionState state; - int get_adapter_display_mode_state; int get_device_caps_state; GraphicsStateGuardian::ShaderModel shader_model; @@ -119,6 +118,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para int window_height; int window_bits_per_pixel; int total_display_modes; + int current_display_mode_index; DisplayMode *display_mode_array; uint64_t physical_memory; @@ -141,6 +141,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para window_height = 0; window_bits_per_pixel = 0; total_display_modes = 0; + current_display_mode_index = -1; display_mode_array = nullptr; minimum_width = display_search_parameters._minimum_width; @@ -155,7 +156,6 @@ static int get_display_information (DisplaySearchParameters &display_search_para texture_memory = 0; state = DisplayInformation::DS_unknown; - get_adapter_display_mode_state = false; get_device_caps_state = false; physical_memory = 0; @@ -195,6 +195,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para device_type = D3DDEVTYPE_HAL; // windowed mode max res and format + bool get_adapter_display_mode_state = false; if (direct_3d -> GetAdapterDisplayMode (adapter, ¤t_d3d_display_mode) == D3D_OK) { if (debug) { printf ("current mode w = %d h = %d r = %d f = %d \n", @@ -430,6 +431,14 @@ static int get_display_information (DisplaySearchParameters &display_search_para display_mode -> refresh_rate = d3d_display_mode.RefreshRate; display_mode -> fullscreen_only = display_format_array [format_index].fullscreen_only; + if (get_adapter_display_mode_state && + d3d_display_mode.Width == current_d3d_display_mode.Width && + d3d_display_mode.Height == current_d3d_display_mode.Height && + d3d_display_mode.RefreshRate == current_d3d_display_mode.RefreshRate && + d3d_display_mode.Format == current_d3d_display_mode.Format) { + current_display_mode_index = total_display_modes; + } + total_display_modes++; } } @@ -589,7 +598,7 @@ static int get_display_information (DisplaySearchParameters &display_search_para if (success) { display_information -> _state = state; - display_information -> _get_adapter_display_mode_state = get_adapter_display_mode_state; + display_information -> _current_display_mode_index = current_display_mode_index; display_information -> _get_device_caps_state = get_device_caps_state; display_information -> _maximum_window_width = window_width; display_information -> _maximum_window_height = window_height; diff --git a/panda/src/windisplay/winGraphicsPipe.cxx b/panda/src/windisplay/winGraphicsPipe.cxx index eb29048c65..f24b25edad 100644 --- a/panda/src/windisplay/winGraphicsPipe.cxx +++ b/panda/src/windisplay/winGraphicsPipe.cxx @@ -340,9 +340,21 @@ WinGraphicsPipe() { if (windisplay_cat.is_debug()) { windisplay_cat.debug() << "Using EnumDisplaySettings to fetch display information.\n"; } + pvector display_modes; + DisplayMode current_mode = {0}; + int current_mode_index = -1; DEVMODE dm{}; dm.dmSize = sizeof(dm); + + if (EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &dm) != 0) { + current_mode.width = dm.dmPelsWidth; + current_mode.height = dm.dmPelsHeight; + current_mode.bits_per_pixel = dm.dmBitsPerPel; + current_mode.refresh_rate = dm.dmDisplayFrequency; + current_mode.fullscreen_only = 0; + } + for (int i = 0; EnumDisplaySettings(nullptr, i, &dm) != 0; ++i) { DisplayMode mode; mode.width = dm.dmPelsWidth; @@ -351,6 +363,9 @@ WinGraphicsPipe() { mode.refresh_rate = dm.dmDisplayFrequency; mode.fullscreen_only = 0; if (i == 0 || mode != display_modes.back()) { + if (current_mode_index < 0 && mode == current_mode) { + current_mode_index = (int)display_modes.size(); + } display_modes.push_back(mode); } } @@ -358,6 +373,7 @@ WinGraphicsPipe() { // Copy this information to the DisplayInformation object. _display_information->_total_display_modes = display_modes.size(); if (!display_modes.empty()) { + _display_information->_current_display_mode_index = current_mode_index; _display_information->_display_mode_array = new DisplayMode[display_modes.size()]; std::copy(display_modes.begin(), display_modes.end(), _display_information->_display_mode_array); diff --git a/panda/src/x11display/x11GraphicsPipe.cxx b/panda/src/x11display/x11GraphicsPipe.cxx index e871cb20a7..974e67dd3c 100644 --- a/panda/src/x11display/x11GraphicsPipe.cxx +++ b/panda/src/x11display/x11GraphicsPipe.cxx @@ -224,11 +224,25 @@ x11GraphicsPipe(const std::string &display) : x11display_cat.debug() << "Using XRRScreenResources to obtain display modes\n"; } + + // Query current configuration, we just grab the first CRTC for now, + // since we don't have a way to represent multiple monitors. + RRMode current_mode_id = 0; + if (res->ncrtc > 0) { + if (auto info = get_crtc_info(res.get(), res->crtcs[0])) { + current_mode_id = info->mode; + } + } + _display_information->_total_display_modes = res->nmode; _display_information->_display_mode_array = new DisplayMode[res->nmode]; for (int i = 0; i < res->nmode; ++i) { XRRModeInfo &mode = res->modes[i]; + if (mode.id == current_mode_id) { + _display_information->_current_display_mode_index = i; + } + DisplayMode *dm = _display_information->_display_mode_array + i; dm->width = mode.width; dm->height = mode.height;