From 945f16d5e41397d77e42e47ce7b7a5528bfad989 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Mon, 25 Jan 2010 21:44:28 +0100
Subject: [PATCH 03/18] WineD3D: Add an internal event query finish function

This matches glFinishFenceAPPLE/glFinishFenceNV, just on top of the
wined3d event query interface.
---
 dlls/wined3d/query.c           |   63 ++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |    2 +
 2 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 220a316..5ff4656 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -243,6 +243,69 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void
     return S_OK;
 }
 
+HRESULT wined3d_event_query_finish(IWineD3DQuery* iface)
+{
+    IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
+    struct wined3d_context *context;
+    struct wined3d_event_query *query = This->extendedData;
+    const struct wined3d_gl_info *gl_info = &This->device->adapter->gl_info;
+    HRESULT hr = WINED3D_OK;
+
+    TRACE("(%p)\n", This);
+
+    if (!query->context)
+    {
+        TRACE("Query not started\n");
+        return WINED3D_OK;
+    }
+
+    if (query->context->tid != GetCurrentThreadId() && !gl_info->supported[ARB_SYNC])
+    {
+        /* A glFinish does not reliably wait for draws in other contexts. The caller has
+         * to find its own way to cope with the thread switch
+         */
+        WARN("Wrong thread, returning WINED3DERR_INVALIDCALL\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    context = context_acquire(This->device, query->context->current_rt, CTXUSAGE_RESOURCELOAD);
+
+    ENTER_GL();
+    if (gl_info->supported[ARB_SYNC])
+    {
+        GLenum ret = GL_EXTCALL(glClientWaitSync(query->object.sync, GL_SYNC_FLUSH_COMMANDS_BIT, ~0U));
+        checkGLcall("glClientWaitSync");
+
+        switch (ret)
+        {
+            case GL_ALREADY_SIGNALED:
+            case GL_CONDITION_SATISFIED:
+                break;
+
+                /* We don't expect a timeout for a ~584 year wait */
+            case GL_TIMEOUT_EXPIRED:
+            case GL_WAIT_FAILED:
+            default:
+                ERR("glClientWaitSync returned %#x.\n", ret);
+                hr = WINED3DERR_INVALIDCALL;
+        }
+    }
+    else if (context->gl_info->supported[APPLE_FENCE])
+    {
+        GL_EXTCALL(glFinishFenceAPPLE(query->object.id));
+        checkGLcall("glFinishFenceAPPLE");
+    }
+    else if (context->gl_info->supported[NV_FENCE])
+    {
+        GL_EXTCALL(glFinishFenceNV(query->object.id));
+        checkGLcall("glFinishFenceNV");
+    }
+    LEAVE_GL();
+
+    context_release(context);
+    return hr;
+}
+
 static DWORD  WINAPI IWineD3DEventQueryImpl_GetDataSize(IWineD3DQuery* iface){
     TRACE("(%p) : type D3DQUERY_EVENT\n", iface);
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 164cc6b..0ea4bb9 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2357,6 +2357,8 @@ typedef struct IWineD3DQueryImpl
 HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device,
         WINED3DQUERYTYPE type, IUnknown *parent) DECLSPEC_HIDDEN;
 
+HRESULT wined3d_event_query_finish(IWineD3DQuery* iface) DECLSPEC_HIDDEN;
+
 /* IWineD3DBuffer */
 
 /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other
-- 
1.6.4.4

