[PATCH 09/12] wined3d/query: Add support for D3DQUERY_TIMESTAMPDISJOINT queries.

Adam Martinson amartinson at codeweavers.com
Wed May 4 13:00:50 CDT 2011


---
 dlls/wined3d/query.c     |  233 ++++++++++++++++++++++++++++++++++++++++++++++
 include/wine/wined3d.idl |    6 +
 2 files changed, 239 insertions(+), 0 deletions(-)

diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index cb471e3..bea91f5 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -27,6 +27,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 
+#define ARB_TIMER_QUERY_FREQ 1000000000 /* nanoseconds */
+
 BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info)
 {
     return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE];
@@ -271,6 +273,7 @@ ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
             break;
 
         case WINED3DQUERYTYPE_TIMESTAMP:
+        case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
             {
                 struct wined3d_timestamp_query *tsq = query->extendedData;
 
@@ -502,6 +505,133 @@ static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query,
     return res;
 }
 
+/* Only called when GL_ARB_timer_query is supported. */
+static HRESULT wined3d_timestampdisjoint_query_ops_get_data(struct wined3d_query *query,
+                                                            void *pData, DWORD dwSize, DWORD flags)
+{
+    const struct wined3d_gl_info *gl_info = &query->device->adapter->gl_info;
+    struct wined3d_timestamp_query *This = query->extendedData;
+    struct wined3d_context *context;
+    GLuint available;
+    UINT64 time_start, time_end, time_elapsed;
+    HRESULT res;
+
+    TRACE("(%p) : type D3DQUERY_TIMESTAMPDISJOINT, pData %p, dwSize %#x, flags %#x.\n", query, pData, dwSize, flags);
+
+    if (!This->context)
+        query->state = QUERY_CREATED;
+
+    if (query->state == QUERY_CREATED)
+    {
+        /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
+        TRACE("Query wasn't yet started, returning S_OK\n");
+        if (pData)
+            switch (dwSize)
+            {
+            case 0:
+                break;
+
+            case sizeof(BOOL): /* D3D9- */
+                *((BOOL*)pData) = TRUE;
+                break;
+
+            case sizeof(WINED3DQUERY_TIMESTAMPDISJOINT_DATA): /* D3D10+ */
+                ((WINED3DQUERY_TIMESTAMPDISJOINT_DATA*)pData)->Disjoint = TRUE;
+                ((WINED3DQUERY_TIMESTAMPDISJOINT_DATA*)pData)->Frequency = 0;
+                break;
+
+            default:
+                FIXME("invalid dwSize %#x\n", dwSize);
+            }
+
+        return S_OK;
+    }
+
+    if (query->state == QUERY_BUILDING)
+    {
+        TRACE("Query is building, returning S_FALSE\n");
+        return S_FALSE;
+    }
+
+    if (This->context->tid != GetCurrentThreadId())
+    {
+        FIXME("%p Wrong thread, returning 0.\n", query);
+        if (pData)
+            switch (dwSize)
+            {
+            case 0:
+                break;
+
+            case sizeof(BOOL): /* D3D9- */
+                *((BOOL*)pData) = TRUE;
+                break;
+
+            case sizeof(WINED3DQUERY_TIMESTAMPDISJOINT_DATA): /* D3D10+ */
+                ((WINED3DQUERY_TIMESTAMPDISJOINT_DATA*)pData)->Disjoint = TRUE;
+                ((WINED3DQUERY_TIMESTAMPDISJOINT_DATA*)pData)->Frequency = 0;
+                break;
+
+            default:
+                FIXME("invalid dwSize %#x\n", dwSize);
+            }
+        return S_OK;
+    }
+
+    context = context_acquire(query->device, This->context->current_rt);
+
+    ENTER_GL();
+
+    GL_EXTCALL(glGetQueryObjectuivARB(This->ids[2], GL_QUERY_RESULT_AVAILABLE_ARB, &available));
+    checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)");
+    TRACE("available %#x.\n", available);
+
+    if (available)
+    {
+        if (pData)
+        {
+            BOOL disjoint;
+
+            GL_EXTCALL(glGetQueryObjectui64v(This->ids[0], GL_QUERY_RESULT_ARB, &time_start));
+            checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
+            GL_EXTCALL(glGetQueryObjectui64v(This->ids[1], GL_QUERY_RESULT_ARB, &time_end));
+            checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
+            GL_EXTCALL(glGetQueryObjectui64v(This->ids[2], GL_QUERY_RESULT_ARB, &time_elapsed));
+            checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
+
+            disjoint = ((time_start >= time_end) || ((time_end - time_start) > time_elapsed));
+
+            switch (dwSize)
+            {
+            case 0:
+                break;
+
+            case sizeof(BOOL): /* D3D9- */
+                *((BOOL*)pData) = disjoint;
+                break;
+
+            case sizeof(WINED3DQUERY_TIMESTAMPDISJOINT_DATA): /* D3D10+ */
+                ((WINED3DQUERY_TIMESTAMPDISJOINT_DATA*)pData)->Disjoint = disjoint;
+                ((WINED3DQUERY_TIMESTAMPDISJOINT_DATA*)pData)->Frequency = ARB_TIMER_QUERY_FREQ;
+                break;
+
+            default:
+                FIXME("invalid dwSize %#x\n", dwSize);
+            }
+        }
+        res = S_OK;
+    }
+    else
+    {
+        res = S_FALSE;
+    }
+
+    LEAVE_GL();
+
+    context_release(context);
+
+    return res;
+}
+
 WINED3DQUERYTYPE CDECL wined3d_query_get_type(const struct wined3d_query *query)
 {
     TRACE("query %p.\n", query);
@@ -658,6 +788,83 @@ static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DW
     return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
 }
 
