wined3d: Create a wined3d internal event query interface.
authorStefan Dösinger <stefan@codeweavers.com>
Wed, 3 Mar 2010 21:45:34 +0000 (22:45 +0100)
committerAlexandre Julliard <julliard@winehq.org>
Fri, 5 Mar 2010 11:39:07 +0000 (12:39 +0100)
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
dlls/wined3d/wined3d_private.h

index 85d5311c3bda7929d6fc5ada780707b4efc9a054..97ad5bd44314d1dc31eed22e9df85946f61fc84b 100644 (file)
 #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;
 }
index ebfa7a47482166e822382c3ebd652767c4d52cb2..616a391be2c7fa5ebf9d8a5ac72e741217d006e2 100644 (file)
@@ -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;