Stefan Dösinger : wined3d: Create a wined3d internal event query interface.

Alexandre Julliard julliard at winehq.org
Fri Mar 5 09:42:54 CST 2010


Module: wine
Branch: master
Commit: a0d1a55650a6070a239a5df4cac6be01e809fcf2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a0d1a55650a6070a239a5df4cac6be01e809fcf2

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Wed Mar  3 22:45:34 2010 +0100

wined3d: Create a wined3d internal event query interface.

The newly created wined3d_event_query_test will be available for
wined3d-internal use, primarily for synchronizing buffer updates when
using GL_APPLE_flush_buffer_range.

The wined3d_event_query interface will contain most of the functionality:
* Selecting the proper GL extension
* Context handling
* Thread handling

The IWineD3DEventQuery COM interface will use the internal interface
and implement event query faking on top of it (to enable games that
require event queries able to run on drivers that don't implement the
GL extension).

---

 dlls/wined3d/query.c           |  168 ++++++++++++++++++++++++----------------
 dlls/wined3d/wined3d_private.h |   10 +++
 2 files changed, 111 insertions(+), 67 deletions(-)

diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 85d5311..97ad5bd 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -24,15 +24,88 @@
 #include "config.h"
 #include "wined3d_private.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+#define GLINFO_LOCATION (*gl_info)
+
+static enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
+{
+    struct wined3d_context *context;
+    const struct wined3d_gl_info *gl_info;
+    enum wined3d_event_query_result ret;
+    BOOL fence_result;
+
+    TRACE("(%p) : device %p\n", query, device);
+
+    if (query->context == NULL)
+    {
+        TRACE("Query not started\n");
+        return WINED3D_EVENT_QUERY_NOT_STARTED;
+    }
+
+    if (!query->context->gl_info->supported[ARB_SYNC] && query->context->tid != GetCurrentThreadId())
+    {
+        WARN("Event query tested from wrong thread\n");
+        return WINED3D_EVENT_QUERY_WRONG_THREAD;
+    }
+
+    context = context_acquire(device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+    gl_info = context->gl_info;
+
+    ENTER_GL();
+
+    if (gl_info->supported[ARB_SYNC])
+    {
+        GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0));
+        checkGLcall("glClientWaitSync");
+
+        switch (gl_ret)
+        {
+            case GL_ALREADY_SIGNALED:
+            case GL_CONDITION_SATISFIED:
+                ret = WINED3D_EVENT_QUERY_OK;
+                break;
+
+            case GL_TIMEOUT_EXPIRED:
+                ret = WINED3D_EVENT_QUERY_WAITING;
+                break;
+
+            case GL_WAIT_FAILED:
+            default:
+                ERR("glClientWaitSync returned %#x.\n", gl_ret);
+                ret = WINED3D_EVENT_QUERY_ERROR;
+        }
+    }
+    else if (gl_info->supported[APPLE_FENCE])
+    {
+        fence_result = GL_EXTCALL(glTestFenceAPPLE(query->object.id));
+        checkGLcall("glTestFenceAPPLE");
+        if (fence_result) ret = WINED3D_EVENT_QUERY_OK;
+        else ret = WINED3D_EVENT_QUERY_WAITING;
+    }
+    else if (gl_info->supported[NV_FENCE])
+    {
+        fence_result = GL_EXTCALL(glTestFenceNV(query->object.id));
+        checkGLcall("glTestFenceNV");
+        if (fence_result) ret = WINED3D_EVENT_QUERY_OK;
+        else ret = WINED3D_EVENT_QUERY_WAITING;
+    }
+    else
+    {
+        ret = WINED3D_EVENT_QUERY_UNSUPPORTED;
+    }
+
+    LEAVE_GL();
+
+    context_release(context);
+    return ret;
+}
+
 /*
  * Occlusion Queries:
  * http://www.gris.uni-tuebingen.de/~bartz/Publications/paper/hww98.pdf
  * http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt
  */
 
-WINE_DEFAULT_DEBUG_CHANNEL(d3d);
-#define GLINFO_LOCATION (*gl_info)
-
 /* *******************************************
    IWineD3DQuery IUnknown parts follow
    ******************************************* */
@@ -179,78 +252,39 @@ 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;
-    const struct wined3d_gl_info *gl_info;
-    struct wined3d_context *context;
     BOOL *data = pData;
+    enum wined3d_event_query_result ret;
 
     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)
+    ret = wined3d_event_query_test(query, This->device);
+    switch(ret)
     {
-        TRACE("Query not started, returning TRUE.\n");
-        *data = TRUE;
-
-        return S_OK;
-    }
-
-    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");
-        *data = TRUE;
-
-        return S_OK;
-    }
-
-    context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
-    gl_info = context->gl_info;
-
-    ENTER_GL();
+        case WINED3D_EVENT_QUERY_OK:
+        case WINED3D_EVENT_QUERY_NOT_STARTED:
+            *data = TRUE;
+            break;
 
-    if (gl_info->supported[ARB_SYNC])
-    {
-        GLenum ret = GL_EXTCALL(glClientWaitSync(query->object.sync, 0, 0));
-        checkGLcall("glClientWaitSync");
+        case WINED3D_EVENT_QUERY_WAITING:
+            *data = FALSE;
+            break;
 
-        switch (ret)
-        {
-            case GL_ALREADY_SIGNALED:
-            case GL_CONDITION_SATISFIED:
-                *data = TRUE;
-                break;
+        case WINED3D_EVENT_QUERY_WRONG_THREAD:
+            FIXME("(%p) Wrong thread, reporting GPU idle.\n", This);
+            *data = TRUE;
+            break;
 
-            case GL_TIMEOUT_EXPIRED:
-                *data = FALSE;
-                break;
+        case WINED3D_EVENT_QUERY_UNSUPPORTED:
+            WARN("(%p): Event query not supported by GL, reporting GPU idle\n", This);
+            *data = TRUE;
+            break;
 
-            case GL_WAIT_FAILED:
-            default:
-                ERR("glClientWaitSync returned %#x.\n", ret);
-                *data = FALSE;
-                break;
-        }
+        case WINED3D_EVENT_QUERY_ERROR:
+            ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n");
+            return WINED3DERR_INVALIDCALL;
     }
-    else if (gl_info->supported[APPLE_FENCE])
-    {
-        *data = GL_EXTCALL(glTestFenceAPPLE(query->object.id));
-        checkGLcall("glTestFenceAPPLE");
-    }
-    else if (gl_info->supported[NV_FENCE])
-    {
-        *data = GL_EXTCALL(glTestFenceNV(query->object.id));
-        checkGLcall("glTestFenceNV");
-    }
-    else
-    {
-        WARN("(%p): reporting GPU idle\n", This);
-        *data = TRUE;
-    }
-
-    LEAVE_GL();
-
-    context_release(context);
 
     return S_OK;
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index ebfa7a4..616a391 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1030,6 +1030,16 @@ struct wined3d_event_query
     struct wined3d_context *context;
 };
 
+enum wined3d_event_query_result
+{
+    WINED3D_EVENT_QUERY_OK,
+    WINED3D_EVENT_QUERY_WAITING,
+    WINED3D_EVENT_QUERY_NOT_STARTED,
+    WINED3D_EVENT_QUERY_WRONG_THREAD,
+    WINED3D_EVENT_QUERY_ERROR,
+    WINED3D_EVENT_QUERY_UNSUPPORTED
+};
+
 struct wined3d_context
 {
     const struct wined3d_gl_info *gl_info;




More information about the wine-cvs mailing list