[PATCH 3/5] wined3d: Add an ARB_sync implementation of event queries.

Henri Verbeet hverbeet at codeweavers.com
Mon Jan 25 12:51:30 CST 2010


---
 dlls/wined3d/context.c         |   55 +++++++++++++++++++++++++++++-----------
 dlls/wined3d/query.c           |   49 +++++++++++++++++++++++++++++------
 dlls/wined3d/wined3d_private.h |   10 ++++++-
 3 files changed, 88 insertions(+), 26 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 2aec7d6..a3da14a 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -532,32 +532,38 @@ void context_alloc_event_query(struct wined3d_context *context, struct wined3d_e
 
     if (context->free_event_query_count)
     {
-        query->id = context->free_event_queries[--context->free_event_query_count];
+        query->object = context->free_event_queries[--context->free_event_query_count];
     }
     else
     {
-        if (gl_info->supported[APPLE_FENCE])
+        if (gl_info->supported[ARB_SYNC])
+        {
+            /* Using ARB_sync, not much to do here. */
+            query->object.sync = NULL;
+            TRACE("Allocated event query %p in context %p.\n", query->object.sync, context);
+        }
+        else if (gl_info->supported[APPLE_FENCE])
         {
             ENTER_GL();
-            GL_EXTCALL(glGenFencesAPPLE(1, &query->id));
+            GL_EXTCALL(glGenFencesAPPLE(1, &query->object.id));
             checkGLcall("glGenFencesAPPLE");
             LEAVE_GL();
 
-            TRACE("Allocated event query %u in context %p.\n", query->id, context);
+            TRACE("Allocated event query %u in context %p.\n", query->object.id, context);
         }
         else if(gl_info->supported[NV_FENCE])
         {
             ENTER_GL();
-            GL_EXTCALL(glGenFencesNV(1, &query->id));
+            GL_EXTCALL(glGenFencesNV(1, &query->object.id));
             checkGLcall("glGenFencesNV");
             LEAVE_GL();
 
-            TRACE("Allocated event query %u in context %p.\n", query->id, context);
+            TRACE("Allocated event query %u in context %p.\n", query->object.id, context);
         }
         else
         {
             WARN("Event queries not supported, not allocating query id.\n");
-            query->id = 0;
+            query->object.id = 0;
         }
     }
 
@@ -575,12 +581,12 @@ void context_free_event_query(struct wined3d_event_query *query)
     if (context->free_event_query_count >= context->free_event_query_size - 1)
     {
         UINT new_size = context->free_event_query_size << 1;
-        GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_event_queries,
+        union wined3d_gl_query_object *new_data = HeapReAlloc(GetProcessHeap(), 0, context->free_event_queries,
                 new_size * sizeof(*context->free_event_queries));
 
         if (!new_data)
         {
-            ERR("Failed to grow free list, leaking query %u in context %p.\n", query->id, context);
+            ERR("Failed to grow free list, leaking query %u in context %p.\n", query->object.id, context);
             return;
         }
 
@@ -588,7 +594,7 @@ void context_free_event_query(struct wined3d_event_query *query)
         context->free_event_queries = new_data;
     }
 
-    context->free_event_queries[context->free_event_query_count++] = query->id;
+    context->free_event_queries[context->free_event_query_count++] = query->object;
 }
 
 void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type)
@@ -661,6 +667,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
     struct fbo_entry *entry, *entry2;
     HGLRC restore_ctx;
     HDC restore_dc;
+    unsigned int i;
 
     restore_ctx = pwglGetCurrentContext();
     restore_dc = pwglGetCurrentDC();
@@ -682,8 +689,12 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
     {
         if (context->valid)
         {
-            if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->id));
-            else if (gl_info->supported[NV_FENCE]) GL_EXTCALL(glDeleteFencesNV(1, &event_query->id));
+            if (gl_info->supported[ARB_SYNC])
+            {
+                if (event_query->object.sync) GL_EXTCALL(glDeleteSync(event_query->object.sync));
+            }
+            else if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->object.id));
+            else if (gl_info->supported[NV_FENCE]) GL_EXTCALL(glDeleteFencesNV(1, &event_query->object.id));
         }
         event_query->context = NULL;
     }
@@ -720,10 +731,24 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
         if (gl_info->supported[ARB_OCCLUSION_QUERY])
             GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, context->free_occlusion_queries));
 
-        if (gl_info->supported[APPLE_FENCE])
-            GL_EXTCALL(glDeleteFencesAPPLE(context->free_event_query_count, context->free_event_queries));
+        if (gl_info->supported[ARB_SYNC])
+        {
+            if (event_query->object.sync) GL_EXTCALL(glDeleteSync(event_query->object.sync));
+        }
+        else if (gl_info->supported[APPLE_FENCE])
+        {
+            for (i = 0; i < context->free_event_query_count; ++i)
+            {
+                GL_EXTCALL(glDeleteFencesAPPLE(1, &context->free_event_queries[i].id));
+            }
+        }
         else if (gl_info->supported[NV_FENCE])
