diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 2aec7d6bfd..a3da14a19e 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -532,32 +532,38 @@ void context_alloc_event_query(struct wined3d_context *context, struct wined3d_e 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 { - 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(); - GL_EXTCALL(glGenFencesAPPLE(1, &query->id)); + GL_EXTCALL(glGenFencesAPPLE(1, &query->object.id)); checkGLcall("glGenFencesAPPLE"); 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]) { ENTER_GL(); - GL_EXTCALL(glGenFencesNV(1, &query->id)); + GL_EXTCALL(glGenFencesNV(1, &query->object.id)); checkGLcall("glGenFencesNV"); 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 { 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) if (context->free_event_query_count >= 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)); 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; } @@ -588,7 +594,7 @@ void context_free_event_query(struct wined3d_event_query *query) 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) @@ -661,6 +667,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context) struct fbo_entry *entry, *entry2; HGLRC restore_ctx; HDC restore_dc; + unsigned int i; restore_ctx = pwglGetCurrentContext(); restore_dc = pwglGetCurrentDC(); @@ -682,8 +689,12 @@ static void context_destroy_gl_resources(struct wined3d_context *context) { if (context->valid) { - if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->id)); - else if (gl_info->supported[NV_FENCE]) GL_EXTCALL(glDeleteFencesNV(1, &event_query->id)); + if (gl_info->supported[ARB_SYNC]) + { + 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; } @@ -720,10 +731,24 @@ 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[APPLE_FENCE]) - GL_EXTCALL(glDeleteFencesAPPLE(context->free_event_query_count, context->free_event_queries)); + if (gl_info->supported[ARB_SYNC]) + { + 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]) - 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"); } diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index cc7d7aa27d..85d5311c3b 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -195,7 +195,7 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void 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 */ FIXME("Wrong thread, reporting GPU idle.\n"); @@ -209,14 +209,37 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void ENTER_GL(); - if (gl_info->supported[APPLE_FENCE]) + if (gl_info->supported[ARB_SYNC]) { - *data = GL_EXTCALL(glTestFenceAPPLE(query->id)); + 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->object.id)); checkGLcall("glTestFenceAPPLE"); } else if (gl_info->supported[NV_FENCE]) { - *data = GL_EXTCALL(glTestFenceNV(query->id)); + *data = GL_EXTCALL(glTestFenceNV(query->object.id)); checkGLcall("glTestFenceNV"); } else @@ -262,7 +285,7 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD 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 = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD); @@ -283,14 +306,21 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD ENTER_GL(); - if (gl_info->supported[APPLE_FENCE]) + if (gl_info->supported[ARB_SYNC]) { - GL_EXTCALL(glSetFenceAPPLE(query->id)); + 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->object.id)); checkGLcall("glSetFenceAPPLE"); } 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"); } @@ -450,7 +480,8 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device, case WINED3DQUERYTYPE_EVENT: 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 * menu correctly otherwise. Pretend to support it, faking diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6c780201d3..164cc6b5f2 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1014,10 +1014,16 @@ struct wined3d_occlusion_query struct wined3d_context *context; }; +union wined3d_gl_query_object +{ + GLuint id; + GLsync sync; +}; + struct wined3d_event_query { struct list entry; - GLuint id; + union wined3d_gl_query_object object; struct wined3d_context *context; }; @@ -1090,7 +1096,7 @@ struct wined3d_context UINT free_occlusion_query_count; 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_count; struct list event_queries;