diff --git a/gdk/quartz/gdkdrawable-quartz.c b/gdk/quartz/gdkdrawable-quartz.c index ce1513e5ea..97b17a9729 100644 --- a/gdk/quartz/gdkdrawable-quartz.c +++ b/gdk/quartz/gdkdrawable-quartz.c @@ -19,6 +19,7 @@ */ #include "config.h" +#include #include #include "gdkprivate-quartz.h" @@ -725,6 +726,39 @@ gdk_quartz_drawable_get_context (GdkDrawable *drawable, return GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->get_context (drawable, antialias); } +/* Help preventing "beam synch penalty" where CG makes all graphics code + * block until the next vsync if we try to flush (including call display on + * a view) too often. We do this by limiting the manual flushing done + * outside of expose calls to less than 20Hz, this should leave enough room + * for the 60Hz max rate including the "regular" flushing. + * + * If cg_context is NULL, no flushing is done, only registering that a flush + * was made externally. + */ +void +_gdk_quartz_drawable_flush (CGContextRef cg_context) +{ + static struct timeval prev_tv; + struct timeval tv; + gint ms; + + gettimeofday (&tv, NULL); + + if (cg_context) + { + ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000; + + /* ~20Hz. */ + if (ms > 50) + { + CGContextFlush (cg_context); + prev_tv = tv; + } + } + else + prev_tv = tv; +} + void gdk_quartz_drawable_release_context (GdkDrawable *drawable, CGContextRef cg_context) @@ -738,7 +772,10 @@ gdk_quartz_drawable_release_context (GdkDrawable *drawable, /* See comment in gdk_quartz_drawable_get_context(). */ if (window_impl->in_paint_rect_count == 0) - [window_impl->view unlockFocus]; + { + _gdk_quartz_drawable_flush (cg_context); + [window_impl->view unlockFocus]; + } } else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable)) CGContextRelease (cg_context); diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h index 299616ff1a..8bb7ea596a 100644 --- a/gdk/quartz/gdkprivate-quartz.h +++ b/gdk/quartz/gdkprivate-quartz.h @@ -180,6 +180,7 @@ gboolean _gdk_quartz_keys_is_modifier (guint keycode); /* Drawable */ void _gdk_quartz_drawable_finish (GdkDrawable *drawable); +void _gdk_quartz_drawable_flush (CGContextRef cg_context); /* Geometry */ void _gdk_quartz_window_scroll (GdkWindow *window, diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index 0586460a1f..f112497e4f 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -424,6 +424,8 @@ _gdk_windowing_after_process_all_updates (void) [[nswindow contentView] displayIfNeeded]; + _gdk_quartz_drawable_flush (NULL); + [nswindow enableFlushWindow]; [nswindow flushWindow]; [nswindow release];