Commit 96b15092 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Add an ARB_sync implementation of event queries.

parent c698171f
...@@ -532,32 +532,38 @@ void context_alloc_event_query(struct wined3d_context *context, struct wined3d_e ...@@ -532,32 +532,38 @@ void context_alloc_event_query(struct wined3d_context *context, struct wined3d_e
if (context->free_event_query_count) if (context->free_event_query_count)
{ {
query->id = context->free_event_queries[--context->free_event_query_count]; query->object = context->free_event_queries[--context->free_event_query_count];
} }
else else
{ {
if (gl_info->supported[APPLE_FENCE]) if (gl_info->supported[ARB_SYNC])
{
/* Using ARB_sync, not much to do here. */
query->object.sync = NULL;
TRACE("Allocated event query %p in context %p.\n", query->object.sync, context);
}
else if (gl_info->supported[APPLE_FENCE])
{ {
ENTER_GL(); ENTER_GL();
GL_EXTCALL(glGenFencesAPPLE(1, &query->id)); GL_EXTCALL(glGenFencesAPPLE(1, &query->object.id));
checkGLcall("glGenFencesAPPLE"); checkGLcall("glGenFencesAPPLE");
LEAVE_GL(); LEAVE_GL();
TRACE("Allocated event query %u in context %p.\n", query->id, context); TRACE("Allocated event query %u in context %p.\n", query->object.id, context);
} }
else if(gl_info->supported[NV_FENCE]) else if(gl_info->supported[NV_FENCE])
{ {
ENTER_GL(); ENTER_GL();
GL_EXTCALL(glGenFencesNV(1, &query->id)); GL_EXTCALL(glGenFencesNV(1, &query->object.id));
checkGLcall("glGenFencesNV"); checkGLcall("glGenFencesNV");
LEAVE_GL(); LEAVE_GL();
TRACE("Allocated event query %u in context %p.\n", query->id, context); TRACE("Allocated event query %u in context %p.\n", query->object.id, context);
} }
else else
{ {
WARN("Event queries not supported, not allocating query id.\n"); WARN("Event queries not supported, not allocating query id.\n");
query->id = 0; query->object.id = 0;
} }
} }
...@@ -575,12 +581,12 @@ void context_free_event_query(struct wined3d_event_query *query) ...@@ -575,12 +581,12 @@ void context_free_event_query(struct wined3d_event_query *query)
if (context->free_event_query_count >= context->free_event_query_size - 1) if (context->free_event_query_count >= context->free_event_query_size - 1)
{ {
UINT new_size = context->free_event_query_size << 1; UINT new_size = context->free_event_query_size << 1;
GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_event_queries, union wined3d_gl_query_object *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_event_queries,
new_size * sizeof(*context->free_event_queries)); new_size * sizeof(*context->free_event_queries));
if (!new_data) if (!new_data)
{ {
ERR("Failed to grow free list, leaking query %u in context %p.\n", query->id, context); ERR("Failed to grow free list, leaking query %u in context %p.\n", query->object.id, context);
return; return;
} }
...@@ -588,7 +594,7 @@ void context_free_event_query(struct wined3d_event_query *query) ...@@ -588,7 +594,7 @@ void context_free_event_query(struct wined3d_event_query *query)
context->free_event_queries = new_data; context->free_event_queries = new_data;
} }
context->free_event_queries[context->free_event_query_count++] = query->id; context->free_event_queries[context->free_event_query_count++] = query->object;
} }
void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type) void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type)
...@@ -661,6 +667,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context) ...@@ -661,6 +667,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
struct fbo_entry *entry, *entry2; struct fbo_entry *entry, *entry2;
HGLRC restore_ctx; HGLRC restore_ctx;
HDC restore_dc; HDC restore_dc;
unsigned int i;
restore_ctx = pwglGetCurrentContext(); restore_ctx = pwglGetCurrentContext();
restore_dc = pwglGetCurrentDC(); restore_dc = pwglGetCurrentDC();
...@@ -682,8 +689,12 @@ static void context_destroy_gl_resources(struct wined3d_context *context) ...@@ -682,8 +689,12 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
{ {
if (context->valid) if (context->valid)
{ {
if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->id)); if (gl_info->supported[ARB_SYNC])
else if (gl_info->supported[NV_FENCE]) GL_EXTCALL(glDeleteFencesNV(1, &event_query->id)); {
if (event_query->object.sync) GL_EXTCALL(glDeleteSync(event_query->object.sync));
}
else if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->object.id));
else if (gl_info->supported[NV_FENCE]) GL_EXTCALL(glDeleteFencesNV(1, &event_query->object.id));
} }
event_query->context = NULL; event_query->context = NULL;
} }
...@@ -720,10 +731,24 @@ static void context_destroy_gl_resources(struct wined3d_context *context) ...@@ -720,10 +731,24 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
if (gl_info->supported[ARB_OCCLUSION_QUERY]) if (gl_info->supported[ARB_OCCLUSION_QUERY])
GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries)); GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries));
if (gl_info->supported[APPLE_FENCE]) if (gl_info->supported[ARB_SYNC])
GL_EXTCALL(glDeleteFencesAPPLE(context->free_event_query_count, context->free_event_queries)); {
if (event_query->object.sync) GL_EXTCALL(glDeleteSync(event_query->object.sync));
}
else if (gl_info->supported[APPLE_FENCE])
{
for (i = 0; i < context->free_event_query_count; ++i)
{
GL_EXTCALL(glDeleteFencesAPPLE(1, &context->free_event_queries[i].id));
}
}
else if (gl_info->supported[NV_FENCE]) else if (gl_info->supported[NV_FENCE])
GL_EXTCALL(glDeleteFencesNV(context->free_event_query_count, context->free_event_queries)); {
for (i = 0; i < context->free_event_query_count; ++i)
{
GL_EXTCALL(glDeleteFencesNV(1, &context->free_event_queries[i].id));
}
}
checkGLcall("context cleanup"); checkGLcall("context cleanup");
} }
......
...@@ -195,7 +195,7 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void ...@@ -195,7 +195,7 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void
return S_OK; return S_OK;
} }
if (query->context->tid != GetCurrentThreadId()) if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
{ {
/* See comment in IWineD3DQuery::Issue, event query codeblock */ /* See comment in IWineD3DQuery::Issue, event query codeblock */
FIXME("Wrong thread, reporting GPU idle.\n"); FIXME("Wrong thread, reporting GPU idle.\n");
...@@ -209,14 +209,37 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void ...@@ -209,14 +209,37 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void
ENTER_GL(); ENTER_GL();
if (gl_info->supported[APPLE_FENCE]) if (gl_info->supported[ARB_SYNC])
{
GLenum ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0));
checkGLcall("glClientWaitSync");
switch (ret)
{
case GL_ALREADY_SIGNALED:
case GL_CONDITION_SATISFIED:
*data = TRUE;
break;
case GL_TIMEOUT_EXPIRED:
*data = FALSE;
break;
case GL_WAIT_FAILED:
default:
ERR("glClientWaitSync returned %#x.\n", ret);
*data = FALSE;
break;
}
}
else if (gl_info->supported[APPLE_FENCE])
{ {
*data = GL_EXTCALL(glTestFenceAPPLE(query->id)); *data = GL_EXTCALL(glTestFenceAPPLE(query->object.id));
checkGLcall("glTestFenceAPPLE"); checkGLcall("glTestFenceAPPLE");
} }
else if (gl_info->supported[NV_FENCE]) else if (gl_info->supported[NV_FENCE])
{ {
*data = GL_EXTCALL(glTestFenceNV(query->id)); *data = GL_EXTCALL(glTestFenceNV(query->object.id));
checkGLcall("glTestFenceNV"); checkGLcall("glTestFenceNV");
} }
else else
...@@ -262,7 +285,7 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD ...@@ -262,7 +285,7 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD
if (query->context) if (query->context)
{ {
if (query->context->tid != GetCurrentThreadId()) if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
{ {
context_free_event_query(query); context_free_event_query(query);
context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD); context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD);
...@@ -283,14 +306,21 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD ...@@ -283,14 +306,21 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD
ENTER_GL(); ENTER_GL();
if (gl_info->supported[APPLE_FENCE]) if (gl_info->supported[ARB_SYNC])
{
if (query->object.sync) GL_EXTCALL(glDeleteSync(query->object.sync));
checkGLcall("glDeleteSync");
query->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
checkGLcall("glFenceSync");
}
else if (gl_info->supported[APPLE_FENCE])
{ {
GL_EXTCALL(glSetFenceAPPLE(query->id)); GL_EXTCALL(glSetFenceAPPLE(query->object.id));
checkGLcall("glSetFenceAPPLE"); checkGLcall("glSetFenceAPPLE");
} }
else if (gl_info->supported[NV_FENCE]) else if (gl_info->supported[NV_FENCE])
{ {
GL_EXTCALL(glSetFenceNV(query->id, GL_ALL_COMPLETED_NV)); GL_EXTCALL(glSetFenceNV(query->object.id, GL_ALL_COMPLETED_NV));
checkGLcall("glSetFenceNV"); checkGLcall("glSetFenceNV");
} }
...@@ -450,7 +480,8 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device, ...@@ -450,7 +480,8 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device,
case WINED3DQUERYTYPE_EVENT: case WINED3DQUERYTYPE_EVENT:
TRACE("Event query.\n"); TRACE("Event query.\n");
if (!gl_info->supported[NV_FENCE] && !gl_info->supported[APPLE_FENCE]) if (!gl_info->supported[ARB_SYNC] && !gl_info->supported[NV_FENCE]
&& !gl_info->supported[APPLE_FENCE])
{ {
/* Half-Life 2 needs this query. It does not render the main /* Half-Life 2 needs this query. It does not render the main
* menu correctly otherwise. Pretend to support it, faking * menu correctly otherwise. Pretend to support it, faking
......
...@@ -1014,10 +1014,16 @@ struct wined3d_occlusion_query ...@@ -1014,10 +1014,16 @@ struct wined3d_occlusion_query
struct wined3d_context *context; struct wined3d_context *context;
}; };
union wined3d_gl_query_object
{
GLuint id;
GLsync sync;
};
struct wined3d_event_query struct wined3d_event_query
{ {
struct list entry; struct list entry;
GLuint id; union wined3d_gl_query_object object;
struct wined3d_context *context; struct wined3d_context *context;
}; };
...@@ -1090,7 +1096,7 @@ struct wined3d_context ...@@ -1090,7 +1096,7 @@ struct wined3d_context
UINT free_occlusion_query_count; UINT free_occlusion_query_count;
struct list occlusion_queries; struct list occlusion_queries;
GLuint *free_event_queries; union wined3d_gl_query_object *free_event_queries;
UINT free_event_query_size; UINT free_event_query_size;
UINT free_event_query_count; UINT free_event_query_count;
struct list event_queries; struct list event_queries;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment