Merge pull request #57335 from jordigcs/display-refresh-rate
This commit is contained in:
commit
d235c1bb19
19 changed files with 172 additions and 0 deletions
|
@ -399,6 +399,14 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_refresh_rate" qualifiers="const">
|
||||
<return type="float" />
|
||||
<argument index="0" name="screen" type="int" default="-1" />
|
||||
<description>
|
||||
Returns the current refresh rate of the specified screen. If [code]screen[/code] is [code]SCREEN_OF_MAIN_WINDOW[/code] (the default value), a screen with the main window will be used.
|
||||
[b]Note:[/b] Returns [code]60.0[/code] if the DisplayServer fails to find the refresh rate for the specified screen. On HTML5, [method screen_get_refresh_rate] will always return [code]60.0[/code] as there is no way to retrieve the refresh rate on that platform.
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_scale" qualifiers="const">
|
||||
<return type="float" />
|
||||
<argument index="0" name="screen" type="int" default="-1" />
|
||||
|
|
|
@ -161,6 +161,16 @@ int DisplayServerAndroid::screen_get_dpi(int p_screen) const {
|
|||
return godot_io_java->get_screen_dpi();
|
||||
}
|
||||
|
||||
float DisplayServerAndroid::screen_get_refresh_rate(int p_screen) const {
|
||||
GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
|
||||
if (!godot_io_java) {
|
||||
ERR_PRINT("An error occured while trying to get the screen refresh rate.");
|
||||
return SCREEN_REFRESH_RATE_FALLBACK;
|
||||
}
|
||||
|
||||
return godot_io_java->get_screen_refresh_rate(SCREEN_REFRESH_RATE_FALLBACK);
|
||||
}
|
||||
|
||||
bool DisplayServerAndroid::screen_is_touchscreen(int p_screen) const {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@ public:
|
|||
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
|
||||
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
|
||||
|
|
|
@ -226,6 +226,14 @@ public class GodotIO {
|
|||
return (int)(metrics.density * 160f);
|
||||
}
|
||||
|
||||
public double getScreenRefreshRate(double fallback) {
|
||||
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
if (display != null) {
|
||||
return display.getRefreshRate();
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
public int[] screenGetUsableRect() {
|
||||
DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
|
||||
Display display = activity.getWindowManager().getDefaultDisplay();
|
||||
|
|
|
@ -53,6 +53,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
|
|||
_get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;");
|
||||
_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");
|
||||
_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");
|
||||
_get_screen_refresh_rate = p_env->GetMethodID(cls, "getScreenRefreshRate", "(D)D");
|
||||
_screen_get_usable_rect = p_env->GetMethodID(cls, "screenGetUsableRect", "()[I"),
|
||||
_get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;");
|
||||
_show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;ZIII)V");
|
||||
|
@ -136,6 +137,19 @@ int GodotIOJavaWrapper::get_screen_dpi() {
|
|||
}
|
||||
}
|
||||
|
||||
float GodotIOJavaWrapper::get_screen_refresh_rate(float fallback) {
|
||||
if (_get_screen_refresh_rate) {
|
||||
JNIEnv *env = get_jni_env();
|
||||
if (env == nullptr) {
|
||||
ERR_PRINT("An error occured while trying to get screen refresh rate.");
|
||||
return fallback;
|
||||
}
|
||||
return (float)env->CallDoubleMethod(godot_io_instance, _get_screen_refresh_rate, (double)fallback);
|
||||
}
|
||||
ERR_PRINT("An error occured while trying to get the screen refresh rate.");
|
||||
return fallback;
|
||||
}
|
||||
|
||||
void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) {
|
||||
if (_screen_get_usable_rect) {
|
||||
JNIEnv *env = get_jni_env();
|
||||
|
|
|
@ -51,6 +51,7 @@ private:
|
|||
jmethodID _get_locale = 0;
|
||||
jmethodID _get_model = 0;
|
||||
jmethodID _get_screen_DPI = 0;
|
||||
jmethodID _get_screen_refresh_rate = 0;
|
||||
jmethodID _screen_get_usable_rect = 0;
|
||||
jmethodID _get_unique_id = 0;
|
||||
jmethodID _show_keyboard = 0;
|
||||
|
@ -71,6 +72,7 @@ public:
|
|||
String get_locale();
|
||||
String get_model();
|
||||
int get_screen_dpi();
|
||||
float get_screen_refresh_rate(float fallback);
|
||||
void screen_get_usable_rect(int (&p_rect_xywh)[4]);
|
||||
String get_unique_id();
|
||||
bool has_vk();
|
||||
|
|
|
@ -129,6 +129,7 @@ public:
|
|||
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
|
||||
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
|
||||
|
||||
|
|
|
@ -393,6 +393,10 @@ int DisplayServerIPhone::screen_get_dpi(int p_screen) const {
|
|||
}
|
||||
}
|
||||
|
||||
float DisplayServerIPhone::screen_get_refresh_rate(int p_screen) const {
|
||||
return [UIScreen mainScreen].maximumFramesPerSecond;
|
||||
}
|
||||
|
||||
float DisplayServerIPhone::screen_get_scale(int p_screen) const {
|
||||
return [UIScreen mainScreen].nativeScale;
|
||||
}
|
||||
|
|
|
@ -794,6 +794,10 @@ float DisplayServerJavaScript::screen_get_scale(int p_screen) const {
|
|||
return godot_js_display_pixel_ratio_get();
|
||||
}
|
||||
|
||||
float DisplayServerJavaScript::screen_get_refresh_rate(int p_screen) const {
|
||||
return SCREEN_REFRESH_RATE_FALLBACK; // Javascript doesn't have much of a need for the screen refresh rate, and there's no native way to do so.
|
||||
}
|
||||
|
||||
Vector<DisplayServer::WindowID> DisplayServerJavaScript::get_window_list() const {
|
||||
Vector<WindowID> ret;
|
||||
ret.push_back(MAIN_WINDOW_ID);
|
||||
|
|
|
@ -139,6 +139,7 @@ public:
|
|||
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
|
||||
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override;
|
||||
virtual void virtual_keyboard_hide() override;
|
||||
|
|
|
@ -1054,6 +1054,66 @@ int DisplayServerX11::screen_get_dpi(int p_screen) const {
|
|||
return 96;
|
||||
}
|
||||
|
||||
float DisplayServerX11::screen_get_refresh_rate(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
|
||||
p_screen = window_get_current_screen();
|
||||
}
|
||||
|
||||
//invalid screen?
|
||||
ERR_FAIL_INDEX_V(p_screen, get_screen_count(), SCREEN_REFRESH_RATE_FALLBACK);
|
||||
|
||||
//Use xrandr to get screen refresh rate.
|
||||
if (xrandr_ext_ok) {
|
||||
XRRScreenResources *screen_info = XRRGetScreenResources(x11_display, windows[MAIN_WINDOW_ID].x11_window);
|
||||
if (screen_info) {
|
||||
RRMode current_mode = 0;
|
||||
xrr_monitor_info *monitors = nullptr;
|
||||
|
||||
if (xrr_get_monitors) {
|
||||
int count = 0;
|
||||
monitors = xrr_get_monitors(x11_display, windows[MAIN_WINDOW_ID].x11_window, true, &count);
|
||||
ERR_FAIL_INDEX_V(p_screen, count, SCREEN_REFRESH_RATE_FALLBACK);
|
||||
} else {
|
||||
ERR_PRINT("An error occured while trying to get the screen refresh rate.");
|
||||
return SCREEN_REFRESH_RATE_FALLBACK;
|
||||
}
|
||||
|
||||
bool found_active_mode = false;
|
||||
for (int crtc = 0; crtc < screen_info->ncrtc; crtc++) { // Loop through outputs to find which one is currently outputting.
|
||||
XRRCrtcInfo *monitor_info = XRRGetCrtcInfo(x11_display, screen_info, screen_info->crtcs[crtc]);
|
||||
if (monitor_info->x != monitors[p_screen].x || monitor_info->y != monitors[p_screen].y) { // If X and Y aren't the same as the monitor we're looking for, this isn't the right monitor. Continue.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (monitor_info->mode != None) {
|
||||
current_mode = monitor_info->mode;
|
||||
found_active_mode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_active_mode) {
|
||||
for (int mode = 0; mode < screen_info->nmode; mode++) {
|
||||
XRRModeInfo m_info = screen_info->modes[mode];
|
||||
if (m_info.id == current_mode) {
|
||||
return (float)m_info.dotClock / ((float)m_info.hTotal * (float)m_info.vTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ERR_PRINT("An error occured while trying to get the screen refresh rate."); // We should have returned the refresh rate by now. An error must have occured.
|
||||
return SCREEN_REFRESH_RATE_FALLBACK;
|
||||
} else {
|
||||
ERR_PRINT("An error occured while trying to get the screen refresh rate.");
|
||||
return SCREEN_REFRESH_RATE_FALLBACK;
|
||||
}
|
||||
}
|
||||
ERR_PRINT("An error occured while trying to get the screen refresh rate.");
|
||||
return SCREEN_REFRESH_RATE_FALLBACK;
|
||||
}
|
||||
|
||||
bool DisplayServerX11::screen_is_touchscreen(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
|
|
@ -303,6 +303,7 @@ public:
|
|||
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
|
||||
#if defined(DBUS_ENABLED)
|
||||
|
|
|
@ -230,6 +230,7 @@ public:
|
|||
virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_max_scale() const override;
|
||||
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
|
||||
virtual Vector<int> get_window_list() const override;
|
||||
|
||||
|
|
|
@ -2203,6 +2203,24 @@ Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const {
|
|||
return Rect2i();
|
||||
}
|
||||
|
||||
float DisplayServerOSX::screen_get_refresh_rate(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
|
||||
p_screen = window_get_current_screen();
|
||||
}
|
||||
|
||||
NSArray *screenArray = [NSScreen screens];
|
||||
if ((NSUInteger)p_screen < [screenArray count]) {
|
||||
NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription];
|
||||
const CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode([[description objectForKey:@"NSScreenNumber"] unsignedIntValue]);
|
||||
const double displayRefreshRate = CGDisplayModeGetRefreshRate(displayMode);
|
||||
return (float)displayRefreshRate;
|
||||
}
|
||||
ERR_PRINT("An error occured while trying to get the screen refresh rate.");
|
||||
return SCREEN_REFRESH_RATE_FALLBACK;
|
||||
}
|
||||
|
||||
Vector<DisplayServer::WindowID> DisplayServerOSX::get_window_list() const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
|
|
@ -326,6 +326,12 @@ typedef struct {
|
|||
Rect2i rect;
|
||||
} EnumRectData;
|
||||
|
||||
typedef struct {
|
||||
int count;
|
||||
int screen;
|
||||
float rate;
|
||||
} EnumRefreshRateData;
|
||||
|
||||
static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
|
||||
EnumSizeData *data = (EnumSizeData *)dwData;
|
||||
if (data->count == data->screen) {
|
||||
|
@ -363,6 +369,26 @@ static BOOL CALLBACK _MonitorEnumProcUsableSize(HMONITOR hMonitor, HDC hdcMonito
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK _MonitorEnumProcRefreshRate(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
|
||||
EnumRefreshRateData *data = (EnumRefreshRateData *)dwData;
|
||||
if (data->count == data->screen) {
|
||||
MONITORINFOEXW minfo;
|
||||
memset(&minfo, 0, sizeof(minfo));
|
||||
minfo.cbSize = sizeof(minfo);
|
||||
GetMonitorInfoW(hMonitor, &minfo);
|
||||
|
||||
DEVMODEW dm;
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
EnumDisplaySettingsW(minfo.szDevice, ENUM_CURRENT_SETTINGS, &dm);
|
||||
|
||||
data->rate = dm.dmDisplayFrequency;
|
||||
}
|
||||
|
||||
data->count++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Rect2i DisplayServerWindows::screen_get_usable_rect(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -446,6 +472,13 @@ int DisplayServerWindows::screen_get_dpi(int p_screen) const {
|
|||
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcDpi, (LPARAM)&data);
|
||||
return data.dpi;
|
||||
}
|
||||
float DisplayServerWindows::screen_get_refresh_rate(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
EnumRefreshRateData data = { 0, p_screen == SCREEN_OF_MAIN_WINDOW ? window_get_current_screen() : p_screen, SCREEN_REFRESH_RATE_FALLBACK };
|
||||
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcRefreshRate, (LPARAM)&data);
|
||||
return data.rate;
|
||||
}
|
||||
|
||||
bool DisplayServerWindows::screen_is_touchscreen(int p_screen) const {
|
||||
#ifndef _MSC_VER
|
||||
|
|
|
@ -457,6 +457,7 @@ public:
|
|||
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
|
||||
virtual void screen_set_orientation(ScreenOrientation p_orientation, int p_screen = SCREEN_OF_MAIN_WINDOW) override;
|
||||
|
|
|
@ -380,6 +380,7 @@ void DisplayServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("screen_get_scale", "screen"), &DisplayServer::screen_get_scale, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_is_touchscreen", "screen"), &DisplayServer::screen_is_touchscreen, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_max_scale"), &DisplayServer::screen_get_max_scale);
|
||||
ClassDB::bind_method(D_METHOD("screen_get_refresh_rate", "screen"), &DisplayServer::screen_get_refresh_rate, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("screen_set_orientation", "orientation", "screen"), &DisplayServer::screen_set_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_orientation", "screen"), &DisplayServer::screen_get_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
|
|
|
@ -174,6 +174,8 @@ public:
|
|||
SCREEN_OF_MAIN_WINDOW = -1
|
||||
};
|
||||
|
||||
const float SCREEN_REFRESH_RATE_FALLBACK = 60.0; // Returned by screen_get_refresh_rate if the method fails. Most screens are 60hz as of 2022.
|
||||
|
||||
virtual int get_screen_count() const = 0;
|
||||
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
|
||||
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
|
||||
|
@ -188,6 +190,7 @@ public:
|
|||
}
|
||||
return scale;
|
||||
}
|
||||
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const = 0;
|
||||
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
|
||||
|
||||
// Keep the ScreenOrientation enum values in sync with the `display/window/handheld/orientation`
|
||||
|
|
|
@ -62,6 +62,7 @@ public:
|
|||
int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return 96; /* 0 might cause issues */ }
|
||||
float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return 1; }
|
||||
float screen_get_max_scale() const override { return 1; }
|
||||
float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return SCREEN_REFRESH_RATE_FALLBACK; }
|
||||
|
||||
Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); }
|
||||
|
||||
|
|
Loading…
Reference in a new issue