macOS: Fix rendering getting stuck on some machines after sleep/screensaver
This is caused, as far as I can tell, by CVDisplayLink getting stuck. Apple apparently are incapable of writing a simple timer robustly. So if it remains stuck after a second delete and recreate it to force it to restart. Fixes #2016
This commit is contained in:
parent
cc2afef390
commit
e4b4a35375
@ -37,6 +37,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
|
|||||||
- macOS: When the Apple Color Emoji font lacks an emoji glyph search for it in other
|
- macOS: When the Apple Color Emoji font lacks an emoji glyph search for it in other
|
||||||
installed fonts (:iss:`3591`)
|
installed fonts (:iss:`3591`)
|
||||||
|
|
||||||
|
- macOS: Fix rendering getting stuck on some machines after sleep/screensaver
|
||||||
|
(:iss:`2016`)
|
||||||
|
|
||||||
- Add a few more special commandline arguments for the launch command. Now all
|
- Add a few more special commandline arguments for the launch command. Now all
|
||||||
``KITTY_PIPE_DATA`` is also available via command line argument substitution
|
``KITTY_PIPE_DATA`` is also available via command line argument substitution
|
||||||
(:iss:`3593`)
|
(:iss:`3593`)
|
||||||
|
|||||||
@ -316,6 +316,7 @@ void _glfwClearDisplayLinks() {
|
|||||||
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
|
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||||
_glfw.ns.displayLinks.entries[i].displayLink = nil;
|
_glfw.ns.displayLinks.entries[i].displayLink = nil;
|
||||||
_glfw.ns.displayLinks.entries[i].lastRenderFrameRequestedAt = 0;
|
_glfw.ns.displayLinks.entries[i].lastRenderFrameRequestedAt = 0;
|
||||||
|
_glfw.ns.displayLinks.entries[i].first_unserviced_render_frame_request_at = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_glfw.ns.displayLinks.count = 0;
|
_glfw.ns.displayLinks.count = 0;
|
||||||
@ -333,7 +334,14 @@ static CVReturn displayLinkCallback(
|
|||||||
return kCVReturnSuccess;
|
return kCVReturnSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void createDisplayLink(CGDirectDisplayID displayID) {
|
void
|
||||||
|
_glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry) {
|
||||||
|
CVDisplayLinkCreateWithCGDisplay(entry->displayID, &entry->displayLink);
|
||||||
|
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)entry->displayID);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
createDisplayLink(CGDirectDisplayID displayID) {
|
||||||
if (_glfw.ns.displayLinks.count >= sizeof(_glfw.ns.displayLinks.entries)/sizeof(_glfw.ns.displayLinks.entries[0]) - 1) return;
|
if (_glfw.ns.displayLinks.count >= sizeof(_glfw.ns.displayLinks.entries)/sizeof(_glfw.ns.displayLinks.entries[0]) - 1) return;
|
||||||
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||||
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return;
|
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return;
|
||||||
@ -341,8 +349,7 @@ static inline void createDisplayLink(CGDirectDisplayID displayID) {
|
|||||||
_GLFWDisplayLinkNS *entry = &_glfw.ns.displayLinks.entries[_glfw.ns.displayLinks.count++];
|
_GLFWDisplayLinkNS *entry = &_glfw.ns.displayLinks.entries[_glfw.ns.displayLinks.count++];
|
||||||
memset(entry, 0, sizeof(_GLFWDisplayLinkNS));
|
memset(entry, 0, sizeof(_GLFWDisplayLinkNS));
|
||||||
entry->displayID = displayID;
|
entry->displayID = displayID;
|
||||||
CVDisplayLinkCreateWithCGDisplay(displayID, &entry->displayLink);
|
_glfw_create_cv_display_link(entry);
|
||||||
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)displayID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll for changes in the set of connected monitors
|
// Poll for changes in the set of connected monitors
|
||||||
|
|||||||
3
glfw/cocoa_platform.h
vendored
3
glfw/cocoa_platform.h
vendored
@ -158,7 +158,7 @@ typedef struct _GLFWDisplayLinkNS
|
|||||||
{
|
{
|
||||||
CVDisplayLinkRef displayLink;
|
CVDisplayLinkRef displayLink;
|
||||||
CGDirectDisplayID displayID;
|
CGDirectDisplayID displayID;
|
||||||
monotonic_t lastRenderFrameRequestedAt;
|
monotonic_t lastRenderFrameRequestedAt, first_unserviced_render_frame_request_at;
|
||||||
} _GLFWDisplayLinkNS;
|
} _GLFWDisplayLinkNS;
|
||||||
|
|
||||||
// Cocoa-specific global data
|
// Cocoa-specific global data
|
||||||
@ -246,3 +246,4 @@ void _glfwDispatchTickCallback(void);
|
|||||||
void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
||||||
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
||||||
void _glfwCocoaPostEmptyEvent(void);
|
void _glfwCocoaPostEmptyEvent(void);
|
||||||
|
void _glfw_create_cv_display_link(_GLFWDisplayLinkNS *entry);
|
||||||
|
|||||||
@ -317,6 +317,7 @@ _glfwShutdownCVDisplayLink(unsigned long long timer_id UNUSED, void *user_data U
|
|||||||
_GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i];
|
_GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i];
|
||||||
if (dl->displayLink) CVDisplayLinkStop(dl->displayLink);
|
if (dl->displayLink) CVDisplayLinkStop(dl->displayLink);
|
||||||
dl->lastRenderFrameRequestedAt = 0;
|
dl->lastRenderFrameRequestedAt = 0;
|
||||||
|
dl->first_unserviced_render_frame_request_at = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,10 +341,22 @@ requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) {
|
|||||||
_GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i];
|
_GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i];
|
||||||
if (dl->displayID == displayID) {
|
if (dl->displayID == displayID) {
|
||||||
dl->lastRenderFrameRequestedAt = now;
|
dl->lastRenderFrameRequestedAt = now;
|
||||||
|
if (!dl->first_unserviced_render_frame_request_at) dl->first_unserviced_render_frame_request_at = now;
|
||||||
if (!CVDisplayLinkIsRunning(dl->displayLink)) CVDisplayLinkStart(dl->displayLink);
|
if (!CVDisplayLinkIsRunning(dl->displayLink)) CVDisplayLinkStart(dl->displayLink);
|
||||||
|
else if (now - dl->first_unserviced_render_frame_request_at > s_to_monotonic_t(1ll)) {
|
||||||
|
// display link is stuck need to recreate it because Apple cant even
|
||||||
|
// get a simple timer right
|
||||||
|
CVDisplayLinkRelease(dl->displayLink); dl->displayLink = nil;
|
||||||
|
dl->first_unserviced_render_frame_request_at = now;
|
||||||
|
_glfw_create_cv_display_link(dl);
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"CVDisplayLink stuck possibly because of sleep/screensaver + Apple's incompetence, recreating.");
|
||||||
|
if (!CVDisplayLinkIsRunning(dl->displayLink)) CVDisplayLinkStart(dl->displayLink);
|
||||||
|
}
|
||||||
} else if (dl->displayLink && dl->lastRenderFrameRequestedAt && now - dl->lastRenderFrameRequestedAt >= DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL) {
|
} else if (dl->displayLink && dl->lastRenderFrameRequestedAt && now - dl->lastRenderFrameRequestedAt >= DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL) {
|
||||||
CVDisplayLinkStop(dl->displayLink);
|
CVDisplayLinkStop(dl->displayLink);
|
||||||
dl->lastRenderFrameRequestedAt = 0;
|
dl->lastRenderFrameRequestedAt = 0;
|
||||||
|
dl->first_unserviced_render_frame_request_at = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2141,6 +2154,12 @@ _glfwDispatchRenderFrame(CGDirectDisplayID displayID) {
|
|||||||
}
|
}
|
||||||
w = w->next;
|
w = w->next;
|
||||||
}
|
}
|
||||||
|
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||||
|
_GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i];
|
||||||
|
if (dl->displayID == displayID) {
|
||||||
|
dl->first_unserviced_render_frame_request_at = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user