diff options
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_device.c | 25 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_device.h | 4 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c | 2 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_ext_swapinterval.c | 25 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_framebuffer.c | 37 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_framebuffer.h | 3 | ||||
-rw-r--r-- | src/gallium/state_trackers/wgl/stw_getprocaddress.c | 2 |
7 files changed, 86 insertions, 12 deletions
diff --git a/src/gallium/state_trackers/wgl/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c index b57f96f2e87..42a2f0e82f9 100644 --- a/src/gallium/state_trackers/wgl/stw_device.c +++ b/src/gallium/state_trackers/wgl/stw_device.c @@ -63,6 +63,24 @@ stw_get_param(struct st_manager *smapi, } } + +/** Get the refresh rate for the monitor, in Hz */ +static int +get_refresh_rate(void) +{ + DEVMODE devModes; + + if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devModes)) { + /* clamp the value, just in case we get garbage */ + return CLAMP(devModes.dmDisplayFrequency, 30, 120); + } + else { + /* reasonable default */ + return 60; + } +} + + boolean stw_init(const struct stw_winsys *stw_winsys) { @@ -116,6 +134,13 @@ stw_init(const struct stw_winsys *stw_winsys) stw_pixelformat_init(); + /* env var override for WGL_EXT_swap_control, useful for testing/debugging */ + const char *s = os_get_option("SVGA_SWAP_INTERVAL"); + if (s) { + stw_dev->swap_interval = atoi(s); + } + stw_dev->refresh_rate = get_refresh_rate(); + stw_dev->initialized = true; return TRUE; diff --git a/src/gallium/state_trackers/wgl/stw_device.h b/src/gallium/state_trackers/wgl/stw_device.h index ecf212d7cb6..766975c292c 100644 --- a/src/gallium/state_trackers/wgl/stw_device.h +++ b/src/gallium/state_trackers/wgl/stw_device.h @@ -78,6 +78,10 @@ struct stw_device unsigned long memdbg_no; #endif + /** WGL_EXT_swap_control */ + int refresh_rate; + int swap_interval; + bool initialized; }; diff --git a/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c b/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c index 06af8b1e994..996eb586d94 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c +++ b/src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c @@ -45,7 +45,7 @@ static const char *stw_extension_string = "WGL_EXT_create_context_es_profile " "WGL_EXT_create_context_es2_profile " "WGL_ARB_make_current_read " -/* "WGL_EXT_swap_interval " */ + "WGL_EXT_swap_control " "WGL_EXT_extensions_string"; diff --git a/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c b/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c index b960913ccbb..b2074a73fb7 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c +++ b/src/gallium/state_trackers/wgl/stw_ext_swapinterval.c @@ -33,25 +33,30 @@ #include <GL/gl.h> #include <GL/wglext.h> #include "util/u_debug.h" +#include "stw_device.h" -/* A dummy implementation of this extension. - * - * Required as some applications retrieve and call these functions - * regardless of the fact that we don't advertise the extension and - * further more the results of wglGetProcAddress are NULL. + +/** + * Note that our implementation of swap intervals is a bit of a hack. + * We implement it based on querying the time and Sleep()'ing. We don't + * sync to the vblank. */ WINGDIAPI BOOL APIENTRY wglSwapIntervalEXT(int interval) { - (void) interval; - debug_printf("%s: %d\n", __FUNCTION__, interval); + if (interval < 0) { + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + if (stw_dev) { + stw_dev->swap_interval = interval; + } return TRUE; } + WINGDIAPI int APIENTRY wglGetSwapIntervalEXT(void) { - return 0; + return stw_dev ? stw_dev->swap_interval : 0; } - - diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.c b/src/gallium/state_trackers/wgl/stw_framebuffer.c index 09b57766dc0..321fbb6ea77 100644 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.c +++ b/src/gallium/state_trackers/wgl/stw_framebuffer.c @@ -30,6 +30,7 @@ #include "pipe/p_screen.h" #include "util/u_memory.h" #include "hud/hud_context.h" +#include "os/os_time.h" #include "state_tracker/st_api.h" #include "stw_icd.h" @@ -580,6 +581,38 @@ stw_framebuffer_present_locked(HDC hdc, } +/** + * This is called just before issuing the buffer swap/present. + * We query the current time and determine if we should sleep before + * issuing the swap/present. + * This is a bit of a hack and is certainly not very accurate but it + * basically works. + * This is for the WGL_ARB_swap_interval extension. + */ +static void +wait_swap_interval(struct stw_framebuffer *fb) +{ + /* Note: all time variables here are in units of microseconds */ + int64_t cur_time = os_time_get_nano() / 1000; + + if (fb->prev_swap_time != 0) { + /* Compute time since previous swap */ + int64_t delta = cur_time - fb->prev_swap_time; + int64_t min_swap_period = + 1.0e6 / stw_dev->refresh_rate * stw_dev->swap_interval; + + /* if time since last swap is less than wait period, wait */ + if (delta < min_swap_period) { + float fudge = 1.75f; /* emperical fudge factor */ + int64_t wait = (min_swap_period - delta) * fudge; + os_time_sleep(wait); + } + } + + fb->prev_swap_time = cur_time; +} + + BOOL APIENTRY DrvSwapBuffers(HDC hdc) { @@ -615,6 +648,10 @@ DrvSwapBuffers(HDC hdc) } } + if (stw_dev->swap_interval != 0) { + wait_swap_interval(fb); + } + return stw_st_swap_framebuffer_locked(hdc, fb->stfb); } diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.h b/src/gallium/state_trackers/wgl/stw_framebuffer.h index 029fb9ffa34..d44c3a6634a 100644 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.h +++ b/src/gallium/state_trackers/wgl/stw_framebuffer.h @@ -108,6 +108,9 @@ struct stw_framebuffer HANDLE hSharedSurface; struct stw_shared_surface *shared_surface; + /* For WGL_EXT_swap_control */ + int64_t prev_swap_time; + /** * This is protected by stw_device::fb_mutex, not the mutex above. * diff --git a/src/gallium/state_trackers/wgl/stw_getprocaddress.c b/src/gallium/state_trackers/wgl/stw_getprocaddress.c index 9273d103310..c8138f61fa4 100644 --- a/src/gallium/state_trackers/wgl/stw_getprocaddress.c +++ b/src/gallium/state_trackers/wgl/stw_getprocaddress.c @@ -67,7 +67,7 @@ static const struct stw_extension_entry stw_extension_entries[] = { /* WGL_EXT_extensions_string */ STW_EXTENSION_ENTRY( wglGetExtensionsStringEXT ), - /* WGL_EXT_swap_interval */ + /* WGL_EXT_swap_control */ STW_EXTENSION_ENTRY( wglGetSwapIntervalEXT ), STW_EXTENSION_ENTRY( wglSwapIntervalEXT ), |