[PATCH 04/11] wined3d: Add support for D3DQUERY_TIMESTAMP queries.
Adam Martinson
amartinson at codeweavers.com
Mon May 23 15:13:45 CDT 2011
---
dlls/wined3d/context.c | 80 +++++++++++++++++++
dlls/wined3d/query.c | 165 +++++++++++++++++++++++++++++++++++++---
dlls/wined3d/wined3d_private.h | 17 ++++
3 files changed, 250 insertions(+), 12 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 0494252..02aa5c4 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -650,6 +650,66 @@ void context_free_event_query(struct wined3d_event_query *query)
context->free_event_queries[context->free_event_query_count++] = query->object;
}
+/* Context activation is done by the caller.
+ * Only called when GL_ARB_timer_query is supported. */
+void context_alloc_timestamp_query(struct wined3d_context *context, struct wined3d_timestamp_query *query)
+{
+ const struct wined3d_gl_info *gl_info = context->gl_info;
+ int i, n_new;
+
+ for (i = 0; i < query->n_ids && i < context->free_timestamp_query_count; ++i)
+ query->ids[i] = context->free_timestamp_queries[--context->free_timestamp_query_count];
+
+ if ((n_new = query->n_ids - i))
+ {
+
+ ENTER_GL();
+ GL_EXTCALL(glGenQueriesARB(n_new, &query->ids[i]));
+ checkGLcall("glGenQueriesARB");
+ LEAVE_GL();
+
+ if (TRACE_ON(d3d))
+ {
+ for (; i < query->n_ids; ++i)
+ TRACE("Allocated timestamp query %u in context %p.\n", query->ids[i], context);
+ }
+ }
+
+ query->context = context;
+ list_add_head(&context->timestamp_queries, &query->entry);
+}
+
+/* Context activation is done by the caller.
+ * Only called when GL_ARB_timer_query is supported. */
+void context_free_timestamp_query(struct wined3d_timestamp_query *query)
+{
+ struct wined3d_context *context = query->context;
+ int i;
+
+ list_remove(&query->entry);
+ query->context = NULL;
+
+ if (context->free_timestamp_query_count + query->n_ids >= context->free_timestamp_query_size)
+ {
+ UINT new_size = context->free_timestamp_query_size << 1;
+ GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_timestamp_queries,
+ new_size * sizeof(*context->free_timestamp_queries));
+
+ if (!new_data)
+ {
+ for (i = 0; i < query->n_ids; ++i)
+ ERR("Failed to grow free list, leaking query %u in context %p.\n", query->ids[i], context);
+ return;
+ }
+
+ context->free_timestamp_query_size = new_size;
+ context->free_timestamp_queries = new_data;
+ }
+
+ for (i = 0; i < query->n_ids; ++i)
+ context->free_timestamp_queries[context->free_timestamp_query_count++] = query->ids[i];
+}
+
typedef void (context_fbo_entry_func_t)(struct wined3d_context *context, struct fbo_entry *entry);
static void context_enum_surface_fbo_entries(struct wined3d_device *device,
@@ -924,6 +984,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
const struct wined3d_gl_info *gl_info = context->gl_info;
struct wined3d_occlusion_query *occlusion_query;
struct wined3d_event_query *event_query;
+ struct wined3d_timestamp_query *timestamp_query;
struct fbo_entry *entry, *entry2;
HGLRC restore_ctx;
HDC restore_dc;
@@ -960,6 +1021,13 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
event_query->context = NULL;
}
+ LIST_FOR_EACH_ENTRY(timestamp_query, &context->timestamp_queries, struct wined3d_timestamp_query, entry)
+ {
+ if (context->valid && gl_info->supported[ARB_TIMER_QUERY])
+ GL_EXTCALL(glDeleteQueriesARB(timestamp_query->n_ids, timestamp_query->ids));
+ timestamp_query->context = NULL;
+ }
+
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_destroy_list, struct fbo_entry, entry)
{
if (!context->valid) entry->id = 0;
@@ -987,6 +1055,9 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
if (gl_info->supported[ARB_OCCLUSION_QUERY])
GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries));
+ if (gl_info->supported[ARB_TIMER_QUERY])
+ GL_EXTCALL(glDeleteQueriesARB(context->free_timestamp_query_count, context->free_timestamp_queries));
+
if (gl_info->supported[ARB_SYNC])
{
for (i = 0; i < context->free_event_query_count; ++i)
@@ -1016,6 +1087,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries);
HeapFree(GetProcessHeap(), 0, context->free_event_queries);
+ HeapFree(GetProcessHeap(), 0, context->free_timestamp_queries);
if (restore_ctx)
{
@@ -1512,6 +1584,13 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
list_init(&ret->event_queries);
+ ret->free_timestamp_query_size = 4;
+ ret->free_timestamp_queries = HeapAlloc(GetProcessHeap(), 0,
+ ret->free_timestamp_query_size * sizeof(*ret->free_timestamp_queries));
+ if (!ret->free_timestamp_queries) goto out;
+
+ list_init(&ret->timestamp_queries);
+
TRACE("Successfully created new context %p\n", ret);
list_init(&ret->fbo_list);
@@ -1660,6 +1739,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
out:
HeapFree(GetProcessHeap(), 0, ret->free_event_queries);
HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
+ HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries);
HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
HeapFree(GetProcessHeap(), 0, ret->blit_targets);
HeapFree(GetProcessHeap(), 0, ret->pshader_const_dirty);
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index ca4426f..c0d5c63 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -4,6 +4,7 @@
* Copyright 2005 Oliver Stieber
* Copyright 2007-2008 Stefan Dösinger for CodeWeavers
* Copyright 2009-2010 Henri Verbeet for CodeWeavers.
+ * Copyright 2011 Adam Martinson for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -253,17 +254,35 @@ ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
* deleting the query will obviously leak it, but that's still better
* than potentially deleting a different query with the same id in this
* context, and (still) leaking the actual query. */
- if (query->type == WINED3DQUERYTYPE_EVENT)
+ switch (query->type)
{
- struct wined3d_event_query *event_query = query->extendedData;
- if (event_query) wined3d_event_query_destroy(event_query);
- }
- else if (query->type == WINED3DQUERYTYPE_OCCLUSION)
- {
- struct wined3d_occlusion_query *oq = query->extendedData;
+ case WINED3DQUERYTYPE_EVENT:
+ {
+ struct wined3d_event_query *event_query = query->extendedData;
+ if (event_query) wined3d_event_query_destroy(event_query);
+ }
+ break;
+
+ case WINED3DQUERYTYPE_OCCLUSION:
+ {
+ struct wined3d_occlusion_query *oq = query->extendedData;
- if (oq->context) context_free_occlusion_query(oq);
- HeapFree(GetProcessHeap(), 0, query->extendedData);
+ if (oq->context) context_free_occlusion_query(oq);
+ HeapFree(GetProcessHeap(), 0, query->extendedData);
+ }
+ break;
+
+ case WINED3DQUERYTYPE_TIMESTAMP:
+ {
+ struct wined3d_timestamp_query *tsq = query->extendedData;
+
+ if (tsq->context) context_free_timestamp_query(tsq);
+ HeapFree(GetProcessHeap(), 0, query->extendedData);
+ }
+ break;
+
+ default:
+ break;
}
HeapFree(GetProcessHeap(), 0, query);
@@ -414,6 +433,69 @@ static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query,
return S_OK;
}
+/* Only called when GL_ARB_timer_query is supported. */
+static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query,
+ void *data, DWORD size, DWORD flags)
+{
+ const struct wined3d_gl_info *gl_info = &query->device->adapter->gl_info;
+ struct wined3d_timestamp_query *timestamp_query = query->extendedData;
+ struct wined3d_context *context;
+ GLuint available;
+ UINT64 *timestamp = data;
+ HRESULT res;
+
+ TRACE("(%p) : type D3DQUERY_TIMESTAMP, data %p, size %#x, flags %#x.\n", query, data, size, flags);
+
+ if (!timestamp_query->context)
+ query->state = QUERY_CREATED;
+
+ if (query->state != QUERY_SIGNALLED)
+ {
+ /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
+ TRACE("Query wasn't yet started, returning S_OK\n");
+ if (timestamp)
+ *timestamp = 0;
+ return S_OK;
+ }
+
+ if (timestamp_query->context->tid != GetCurrentThreadId())
+ {
+ FIXME("%p Wrong thread, returning 0.\n", query);
+ if (timestamp)
+ *timestamp = 0;
+ return S_OK;
+ }
+
+ context = context_acquire(query->device, timestamp_query->context->current_rt);
+
+ ENTER_GL();
+
+ GL_EXTCALL(glGetQueryObjectuivARB(timestamp_query->ids[0], GL_QUERY_RESULT_AVAILABLE_ARB, &available));
+ checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
+ TRACE("available %#x.\n", available);
+
+ if (available)
+ {
+ if (timestamp)
+ {
+ GL_EXTCALL(glGetQueryObjectui64v(timestamp_query->ids[0], GL_QUERY_RESULT_ARB, timestamp));
+ checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
+ TRACE("Returning 0x%08x%08x.\n", (UINT)((*timestamp) >> 32), (UINT)((*timestamp) & 0xFFFFFFFF));
+ }
+ res = S_OK;
+ }
+ else
+ {
+ res = S_FALSE;
+ }
+
+ LEAVE_GL();
+
+ context_release(context);
+
+ return res;
+}
+
WINED3DQUERYTYPE CDECL wined3d_query_get_type(const struct wined3d_query *query)
{
TRACE("query %p.\n", query);
@@ -537,6 +619,39 @@ static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DW
return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */
}
+/* Only called when GL_ARB_timer_query is supported. */
+static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags)
+{
+ const struct wined3d_gl_info *gl_info = &query->device->adapter->gl_info;
+ struct wined3d_timestamp_query *timestamp_query = query->extendedData;
+ struct wined3d_context *context;
+
+ TRACE("query %p, flags %#x.\n", query, flags);
+
+ /* MSDN: D3DISSUE_BEGIN not supported */
+
+ if (!timestamp_query->context)
+ {
+ context = context_acquire(query->device, NULL);
+ context_alloc_timestamp_query(context, timestamp_query);
+ }
+ else
+ {
+ context = context_acquire(query->device, timestamp_query->context->current_rt);
+ }
+
+ ENTER_GL();
+ GL_EXTCALL(glQueryCounter(timestamp_query->ids[0], GL_TIMESTAMP_ARB));
+ checkGLcall("glQueryCounter(GL_TIMESTAMP)");
+ LEAVE_GL();
+
+ context_release(context);
+
+ query->state = QUERY_SIGNALLED;
+
+ return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */
+}
+
static const struct wined3d_query_ops event_query_ops =
{
wined3d_event_query_ops_get_data,
@@ -549,6 +664,12 @@ static const struct wined3d_query_ops occlusion_query_ops =
wined3d_occlusion_query_ops_issue,
};
+static const struct wined3d_query_ops timestamp_query_ops =
+{
+ wined3d_timestamp_query_ops_get_data,
+ wined3d_timestamp_query_ops_issue,
+};
+
static HRESULT query_init(struct wined3d_query *query, struct wined3d_device *device, WINED3DQUERYTYPE type)
{
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
@@ -593,12 +714,32 @@ static HRESULT query_init(struct wined3d_query *query, struct wined3d_device *de
}
break;
- case WINED3DQUERYTYPE_VCACHE:
- case WINED3DQUERYTYPE_RESOURCEMANAGER:
- case WINED3DQUERYTYPE_VERTEXSTATS:
case WINED3DQUERYTYPE_TIMESTAMP:
+ TRACE("Timestamp query.\n");
+ if (!gl_info->supported[ARB_TIMER_QUERY])
+ {
+ WARN("GL_ARB_timer_query not supported, returning WINED3DERR_NOTAVAILABLE.\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ query->data_size = sizeof(UINT64);
+ query->query_ops = ×tamp_query_ops;
+ query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct wined3d_timestamp_query));
+ if (!query->extendedData)
+ {
+ ERR("Failed to allocate event query memory.\n");
+ return E_OUTOFMEMORY;
+ }
+ ((struct wined3d_timestamp_query *)query->extendedData)->n_ids = 1;
+ ((struct wined3d_timestamp_query *)query->extendedData)->context = NULL;
+
+ break;
+
case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
case WINED3DQUERYTYPE_TIMESTAMPFREQ:
+ case WINED3DQUERYTYPE_VCACHE:
+ case WINED3DQUERYTYPE_RESOURCEMANAGER:
+ case WINED3DQUERYTYPE_VERTEXSTATS:
case WINED3DQUERYTYPE_PIPELINETIMINGS:
case WINED3DQUERYTYPE_INTERFACETIMINGS:
case WINED3DQUERYTYPE_VERTEXTIMINGS:
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index aaf1423..39b39f8 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1019,6 +1019,15 @@ struct wined3d_event_query
struct wined3d_context *context;
};
+struct wined3d_timestamp_query
+{
+ struct list entry;
+ struct wined3d_context *context;
+ int n_ids;
+ GLuint ids[3];
+};
+
+
enum wined3d_event_query_result
{
WINED3D_EVENT_QUERY_OK,
@@ -1110,6 +1119,11 @@ struct wined3d_context
UINT free_event_query_count;
struct list event_queries;
+ GLuint *free_timestamp_queries;
+ UINT free_timestamp_query_size;
+ UINT free_timestamp_query_count;
+ struct list timestamp_queries;
+
/* Extension emulation */
GLint gl_fog_source;
GLfloat fog_coord_value;
@@ -1208,6 +1222,8 @@ void context_alloc_event_query(struct wined3d_context *context,
struct wined3d_event_query *query) DECLSPEC_HIDDEN;
void context_alloc_occlusion_query(struct wined3d_context *context,
struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
+void context_alloc_timestamp_query(struct wined3d_context *context,
+ struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN;
void context_apply_blit_state(struct wined3d_context *context, struct wined3d_device *device) DECLSPEC_HIDDEN;
BOOL context_apply_clear_state(struct wined3d_context *context, struct wined3d_device *device,
UINT rt_count, struct wined3d_surface **rts, struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN;
@@ -1223,6 +1239,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, stru
void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN;
void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
+void context_free_timestamp_query(struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN;
struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN;
DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN;
void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN;
--
1.7.1
--------------040801020906020701060908
Content-Type: text/x-patch;
name="0005-wined3d-query-Add-support-for-D3DQUERY_TIMESTAMPDISJ.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename*0="0005-wined3d-query-Add-support-for-D3DQUERY_TIMESTAMPDISJ.pa";
filename*1="tch"
More information about the wine-devel
mailing list