-            GL_EXTCALL(glDeleteFencesNV(context->free_event_query_count, context->free_event_queries));
+        {
+            for (i = 0; i < context->free_event_query_count; ++i)
+            {
+                GL_EXTCALL(glDeleteFencesNV(1, &context->free_event_queries[i].id));
+            }
+        }
 
         checkGLcall("context cleanup");
     }
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index cc7d7aa..85d5311 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -195,7 +195,7 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void
         return S_OK;
     }
 
-    if (query->context->tid != GetCurrentThreadId())
+    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");
@@ -209,14 +209,37 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void
 
     ENTER_GL();
 
-    if (gl_info->supported[APPLE_FENCE])
+    if (gl_info->supported[ARB_SYNC])
+    {
+        GLenum ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0));
+        checkGLcall("glClientWaitSync");
+
+        switch (ret)
+        {
+            case GL_ALREADY_SIGNALED:
+            case GL_CONDITION_SATISFIED:
+                *data = TRUE;
+                break;
+
+            case GL_TIMEOUT_EXPIRED:
+                *data = FALSE;
+                break;
+
+            case GL_WAIT_FAILED:
+            default:
+                ERR("glClientWaitSync returned %#x.\n", ret);
+                *data = FALSE;
+                break;
+        }
+    }
+    else if (gl_info->supported[APPLE_FENCE])
     {
-        *data = GL_EXTCALL(glTestFenceAPPLE(query->id));
+        *data = GL_EXTCALL(glTestFenceAPPLE(query->object.id));
         checkGLcall("glTestFenceAPPLE");
     }
     else if (gl_info->supported[NV_FENCE])
     {
-        *data = GL_EXTCALL(glTestFenceNV(query->id));
+        *data = GL_EXTCALL(glTestFenceNV(query->object.id));
         checkGLcall("glTestFenceNV");
     }
     else
@@ -262,7 +285,7 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface,  DWORD
 
         if (query->context)
         {
-            if (query->context->tid != GetCurrentThreadId())
+            if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
             {
                 context_free_event_query(query);
                 context = context_acquire(This->device, NULL, CTXUSAGE_RESOURCELOAD);
@@ -283,14 +306,21 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface,  DWORD
 
         ENTER_GL();
 
-        if (gl_info->supported[APPLE_FENCE])
+        if (gl_info->supported[ARB_SYNC])
+        {
+            if (query->object.sync) GL_EXTCALL(glDeleteSync(query->object.sync));
+            checkGLcall("glDeleteSync");
+            query->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
+            checkGLcall("glFenceSync");
+        }
+        else if (gl_info->supported[APPLE_FENCE])
         {
-            GL_EXTCALL(glSetFenceAPPLE(query->id));
+            GL_EXTCALL(glSetFenceAPPLE(query->object.id));
             checkGLcall("glSetFenceAPPLE");
         }
         else if (gl_info->supported[NV_FENCE])
         {
-            GL_EXTCALL(glSetFenceNV(query->id, GL_ALL_COMPLETED_NV));
+            GL_EXTCALL(glSetFenceNV(query->object.id, GL_ALL_COMPLETED_NV));
             checkGLcall("glSetFenceNV");
         }
 
@@ -450,7 +480,8 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device,
 
         case WINED3DQUERYTYPE_EVENT:
             TRACE("Event query.\n");
-            if (!gl_info->supported[NV_FENCE] && !gl_info->supported[APPLE_FENCE])
+            if (!gl_info->supported[ARB_SYNC] && !gl_info->supported[NV_FENCE]
+                    && !gl_info->supported[APPLE_FENCE])
             {
                 /* Half-Life 2 needs this query. It does not render the main
                  * menu correctly otherwise. Pretend to support it, faking
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 6c78020..164cc6b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1014,10 +1014,16 @@ struct wined3d_occlusion_query
     struct wined3d_context *context;
 };
 
+union wined3d_gl_query_object
+{
+    GLuint id;
+    GLsync sync;
+};
+
 struct wined3d_event_query
 {
     struct list entry;
-    GLuint id;
+    union wined3d_gl_query_object object;
     struct wined3d_context *context;
 };
 
@@ -1090,7 +1096,7 @@ struct wined3d_context
     UINT free_occlusion_query_count;
     struct list occlusion_queries;
 
-    GLuint *free_event_queries;
+    union wined3d_gl_query_object *free_event_queries;
     UINT free_event_query_size;
     UINT free_event_query_count;
     struct list event_queries;
-- 
1.6.4.4




More information about the wine-patches mailing list