query.c revision ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2
af062818b47340eef15700d2f0211576ba3506eevboxsync * IWineD3DQuery implementation
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright 2005 Oliver Stieber
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
5112e32d7072e280613921c982a6672f2c859cf3vboxsync * Copyright 2009 Henri Verbeet for CodeWeavers.
af062818b47340eef15700d2f0211576ba3506eevboxsync * This library is free software; you can redistribute it and/or
af062818b47340eef15700d2f0211576ba3506eevboxsync * modify it under the terms of the GNU Lesser General Public
af062818b47340eef15700d2f0211576ba3506eevboxsync * License as published by the Free Software Foundation; either
af062818b47340eef15700d2f0211576ba3506eevboxsync * version 2.1 of the License, or (at your option) any later version.
af062818b47340eef15700d2f0211576ba3506eevboxsync * This library is distributed in the hope that it will be useful,
af062818b47340eef15700d2f0211576ba3506eevboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
af062818b47340eef15700d2f0211576ba3506eevboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * Lesser General Public License for more details.
af062818b47340eef15700d2f0211576ba3506eevboxsync * You should have received a copy of the GNU Lesser General Public
af062818b47340eef15700d2f0211576ba3506eevboxsync * License along with this library; if not, write to the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync * other than GPL or LGPL is available it will apply instead, Sun elects to use only
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync * a choice of LGPL license versions is made available with the language indicating
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync * of the LGPL is applied is otherwise unspecified.
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncBOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info)
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE];
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncvoid wined3d_event_query_destroy(struct wined3d_event_query *query)
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if (query->context) context_free_event_query(query);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncenum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0));
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync fence_result = GL_EXTCALL(glTestFenceAPPLE(query->object.id));
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync fence_result = GL_EXTCALL(glTestFenceNV(query->object.id));
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync ERR("Event query created despite lack of GL support\n");
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncenum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC])
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync /* A glFinish does not reliably wait for draws in other contexts. The caller has
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync * to find its own way to cope with the thread switch
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, ~(GLuint64)0));
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync /* We don't expect a timeout for a ~584 year wait */
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncvoid wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync if (query->object.sync) GL_EXTCALL(glDeleteSync(query->object.sync));
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync query->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync GL_EXTCALL(glSetFenceNV(query->object.id, GL_ALL_COMPLETED_NV));
af062818b47340eef15700d2f0211576ba3506eevboxsync * Occlusion Queries:
af062818b47340eef15700d2f0211576ba3506eevboxsync * http://www.gris.uni-tuebingen.de/~bartz/Publications/paper/hww98.pdf
af062818b47340eef15700d2f0211576ba3506eevboxsync * http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt
af062818b47340eef15700d2f0211576ba3506eevboxsync/* *******************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQuery IUnknown parts follow
af062818b47340eef15700d2f0211576ba3506eevboxsync ******************************************* */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic HRESULT WINAPI IWineD3DQueryImpl_QueryInterface(IWineD3DQuery *iface, REFIID riid, LPVOID *ppobj)
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
af062818b47340eef15700d2f0211576ba3506eevboxsync TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic ULONG WINAPI IWineD3DQueryImpl_AddRef(IWineD3DQuery *iface) {
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
af062818b47340eef15700d2f0211576ba3506eevboxsync TRACE("(%p) : AddRef increasing from %d\n", This, This->ref);
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic ULONG WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
af062818b47340eef15700d2f0211576ba3506eevboxsync TRACE("(%p) : Releasing from %d\n", This, This->ref);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (ref == 0) {
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync /* Queries are specific to the GL context that created them. Not
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * deleting the query will obviously leak it, but that's still better
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * than potentially deleting a different query with the same id in this
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync * context, and (still) leaking the actual query. */
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync struct wined3d_event_query *query = This->extendedData;
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync struct wined3d_occlusion_query *query = This->extendedData;
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync if (query->context) context_free_occlusion_query(query);
af062818b47340eef15700d2f0211576ba3506eevboxsync/* *******************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQuery IWineD3DQuery parts follow
af062818b47340eef15700d2f0211576ba3506eevboxsync ******************************************* */
5112e32d7072e280613921c982a6672f2c859cf3vboxsyncstatic HRESULT WINAPI IWineD3DQueryImpl_GetParent(IWineD3DQuery *iface, IUnknown **parent)
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync struct wined3d_occlusion_query *query = This->extendedData;
5112e32d7072e280613921c982a6672f2c859cf3vboxsync const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
af062818b47340eef15700d2f0211576ba3506eevboxsync TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);
af062818b47340eef15700d2f0211576ba3506eevboxsync /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
af062818b47340eef15700d2f0211576ba3506eevboxsync TRACE("Query wasn't yet started, returning S_OK\n");
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Msdn says this returns an error, but our tests show that S_FALSE is returned */
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync WARN("(%p) : Occlusion queries not supported. Returning 1.\n", This);
5112e32d7072e280613921c982a6672f2c859cf3vboxsync context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
040b4a09341f574825386333398110f4db3e1e51vboxsync checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_ARB, &samples));
040b4a09341f574825386333398110f4db3e1e51vboxsync checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync TRACE("(%p) : Returning %d samples.\n", This, samples);
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync struct wined3d_event_query *query = This->extendedData;
af062818b47340eef15700d2f0211576ba3506eevboxsync TRACE("(%p) : type D3DQUERY_EVENT, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync WARN("(%p): Event query not supported by GL, reporting GPU idle\n", This);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync ret = wined3d_event_query_test(query, This->device);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync FIXME("(%p) Wrong thread, reporting GPU idle.\n", This);
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n");
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DWORD WINAPI IWineD3DEventQueryImpl_GetDataSize(IWineD3DQuery* iface){
af062818b47340eef15700d2f0211576ba3506eevboxsync return sizeof(BOOL);
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DWORD WINAPI IWineD3DOcclusionQueryImpl_GetDataSize(IWineD3DQuery* iface){
af062818b47340eef15700d2f0211576ba3506eevboxsync return sizeof(DWORD);
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic WINED3DQUERYTYPE WINAPI IWineD3DQueryImpl_GetType(IWineD3DQuery* iface){
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD dwIssueFlags) {
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
af062818b47340eef15700d2f0211576ba3506eevboxsync TRACE("(%p) : dwIssueFlags %#x, type D3DQUERY_EVENT\n", This, dwIssueFlags);
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync struct wined3d_event_query *query = This->extendedData;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync /* Faked event query support */
af062818b47340eef15700d2f0211576ba3506eevboxsync /* Started implicitly at device creation */
af062818b47340eef15700d2f0211576ba3506eevboxsync ERR("Event query issued with START flag - what to do?\n");
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, DWORD dwIssueFlags) {
af062818b47340eef15700d2f0211576ba3506eevboxsync IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
5112e32d7072e280613921c982a6672f2c859cf3vboxsync const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync struct wined3d_occlusion_query *query = This->extendedData;
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync /* This is allowed according to msdn and our tests. Reset the query and restart */
5112e32d7072e280613921c982a6672f2c859cf3vboxsync context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD);
5112e32d7072e280613921c982a6672f2c859cf3vboxsync context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync if (query->context) context_free_occlusion_query(query);
5112e32d7072e280613921c982a6672f2c859cf3vboxsync context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD);
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query->id));
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync /* Msdn says _END on a non-building occlusion query returns an error, but
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync * our tests show that it returns OK. But OpenGL doesn't like it, so avoid
114410893548b9522c46fdcbd8f63385eb8bfb68vboxsync * generating an error
5112e32d7072e280613921c982a6672f2c859cf3vboxsync context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
af062818b47340eef15700d2f0211576ba3506eevboxsync FIXME("(%p) : Occlusion queries not supported\n", This);
af062818b47340eef15700d2f0211576ba3506eevboxsync return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncstatic const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl =
af062818b47340eef15700d2f0211576ba3506eevboxsync /*** IUnknown methods ***/
af062818b47340eef15700d2f0211576ba3506eevboxsync /*** IWineD3Dquery methods ***/
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncstatic const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl =
af062818b47340eef15700d2f0211576ba3506eevboxsync /*** IUnknown methods ***/
af062818b47340eef15700d2f0211576ba3506eevboxsync /*** IWineD3Dquery methods ***/
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsyncHRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device,
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY.\n");
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync query->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_occlusion_query));
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync ERR("Failed to allocate occlusion query extended data.\n");
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync ((struct wined3d_occlusion_query *)query->extendedData)->context = NULL;
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync /* Half-Life 2 needs this query. It does not render the main
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync * menu correctly otherwise. Pretend to support it, faking
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync * this query does not do much harm except potentially
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync * lowering performance. */
ee6bcfc59fe3b0230aad85e2ef63d0402b7719b2vboxsync FIXME("Event query: Unimplemented, but pretending to be supported.\n");