From c5cf83b6acaafdb3c42e741713026a2c58b805ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Fri, 12 Feb 2010 20:38:25 +0100
Subject: [PATCH 03/12] WineD3D: Add wined3d_event_query_create and destroy

---
 dlls/wined3d/query.c           |   61 ++++++++++++++++++++++++++++-----------
 dlls/wined3d/wined3d_private.h |    3 +-
 2 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 43c27d8..f813819 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -70,17 +70,16 @@ static ULONG  WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
         if (This->type == WINED3DQUERYTYPE_EVENT)
         {
             struct wined3d_event_query *query = This->extendedData;
-
-            if (query->context) context_free_event_query(query);
+            if (query) wined3d_event_query_destroy(query);
         }
         else if (This->type == WINED3DQUERYTYPE_OCCLUSION)
         {
             struct wined3d_occlusion_query *query = This->extendedData;
 
             if (query->context) context_free_occlusion_query(query);
+            HeapFree(GetProcessHeap(), 0, This->extendedData);
         }
 
-        HeapFree(GetProcessHeap(), 0, This->extendedData);
         HeapFree(GetProcessHeap(), 0, This);
     }
     return ref;
@@ -184,6 +183,12 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void
     TRACE("(%p) : type D3DQUERY_EVENT, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);
 
     if (!pData || !dwSize) return S_OK;
+    if (!query)
+    {
+        WARN("(%p): Event query not supported by GL, reporting GPU idle\n", This);
+        *data = TRUE;
+        return S_OK;
+    }
 
     if (data)
     {
@@ -206,11 +211,6 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void
                 *data = TRUE;
                 break;
 
-            case WINED3D_EVENT_QUERY_UNSUPPORTED:
-                WARN("(%p): Event query not supported by GL, reporting GPU idle\n", This);
-                *data = TRUE;
-                break;
-
             case WINED3D_EVENT_QUERY_ERROR:
                 ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n");
                 return WINED3DERR_INVALIDCALL;
@@ -244,6 +244,10 @@ static HRESULT  WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface,  DWORD
     if (dwIssueFlags & WINED3DISSUE_END)
     {
         struct wined3d_event_query *query = This->extendedData;
+
+        /* Faked event query support */
+        if (!query) return WINED3D_OK;
+
         wined3d_event_query_issue(query, This->device);
     }
     else if(dwIssueFlags & WINED3DISSUE_BEGIN)
@@ -376,6 +380,7 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device,
         WINED3DQUERYTYPE type, IUnknown *parent)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
+    HRESULT hr;
 
     switch (type)
     {
@@ -398,8 +403,9 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device,
 
         case WINED3DQUERYTYPE_EVENT:
             TRACE("Event query.\n");
-            if (!gl_info->supported[ARB_SYNC] && !gl_info->supported[NV_FENCE]
-                    && !gl_info->supported[APPLE_FENCE])
+            query->lpVtbl = &IWineD3DEventQuery_Vtbl;
+            hr = wined3d_event_query_init(gl_info, (struct wined3d_event_query **) &query->extendedData);
+            if (hr == E_NOTIMPL)
             {
                 /* Half-Life 2 needs this query. It does not render the main
                  * menu correctly otherwise. Pretend to support it, faking
@@ -407,14 +413,10 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device,
                  * lowering performance. */
                 FIXME("Event query: Unimplemented, but pretending to be supported.\n");
             }
-            query->lpVtbl = &IWineD3DEventQuery_Vtbl;
-            query->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_event_query));
-            if (!query->extendedData)
+            else if(FAILED(hr))
             {
-                ERR("Failed to allocate event query extended data.\n");
-                return E_OUTOFMEMORY;
+                return hr;
             }
-            ((struct wined3d_event_query *)query->extendedData)->context = NULL;
             break;
 
         case WINED3DQUERYTYPE_VCACHE:
@@ -443,6 +445,30 @@ HRESULT query_init(IWineD3DQueryImpl *query, IWineD3DDeviceImpl *device,
     return WINED3D_OK;
 }
 
+HRESULT wined3d_event_query_init(const struct wined3d_gl_info *gl_info, struct wined3d_event_query **query)
+{
+    struct wined3d_event_query *ret;
+    *query = NULL;
+    if (!gl_info->supported[ARB_SYNC] && !gl_info->supported[NV_FENCE]
+        && !gl_info->supported[APPLE_FENCE]) return E_NOTIMPL;
+    
+    ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
+    if (!ret)
+    {
+        ERR("Failed to allocate a wined3d event query structure.\n");
+        return E_OUTOFMEMORY;
+    }
+    ret->context = NULL;
+    *query = ret;
+    return WINED3D_OK;
+}
+
+void wined3d_event_query_destroy(struct wined3d_event_query *query)
+{
+    if (query->context) context_free_event_query(query);
+    HeapFree(GetProcessHeap(), 0, query);
+}
+
 enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device)
 {
     struct wined3d_context *context;
@@ -507,7 +533,8 @@ enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_qu
     }
     else
     {
-        ret = WINED3D_EVENT_QUERY_UNSUPPORTED;
+        ERR("Event query created despite lack of GL support\n");
+        ret = WINED3D_EVENT_QUERY_ERROR;
     }
 
     LEAVE_GL();
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 4244652..f6a28a9 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1036,11 +1036,12 @@ enum wined3d_event_query_result
     WINED3D_EVENT_QUERY_NOT_STARTED,
     WINED3D_EVENT_QUERY_WRONG_THREAD,
     WINED3D_EVENT_QUERY_ERROR,
-    WINED3D_EVENT_QUERY_UNSUPPORTED
 };
 
 enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN;
 void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN;
+HRESULT wined3d_event_query_init(const struct wined3d_gl_info *gl_info, struct wined3d_event_query **query) DECLSPEC_HIDDEN;
+void wined3d_event_query_destroy(struct wined3d_event_query *query) DECLSPEC_HIDDEN;
 
 struct wined3d_context
 {
-- 
1.6.4.4

