From 27d9f233d4d8155d4c00e4313dd7402932e5c9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1?= =?UTF-8?q?=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= Date: Mon, 9 Apr 2018 20:16:23 +0000 Subject: [PATCH] GDK W32: use clock after_paint signal for timing updates * Previous commit had misleading info. The code was added to begin_paint() instead of end_paint(). Though that did not affect its performance in any visible way. * Company advised to move the code to an "after_paint" signal handler, so that it works on all renderers, not just Cairo. This change caused high fluctuation in FPS values in fishbowl when it is put in a situation where it cannot achieve 60fps (such as using Cairo renderer at ultra-high resolution). This seems to be deliberate and not a bug. --- gdk/win32/gdksurface-win32.c | 73 +++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c index ed128137d1..fc5a2fe943 100644 --- a/gdk/win32/gdksurface-win32.c +++ b/gdk/win32/gdksurface-win32.c @@ -128,6 +128,8 @@ typedef struct _AeroSnapEdgeRegion AeroSnapEdgeRegion; */ #define AEROSNAP_INDICATOR_ANIMATION_TICK (16) +static void gdk_win32_impl_frame_clock_after_paint (GdkFrameClock *clock, + GdkSurface *surface); static gboolean _gdk_surface_get_functions (GdkSurface *window, GdkWMFunction *functions); static HDC _gdk_win32_impl_acquire_dc (GdkSurfaceImplWin32 *impl); @@ -338,43 +340,12 @@ gdk_win32_surface_begin_paint (GdkSurface *window) { GdkSurfaceImplWin32 *impl; RECT window_rect; - DWM_TIMING_INFO timing_info; - LARGE_INTEGER tick_frequency; - GdkFrameTimings *timings = NULL; - GdkFrameClock *clock = NULL; if (window == NULL || GDK_SURFACE_DESTROYED (window)) return TRUE; impl = GDK_SURFACE_IMPL_WIN32 (window->impl); - clock = gdk_surface_get_frame_clock (window); - - if (clock) - timings = gdk_frame_clock_get_timings (clock, gdk_frame_clock_get_frame_counter (clock)); - - if (timings) - { - timings->refresh_interval = 16667; /* default to 1/60th of a second */ - timings->presentation_time = 0; - - if (QueryPerformanceFrequency (&tick_frequency)) - { - HRESULT hr; - - timing_info.cbSize = sizeof (timing_info); - hr = DwmGetCompositionTimingInfo (NULL, &timing_info); - - if (SUCCEEDED (hr)) - { - timings->refresh_interval = timing_info.qpcRefreshPeriod * (gdouble)G_USEC_PER_SEC / tick_frequency.QuadPart; - timings->presentation_time = timing_info.qpcCompose * (gdouble)G_USEC_PER_SEC / tick_frequency.QuadPart; - } - } - - timings->complete = TRUE; - } - /* Layered windows are moved *after* repaint. * We supply our own surface, return FALSE to make GDK use it. */ @@ -507,6 +478,39 @@ gdk_win32_surface_end_paint (GdkSurface *window) 0, &blender, ULW_ALPHA)); } +static void +gdk_win32_impl_frame_clock_after_paint (GdkFrameClock *clock, + GdkSurface *surface) +{ + DWM_TIMING_INFO timing_info; + LARGE_INTEGER tick_frequency; + GdkFrameTimings *timings; + + timings = gdk_frame_clock_get_timings (clock, gdk_frame_clock_get_frame_counter (clock)); + + if (timings) + { + timings->refresh_interval = 16667; /* default to 1/60th of a second */ + timings->presentation_time = 0; + + if (QueryPerformanceFrequency (&tick_frequency)) + { + HRESULT hr; + + timing_info.cbSize = sizeof (timing_info); + hr = DwmGetCompositionTimingInfo (NULL, &timing_info); + + if (SUCCEEDED (hr)) + { + timings->refresh_interval = timing_info.qpcRefreshPeriod * (gdouble)G_USEC_PER_SEC / tick_frequency.QuadPart; + timings->presentation_time = timing_info.qpcCompose * (gdouble)G_USEC_PER_SEC / tick_frequency.QuadPart; + } + } + + timings->complete = TRUE; + } +} + void _gdk_win32_adjust_client_rect (GdkSurface *window, RECT *rect) @@ -751,6 +755,7 @@ _gdk_win32_display_create_surface_impl (GdkDisplay *display, gint window_width, window_height; gint offset_x = 0, offset_y = 0; gint x, y, real_x = 0, real_y = 0; + GdkFrameClock *frame_clock; g_return_if_fail (display == _gdk_display); @@ -948,6 +953,12 @@ _gdk_win32_display_create_surface_impl (GdkDisplay *display, // gdk_surface_set_skip_taskbar_hint (window, TRUE); _gdk_win32_surface_enable_transparency (window); + + frame_clock = gdk_surface_get_frame_clock (window); + g_signal_connect (frame_clock, + "after-paint", + G_CALLBACK (gdk_win32_impl_frame_clock_after_paint), + window); } GdkSurface *