OK, I give up. Pigglesworth, HAALP. What do I do wrong??!
[reactos.git] / reactos / dll / directx / wine / wined3d / query.c
index 2a2c1b1..481177f 100644 (file)
@@ -62,22 +62,38 @@ static ULONG  WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
     TRACE("(%p) : Releasing from %d\n", This, This->ref);
     ref = InterlockedDecrement(&This->ref);
     if (ref == 0) {
+        ENTER_GL();
         /* Queries are specific to the GL context that created them. Not
          * deleting the query will obviously leak it, but that's still better
          * than potentially deleting a different query with the same id in this
          * context, and (still) leaking the actual query. */
-        if (This->type == WINED3DQUERYTYPE_EVENT)
-        {
-            struct wined3d_event_query *query = This->extendedData;
-
-            if (query->context) context_free_event_query(query);
-        }
-        else if (This->type == WINED3DQUERYTYPE_OCCLUSION)
-        {
-            struct wined3d_occlusion_query *query = This->extendedData;
-
-            if (query->context) context_free_occlusion_query(query);
+        if(This->type == WINED3DQUERYTYPE_EVENT) {
+            if (((WineQueryEventData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext
+                    || This->wineD3DDevice->activeContext->tid != GetCurrentThreadId())
+            {
+                FIXME("Query was created in a different context, skipping deletion\n");
+            }
+            else if(GL_SUPPORT(APPLE_FENCE))
+            {
+                GL_EXTCALL(glDeleteFencesAPPLE(1, &((WineQueryEventData *)(This->extendedData))->fenceId));
+                checkGLcall("glDeleteFencesAPPLE");
+            } else if(GL_SUPPORT(NV_FENCE)) {
+                GL_EXTCALL(glDeleteFencesNV(1, &((WineQueryEventData *)(This->extendedData))->fenceId));
+                checkGLcall("glDeleteFencesNV");
+            }
+        } else if(This->type == WINED3DQUERYTYPE_OCCLUSION && GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
+            if (((WineQueryOcclusionData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext
+                    || This->wineD3DDevice->activeContext->tid != GetCurrentThreadId())
+            {
+                FIXME("Query was created in a different context, skipping deletion\n");
+            }
+            else
+            {
+                GL_EXTCALL(glDeleteQueriesARB(1, &((WineQueryOcclusionData *)(This->extendedData))->queryId));
+                checkGLcall("glDeleteQueriesARB");
+            }
         }
+        LEAVE_GL();
 
         HeapFree(GetProcessHeap(), 0, This->extendedData);
         HeapFree(GetProcessHeap(), 0, This);
@@ -270,7 +286,7 @@ static HRESULT  WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa
 
 static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
-    struct wined3d_occlusion_query *query = This->extendedData;
+    GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId;
     DWORD* data = pData;
     GLuint available;
     GLuint samples;
@@ -278,8 +294,6 @@ static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface,
 
     TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);
 
-    if (!query->context) This->state = QUERY_CREATED;
-
     if (This->state == QUERY_CREATED)
     {
         /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
@@ -302,27 +316,26 @@ static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface,
         return S_OK;
     }
 
-    if (query->context->tid != GetCurrentThreadId())
+    if (((WineQueryOcclusionData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext
+            || This->wineD3DDevice->activeContext->tid != GetCurrentThreadId())
     {
-        FIXME("%p Wrong thread, returning 1.\n", This);
+        FIXME("%p Wrong context, returning 1.\n", This);
         *data = 1;
         return S_OK;
     }
 
-    ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
-
     ENTER_GL();
 
-    GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
-    checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
+    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(query->id, GL_QUERY_RESULT_ARB, &samples));
-            checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
+            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;
         }
@@ -340,52 +353,32 @@ 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;
     BOOL* data = pData;
-
+    WineD3DContext *ctx;
     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)
-    {
-        ERR("Query not started, returning TRUE.\n");
-        *data = TRUE;
-
+    ctx = ((WineQueryEventData *)This->extendedData)->ctx;
+    if(pData == NULL || dwSize == 0) {
         return S_OK;
-    }
-
-    if (query->context->tid != GetCurrentThreadId())
-    {
+    } if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
         /* See comment in IWineD3DQuery::Issue, event query codeblock */
-        FIXME("Wrong thread, reporting GPU idle.\n");
+        FIXME("Query context not active, reporting GPU idle\n");
         *data = TRUE;
-
-        return S_OK;
-    }
-
-    ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
-
-    ENTER_GL();
-
-    if (GL_SUPPORT(APPLE_FENCE))
-    {
-        *data = GL_EXTCALL(glTestFenceAPPLE(query->id));
+    } else if(GL_SUPPORT(APPLE_FENCE)) {
+        ENTER_GL();
+        *data = GL_EXTCALL(glTestFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId));
         checkGLcall("glTestFenceAPPLE");
-    }
-    else if (GL_SUPPORT(NV_FENCE))
-    {
-        *data = GL_EXTCALL(glTestFenceNV(query->id));
+        LEAVE_GL();
+    } else if(GL_SUPPORT(NV_FENCE)) {
+        ENTER_GL();
+        *data = GL_EXTCALL(glTestFenceNV(((WineQueryEventData *)This->extendedData)->fenceId));
         checkGLcall("glTestFenceNV");
-    }
-    else
-    {
+        LEAVE_GL();
+    } else {
         WARN("(%p): reporting GPU idle\n", This);
         *data = TRUE;
     }
 
-    LEAVE_GL();
-
     return S_OK;
 }
 
@@ -462,47 +455,29 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface,  DWORD
     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
 
     TRACE("(%p) : dwIssueFlags %#x, type D3DQUERY_EVENT\n", This, dwIssueFlags);
-    if (dwIssueFlags & WINED3DISSUE_END)
-    {
-        struct wined3d_event_query *query = This->extendedData;
-        struct wined3d_context *context;
-
-        if (query->context)
-        {
-            if (query->context->tid != GetCurrentThreadId())
-            {
-                context_free_event_query(query);
-                context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
-                context_alloc_event_query(context, query);
-            }
-            else
-            {
-                ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
-            }
-        }
-        else
-        {
-            context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
-            context_alloc_event_query(context, query);
-        }
-
-        ENTER_GL();
-
-        if (GL_SUPPORT(APPLE_FENCE))
-        {
-            GL_EXTCALL(glSetFenceAPPLE(query->id));
+    if (dwIssueFlags & WINED3DISSUE_END) {
+        WineD3DContext *ctx = ((WineQueryEventData *)This->extendedData)->ctx;
+        if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
+            /* GL fences can be used only from the context that created them,
+             * so if a different context is active, don't bother setting the query. The penalty
+             * of a context switch is most likely higher than the gain of a correct query result
+             *
+             * If the query is used from a different thread, don't bother creating a multithread
+             * context - there's no point in doing that as the query would be unusable anyway
+             */
+            WARN("Query context not active\n");
+        } else if(GL_SUPPORT(APPLE_FENCE)) {
+            ENTER_GL();
+            GL_EXTCALL(glSetFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId));
             checkGLcall("glSetFenceAPPLE");
-        }
-        else if (GL_SUPPORT(NV_FENCE))
-        {
-            GL_EXTCALL(glSetFenceNV(query->id, GL_ALL_COMPLETED_NV));
+            LEAVE_GL();
+        } else if (GL_SUPPORT(NV_FENCE)) {
+            ENTER_GL();
+            GL_EXTCALL(glSetFenceNV(((WineQueryEventData *)This->extendedData)->fenceId, GL_ALL_COMPLETED_NV));
             checkGLcall("glSetFenceNV");
+            LEAVE_GL();
         }
-
-        LEAVE_GL();
-    }
-    else if(dwIssueFlags & WINED3DISSUE_BEGIN)
-    {
+    } else if(dwIssueFlags & WINED3DISSUE_BEGIN) {
         /* Started implicitly at device creation */
         ERR("Event query issued with START flag - what to do?\n");
     }
@@ -519,67 +494,34 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface,  DWORD
 static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface,  DWORD dwIssueFlags) {
     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
 
-    if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
-    {
-        struct wined3d_occlusion_query *query = This->extendedData;
-        struct wined3d_context *context;
-
-        /* This is allowed according to msdn and our tests. Reset the query and restart */
-        if (dwIssueFlags & WINED3DISSUE_BEGIN)
-        {
-            if (This->state == QUERY_BUILDING)
-            {
-                if (query->context->tid != GetCurrentThreadId())
-                {
-                    FIXME("Wrong thread, can't restart query.\n");
-
-                    context_free_occlusion_query(query);
-                    context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
-                    context_alloc_occlusion_query(context, query);
-                }
-                else
-                {
-                    ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+    if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
+        WineD3DContext *ctx = ((WineQueryOcclusionData *)This->extendedData)->ctx;
 
-                    ENTER_GL();
+        if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
+            FIXME("Not the owning context, can't start query\n");
+        } else {
+            ENTER_GL();
+            /* 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()");
-                    LEAVE_GL();
                 }
-            }
-            else
-            {
-                if (query->context) context_free_occlusion_query(query);
-                context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD);
-                context_alloc_occlusion_query(context, query);
-            }
 
-            ENTER_GL();
-            GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query->id));
-            checkGLcall("glBeginQuery()");
-            LEAVE_GL();
-        }
-        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)
-            {
-                if (query->context->tid != GetCurrentThreadId())
-                {
-                    FIXME("Wrong thread, can't end query.\n");
-                }
-                else
-                {
-                    ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
-
-                    ENTER_GL();
+                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()");
-                    LEAVE_GL();
                 }
             }
+            LEAVE_GL();
         }
     } else {
         FIXME("(%p) : Occlusion queries not supported\n", This);