[gtk/wip/chergert/for-4-6: 13/56] macos: use video mode for refresh rate and interval
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/for-4-6: 13/56] macos: use video mode for refresh rate and interval
- Date: Wed, 16 Mar 2022 19:25:44 +0000 (UTC)
commit df2fb3b5209dcb0740a0af6d8fde5b490e310169
Author: Christian Hergert <christian hergert me>
Date: Sun Feb 27 23:17:40 2022 -0800
macos: use video mode for refresh rate and interval
Using the mode allows better detection of refresh rate and refresh
interval for the CVDisplayLink bridge to GdkFrameClock. Using it can help
ensure that our 144hz displays can actually reach that rather than falling
back to just 60hz.
This will also need future commits to rework the displaylink source to be
per-monitor.
gdk/macos/gdkdisplaylinksource.c | 61 ++++++++++++++++++++++++++++------------
gdk/macos/gdkdisplaylinksource.h | 4 ++-
2 files changed, 46 insertions(+), 19 deletions(-)
---
diff --git a/gdk/macos/gdkdisplaylinksource.c b/gdk/macos/gdkdisplaylinksource.c
index 8b2f1a013f..fe75eb3a55 100644
--- a/gdk/macos/gdkdisplaylinksource.c
+++ b/gdk/macos/gdkdisplaylinksource.c
@@ -65,7 +65,7 @@ gdk_display_link_source_dispatch (GSource *source,
impl->needs_dispatch = FALSE;
- if (callback != NULL)
+ if (!impl->paused && callback != NULL)
ret = callback (user_data);
return ret;
@@ -76,7 +76,9 @@ gdk_display_link_source_finalize (GSource *source)
{
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
- CVDisplayLinkStop (impl->display_link);
+ if (!impl->paused)
+ CVDisplayLinkStop (impl->display_link);
+
CVDisplayLinkRelease (impl->display_link);
}
@@ -90,12 +92,18 @@ static GSourceFuncs gdk_display_link_source_funcs = {
void
gdk_display_link_source_pause (GdkDisplayLinkSource *source)
{
+ g_return_if_fail (source->paused == FALSE);
+
+ source->paused = TRUE;
CVDisplayLinkStop (source->display_link);
}
void
gdk_display_link_source_unpause (GdkDisplayLinkSource *source)
{
+ g_return_if_fail (source->paused == TRUE);
+
+ source->paused = FALSE;
CVDisplayLinkStart (source->display_link);
}
@@ -160,16 +168,16 @@ gdk_display_link_source_frame_cb (CVDisplayLinkRef display_link,
* Returns: (transfer full): A newly created `GSource`
*/
GSource *
-gdk_display_link_source_new (CGDirectDisplayID display_id)
+gdk_display_link_source_new (CGDirectDisplayID display_id,
+ CGDisplayModeRef mode)
{
GdkDisplayLinkSource *impl;
GSource *source;
- CVReturn ret;
- double period;
source = g_source_new (&gdk_display_link_source_funcs, sizeof *impl);
impl = (GdkDisplayLinkSource *)source;
impl->display_id = display_id;
+ impl->paused = TRUE;
/* Create DisplayLink for timing information for the display in
* question so that we can produce graphics for that display at whatever
@@ -178,21 +186,34 @@ gdk_display_link_source_new (CGDirectDisplayID display_id)
if (CVDisplayLinkCreateWithCGDisplay (display_id, &impl->display_link) != kCVReturnSuccess)
{
g_warning ("Failed to initialize CVDisplayLink!");
- return source;
+ goto failure;
}
- /*
- * Determine our nominal period between frames.
- */
- period = CVDisplayLinkGetActualOutputVideoRefreshPeriod (impl->display_link);
- if (period == 0.0)
- period = 1.0 / 60.0;
- impl->refresh_interval = period * 1000000L;
- impl->refresh_rate = 1.0 / period * 1000L;
-
- /*
- * Wire up our callback to be executed within the high-priority thread.
- */
+ impl->refresh_rate = CGDisplayModeGetRefreshRate (mode) * 1000.0;
+
+ if (impl->refresh_rate == 0)
+ {
+ const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod (impl->display_link);
+ if (!(time.flags & kCVTimeIsIndefinite))
+ impl->refresh_rate = (double)time.timeScale / (double)time.timeValue * 1000.0;
+ }
+
+ if (impl->refresh_rate != 0)
+ {
+ impl->refresh_interval = 1000000.0 / (double)impl->refresh_rate * 1000.0;
+ }
+ else
+ {
+ double period = CVDisplayLinkGetActualOutputVideoRefreshPeriod (impl->display_link);
+
+ if (period == 0.0)
+ period = 1.0 / 60.0;
+
+ impl->refresh_rate = 1.0 / period * 1000L;
+ impl->refresh_interval = period * 1000000L;
+ }
+
+ /* Wire up our callback to be executed within the high-priority thread. */
CVDisplayLinkSetOutputCallback (impl->display_link,
gdk_display_link_source_frame_cb,
source);
@@ -200,6 +221,10 @@ gdk_display_link_source_new (CGDirectDisplayID display_id)
g_source_set_static_name (source, "[gdk] quartz frame clock");
return source;
+
+failure:
+ g_source_unref (source);
+ return NULL;
}
static gint64
diff --git a/gdk/macos/gdkdisplaylinksource.h b/gdk/macos/gdkdisplaylinksource.h
index bff1c91475..6f465907a2 100644
--- a/gdk/macos/gdkdisplaylinksource.h
+++ b/gdk/macos/gdkdisplaylinksource.h
@@ -36,12 +36,14 @@ typedef struct
CVDisplayLinkRef display_link;
gint64 refresh_interval;
guint refresh_rate;
+ guint paused : 1;
volatile gint64 presentation_time;
volatile guint needs_dispatch;
} GdkDisplayLinkSource;
-GSource *gdk_display_link_source_new (CGDirectDisplayID display_id);
+GSource *gdk_display_link_source_new (CGDirectDisplayID display_id,
+ CGDisplayModeRef mode);
void gdk_display_link_source_pause (GdkDisplayLinkSource *source);
void gdk_display_link_source_unpause (GdkDisplayLinkSource *source);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]