summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r--src/gallium/state_trackers/wgl/stw_device.c25
-rw-r--r--src/gallium/state_trackers/wgl/stw_device.h4
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_extensionsstring.c2
-rw-r--r--src/gallium/state_trackers/wgl/stw_ext_swapinterval.c25
-rw-r--r--src/gallium/state_trackers/wgl/stw_framebuffer.c37
-rw-r--r--src/gallium/state_trackers/wgl/stw_framebuffer.h3
-rw-r--r--src/gallium/state_trackers/wgl/stw_getprocaddress.c2
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 ),