Next try. This time I reverted most of my header changes and just needed to add some...
[reactos.git] / reactos / dll / directx / wine / wined3d / query.c
index 481177f..2a2c1b1 100644 (file)
@@ -62,38 +62,22 @@ 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) {
-            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");
-            }
+        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);
         }
-        LEAVE_GL();
 
         HeapFree(GetProcessHeap(), 0, This->extendedData);
         HeapFree(GetProcessHeap(), 0, This);
@@ -286,7 +270,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;
-    GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId;
+    struct wined3d_occlusion_query *query = This->extendedData;
     DWORD* data = pData;
     GLuint available;
     GLuint samples;
@@ -294,6 +278,8 @@ 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 */
@@ -316,26 +302,27 @@ static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface,
         return S_OK;
     }
 
-    if (((WineQueryOcclusionData *)This->extendedData)->ctx != This->wineD3DDevice->activeContext
-            || This->wineD3DDevice->activeContext->tid != GetCurrentThreadId())
+    if (query->context->tid != GetCurrentThreadId())
     {
-        FIXME("%p Wrong context, returning 1.\n", This);
+        FIXME("%p Wrong thread, returning 1.\n", This);
         *data = 1;
         return S_OK;
     }
 
+    ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+
     ENTER_GL();
 
-    GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
-    checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n");
+    GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
+    checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
     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");
+            GL_EXTCALL(glGetQueryObjectuivARB(query->id, GL_QUERY_RESULT_ARB, &samples));
+            checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
             TRACE("(%p) : Returning %d samples.\n", This, samples);
             *data = samples;
         }
@@ -353,32 +340,52 @@ 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);
 
-    ctx = ((WineQueryEventData *)This->extendedData)->ctx;
-    if(pData == NULL || dwSize == 0) {
+    if (!pData || !dwSize) return S_OK;
+
+    if (!query->context)
+    {
+        ERR("Query not started, returning TRUE.\n");
+        *data = TRUE;
+
         return S_OK;
-    } if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
+    }
+
+    if (query->context->tid != GetCurrentThreadId())
+    {
         /* See comment in IWineD3DQuery::Issue, event query codeblock */
-        FIXME("Query context not active, reporting GPU idle\n");
+        FIXME("Wrong thread, reporting GPU idle.\n");
         *data = TRUE;
-    } else if(GL_SUPPORT(APPLE_FENCE)) {
-        ENTER_GL();
-        *data = GL_EXTCALL(glTestFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId));
+
+        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));
         checkGLcall("glTestFenceAPPLE");
-        LEAVE_GL();
-    } else if(GL_SUPPORT(NV_FENCE)) {
-        ENTER_GL();
-        *data = GL_EXTCALL(glTestFenceNV(((WineQueryEventData *)This->extendedData)->fenceId));
+    }
+    else if (GL_SUPPORT(NV_FENCE))
+    {
+        *data = GL_EXTCALL(glTestFenceNV(query->id));
         checkGLcall("glTestFenceNV");
-        LEAVE_GL();
-    } else {
+    }
+    else
+    {
         WARN("(%p): reporting GPU idle\n", This);
         *data = TRUE;
     }
 
+    LEAVE_GL();
+
     return S_OK;
 }
 
@@ -455,29 +462,47 @@ 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) {
-        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));
+    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));
             checkGLcall("glSetFenceAPPLE");
-            LEAVE_GL();
-        } else if (GL_SUPPORT(NV_FENCE)) {
-            ENTER_GL();
-            GL_EXTCALL(glSetFenceNV(((WineQueryEventData *)This->extendedData)->fenceId, GL_ALL_COMPLETED_NV));
+        }
+        else if (GL_SUPPORT(NV_FENCE))
+        {
+            GL_EXTCALL(glSetFenceNV(query->id, GL_ALL_COMPLETED_NV));
             checkGLcall("glSetFenceNV");
-            LEAVE_GL();
         }
-    } else if(dwIssueFlags & WINED3DISSUE_BEGIN) {
+
+        LEAVE_GL();
+    }
+    else if(dwIssueFlags & WINED3DISSUE_BEGIN)
+    {
         /* Started implicitly at device creation */
         ERR("Event query issued with START flag - what to do?\n");
     }
@@ -494,34 +519,67 @@ 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)) {
-        WineD3DContext *ctx = ((WineQueryOcclusionData *)This->extendedData)->ctx;
+    if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
+    {
+        struct wined3d_occlusion_query *query = This->extendedData;
+        struct wined3d_context *context;
 
-        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) {
+        /* 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);
+
+                    ENTER_GL();
                     GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
                     checkGLcall("glEndQuery()");
+                    LEAVE_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) {
+            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(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
                     checkGLcall("glEndQuery()");
+                    LEAVE_GL();
                 }
             }
-            LEAVE_GL();
         }
     } else {
         FIXME("(%p) : Occlusion queries not supported\n", This);