diff options
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_queryobj.c | 15 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/intel_screen.c | 49 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/intel_screen.h | 2 |
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? |