summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/drivers/dri/i965/brw_queryobj.c15
-rw-r--r--src/mesa/drivers/dri/i965/intel_screen.c49
-rw-r--r--src/mesa/drivers/dri/i965/intel_screen.h2
3 files changed, 49 insertions, 17 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
index aea4d9b77d3..d6b012c392e 100644
--- a/src/mesa/drivers/dri/i965/brw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
@@ -497,13 +497,22 @@ brw_get_timestamp(struct gl_context *ctx)
struct brw_context *brw = brw_context(ctx);
uint64_t result = 0;
- drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &result);
+ switch (brw->intelScreen->hw_has_timestamp) {
+ case 3: /* New kernel, always full 36bit accuracy */
+ drm_intel_reg_read(brw->bufmgr, TIMESTAMP | 1, &result);
+ break;
+ case 2: /* 64bit kernel, result is left-shifted by 32bits, losing 4bits */
+ drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &result);
+ result = result >> 32;
+ break;
+ case 1: /* 32bit kernel, result is 36bit wide but may be inaccurate! */
+ drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &result);
+ break;
+ }
/* See logic in brw_queryobj_get_results() */
- result = result >> 32;
result *= 80;
result &= (1ull << 36) - 1;
-
return result;
}
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index 1470b059d9b..65a17664188 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -1123,25 +1123,48 @@ intel_detect_swizzling(struct intel_screen *screen)
return true;
}
-static bool
+static int
intel_detect_timestamp(struct intel_screen *screen)
{
- uint64_t dummy = 0;
- int loop = 10;
+ uint64_t dummy = 0, last = 0;
+ int upper, lower, loops;
- /*
- * On 32bit systems, some old kernels trigger a hw bug resulting in the
- * TIMESTAMP register being shifted and the low 32bits always zero. Detect
- * this by repeating the read a few times and check the register is
- * incrementing every 80ns as expected and not stuck on zero (as would be
- * the case with the buggy kernel/hw.).
+ /* On 64bit systems, some old kernels trigger a hw bug resulting in the
+ * TIMESTAMP register being shifted and the low 32bits always zero.
+ *
+ * More recent kernels offer an interface to read the full 36bits
+ * everywhere.
*/
- do {
+ if (drm_intel_reg_read(screen->bufmgr, TIMESTAMP | 1, &dummy) == 0)
+ return 3;
+
+ /* Determine if we have a 32bit or 64bit kernel by inspecting the
+ * upper 32bits for a rapidly changing timestamp.
+ */
+ if (drm_intel_reg_read(screen->bufmgr, TIMESTAMP, &last))
+ return 0;
+
+ upper = lower = 0;
+ for (loops = 0; loops < 10; loops++) {
+ /* The TIMESTAMP should change every 80ns, so several round trips
+ * through the kernel should be enough to advance it.
+ */
if (drm_intel_reg_read(screen->bufmgr, TIMESTAMP, &dummy))
- return false;
- } while ((dummy & 0xffffffff) == 0 && --loop);
+ return 0;
+
+ upper += (dummy >> 32) != (last >> 32);
+ if (upper > 1) /* beware 32bit counter overflow */
+ return 2; /* upper dword holds the low 32bits of the timestamp */
+
+ lower += (dummy & 0xffffffff) != (last & 0xffffffff);
+ if (lower > 1)
+ return 1; /* timestamp is unshifted */
+
+ last = dummy;
+ }
- return loop > 0;
+ /* No advancement? No timestamp! */
+ return 0;
}
/**
diff --git a/src/mesa/drivers/dri/i965/intel_screen.h b/src/mesa/drivers/dri/i965/intel_screen.h
index a741c94e0ff..fd5143eecba 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.h
+++ b/src/mesa/drivers/dri/i965/intel_screen.h
@@ -52,7 +52,7 @@ struct intel_screen
bool hw_has_swizzling;
- bool hw_has_timestamp;
+ int hw_has_timestamp;
/**
* Does the kernel support resource streamer?