+/**
+ * Driver hook for glQueryCounter().
+ *
+ * This handles GL_TIMESTAMP queries, which perform a pipelined read of the
+ * current GPU time. This is unlike GL_TIME_ELAPSED, which measures the
+ * time while the query is active.
+ */
+void
+brw_query_counter(struct gl_context *ctx, struct gl_query_object *q)
+{
+ struct brw_context *brw = brw_context(ctx);
+ struct brw_query_object *query = (struct brw_query_object *) q;
+
+ assert(q->Target == GL_TIMESTAMP);
+
+ drm_intel_bo_unreference(query->bo);
+ query->bo = drm_intel_bo_alloc(brw->bufmgr, "timestamp query", 4096, 4096);
+ brw_write_timestamp(brw, query->bo, 0);
+
+ query->flushed = false;
+}
+
+/**
+ * Read the TIMESTAMP register immediately (in a non-pipelined fashion).
+ *
+ * This is used to implement the GetTimestamp() driver hook.
+ */
+static uint64_t
+brw_get_timestamp(struct gl_context *ctx)
+{
+ struct brw_context *brw = brw_context(ctx);
+ uint64_t result = 0;
+
+ 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 *= 80;
+ result &= (1ull << 36) - 1;
+ return result;
+}
+
+/**
+ * Is this type of query written by PIPE_CONTROL?
+ */
+bool
+brw_is_query_pipelined(struct brw_query_object *query)
+{
+ switch (query->Base.Target) {
+ case GL_TIMESTAMP:
+ case GL_TIME_ELAPSED:
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ case GL_SAMPLES_PASSED_ARB:
+ return true;
+
+ case GL_PRIMITIVES_GENERATED:
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ case GL_VERTICES_SUBMITTED_ARB:
+ case GL_PRIMITIVES_SUBMITTED_ARB:
+ case GL_VERTEX_SHADER_INVOCATIONS_ARB:
+ case GL_GEOMETRY_SHADER_INVOCATIONS:
+ case GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB:
+ case GL_FRAGMENT_SHADER_INVOCATIONS_ARB:
+ case GL_CLIPPING_INPUT_PRIMITIVES_ARB:
+ case GL_CLIPPING_OUTPUT_PRIMITIVES_ARB:
+ case GL_COMPUTE_SHADER_INVOCATIONS_ARB:
+ case GL_TESS_CONTROL_SHADER_PATCHES_ARB:
+ case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB:
+ return false;
+
+ default:
+ unreachable("Unrecognized query target in is_query_pipelined()");
+ }
+}
+
+/* Initialize query object functions used on all generations. */
+void brw_init_common_queryobj_functions(struct dd_function_table *functions)