From 01bca92ae8ef8086f035e8cc9b7ebf48f0520f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Wed, 3 Mar 2010 22:45:34 +0100 Subject: [PATCH 01/18] WineD3D: Create a wined3d internal event query interface The newly created wined3d_event_query_test will be available for wined3d-internal use, primarily for synchronizing buffer updates when using GL_APPLE_flush_buffer_range. The wined3d_event_query interface will contain most of the functionality: * Selecting the proper GL extension * Context handling * Thread handling The IWineD3DEventQuery COM interface will use the internal interface and implement event query faking on top of it (to enable games that require event queries able to run on drivers that don't implement the GL extension) --- dlls/wined3d/query.c | 168 ++++++++++++++++++++++++---------------- dlls/wined3d/wined3d_private.h | 10 +++ 2 files changed, 111 insertions(+), 67 deletions(-) diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index 85d5311..97ad5bd 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -24,15 +24,88 @@ #include "config.h" #include "wined3d_private.h" +WINE_DEFAULT_DEBUG_CHANNEL(d3d); +#define GLINFO_LOCATION (*gl_info) + +static enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) +{ + struct wined3d_context *context; + const struct wined3d_gl_info *gl_info; + enum wined3d_event_query_result ret; + BOOL fence_result; + + TRACE("(%p) : device %p\n", query, device); + + if (query->context == NULL) + { + TRACE("Query not started\n"); + return WINED3D_EVENT_QUERY_NOT_STARTED; + } + + if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId()) + { + WARN("Event query tested from wrong thread\n"); + return WINED3D_EVENT_QUERY_WRONG_THREAD; + } + + context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + gl_info = context->gl_info; + + ENTER_GL(); + + if (gl_info->supported[ARB_SYNC]) + { + GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0)); + checkGLcall("glClientWaitSync"); + + switch (gl_ret) + { + case GL_ALREADY_SIGNALED: + case GL_CONDITION_SATISFIED: + ret = WINED3D_EVENT_QUERY_OK; + break; + + case GL_TIMEOUT_EXPIRED: + ret = WINED3D_EVENT_QUERY_WAITING; + break; + + case GL_WAIT_FAILED: + default: + ERR("glClientWaitSync returned %#x.\n", gl_ret); + ret = WINED3D_EVENT_QUERY_ERROR; + } + } + else if (gl_info->supported[APPLE_FENCE]) + { + fence_result = GL_EXTCALL(glTestFenceAPPLE(query->object.id)); + checkGLcall("glTestFenceAPPLE"); + if (fence_result) ret = WINED3D_EVENT_QUERY_OK; + else ret = WINED3D_EVENT_QUERY_WAITING; + } + else if (gl_info->supported[NV_FENCE]) + { + fence_result = GL_EXTCALL(glTestFenceNV(query->object.id)); + checkGLcall("glTestFenceNV"); + if (fence_result) ret = WINED3D_EVENT_QUERY_OK; + else ret = WINED3D_EVENT_QUERY_WAITING; + } + else + { + ret = WINED3D_EVENT_QUERY_UNSUPPORTED; + } + + LEAVE_GL(); + + context_release(context); + return ret; +} + /* * Occlusion Queries: * http://www.gris.uni-tuebingen.de/~bartz/Publications/paper/hww98.pdf * http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt */ -WINE_DEFAULT_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION (*gl_info) - /* ******************************************* IWineD3DQuery IUnknown parts follow ******************************************* */ @@ -179,78 +252,39 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; struct wined3d_event_query *query = This->extendedData; - const struct wined3d_gl_info *gl_info; - struct wined3d_context *context; BOOL *data = pData; + enum wined3d_event_query_result ret; TRACE("(%p) : type D3DQUERY_EVENT, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags); if (!pData || !dwSize) return S_OK; - if (!query->context) + ret = wined3d_event_query_test(query, This->device); + switch(ret) { - TRACE("Query not started, returning TRUE.\n"); - *data = TRUE; - - return S_OK; - } - - 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"); - *data = TRUE; - - return S_OK; - } - - context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD); - gl_info = context->gl_info; - - ENTER_GL(); + case WINED3D_EVENT_QUERY_OK: + case WINED3D_EVENT_QUERY_NOT_STARTED: + *data = TRUE; + break; - if (gl_info->supported[ARB_SYNC]) - { - GLenum ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0)); - checkGLcall("glClientWaitSync"); + case WINED3D_EVENT_QUERY_WAITING: + *data = FALSE; + break; - switch (ret) - { - case GL_ALREADY_SIGNALED: - case GL_CONDITION_SATISFIED: - *data = TRUE; - break; + case WINED3D_EVENT_QUERY_WRONG_THREAD: + FIXME("(%p) Wrong thread, reporting GPU idle.\n", This); + *data = TRUE; + break; - case GL_TIMEOUT_EXPIRED: - *data = FALSE; - break; + case WINED3D_EVENT_QUERY_UNSUPPORTED: + WARN("(%p): Event query not supported by GL, reporting GPU idle\n", This); + *data = TRUE; + break; - case GL_WAIT_FAILED: - default: - ERR("glClientWaitSync returned %#x.\n", ret); - *data = FALSE; - break; - } + case WINED3D_EVENT_QUERY_ERROR: + ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n"); + return WINED3DERR_INVALIDCALL; } - 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->object.id)); - checkGLcall("glTestFenceNV"); - } - else - { - WARN("(%p): reporting GPU idle\n", This); - *data = TRUE; - } - - LEAVE_GL(); - - context_release(context); return S_OK; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index ebfa7a4..616a391 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1030,6 +1030,16 @@ struct wined3d_event_query struct wined3d_context *context; }; +enum wined3d_event_query_result +{ + WINED3D_EVENT_QUERY_OK, + WINED3D_EVENT_QUERY_WAITING, + WINED3D_EVENT_QUERY_NOT_STARTED, + WINED3D_EVENT_QUERY_WRONG_THREAD, + WINED3D_EVENT_QUERY_ERROR, + WINED3D_EVENT_QUERY_UNSUPPORTED +}; + struct wined3d_context { const struct wined3d_gl_info *gl_info; -- 1.6.4.4