+/* Only called when GL_ARB_timer_query is supported. */
+static HRESULT wined3d_timestampdisjoint_query_ops_issue(struct wined3d_query *query, DWORD flags)
+{
+    const struct wined3d_gl_info *gl_info = &query->device->adapter->gl_info;
+    struct wined3d_timestamp_query *This = query->extendedData;
+    struct wined3d_context *context;
+
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    if (flags & WINED3DISSUE_BEGIN)
+    {
+        if (query->state == QUERY_BUILDING)
+        {
+            if (This->context->tid != GetCurrentThreadId())
+            {
+                FIXME("Wrong thread, can't restart query.\n");
+
+                context_free_timestamp_query(This);
+                context = context_acquire(query->device, NULL);
+                context_alloc_timestamp_query(context, This);
+            }
+            else
+            {
+                context = context_acquire(query->device, This->context->current_rt);
+
+                ENTER_GL();
+                GL_EXTCALL(glEndQueryARB(GL_TIME_ELAPSED_ARB));
+                checkGLcall("glEndQuery(GL_TIME_ELAPSED)");
+                LEAVE_GL();
+            }
+        }
+        else
+        {
+            if (This->context) context_free_timestamp_query(This);
+            context = context_acquire(query->device, NULL);
+            context_alloc_timestamp_query(context, This);
+        }
+
+        ENTER_GL();
+        GL_EXTCALL(glBeginQueryARB(GL_TIME_ELAPSED_ARB, This->ids[2]));
+        checkGLcall("glBeginQuery(GL_TIME_ELAPSED)");
+        GL_EXTCALL(glQueryCounter(This->ids[0], GL_TIMESTAMP_ARB));
+        checkGLcall("glQueryCounter(GL_TIMESTAMP)");
+        LEAVE_GL();
+
+        context_release(context);
+        query->state = QUERY_BUILDING;
+    }
+    if (flags & WINED3DISSUE_END)
+    {
+        if (query->state == QUERY_BUILDING)
+        {
+            if (This->context->tid != GetCurrentThreadId())
+            {
+                FIXME("Wrong thread, can't end query.\n");
+            }
+            else
+            {
+                context = context_acquire(query->device, This->context->current_rt);
+
+                ENTER_GL();
+                GL_EXTCALL(glQueryCounter(This->ids[1], GL_TIMESTAMP_ARB));
+                checkGLcall("glQueryCounter(GL_TIMESTAMP)");
+                GL_EXTCALL(glEndQueryARB(GL_TIME_ELAPSED_ARB));
+                checkGLcall("glEndQuery(GL_TIME_ELAPSED)");
+                LEAVE_GL();
+
+                context_release(context);
+            }
+        }
+
+        query->state = QUERY_SIGNALLED;
+    }
+
+    return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
+}
+
 static const struct wined3d_query_ops event_query_ops =
 {
     wined3d_event_query_ops_get_data,
@@ -676,6 +883,12 @@ static const struct wined3d_query_ops timestamp_query_ops =
     wined3d_timestamp_query_ops_issue,
 };
 
+static const struct wined3d_query_ops timestampdisjoint_query_ops =
+{
+    wined3d_timestampdisjoint_query_ops_get_data,
+    wined3d_timestampdisjoint_query_ops_issue,
+};
+
 HRESULT query_init(struct wined3d_query *query, IWineD3DDeviceImpl *device, WINED3DQUERYTYPE type)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
@@ -742,6 +955,26 @@ HRESULT query_init(struct wined3d_query *query, IWineD3DDeviceImpl *device, WINE
             break;
 
         case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
+            TRACE("Timestampdisjoint query.\n");
+            if (!gl_info->supported[ARB_TIMER_QUERY])
+            {
+                WARN("GL_ARB_timer_query not supported, returning WINED3DERR_NOTAVAILABLE.\n");
+                return WINED3DERR_NOTAVAILABLE;
+            }
+
+            query->data_size = sizeof(WINED3DQUERY_TIMESTAMPDISJOINT_DATA);
+            query->query_ops = &timestampdisjoint_query_ops;
+            query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct wined3d_timestamp_query));
+            if (!query->extendedData)
+            {
+                ERR("Failed to allocate event query memory.\n");
+                return E_OUTOFMEMORY;
+            }
+            ((struct wined3d_timestamp_query *)query->extendedData)->n_ids = 3;
+            ((struct wined3d_timestamp_query *)query->extendedData)->context = NULL;
+
+            break;
+
         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
         case WINED3DQUERYTYPE_VCACHE:
         case WINED3DQUERYTYPE_RESOURCEMANAGER:
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index a449d3a..c1af99b 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -763,6 +763,12 @@ const UINT WINED3DISSUE_BEGIN               = (1 << 1);
 const UINT WINED3DISSUE_END                 = (1 << 0);
 const UINT WINED3DGETDATA_FLUSH             = (1 << 0);
 
+typedef struct _WINED3DQUERY_TIMESTAMPDISJOINT_DATA
+{
+    UINT64 Frequency;
+    BOOL   Disjoint;
+} WINED3DQUERY_TIMESTAMPDISJOINT_DATA;
+
 typedef enum _WINED3DSTATEBLOCKTYPE
 {
     WINED3DSBT_INIT                         = 0,
-- 
1.7.1


--------------020407030507000107030307
Content-Type: text/x-patch;
 name="0010-wined3d-query-Add-support-for-D3DQUERY_TIMESTAMPFREQ.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0010-wined3d-query-Add-support-for-D3DQUERY_TIMESTAMPFREQ.pa";
 filename*1="tch"



More information about the wine-devel mailing list