Skip to content

Commit 9cdf3ff

Browse files
committed
Merge pull request #111639 from timothyqiu/freshy-leaky
X11: Fix memory leak in `screen_get_refresh_rate()`
2 parents 0b47123 + 66e5bce commit 9cdf3ff

File tree

1 file changed

+42
-44
lines changed

1 file changed

+42
-44
lines changed

platform/linuxbsd/x11/display_server_x11.cpp

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,59 +1800,57 @@ Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const {
18001800
float DisplayServerX11::screen_get_refresh_rate(int p_screen) const {
18011801
_THREAD_SAFE_METHOD_
18021802

1803+
ERR_FAIL_COND_V_MSG(!xrandr_ext_ok || !xrr_get_monitors, SCREEN_REFRESH_RATE_FALLBACK, "XRandR extension is not available.");
1804+
18031805
p_screen = _get_screen_index(p_screen);
18041806
int screen_count = get_screen_count();
18051807
ERR_FAIL_INDEX_V(p_screen, screen_count, SCREEN_REFRESH_RATE_FALLBACK);
18061808

1807-
//Use xrandr to get screen refresh rate.
1808-
if (xrandr_ext_ok) {
1809-
XRRScreenResources *screen_info = XRRGetScreenResourcesCurrent(x11_display, windows[MAIN_WINDOW_ID].x11_window);
1810-
if (screen_info) {
1811-
RRMode current_mode = 0;
1812-
xrr_monitor_info *monitors = nullptr;
1813-
1814-
if (xrr_get_monitors) {
1815-
int count = 0;
1816-
monitors = xrr_get_monitors(x11_display, windows[MAIN_WINDOW_ID].x11_window, true, &count);
1817-
ERR_FAIL_INDEX_V(p_screen, count, SCREEN_REFRESH_RATE_FALLBACK);
1818-
} else {
1819-
ERR_PRINT("An error occurred while trying to get the screen refresh rate.");
1820-
return SCREEN_REFRESH_RATE_FALLBACK;
1821-
}
1809+
int target_x;
1810+
int target_y;
1811+
{
1812+
int count = 0;
1813+
xrr_monitor_info *monitors = xrr_get_monitors(x11_display, windows[MAIN_WINDOW_ID].x11_window, true, &count);
1814+
ERR_FAIL_NULL_V(monitors, SCREEN_REFRESH_RATE_FALLBACK);
1815+
if (count <= p_screen) {
1816+
xrr_free_monitors(monitors);
1817+
ERR_FAIL_V_MSG(SCREEN_REFRESH_RATE_FALLBACK, vformat("Invalid screen index: %d (count: %d).", p_screen, count));
1818+
}
1819+
target_x = monitors[p_screen].x;
1820+
target_y = monitors[p_screen].y;
1821+
xrr_free_monitors(monitors);
1822+
}
18221823

1823-
bool found_active_mode = false;
1824-
for (int crtc = 0; crtc < screen_info->ncrtc; crtc++) { // Loop through outputs to find which one is currently outputting.
1825-
XRRCrtcInfo *monitor_info = XRRGetCrtcInfo(x11_display, screen_info, screen_info->crtcs[crtc]);
1826-
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.
1827-
continue;
1828-
}
1824+
XRRScreenResources *screen_res = XRRGetScreenResourcesCurrent(x11_display, windows[MAIN_WINDOW_ID].x11_window);
1825+
ERR_FAIL_NULL_V(screen_res, SCREEN_REFRESH_RATE_FALLBACK);
18291826

1830-
if (monitor_info->mode != None) {
1831-
current_mode = monitor_info->mode;
1832-
found_active_mode = true;
1833-
break;
1834-
}
1835-
}
1836-
1837-
if (found_active_mode) {
1838-
for (int mode = 0; mode < screen_info->nmode; mode++) {
1839-
XRRModeInfo m_info = screen_info->modes[mode];
1840-
if (m_info.id == current_mode) {
1841-
// Snap to nearest 0.01 to stay consistent with other platforms.
1842-
return Math::snapped((float)m_info.dotClock / ((float)m_info.hTotal * (float)m_info.vTotal), 0.01);
1843-
}
1844-
}
1827+
XRRModeInfo *mode_info = nullptr;
1828+
for (int crtc = 0; crtc < screen_res->ncrtc; crtc++) { // Loop through outputs to find which one is currently outputting.
1829+
XRRCrtcInfo *monitor_info = XRRGetCrtcInfo(x11_display, screen_res, screen_res->crtcs[crtc]);
1830+
if (monitor_info->x != target_x || monitor_info->y != target_y || monitor_info->mode == None) {
1831+
XRRFreeCrtcInfo(monitor_info);
1832+
continue;
1833+
}
1834+
for (int mode = 0; mode < screen_res->nmode; mode++) {
1835+
if (screen_res->modes[mode].id == monitor_info->mode) {
1836+
mode_info = &screen_res->modes[mode];
18451837
}
1846-
1847-
ERR_PRINT("An error occurred while trying to get the screen refresh rate."); // We should have returned the refresh rate by now. An error must have occurred.
1848-
return SCREEN_REFRESH_RATE_FALLBACK;
1849-
} else {
1850-
ERR_PRINT("An error occurred while trying to get the screen refresh rate.");
1851-
return SCREEN_REFRESH_RATE_FALLBACK;
18521838
}
1839+
XRRFreeCrtcInfo(monitor_info);
1840+
break;
1841+
}
1842+
1843+
float result;
1844+
if (mode_info) {
1845+
// Snap to nearest 0.01 to stay consistent with other platforms.
1846+
result = Math::snapped((float)mode_info->dotClock / ((float)mode_info->hTotal * (float)mode_info->vTotal), 0.01);
1847+
} else {
1848+
ERR_PRINT("An error occurred while trying to get the screen refresh rate.");
1849+
result = SCREEN_REFRESH_RATE_FALLBACK;
18531850
}
1854-
ERR_PRINT("An error occurred while trying to get the screen refresh rate.");
1855-
return SCREEN_REFRESH_RATE_FALLBACK;
1851+
1852+
XRRFreeScreenResources(screen_res);
1853+
return result;
18561854
}
18571855

18581856
#ifdef DBUS_ENABLED

0 commit comments

Comments
 (0)