[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    Re: Support for D3DQUERY_TIMESTAMP* queries...
From:       Adam Martinson <amartinson () codeweavers ! com>
Date:       2011-05-27 19:16:40
Message-ID: 4DDFF898.6090402 () codeweavers ! com
[Download RAW message or body]

On 05/27/2011 01:23 PM, Adam Martinson wrote:
> On 05/25/2011 11:31 AM, Stefan Dösinger wrote:
>> On Wednesday 25 May 2011 18:23:39 Adam Martinson wrote:
>>> Do you think that needs to be done before I submit those or is that
>>> something that can come later?
>> I'd prefer to have this checked before submitting. It shouldn't take 
>> long.
>> Just write a test app that grabs the timestamp in a loop and prints 
>> it to
>> stdout and see what kind of values it writes. If it does wrap around 
>> in a
>> reasonable amount of time(e.g. a few hours) write a test that waits 
>> for the
>> wraparound to approach, starts a disjoint query, waits until after the
>> wraparound, ends the disjoint query and prints its result.
> Ran a test for 10 mins or so, on my card it behaves like the 
> GL_ARB_timer_query version, except the frequency is 10ns instead of 
> 1ns... so it doesn't look like it would wrap around in my lifetime.  I 
> can include that test with an environment variable to set the number 
> of iterations if you like.
Are these ok to submit now?

["0002-wined3d-Add-support-for-GL_ARB_timer_query.patch" (text/x-patch)]

From 22312de4267235eec7e9720383aaee073fd586a6 Mon Sep 17 00:00:00 2001
From: Adam Martinson <amartinson@codeweavers.com>
Date: Tue, 17 May 2011 11:14:01 -0500
Subject: [PATCH 02/11] wined3d: Add support for GL_ARB_timer_query.
To: wine-patches <wine-patches@winehq.org>
Reply-To: wine-devel <wine-devel@winehq.org>

---
 dlls/wined3d/directx.c    |    1 +
 dlls/wined3d/wined3d_gl.h |   19 +++++++++++++++++++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index a29533e..c643956 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -86,6 +86,7 @@ static const struct {
     {"GL_ARB_texture_non_power_of_two",     ARB_TEXTURE_NON_POWER_OF_TWO,   \
                MAKEDWORD_VERSION(2, 0)     },
     {"GL_ARB_texture_rectangle",            ARB_TEXTURE_RECTANGLE,          0        \
                },
     {"GL_ARB_texture_rg",                   ARB_TEXTURE_RG,                 0        \
}, +    {"GL_ARB_timer_query",                  ARB_TIMER_QUERY,                0     \
                },
     {"GL_ARB_vertex_array_bgra",            ARB_VERTEX_ARRAY_BGRA,          0        \
                },
     {"GL_ARB_vertex_blend",                 ARB_VERTEX_BLEND,               0        \
                },
     {"GL_ARB_vertex_buffer_object",         ARB_VERTEX_BUFFER_OBJECT,       0        \
                },
diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h
index be50b2f..3248bdb 100644
--- a/dlls/wined3d/wined3d_gl.h
+++ b/dlls/wined3d/wined3d_gl.h
@@ -1769,6 +1769,7 @@ typedef enum wined3d_gl_extension
     ARB_TEXTURE_NON_POWER_OF_TWO,
     ARB_TEXTURE_RECTANGLE,
     ARB_TEXTURE_RG,
+    ARB_TIMER_QUERY,
     ARB_VERTEX_ARRAY_BGRA,
     ARB_VERTEX_BLEND,
     ARB_VERTEX_BUFFER_OBJECT,
@@ -2458,6 +2459,17 @@ typedef GLvoid (WINE_GLAPI *PGLFNGETSYNCIVPROC)(GLsync sync, \
GLenum pname, GLsiz  #define GL_RG32UI                                           \
0x823c  #endif
 
+/* GL_ARB_timer_query */
+#ifndef GL_ARB_timer_query
+#define GL_ARB_timer_query 1
+#define GL_TIME_ELAPSED_ARB                                 0x88bf
+#define GL_TIMESTAMP_ARB                                    0x8e28
+#endif
+
+typedef void (WINE_GLAPI *PGLFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
+typedef void (WINE_GLAPI *PGLFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, \
GLint64 *params); +typedef void (WINE_GLAPI *PGLFNGLGETQUERYOBJECTUI64VPROC)(GLuint \
id, GLenum pname, GLuint64 *params); +
 /* GL_ARB_vertex_blend */
 #ifndef GL_ARB_vertex_blend
 #define GL_ARB_vertex_blend 1
@@ -4002,6 +4014,13 @@ typedef BOOL (WINAPI *WINED3D_PFNWGLSWAPINTERVALEXTPROC)(int \
                interval);
             glCompressedTexSubImage3DARB,               ARB_TEXTURE_COMPRESSION,     \
NULL) \  USE_GL_FUNC(PGLFNGETCOMPRESSEDTEXIMAGEPROC, \
             glGetCompressedTexImageARB,                 ARB_TEXTURE_COMPRESSION,     \
NULL) \ +    /* GL_ARB_timer_query */ \
+    USE_GL_FUNC(PGLFNGLQUERYCOUNTERPROC, \
+            glQueryCounter,                             ARB_TIMER_QUERY,             \
NULL) \ +    USE_GL_FUNC(PGLFNGLGETQUERYOBJECTI64VPROC, \
+            glGetQueryObjecti64v,                       ARB_TIMER_QUERY,             \
NULL) \ +    USE_GL_FUNC(PGLFNGLGETQUERYOBJECTUI64VPROC, \
+            glGetQueryObjectui64v,                      ARB_TIMER_QUERY,             \
NULL) \  /* GL_ARB_vertex_blend */ \
     USE_GL_FUNC(PGLFNGLWEIGHTPOINTERARB, \
             glWeightPointerARB,                         ARB_VERTEX_BLEND,            \
                NULL) \
-- 
1.7.1


["0003-d3d9-tests-Add-tests-for-D3DQUERY_TIMESTAMP-queries.patch" (text/x-patch)]

From ca8157a3233c0a022c5c2084120db9a251c2eb8a Mon Sep 17 00:00:00 2001
From: Adam Martinson <amartinson@codeweavers.com>
Date: Fri, 27 May 2011 14:12:36 -0500
Subject: [PATCH 03/11] d3d9/tests: Add tests for D3DQUERY_TIMESTAMP* queries.
To: wine-patches <wine-patches@winehq.org>
Reply-To: wine-devel <wine-devel@winehq.org>

---
 dlls/d3d9/tests/query.c |  301 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 301 insertions(+), 0 deletions(-)

diff --git a/dlls/d3d9/tests/query.c b/dlls/d3d9/tests/query.c
index 97d3508..89daccc 100644
--- a/dlls/d3d9/tests/query.c
+++ b/dlls/d3d9/tests/query.c
@@ -246,6 +246,305 @@ cleanup:
     }
 }
 
+/* Test for basic sanity against \
QueryPerformanceCounter()/QueryPerformanceFrequency() */ +static void \
test_timestamp_queries(IDirect3D9 *d3d, HWND hwnd) +{
+    HRESULT               hr;
+    int                   i, j;
+    IDirect3DDevice9      *device = NULL;
+    D3DPRESENT_PARAMETERS d3dpp;
+    D3DDISPLAYMODE        d3ddm;
+    IDirect3DQuery9       *q_ts1 = NULL, *q_ts2 = NULL, *q_disjoint = NULL, *q_freq \
= NULL; +    UINT64 freq = 0, ts1 = 0, ts2 = 0, elapsed, qp_elapsed1, qp_elapsed2;
+    LARGE_INTEGER qp_freq, qp_ts1, qp_ts2, qp_ts3, qp_ts4;
+    BOOL ts_dj = TRUE;
+    UINT size;
+
+    if (!QueryPerformanceFrequency(&qp_freq))
+    {
+        skip("QueryPerformanceFrequency() failed\n");
+        goto cleanup;
+    }
+
+    IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
+    ZeroMemory(&d3dpp, sizeof(d3dpp));
+    d3dpp.Windowed         = TRUE;
+    d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
+    d3dpp.BackBufferFormat = d3ddm.Format;
+
+    hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, \
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); +    ok(SUCCEEDED(hr) || hr == \
D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr); +    if \
(FAILED(hr)) +    {
+        skip("Failed to create a d3d device\n");
+        goto cleanup;
+    }
+
+    hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &q_ts1);
+    ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE,
+       "IDirect3DDevice9_CreateQuery returned unexpected return value %08x\n", hr);
+    hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &q_ts2);
+    ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE,
+       "IDirect3DDevice9_CreateQuery returned unexpected return value %08x\n", hr);
+    hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &q_freq);
+    ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE,
+       "IDirect3DDevice9_CreateQuery returned unexpected return value %08x\n", hr);
+    hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, \
&q_disjoint); +    ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE,
+       "IDirect3DDevice9_CreateQuery returned unexpected return value %08x\n", hr);
+
+    if(!q_freq || !q_ts1 || !q_ts2 || !q_disjoint)
+    {
+        skip("Timestamp queries not supported\n");
+        goto cleanup;
+    }
+
+    /* Non-issued queries should succeed, but the data is garbage. */
+    hr = IDirect3DQuery9_GetData(q_ts1, &ts1, sizeof(ts1), D3DGETDATA_FLUSH);
+    ok(hr == D3D_OK, "IDirect3DQuery9_GetData(q_ts1) returned %08x\n", hr);
+
+    hr = IDirect3DQuery9_GetData(q_freq, &freq, sizeof(freq), D3DGETDATA_FLUSH);
+    ok(hr == D3D_OK, "IDirect3DQuery9_GetData(q_freq) returned %08x\n", hr);
+
+    hr = IDirect3DQuery9_GetData(q_disjoint, &ts_dj, sizeof(ts_dj), \
D3DGETDATA_FLUSH); +    ok(hr == D3D_OK, "IDirect3DQuery9_GetData(q_disjoint) \
returned %08x\n", hr); +
+    for (i = 0; i < 2; ++i)
+    {
+        do
+        {
+            QueryPerformanceCounter(&qp_ts1);
+
+            hr = IDirect3DQuery9_Issue(q_disjoint, D3DISSUE_BEGIN);
+            ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_disjoint, D3DISSUE_BEGIN) \
returned %08x\n", hr); +
+            hr = IDirect3DQuery9_GetData(q_disjoint, &ts_dj, sizeof(ts_dj), 0);
+            ok(hr == D3D_OK, "IDirect3DQuery9_GetData(q_disjoint) returned %08x\n", \
hr); +
+            hr = IDirect3DQuery9_Issue(q_freq, D3DISSUE_END);
+            ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_freq, D3DISSUE_END) returned \
%08x\n", hr); +
+            hr = IDirect3DQuery9_Issue(q_ts1, D3DISSUE_END);
+            ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_ts1, D3DISSUE_END) returned \
%08x\n", hr); +
+            do
+            {
+                QueryPerformanceCounter(&qp_ts2);
+            }
+            while (qp_ts1.QuadPart == qp_ts2.QuadPart);
+
+            do
+            {
+                QueryPerformanceCounter(&qp_ts3);
+            }
+            while (qp_ts2.QuadPart == qp_ts3.QuadPart);
+
+            hr = IDirect3DQuery9_Issue(q_ts2, D3DISSUE_END);
+            ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_ts2, D3DISSUE_END) returned \
%08x\n", hr); +
+            hr = IDirect3DQuery9_Issue(q_disjoint, D3DISSUE_END);
+            ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_disjoint, D3DISSUE_END) \
returned %08x\n", hr); +
+            do
+            {
+                QueryPerformanceCounter(&qp_ts4);
+            }
+            while (qp_ts3.QuadPart == qp_ts4.QuadPart);
+
+        }
+        while (qp_ts1.QuadPart > qp_ts2.QuadPart || qp_ts2.QuadPart > \
qp_ts3.QuadPart || qp_ts3.QuadPart > qp_ts4.QuadPart); +
+        size = IDirect3DQuery9_GetDataSize(q_ts1);
+        ok(size == sizeof(ts1), "IDirect3DQuery9_GetDataSize(q_ts1) returned %i\n", \
size); +        for (j = 0; (hr = IDirect3DQuery9_GetData(q_ts1, &ts1, size, \
D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +        {
+            Sleep(10);
+        }
+        ok(hr == S_OK, "Timestamp query failed: %08x\n", hr);
+
+        size = IDirect3DQuery9_GetDataSize(q_ts2);
+        ok(size == sizeof(ts2), "IDirect3DQuery9_GetDataSize(q_ts2) returned %i\n", \
size); +        for (j = 0; (hr = IDirect3DQuery9_GetData(q_ts2, &ts2, size, \
D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +        {
+            Sleep(10);
+        }
+        ok(hr == S_OK, "Timestamp query failed: %08x\n", hr);
+
+        size = IDirect3DQuery9_GetDataSize(q_freq);
+        ok(size == sizeof(freq), "IDirect3DQuery9_GetDataSize(q_freq) returned \
%i\n", size); +        for (j = 0; (hr = IDirect3DQuery9_GetData(q_freq, &freq, size, \
D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +        {
+            Sleep(10);
+        }
+        ok(hr == S_OK, "Timestampfreq query failed: %08x\n", hr);
+
+        ts_dj = TRUE;
+        size = IDirect3DQuery9_GetDataSize(q_disjoint);
+        ok(size == sizeof(ts_dj), "IDirect3DQuery9_GetDataSize(q_disjoint) returned \
%i\n", size); +        for (j = 0; (hr = IDirect3DQuery9_GetData(q_disjoint, &ts_dj, \
size, D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +        {
+            Sleep(10);
+        }
+        ok(hr == S_OK, "Timestampdisjoint query failed: %08x\n", hr);
+
+        if (!ts_dj)
+            break;
+    }
+    ok(!ts_dj, "Timestamps may be disjoint\n");
+
+#define NANOSECONDS 1000000000
+    ok(ts1 != ts2, "Timestamps are equal: 0x%08x%08x\n", (UINT)(ts1 >> 32), \
(UINT)(ts1 & 0xFFFFFFFF)); +    elapsed = ((double)(ts2 - ts1) / freq) * NANOSECONDS;
+    qp_elapsed1 = ((double)(qp_ts4.QuadPart - qp_ts1.QuadPart) / qp_freq.QuadPart) * \
NANOSECONDS; +    qp_elapsed2 = ((double)(qp_ts3.QuadPart - qp_ts2.QuadPart) / \
qp_freq.QuadPart) * NANOSECONDS; +
+    /* sanity check */
+    ok(qp_elapsed1 >= elapsed && elapsed >= qp_elapsed2, "Timestamp sanity check \
fail: 0x%08x%08x >= 0x%08x%08x >= 0x%08x%08x\n", +       (UINT)(qp_elapsed1 >> 32), \
(UINT)(qp_elapsed1 & 0xFFFFFFFF), +       (UINT)(elapsed >> 32), (UINT)(elapsed & \
0xFFFFFFFF), +       (UINT)(qp_elapsed2 >> 32), (UINT)(qp_elapsed2 & 0xFFFFFFFF));
+
+cleanup:
+    if (q_ts1) IDirect3DQuery9_Release(q_ts1);
+    if (q_ts2) IDirect3DQuery9_Release(q_ts2);
+    if (q_freq) IDirect3DQuery9_Release(q_freq);
+    if (q_disjoint) IDirect3DQuery9_Release(q_disjoint);
+    if (device)
+    {
+        UINT refcount = IDirect3DDevice9_Release(device);
+        ok(!refcount, "Device has %u references left.\n", refcount);
+    }
+}
+
+/* Test counter overflow */
+static void test_timestampdisjoint_queries(IDirect3D9 *d3d, HWND hwnd)
+{
+    HRESULT               hr;
+    int                   i, j, len;
+    IDirect3DDevice9      *device = NULL;
+    D3DPRESENT_PARAMETERS d3dpp;
+    D3DDISPLAYMODE        d3ddm;
+    IDirect3DQuery9       *q_ts = NULL, *q_disjoint = NULL, *q_freq = NULL;
+    UINT64 freq1 = 0, freq2 = 0, ts1 = 0, ts2 = 0;
+    BOOL ts_dj = TRUE;
+    int iterations;
+
+    if ((len = GetEnvironmentVariableA("D3D9TEST_TSDJ_ITERATIONS", NULL, 0)))
+    {
+        char* buf = HeapAlloc(GetProcessHeap(), 0, len);
+        GetEnvironmentVariableA("D3D9TEST_TSDJ_ITERATIONS", buf, len);
+        iterations = strtol(buf, NULL, 0);
+    }
+    else
+    {
+        iterations = 60;
+    }
+
+    IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
+    ZeroMemory(&d3dpp, sizeof(d3dpp));
+    d3dpp.Windowed         = TRUE;
+    d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
+    d3dpp.BackBufferFormat = d3ddm.Format;
+
+    hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, \
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); +    ok(SUCCEEDED(hr) || hr == \
D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr); +    if \
(FAILED(hr)) +    {
+        skip("Failed to create a d3d device\n");
+        goto cleanup;
+    }
+
+    hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &q_ts);
+    ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE,
+       "IDirect3DDevice9_CreateQuery returned unexpected return value %08x\n", hr);
+    hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &q_freq);
+    ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE,
+       "IDirect3DDevice9_CreateQuery returned unexpected return value %08x\n", hr);
+    hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, \
&q_disjoint); +    ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE,
+       "IDirect3DDevice9_CreateQuery returned unexpected return value %08x\n", hr);
+
+    if(!q_freq || !q_ts || !q_disjoint)
+    {
+        skip("Timestamp queries not supported\n");
+        goto cleanup;
+    }
+
+    hr = IDirect3DQuery9_Issue(q_freq, D3DISSUE_END);
+    ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_freq, D3DISSUE_END) returned %08x\n", \
hr); +
+    for (j = 0; (hr = IDirect3DQuery9_GetData(q_freq, &freq1, sizeof(freq1), \
D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +    {
+        Sleep(10);
+    }
+    ok(hr == S_OK, "Timestampfreq query failed: %08x\n", hr);
+    trace("freq: 0x%08x%08x\n", (UINT)(freq1 >> 32), (UINT)(freq1 & 0xFFFFFFFF));
+
+    hr = IDirect3DQuery9_Issue(q_disjoint, D3DISSUE_BEGIN);
+    ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_disjoint, D3DISSUE_BEGIN) returned \
%08x\n", hr); +
+    hr = IDirect3DQuery9_Issue(q_ts, D3DISSUE_END);
+    ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_ts, D3DISSUE_END) returned %08x\n", \
hr); +
+    for (j = 0; (hr = IDirect3DQuery9_GetData(q_ts, &ts1, sizeof(ts1), \
D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +    {
+        Sleep(10);
+    }
+    ok(hr == S_OK, "Timestamp query failed: %08x\n", hr);
+    trace("ts: 0x%08x%08x\n", (UINT)(ts1 >> 32), (UINT)(ts1 & 0xFFFFFFFF));
+
+    for (i = 0; i < iterations; ++i)
+    {
+        hr = IDirect3DQuery9_Issue(q_freq, D3DISSUE_END);
+        ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_freq, D3DISSUE_END) returned \
%08x\n", hr); +        hr = IDirect3DQuery9_Issue(q_ts, D3DISSUE_END);
+        ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_ts, D3DISSUE_END) returned \
%08x\n", hr); +
+        for (j = 0; (hr = IDirect3DQuery9_GetData(q_freq, &freq2, sizeof(freq2), \
D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +        {
+            Sleep(10);
+        }
+        ok(hr == S_OK, "Timestampfreq query failed: %08x\n", hr);
+
+        trace("freq: 0x%08x%08x\n", (UINT)(freq2 >> 32), (UINT)(freq2 & \
0xFFFFFFFF)); +        if (freq1 != freq2)
+            break;
+
+
+        for (j = 0; (hr = IDirect3DQuery9_GetData(q_ts, &ts2, sizeof(ts2), \
D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +        {
+            Sleep(10);
+        }
+        ok(hr == S_OK, "Timestamp query failed: %08x\n", hr);
+
+        trace("ts: 0x%08x%08x\n", (UINT)(ts2 >> 32), (UINT)(ts2 & 0xFFFFFFFF));
+        if (ts2 < ts1)
+            break;
+
+        Sleep(500);
+    }
+
+    hr = IDirect3DQuery9_Issue(q_disjoint, D3DISSUE_END);
+    ok(hr == D3D_OK, "IDirect3DQuery9_Issue(q_disjoint, D3DISSUE_END) returned \
%08x\n", hr); +
+    for (j = 0; (hr = IDirect3DQuery9_GetData(q_disjoint, &ts_dj, sizeof(ts_dj), \
D3DGETDATA_FLUSH)) == S_FALSE && j < 500; ++j) +    {
+        Sleep(10);
+    }
+    ok(hr == S_OK, "Timestampdisjoint query failed: %08x\n", hr);
+    ok((ts2 < ts1 || freq1 != freq2) == ts_dj, "Timestamps disjoint check \
failed\n"); +
+cleanup:
+    if (q_ts) IDirect3DQuery9_Release(q_ts);
+    if (q_freq) IDirect3DQuery9_Release(q_freq);
+    if (q_disjoint) IDirect3DQuery9_Release(q_disjoint);
+    if (device)
+    {
+        UINT refcount = IDirect3DDevice9_Release(device);
+        ok(!refcount, "Device has %u references left.\n", refcount);
+    }
+}
+
 START_TEST(query)
 {
     HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
@@ -282,6 +581,8 @@ START_TEST(query)
 
         test_query_support(pD3d, hwnd);
         test_occlusion_query_states(pD3d, hwnd);
+        test_timestamp_queries(pD3d, hwnd);
+        test_timestampdisjoint_queries(pD3d, hwnd);
 
         out:
         if(pD3d) IDirect3D9_Release(pD3d);
-- 
1.7.1


["0004-wined3d-Add-support-for-D3DQUERY_TIMESTAMP-queries.patch" (text/x-patch)]

From 1e3276df1159f7719da52c21e820873224019039 Mon Sep 17 00:00:00 2001
From: Adam Martinson <amartinson@codeweavers.com>
Date: Mon, 23 May 2011 15:13:45 -0500
Subject: [PATCH 04/11] wined3d: Add support for D3DQUERY_TIMESTAMP queries.
To: wine-patches <wine-patches@winehq.org>
Reply-To: wine-devel <wine-devel@winehq.org>

---
 dlls/wined3d/context.c         |   80 +++++++++++++++++++
 dlls/wined3d/query.c           |  165 +++++++++++++++++++++++++++++++++++++---
 dlls/wined3d/wined3d_private.h |   17 ++++
 3 files changed, 250 insertions(+), 12 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 0494252..02aa5c4 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -650,6 +650,66 @@ void context_free_event_query(struct wined3d_event_query *query)
     context->free_event_queries[context->free_event_query_count++] = query->object;
 }
 
+/* Context activation is done by the caller.
+ * Only called when GL_ARB_timer_query is supported. */
+void context_alloc_timestamp_query(struct wined3d_context *context, struct \
wined3d_timestamp_query *query) +{
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    int i, n_new;
+
+    for (i = 0; i < query->n_ids && i < context->free_timestamp_query_count; ++i)
+        query->ids[i] = \
context->free_timestamp_queries[--context->free_timestamp_query_count]; +
+    if ((n_new = query->n_ids - i))
+    {
+
+        ENTER_GL();
+        GL_EXTCALL(glGenQueriesARB(n_new, &query->ids[i]));
+        checkGLcall("glGenQueriesARB");
+        LEAVE_GL();
+
+        if (TRACE_ON(d3d))
+        {
+            for (; i < query->n_ids; ++i)
+                TRACE("Allocated timestamp query %u in context %p.\n", \
query->ids[i], context); +        }
+    }
+
+    query->context = context;
+    list_add_head(&context->timestamp_queries, &query->entry);
+}
+
+/* Context activation is done by the caller.
+ * Only called when GL_ARB_timer_query is supported. */
+void context_free_timestamp_query(struct wined3d_timestamp_query *query)
+{
+    struct wined3d_context *context = query->context;
+    int i;
+
+    list_remove(&query->entry);
+    query->context = NULL;
+
+    if (context->free_timestamp_query_count + query->n_ids >= \
context->free_timestamp_query_size) +    {
+        UINT new_size = context->free_timestamp_query_size << 1;
+        GLuint *new_data = HeapReAlloc(GetProcessHeap(), 0, \
context->free_timestamp_queries, +                new_size * \
sizeof(*context->free_timestamp_queries)); +
+        if (!new_data)
+        {
+            for (i = 0; i < query->n_ids; ++i)
+                ERR("Failed to grow free list, leaking query %u in context %p.\n", \
query->ids[i], context); +            return;
+        }
+
+        context->free_timestamp_query_size = new_size;
+        context->free_timestamp_queries = new_data;
+    }
+
+    for (i = 0; i < query->n_ids; ++i)
+        context->free_timestamp_queries[context->free_timestamp_query_count++] = \
query->ids[i]; +}
+
 typedef void (context_fbo_entry_func_t)(struct wined3d_context *context, struct \
fbo_entry *entry);  
 static void context_enum_surface_fbo_entries(struct wined3d_device *device,
@@ -924,6 +984,7 @@ static void context_destroy_gl_resources(struct wined3d_context \
*context)  const struct wined3d_gl_info *gl_info = context->gl_info;
     struct wined3d_occlusion_query *occlusion_query;
     struct wined3d_event_query *event_query;
+    struct wined3d_timestamp_query *timestamp_query;
     struct fbo_entry *entry, *entry2;
     HGLRC restore_ctx;
     HDC restore_dc;
@@ -960,6 +1021,13 @@ static void context_destroy_gl_resources(struct wined3d_context \
*context)  event_query->context = NULL;
     }
 
+    LIST_FOR_EACH_ENTRY(timestamp_query, &context->timestamp_queries, struct \
wined3d_timestamp_query, entry) +    {
+        if (context->valid && gl_info->supported[ARB_TIMER_QUERY])
+            GL_EXTCALL(glDeleteQueriesARB(timestamp_query->n_ids, \
timestamp_query->ids)); +        timestamp_query->context = NULL;
+    }
+
     LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_destroy_list, struct \
fbo_entry, entry)  {
         if (!context->valid) entry->id = 0;
@@ -987,6 +1055,9 @@ static void context_destroy_gl_resources(struct wined3d_context \
*context)  if (gl_info->supported[ARB_OCCLUSION_QUERY])
             GL_EXTCALL(glDeleteQueriesARB(context->free_occlusion_query_count, \
context->free_occlusion_queries));  
+        if (gl_info->supported[ARB_TIMER_QUERY])
+            GL_EXTCALL(glDeleteQueriesARB(context->free_timestamp_query_count, \
context->free_timestamp_queries)); +
         if (gl_info->supported[ARB_SYNC])
         {
             for (i = 0; i < context->free_event_query_count; ++i)
@@ -1016,6 +1087,7 @@ static void context_destroy_gl_resources(struct wined3d_context \
*context)  
     HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries);
     HeapFree(GetProcessHeap(), 0, context->free_event_queries);
+    HeapFree(GetProcessHeap(), 0, context->free_timestamp_queries);
 
     if (restore_ctx)
     {
@@ -1512,6 +1584,13 @@ struct wined3d_context *context_create(struct \
wined3d_swapchain *swapchain,  
     list_init(&ret->event_queries);
 
+    ret->free_timestamp_query_size = 4;
+    ret->free_timestamp_queries = HeapAlloc(GetProcessHeap(), 0,
+            ret->free_timestamp_query_size * sizeof(*ret->free_timestamp_queries));
+    if (!ret->free_timestamp_queries) goto out;
+
+    list_init(&ret->timestamp_queries);
+
     TRACE("Successfully created new context %p\n", ret);
 
     list_init(&ret->fbo_list);
@@ -1660,6 +1739,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain \
*swapchain,  out:
     HeapFree(GetProcessHeap(), 0, ret->free_event_queries);
     HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
+    HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries);
     HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
     HeapFree(GetProcessHeap(), 0, ret->blit_targets);
     HeapFree(GetProcessHeap(), 0, ret->pshader_const_dirty);
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index ca4426f..c0d5c63 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -4,6 +4,7 @@
  * Copyright 2005 Oliver Stieber
  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
  * Copyright 2009-2010 Henri Verbeet for CodeWeavers.
+ * Copyright 2011 Adam Martinson for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -253,17 +254,35 @@ ULONG CDECL wined3d_query_decref(struct wined3d_query *query)
          * deleting the query will obviously leak it, but that's still better
          * than potentially deleting a different query with the same id in this
          * context, and (still) leaking the actual query. */
-        if (query->type == WINED3DQUERYTYPE_EVENT)
+        switch (query->type)
         {
-            struct wined3d_event_query *event_query = query->extendedData;
-            if (event_query) wined3d_event_query_destroy(event_query);
-        }
-        else if (query->type == WINED3DQUERYTYPE_OCCLUSION)
-        {
-            struct wined3d_occlusion_query *oq = query->extendedData;
+        case WINED3DQUERYTYPE_EVENT:
+            {
+                struct wined3d_event_query *event_query = query->extendedData;
+                if (event_query) wined3d_event_query_destroy(event_query);
+            }
+            break;
+
+        case WINED3DQUERYTYPE_OCCLUSION:
+            {
+                struct wined3d_occlusion_query *oq = query->extendedData;
 
-            if (oq->context) context_free_occlusion_query(oq);
-            HeapFree(GetProcessHeap(), 0, query->extendedData);
+                if (oq->context) context_free_occlusion_query(oq);
+                HeapFree(GetProcessHeap(), 0, query->extendedData);
+            }
+            break;
+
+        case WINED3DQUERYTYPE_TIMESTAMP:
+            {
+                struct wined3d_timestamp_query *tsq = query->extendedData;
+
+                if (tsq->context) context_free_timestamp_query(tsq);
+                HeapFree(GetProcessHeap(), 0, query->extendedData);
+            }
+            break;
+
+        default:
+            break;
         }
 
         HeapFree(GetProcessHeap(), 0, query);
@@ -414,6 +433,69 @@ static HRESULT wined3d_event_query_ops_get_data(struct \
wined3d_query *query,  return S_OK;
 }
 
+/* Only called when GL_ARB_timer_query is supported. */
+static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query,
+                                                    void *data, DWORD size, DWORD \
flags) +{
+    const struct wined3d_gl_info *gl_info = &query->device->adapter->gl_info;
+    struct wined3d_timestamp_query *timestamp_query = query->extendedData;
+    struct wined3d_context *context;
+    GLuint available;
+    UINT64 *timestamp = data;
+    HRESULT res;
+
+    TRACE("(%p) : type D3DQUERY_TIMESTAMP, data %p, size %#x, flags %#x.\n", query, \
data, size, flags); +
+    if (!timestamp_query->context)
+        query->state = QUERY_CREATED;
+
+    if (query->state != QUERY_SIGNALLED)
+    {
+        /* 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 (timestamp)
+            *timestamp = 0;
+        return S_OK;
+    }
+
+    if (timestamp_query->context->tid != GetCurrentThreadId())
+    {
+        FIXME("%p Wrong thread, returning 0.\n", query);
+        if (timestamp)
+            *timestamp = 0;
+        return S_OK;
+    }
+
+    context = context_acquire(query->device, timestamp_query->context->current_rt);
+
+    ENTER_GL();
+
+    GL_EXTCALL(glGetQueryObjectuivARB(timestamp_query->ids[0], \
GL_QUERY_RESULT_AVAILABLE_ARB, &available)); +    \
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)"); +    \
TRACE("available %#x.\n", available); +
+    if (available)
+    {
+        if (timestamp)
+        {
+            GL_EXTCALL(glGetQueryObjectui64v(timestamp_query->ids[0], \
GL_QUERY_RESULT_ARB, timestamp)); +            \
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); +            TRACE("Returning \
0x%08x%08x.\n", (UINT)((*timestamp) >> 32), (UINT)((*timestamp) & 0xFFFFFFFF)); +     \
} +        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);
@@ -537,6 +619,39 @@ static HRESULT wined3d_occlusion_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_timestamp_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 *timestamp_query = query->extendedData;
+    struct wined3d_context *context;
+
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    /* MSDN: D3DISSUE_BEGIN not supported */
+
+    if (!timestamp_query->context)
+    {
+        context = context_acquire(query->device, NULL);
+        context_alloc_timestamp_query(context, timestamp_query);
+    }
+    else
+    {
+        context = context_acquire(query->device, \
timestamp_query->context->current_rt); +    }
+
+    ENTER_GL();
+    GL_EXTCALL(glQueryCounter(timestamp_query->ids[0], GL_TIMESTAMP_ARB));
+    checkGLcall("glQueryCounter(GL_TIMESTAMP)");
+    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,
@@ -549,6 +664,12 @@ static const struct wined3d_query_ops occlusion_query_ops =
     wined3d_occlusion_query_ops_issue,
 };
 
+static const struct wined3d_query_ops timestamp_query_ops =
+{
+    wined3d_timestamp_query_ops_get_data,
+    wined3d_timestamp_query_ops_issue,
+};
+
 static HRESULT query_init(struct wined3d_query *query, struct wined3d_device \
*device, WINED3DQUERYTYPE type)  {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
@@ -593,12 +714,32 @@ static HRESULT query_init(struct wined3d_query *query, struct \
wined3d_device *de  }
             break;
 
-        case WINED3DQUERYTYPE_VCACHE:
-        case WINED3DQUERYTYPE_RESOURCEMANAGER:
-        case WINED3DQUERYTYPE_VERTEXSTATS:
         case WINED3DQUERYTYPE_TIMESTAMP:
+            TRACE("Timestamp 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(UINT64);
+            query->query_ops = &timestamp_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 = 1;
+            ((struct wined3d_timestamp_query *)query->extendedData)->context = NULL;
+
+            break;
+
         case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
+        case WINED3DQUERYTYPE_VCACHE:
+        case WINED3DQUERYTYPE_RESOURCEMANAGER:
+        case WINED3DQUERYTYPE_VERTEXSTATS:
         case WINED3DQUERYTYPE_PIPELINETIMINGS:
         case WINED3DQUERYTYPE_INTERFACETIMINGS:
         case WINED3DQUERYTYPE_VERTEXTIMINGS:
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index aaf1423..39b39f8 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1019,6 +1019,15 @@ struct wined3d_event_query
     struct wined3d_context *context;
 };
 
+struct wined3d_timestamp_query
+{
+    struct list             entry;
+    struct wined3d_context *context;
+    int                     n_ids;
+    GLuint                  ids[3];
+};
+
+
 enum wined3d_event_query_result
 {
     WINED3D_EVENT_QUERY_OK,
@@ -1110,6 +1119,11 @@ struct wined3d_context
     UINT free_event_query_count;
     struct list event_queries;
 
+    GLuint *free_timestamp_queries;
+    UINT free_timestamp_query_size;
+    UINT free_timestamp_query_count;
+    struct list timestamp_queries;
+
     /* Extension emulation */
     GLint                   gl_fog_source;
     GLfloat                 fog_coord_value;
@@ -1208,6 +1222,8 @@ void context_alloc_event_query(struct wined3d_context *context,
         struct wined3d_event_query *query) DECLSPEC_HIDDEN;
 void context_alloc_occlusion_query(struct wined3d_context *context,
         struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
+void context_alloc_timestamp_query(struct wined3d_context *context,
+        struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN;
 void context_apply_blit_state(struct wined3d_context *context, struct wined3d_device \
*device) DECLSPEC_HIDDEN;  BOOL context_apply_clear_state(struct wined3d_context \
                *context, struct wined3d_device *device,
         UINT rt_count, struct wined3d_surface **rts, struct wined3d_surface \
*depth_stencil) DECLSPEC_HIDDEN; @@ -1223,6 +1239,7 @@ struct wined3d_context \
*context_create(struct wined3d_swapchain *swapchain, stru  void \
context_destroy(struct wined3d_device *device, struct wined3d_context *context) \
DECLSPEC_HIDDEN;  void context_free_event_query(struct wined3d_event_query *query) \
DECLSPEC_HIDDEN;  void context_free_occlusion_query(struct wined3d_occlusion_query \
*query) DECLSPEC_HIDDEN; +void context_free_timestamp_query(struct \
wined3d_timestamp_query *query) DECLSPEC_HIDDEN;  struct wined3d_context \
*context_get_current(void) DECLSPEC_HIDDEN;  DWORD context_get_tls_idx(void) \
DECLSPEC_HIDDEN;  void context_release(struct wined3d_context *context) \
                DECLSPEC_HIDDEN;
-- 
1.7.1


["0005-wined3d-query-Add-support-for-D3DQUERY_TIMESTAMPDISJ.patch" (text/x-patch)]

From e9ecf1e85f1e6e4832683d95ffbe0407602ac18e Mon Sep 17 00:00:00 2001
From: Adam Martinson <amartinson@codeweavers.com>
Date: Mon, 23 May 2011 15:19:50 -0500
Subject: [PATCH 05/11] wined3d/query: Add support for D3DQUERY_TIMESTAMPDISJOINT \
                queries.
To: wine-patches <wine-patches@winehq.org>
Reply-To: wine-devel <wine-devel@winehq.org>

---
 dlls/wined3d/query.c |  176 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 176 insertions(+), 0 deletions(-)

diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index c0d5c63..a9ff6f4 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -273,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;
 
@@ -496,6 +497,78 @@ 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 *data, \
DWORD size, DWORD flags) +{
+    const struct wined3d_gl_info *gl_info = &query->device->adapter->gl_info;
+    struct wined3d_timestamp_query *timestamp_query = query->extendedData;
+    struct wined3d_context *context;
+    BOOL *disjoint = data;
+    GLuint available;
+    UINT64 time_start, time_end, time_elapsed;
+    HRESULT res;
+
+    TRACE("(%p) : type D3DQUERY_TIMESTAMPDISJOINT, data %p, size %#x, flags %#x.\n", \
query, data, size, flags); +
+    if (!timestamp_query->context)
+        query->state = QUERY_CREATED;
+
+    if (query->state != QUERY_SIGNALLED)
+    {
+        /* 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 (disjoint)
+            *disjoint = TRUE;
+
+        return S_OK;
+    }
+
+    if (timestamp_query->context->tid != GetCurrentThreadId())
+    {
+        FIXME("%p Wrong thread, setting data to TRUE.\n", query);
+        if (disjoint)
+            *disjoint = TRUE;
+
+        return S_OK;
+    }
+
+    context = context_acquire(query->device, timestamp_query->context->current_rt);
+
+    ENTER_GL();
+
+    GL_EXTCALL(glGetQueryObjectuivARB(timestamp_query->ids[2], \
GL_QUERY_RESULT_AVAILABLE_ARB, &available)); +    \
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)"); +    \
TRACE("available %#x.\n", available); +
+    if (available)
+    {
+        if (disjoint)
+        {
+            GL_EXTCALL(glGetQueryObjectui64v(timestamp_query->ids[0], \
GL_QUERY_RESULT_ARB, &time_start)); +            \
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); +            \
GL_EXTCALL(glGetQueryObjectui64v(timestamp_query->ids[1], GL_QUERY_RESULT_ARB, \
&time_end)); +            checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)");
+            GL_EXTCALL(glGetQueryObjectui64v(timestamp_query->ids[2], \
GL_QUERY_RESULT_ARB, &time_elapsed)); +            \
checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); +
+            *disjoint = ((time_start >= time_end) || ((time_end - time_start) > \
time_elapsed)); +        }
+
+        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);
@@ -652,6 +725,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 *timestamp_query = query->extendedData;
+    struct wined3d_context *context;
+
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    if (flags & WINED3DISSUE_BEGIN)
+    {
+        if (query->state == QUERY_BUILDING)
+        {
+            if (timestamp_query->context->tid != GetCurrentThreadId())
+            {
+                FIXME("Wrong thread, can't restart query.\n");
+
+                context_free_timestamp_query(timestamp_query);
+                context = context_acquire(query->device, NULL);
+                context_alloc_timestamp_query(context, timestamp_query);
+            }
+            else
+            {
+                context = context_acquire(query->device, \
timestamp_query->context->current_rt); +
+                ENTER_GL();
+                GL_EXTCALL(glEndQueryARB(GL_TIME_ELAPSED_ARB));
+                checkGLcall("glEndQuery(GL_TIME_ELAPSED)");
+                LEAVE_GL();
+            }
+        }
+        else
+        {
+            if (timestamp_query->context) \
context_free_timestamp_query(timestamp_query); +            context = \
context_acquire(query->device, NULL); +            \
context_alloc_timestamp_query(context, timestamp_query); +        }
+
+        ENTER_GL();
+        GL_EXTCALL(glBeginQueryARB(GL_TIME_ELAPSED_ARB, timestamp_query->ids[2]));
+        checkGLcall("glBeginQuery(GL_TIME_ELAPSED)");
+        GL_EXTCALL(glQueryCounter(timestamp_query->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 (timestamp_query->context->tid != GetCurrentThreadId())
+            {
+                FIXME("Wrong thread, can't end query.\n");
+            }
+            else
+            {
+                context = context_acquire(query->device, \
timestamp_query->context->current_rt); +
+                ENTER_GL();
+                GL_EXTCALL(glQueryCounter(timestamp_query->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,
@@ -670,6 +820,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,
+};
+
 static HRESULT query_init(struct wined3d_query *query, struct wined3d_device \
*device, WINED3DQUERYTYPE type)  {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
@@ -736,6 +892,26 @@ static HRESULT query_init(struct wined3d_query *query, struct \
wined3d_device *de  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(BOOL);
+            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:
-- 
1.7.1


["0006-wined3d-query-Add-support-for-D3DQUERY_TIMESTAMPFREQ.patch" (text/x-patch)]

From 939258fd556764e38362015304b1d67d4b5abb1a Mon Sep 17 00:00:00 2001
From: Adam Martinson <amartinson@codeweavers.com>
Date: Mon, 23 May 2011 14:53:32 -0500
Subject: [PATCH 06/11] wined3d/query: Add support for D3DQUERY_TIMESTAMPFREQ queries.
To: wine-patches <wine-patches@winehq.org>
Reply-To: wine-devel <wine-devel@winehq.org>

---
 dlls/wined3d/query.c   |   45 +++++++++++++++++++++++++++++++++++++++++++++
 include/wine/wined3d.h |    2 ++
 2 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index a9ff6f4..9688d49 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -569,6 +569,22 @@ static HRESULT \
wined3d_timestampdisjoint_query_ops_get_data(struct wined3d_query  return res;
 }
 
+/* Only called when GL_ARB_timer_query is supported. */
+static HRESULT wined3d_timestampfreq_query_ops_get_data(struct wined3d_query *query,
+                                                        void *data, DWORD size, \
DWORD flags) +{
+    UINT64 *freq = data;
+
+    TRACE("(%p) : type D3DQUERY_TIMESTAMPFREQ, data %p, size %#x, flags %#x.\n", \
query, data, size, flags); +
+    /* We never go to the QUERY_BUILDING state for this. */
+
+    if (freq)
+        *freq = WINED3DQUERY_TIMESTAMP_FREQ;
+
+    return S_OK;
+}
+
 WINED3DQUERYTYPE CDECL wined3d_query_get_type(const struct wined3d_query *query)
 {
     TRACE("query %p.\n", query);
@@ -802,6 +818,17 @@ static HRESULT wined3d_timestampdisjoint_query_ops_issue(struct \
wined3d_query *q  return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
 }
 
+/* Only called when GL_ARB_timer_query is supported. */
+static HRESULT wined3d_timestampfreq_query_ops_issue(struct wined3d_query *query, \
DWORD flags) +{
+    TRACE("query %p, flags %#x.\n", query, flags);
+
+    /* MSDN: WINED3DISSUE_BEGIN not supported */
+
+    query->state = QUERY_SIGNALLED;
+    return WINED3D_OK;
+}
+
 static const struct wined3d_query_ops event_query_ops =
 {
     wined3d_event_query_ops_get_data,
@@ -826,6 +853,12 @@ static const struct wined3d_query_ops \
timestampdisjoint_query_ops =  wined3d_timestampdisjoint_query_ops_issue,
 };
 
+static const struct wined3d_query_ops timestampfreq_query_ops =
+{
+    wined3d_timestampfreq_query_ops_get_data,
+    wined3d_timestampfreq_query_ops_issue,
+};
+
 static HRESULT query_init(struct wined3d_query *query, struct wined3d_device \
*device, WINED3DQUERYTYPE type)  {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
@@ -913,6 +946,18 @@ static HRESULT query_init(struct wined3d_query *query, struct \
wined3d_device *de  break;
 
         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
+            TRACE("Timestamp Freqency 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(UINT64);
+            query->query_ops = &timestampfreq_query_ops;
+            query->extendedData = NULL;
+            break;
+
         case WINED3DQUERYTYPE_VCACHE:
         case WINED3DQUERYTYPE_RESOURCEMANAGER:
         case WINED3DQUERYTYPE_VERTEXSTATS:
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index ed269f0..96dcacd 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -740,6 +740,8 @@ typedef enum _WINED3DQUERYTYPE
 #define WINED3DISSUE_END                                        (1 << 0)
 #define WINED3DGETDATA_FLUSH                                    (1 << 0)
 
+#define WINED3DQUERY_TIMESTAMP_FREQ                             1000000000 /* \
nanoseconds */ +
 typedef enum _WINED3DSTATEBLOCKTYPE
 {
     WINED3DSBT_INIT                         = 0,
-- 
1.7.1





[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic