diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 8062896b357..1d7afaa5cc9 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1149,12 +1149,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINE switch(Type) { case WINED3DQUERYTYPE_OCCLUSION: TRACE("(%p) occlusion query\n", This); - /* Use the base Query vtable until we have a occlusion query one */ - vtable = &IWineD3DQuery_Vtbl; if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) hr = WINED3D_OK; else WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n"); + + vtable = &IWineD3DOcclusionQuery_Vtbl; break; case WINED3DQUERYTYPE_EVENT: diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index d69e23d7eda..66fe61354ed 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -158,48 +158,6 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa } break; - case WINED3DQUERYTYPE_OCCLUSION: - { - DWORD* data = pData; - - if(This->state == QUERY_CREATED) { - /* 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"); - res = S_OK; - if(data) *data = 0; - } else if(This->state == QUERY_BUILDING) { - /* Msdn says this returns an error, but our tests show that S_FALSE is returned */ - TRACE("Query is building, returning S_FALSE\n"); - res = S_FALSE; - } else if (GL_SUPPORT(ARB_OCCLUSION_QUERY) && - ((WineQueryOcclusionData *)This->extendedData)->ctx == This->wineD3DDevice->activeContext && - This->wineD3DDevice->activeContext->tid == GetCurrentThreadId()) { - GLuint available; - GLuint samples; - GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId; - - GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available)); - checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n"); - TRACE("(%p) : available %d.\n", This, available); - - if (available) { - if(data) { - GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_ARB, &samples)); - checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)\n"); - TRACE("(%p) : Returning %d samples.\n", This, samples); - *data = samples; - } - res = S_OK; - } else { - res = S_FALSE; - } - } else { - WARN("(%p) : Occlusion queries not supported, or wrong context. Returning 1.\n", This); - *data = 1; - res = S_OK; - } - } - break; case WINED3DQUERYTYPE_TIMESTAMP: { UINT64* data = pData; @@ -307,6 +265,51 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa return res; /* S_OK if the query data is available*/ } +static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { + IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; + DWORD* data = pData; + HRESULT res; + TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags); + + if(This->state == QUERY_CREATED) { + /* 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"); + res = S_OK; + if(data) *data = 0; + } else if(This->state == QUERY_BUILDING) { + /* Msdn says this returns an error, but our tests show that S_FALSE is returned */ + TRACE("Query is building, returning S_FALSE\n"); + res = S_FALSE; + } else if (GL_SUPPORT(ARB_OCCLUSION_QUERY) && + ((WineQueryOcclusionData *)This->extendedData)->ctx == This->wineD3DDevice->activeContext && + This->wineD3DDevice->activeContext->tid == GetCurrentThreadId()) { + GLuint available; + GLuint samples; + GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId; + + GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available)); + checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n"); + TRACE("(%p) : available %d.\n", This, available); + + if (available) { + if(data) { + GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_ARB, &samples)); + checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)\n"); + TRACE("(%p) : Returning %d samples.\n", This, samples); + *data = samples; + } + res = S_OK; + } else { + res = S_FALSE; + } + } else { + WARN("(%p) : Occlusion queries not supported, or wrong context. Returning 1.\n", This); + *data = 1; + res = S_OK; + } + return res; +} + static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; BOOL* data = pData; @@ -351,9 +354,6 @@ static DWORD WINAPI IWineD3DQueryImpl_GetDataSize(IWineD3DQuery* iface){ case WINED3DQUERYTYPE_EVENT: dataSize = sizeof(BOOL); break; - case WINED3DQUERYTYPE_OCCLUSION: - dataSize = sizeof(DWORD); - break; case WINED3DQUERYTYPE_TIMESTAMP: dataSize = sizeof(UINT64); break; @@ -394,6 +394,12 @@ static DWORD WINAPI IWineD3DEventQueryImpl_GetDataSize(IWineD3DQuery* iface){ return sizeof(BOOL); } +static DWORD WINAPI IWineD3DOcclusionQueryImpl_GetDataSize(IWineD3DQuery* iface){ + TRACE("(%p) : type D3DQUERY_OCCLUSION\n", iface); + + return sizeof(DWORD); +} + static WINED3DQUERYTYPE WINAPI IWineD3DQueryImpl_GetType(IWineD3DQuery* iface){ IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface; return This->type; @@ -436,50 +442,55 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD return WINED3D_OK; } +static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, DWORD dwIssueFlags) { + IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface; + + if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) { + WineD3DContext *ctx = ((WineQueryOcclusionData *)This->extendedData)->ctx; + + if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { + WARN("Not the owning context, can't start query\n"); + } else { + /* This is allowed according to msdn and our tests. Reset the query and restart */ + if (dwIssueFlags & WINED3DISSUE_BEGIN) { + if(This->state == QUERY_BUILDING) { + GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); + checkGLcall("glEndQuery()"); + } + + GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, ((WineQueryOcclusionData *)This->extendedData)->queryId)); + checkGLcall("glBeginQuery()"); + } + if (dwIssueFlags & WINED3DISSUE_END) { + /* Msdn says _END on a non-building occlusion query returns an error, but + * our tests show that it returns OK. But OpenGL doesn't like it, so avoid + * generating an error + */ + if(This->state == QUERY_BUILDING) { + GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); + checkGLcall("glEndQuery()"); + } + } + } + } else { + FIXME("(%p) : Occlusion queries not supported\n", This); + } + + if(dwIssueFlags & WINED3DISSUE_BEGIN) { + This->state = QUERY_BUILDING; + } else { + This->state = QUERY_SIGNALLED; + } + return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */ +} + static HRESULT WINAPI IWineD3DQueryImpl_Issue(IWineD3DQuery* iface, DWORD dwIssueFlags){ IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface; TRACE("(%p) : dwIssueFlags %#x, type %#x\n", This, dwIssueFlags, This->type); - switch (This->type) { - case WINED3DQUERYTYPE_OCCLUSION: - if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) { - WineD3DContext *ctx = ((WineQueryOcclusionData *)This->extendedData)->ctx; - - if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) { - WARN("Not the owning context, can't start query\n"); - } else { - /* This is allowed according to msdn and our tests. Reset the query and restart */ - if (dwIssueFlags & WINED3DISSUE_BEGIN) { - if(This->state == QUERY_BUILDING) { - GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); - checkGLcall("glEndQuery()"); - } - - GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, ((WineQueryOcclusionData *)This->extendedData)->queryId)); - checkGLcall("glBeginQuery()"); - } - if (dwIssueFlags & WINED3DISSUE_END) { - /* Msdn says _END on a non-building occlusion query returns an error, but - * our tests show that it returns OK. But OpenGL doesn't like it, so avoid - * generating an error - */ - if(This->state == QUERY_BUILDING) { - GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); - checkGLcall("glEndQuery()"); - } - } - } - } else { - FIXME("(%p) : Occlusion queries not supported\n", This); - } - break; - - default: - /* The fixme is printed when the app asks for the resulting data */ - WARN("(%p) : Unhandled query type %#x\n", This, This->type); - break; - } + /* The fixme is printed when the app asks for the resulting data */ + WARN("(%p) : Unhandled query type %#x\n", This, This->type); if(dwIssueFlags & WINED3DISSUE_BEGIN) { This->state = QUERY_BUILDING; @@ -524,3 +535,18 @@ const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl = IWineD3DQueryImpl_GetType, IWineD3DEventQueryImpl_Issue }; + +const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl = +{ + /*** IUnknown methods ***/ + IWineD3DQueryImpl_QueryInterface, + IWineD3DQueryImpl_AddRef, + IWineD3DQueryImpl_Release, + /*** IWineD3Dquery methods ***/ + IWineD3DQueryImpl_GetParent, + IWineD3DQueryImpl_GetDevice, + IWineD3DOcclusionQueryImpl_GetData, + IWineD3DOcclusionQueryImpl_GetDataSize, + IWineD3DQueryImpl_GetType, + IWineD3DOcclusionQueryImpl_Issue +}; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index f19ad4be414..f6ac50c63d4 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1572,6 +1572,7 @@ typedef struct IWineD3DQueryImpl extern const IWineD3DQueryVtbl IWineD3DQuery_Vtbl; extern const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl; +extern const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl; /* Datastructures for IWineD3DQueryImpl.extendedData */ typedef struct WineQueryOcclusionData {