quartz: Silence requests for ipin on filters.
[wine] / dlls / wined3d / query.c
1 /*
2  * IWineD3DQuery implementation
3  *
4  * Copyright 2005 Oliver Stieber
5  *
6  *
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23
24 #include "config.h"
25 #include "wined3d_private.h"
26
27 /*
28  * Occlusion Queries:
29  * http://www.gris.uni-tuebingen.de/~bartz/Publications/paper/hww98.pdf
30  * http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt
31  */
32
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
34 #define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info
35
36 /* *******************************************
37    IWineD3DQuery IUnknown parts follow
38    ******************************************* */
39 static HRESULT  WINAPI IWineD3DQueryImpl_QueryInterface(IWineD3DQuery *iface, REFIID riid, LPVOID *ppobj)
40 {
41     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
42     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
43     if (IsEqualGUID(riid, &IID_IUnknown)
44         || IsEqualGUID(riid, &IID_IWineD3DBase)
45         || IsEqualGUID(riid, &IID_IWineD3DQuery)) {
46         IUnknown_AddRef(iface);
47         *ppobj = This;
48         return S_OK;
49     }
50     *ppobj = NULL;
51     return E_NOINTERFACE;
52 }
53
54 static ULONG  WINAPI IWineD3DQueryImpl_AddRef(IWineD3DQuery *iface) {
55     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
56     TRACE("(%p) : AddRef increasing from %d\n", This, This->ref);
57     return InterlockedIncrement(&This->ref);
58 }
59
60 static ULONG  WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
61     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
62     ULONG ref;
63     TRACE("(%p) : Releasing from %d\n", This, This->ref);
64     ref = InterlockedDecrement(&This->ref);
65     if (ref == 0) {
66         if(This->type == WINED3DQUERYTYPE_EVENT) {
67             if(GL_SUPPORT(APPLE_FENCE)) {
68                 GL_EXTCALL(glDeleteFencesAPPLE(1, &((WineQueryEventData *)(This->extendedData))->fenceId));
69                 checkGLcall("glDeleteFencesAPPLE");
70             } else if(GL_SUPPORT(NV_FENCE)) {
71                 GL_EXTCALL(glDeleteFencesNV(1, &((WineQueryEventData *)(This->extendedData))->fenceId));
72                 checkGLcall("glDeleteFencesNV");
73             }
74         } else if(This->type == WINED3DQUERYTYPE_OCCLUSION && GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
75             GL_EXTCALL(glDeleteQueriesARB(1, &((WineQueryOcclusionData *)(This->extendedData))->queryId));
76             checkGLcall("glDeleteQueriesARB");
77         }
78
79         HeapFree(GetProcessHeap(), 0, This->extendedData);
80         HeapFree(GetProcessHeap(), 0, This);
81     }
82     return ref;
83 }
84
85 /* *******************************************
86    IWineD3DQuery IWineD3DQuery parts follow
87    ******************************************* */
88 static HRESULT  WINAPI IWineD3DQueryImpl_GetParent(IWineD3DQuery *iface, IUnknown** parent){
89     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
90
91     *parent= (IUnknown*) parent;
92     IUnknown_AddRef(*parent);
93     TRACE("(%p) : returning %p\n", This, *parent);
94     return WINED3D_OK;
95 }
96
97 static HRESULT  WINAPI IWineD3DQueryImpl_GetDevice(IWineD3DQuery* iface, IWineD3DDevice **pDevice){
98     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
99     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
100     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
101     TRACE("(%p) returning %p\n", This, *pDevice);
102     return WINED3D_OK;
103 }
104
105
106 static HRESULT  WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags){
107     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
108     HRESULT res = S_OK;
109
110     TRACE("(%p) : type %#x, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, This->type, pData, dwSize, dwGetDataFlags);
111
112     switch (This->type){
113
114     case WINED3DQUERYTYPE_VCACHE:
115     {
116
117         WINED3DDEVINFO_VCACHE *data = (WINED3DDEVINFO_VCACHE *)pData;
118         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VCACHE\n", This);
119         if(pData == NULL || dwSize == 0) break;
120         data->Pattern     = WINEMAKEFOURCC('C','A','C','H');
121         data->OptMethod   = 0; /*0 get longest strips, 1 optimize vertex cache*/
122         data->CacheSize   = 0; /*cache size, only required if OptMethod == 1*/
123         data->MagicNumber = 0; /*only required if OptMethod == 1 (used internally)*/
124
125     }
126     break;
127     case WINED3DQUERYTYPE_RESOURCEMANAGER:
128     {
129         WINED3DDEVINFO_RESOURCEMANAGER *data = (WINED3DDEVINFO_RESOURCEMANAGER *)pData;
130         int i;
131         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_RESOURCEMANAGER\n", This);
132         if(pData == NULL || dwSize == 0) break;
133         for(i = 0; i < WINED3DRTYPECOUNT; i++){
134             /*I'm setting the default values to 1 so as to reduce the risk of a div/0 in the caller*/
135             /*  isTextureResident could be used to get some of this information  */
136             data->stats[i].bThrashing            = FALSE;
137             data->stats[i].ApproxBytesDownloaded = 1;
138             data->stats[i].NumEvicts             = 1;
139             data->stats[i].NumVidCreates         = 1;
140             data->stats[i].LastPri               = 1;
141             data->stats[i].NumUsed               = 1;
142             data->stats[i].NumUsedInVidMem       = 1;
143             data->stats[i].WorkingSet            = 1;
144             data->stats[i].WorkingSetBytes       = 1;
145             data->stats[i].TotalManaged          = 1;
146             data->stats[i].TotalBytes            = 1;
147         }
148
149     }
150     break;
151     case WINED3DQUERYTYPE_VERTEXSTATS:
152     {
153         WINED3DDEVINFO_VERTEXSTATS *data = (WINED3DDEVINFO_VERTEXSTATS *)pData;
154         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VERTEXSTATS\n", This);
155         if(pData == NULL || dwSize == 0) break;
156         data->NumRenderedTriangles      = 1;
157         data->NumExtraClippingTriangles = 1;
158
159     }
160     break;
161     case WINED3DQUERYTYPE_TIMESTAMP:
162     {
163         UINT64* data = pData;
164         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMP\n", This);
165         if(pData == NULL || dwSize == 0) break;
166         *data = 1; /*Don't know what this is supposed to be*/
167     }
168     break;
169     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
170     {
171         BOOL* data = pData;
172         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMPDISJOINT\n", This);
173         if(pData == NULL || dwSize == 0) break;
174         *data = FALSE; /*Don't know what this is supposed to be*/
175     }
176     break;
177     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
178     {
179         UINT64* data = pData;
180         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMPFREQ\n", This);
181         if(pData == NULL || dwSize == 0) break;
182         *data = 1; /*Don't know what this is supposed to be*/
183     }
184     break;
185     case WINED3DQUERYTYPE_PIPELINETIMINGS:
186     {
187         WINED3DDEVINFO_PIPELINETIMINGS *data = (WINED3DDEVINFO_PIPELINETIMINGS *)pData;
188         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_PIPELINETIMINGS\n", This);
189         if(pData == NULL || dwSize == 0) break;
190
191         data->VertexProcessingTimePercent    =   1.0f;
192         data->PixelProcessingTimePercent     =   1.0f;
193         data->OtherGPUProcessingTimePercent  =  97.0f;
194         data->GPUIdleTimePercent             =   1.0f;
195     }
196     break;
197     case WINED3DQUERYTYPE_INTERFACETIMINGS:
198     {
199         WINED3DDEVINFO_INTERFACETIMINGS *data = (WINED3DDEVINFO_INTERFACETIMINGS *)pData;
200         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_INTERFACETIMINGS\n", This);
201
202         if(pData == NULL || dwSize == 0) break;
203         data->WaitingForGPUToUseApplicationResourceTimePercent =   1.0f;
204         data->WaitingForGPUToAcceptMoreCommandsTimePercent     =   1.0f;
205         data->WaitingForGPUToStayWithinLatencyTimePercent      =   1.0f;
206         data->WaitingForGPUExclusiveResourceTimePercent        =   1.0f;
207         data->WaitingForGPUOtherTimePercent                    =  96.0f;
208     }
209
210     break;
211     case WINED3DQUERYTYPE_VERTEXTIMINGS:
212     {
213         WINED3DDEVINFO_STAGETIMINGS *data = (WINED3DDEVINFO_STAGETIMINGS *)pData;
214         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VERTEXTIMINGS\n", This);
215
216         if(pData == NULL || dwSize == 0) break;
217         data->MemoryProcessingPercent      = 50.0f;
218         data->ComputationProcessingPercent = 50.0f;
219
220     }
221     break;
222     case WINED3DQUERYTYPE_PIXELTIMINGS:
223     {
224         WINED3DDEVINFO_STAGETIMINGS *data = (WINED3DDEVINFO_STAGETIMINGS *)pData;
225         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_PIXELTIMINGS\n", This);
226
227         if(pData == NULL || dwSize == 0) break;
228         data->MemoryProcessingPercent      = 50.0f;
229         data->ComputationProcessingPercent = 50.0f;
230     }
231     break;
232     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
233     {
234         WINED3DDEVINFO_BANDWIDTHTIMINGS *data = (WINED3DDEVINFO_BANDWIDTHTIMINGS *)pData;
235         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_BANDWIDTHTIMINGS\n", This);
236
237         if(pData == NULL || dwSize == 0) break;
238         data->MaxBandwidthUtilized                =  1.0f;
239         data->FrontEndUploadMemoryUtilizedPercent =  1.0f;
240         data->VertexRateUtilizedPercent           =  1.0f;
241         data->TriangleSetupRateUtilizedPercent    =  1.0f;
242         data->FillRateUtilizedPercent             = 97.0f;
243     }
244     break;
245     case WINED3DQUERYTYPE_CACHEUTILIZATION:
246     {
247         WINED3DDEVINFO_CACHEUTILIZATION *data = (WINED3DDEVINFO_CACHEUTILIZATION *)pData;
248         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_CACHEUTILIZATION\n", This);
249
250         if(pData == NULL || dwSize == 0) break;
251         data->TextureCacheHitRate             = 1.0f;
252         data->PostTransformVertexCacheHitRate = 1.0f;
253     }
254
255
256     break;
257     default:
258         FIXME("(%p) Unhandled query type %d\n",This , This->type);
259
260     };
261
262     /*dwGetDataFlags = 0 || D3DGETDATA_FLUSH
263     D3DGETDATA_FLUSH may return WINED3DERR_DEVICELOST if the device is lost
264     */
265     return res; /* S_OK if the query data is available*/
266 }
267
268 static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
269     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
270     DWORD* data = pData;
271     HRESULT res;
272     TRACE("(%p) : type D3DQUERY_OCCLUSION, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);
273
274     if(This->state == QUERY_CREATED) {
275         /* D3D allows GetData on a new query, OpenGL doesn't. So just invent the data ourselves */
276         TRACE("Query wasn't yet started, returning S_OK\n");
277         res = S_OK;
278         if(data) *data = 0;
279     } else if(This->state == QUERY_BUILDING) {
280         /* Msdn says this returns an error, but our tests show that S_FALSE is returned */
281         TRACE("Query is building, returning S_FALSE\n");
282         res = S_FALSE;
283     } else if (GL_SUPPORT(ARB_OCCLUSION_QUERY) &&
284         ((WineQueryOcclusionData *)This->extendedData)->ctx == This->wineD3DDevice->activeContext &&
285                 This->wineD3DDevice->activeContext->tid == GetCurrentThreadId()) {
286         GLuint available;
287         GLuint samples;
288         GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId;
289
290         GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
291         checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n");
292         TRACE("(%p) : available %d.\n", This, available);
293
294         if (available) {
295             if(data) {
296                 GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_ARB, &samples));
297                 checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)\n");
298                 TRACE("(%p) : Returning %d samples.\n", This, samples);
299                 *data = samples;
300             }
301             res = S_OK;
302         } else {
303             res = S_FALSE;
304         }
305     } else {
306         WARN("(%p) : Occlusion queries not supported, or wrong context. Returning 1.\n", This);
307         *data = 1;
308         res = S_OK;
309     }
310     return res;
311 }
312
313 static HRESULT  WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
314     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface;
315     BOOL* data = pData;
316     WineD3DContext *ctx;
317     TRACE("(%p) : type D3DQUERY_EVENT, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags);
318
319     ctx = ((WineQueryEventData *)This->extendedData)->ctx;
320     if(pData == NULL || dwSize == 0) {
321         return S_OK;
322     } if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
323         /* See comment in IWineD3DQuery::Issue, event query codeblock */
324         WARN("Query context not active, reporting GPU idle\n");
325         *data = TRUE;
326     } else if(GL_SUPPORT(APPLE_FENCE)) {
327         *data = GL_EXTCALL(glTestFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId));
328         checkGLcall("glTestFenceAPPLE");
329     } else if(GL_SUPPORT(NV_FENCE)) {
330         *data = GL_EXTCALL(glTestFenceNV(((WineQueryEventData *)This->extendedData)->fenceId));
331         checkGLcall("glTestFenceNV");
332     } else {
333         WARN("(%p): reporting GPU idle\n", This);
334         *data = TRUE;
335     }
336
337     return S_OK;
338 }
339
340 static DWORD  WINAPI IWineD3DQueryImpl_GetDataSize(IWineD3DQuery* iface){
341     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
342     int dataSize = 0;
343     TRACE("(%p) : type %#x\n", This, This->type);
344     switch(This->type){
345     case WINED3DQUERYTYPE_VCACHE:
346         dataSize = sizeof(WINED3DDEVINFO_VCACHE);
347         break;
348     case WINED3DQUERYTYPE_RESOURCEMANAGER:
349         dataSize = sizeof(WINED3DDEVINFO_RESOURCEMANAGER);
350         break;
351     case WINED3DQUERYTYPE_VERTEXSTATS:
352         dataSize = sizeof(WINED3DDEVINFO_VERTEXSTATS);
353         break;
354     case WINED3DQUERYTYPE_EVENT:
355         dataSize = sizeof(BOOL);
356         break;
357     case WINED3DQUERYTYPE_TIMESTAMP:
358         dataSize = sizeof(UINT64);
359         break;
360     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
361         dataSize = sizeof(BOOL);
362         break;
363     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
364         dataSize = sizeof(UINT64);
365         break;
366     case WINED3DQUERYTYPE_PIPELINETIMINGS:
367         dataSize = sizeof(WINED3DDEVINFO_PIPELINETIMINGS);
368         break;
369     case WINED3DQUERYTYPE_INTERFACETIMINGS:
370         dataSize = sizeof(WINED3DDEVINFO_INTERFACETIMINGS);
371         break;
372     case WINED3DQUERYTYPE_VERTEXTIMINGS:
373         dataSize = sizeof(WINED3DDEVINFO_STAGETIMINGS);
374         break;
375     case WINED3DQUERYTYPE_PIXELTIMINGS:
376         dataSize = sizeof(WINED3DDEVINFO_STAGETIMINGS);
377         break;
378     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
379         dataSize = sizeof(WINED3DQUERYTYPE_BANDWIDTHTIMINGS);
380         break;
381     case WINED3DQUERYTYPE_CACHEUTILIZATION:
382         dataSize = sizeof(WINED3DDEVINFO_CACHEUTILIZATION);
383         break;
384     default:
385        FIXME("(%p) Unhandled query type %d\n",This , This->type);
386        dataSize = 0;
387     }
388     return dataSize;
389 }
390
391 static DWORD  WINAPI IWineD3DEventQueryImpl_GetDataSize(IWineD3DQuery* iface){
392     TRACE("(%p) : type D3DQUERY_EVENT\n", iface);
393
394     return sizeof(BOOL);
395 }
396
397 static DWORD  WINAPI IWineD3DOcclusionQueryImpl_GetDataSize(IWineD3DQuery* iface){
398     TRACE("(%p) : type D3DQUERY_OCCLUSION\n", iface);
399
400     return sizeof(DWORD);
401 }
402
403 static WINED3DQUERYTYPE  WINAPI IWineD3DQueryImpl_GetType(IWineD3DQuery* iface){
404     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
405     return This->type;
406 }
407
408
409 static HRESULT  WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface,  DWORD dwIssueFlags) {
410     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
411
412     TRACE("(%p) : dwIssueFlags %#x, type D3DQUERY_EVENT\n", This, dwIssueFlags);
413     if (dwIssueFlags & WINED3DISSUE_END) {
414         WineD3DContext *ctx = ((WineQueryEventData *)This->extendedData)->ctx;
415         if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
416             /* GL fences can be used only from the context that created them,
417              * so if a different context is active, don't bother setting the query. The penalty
418              * of a context switch is most likely higher than the gain of a correct query result
419              *
420              * If the query is used from a different thread, don't bother creating a multithread
421              * context - there's no point in doing that as the query would be unusable anyway
422              */
423             WARN("Query context not active\n");
424         } else if(GL_SUPPORT(APPLE_FENCE)) {
425             GL_EXTCALL(glSetFenceAPPLE(((WineQueryEventData *)This->extendedData)->fenceId));
426             checkGLcall("glSetFenceAPPLE");
427         } else if (GL_SUPPORT(NV_FENCE)) {
428             GL_EXTCALL(glSetFenceNV(((WineQueryEventData *)This->extendedData)->fenceId, GL_ALL_COMPLETED_NV));
429             checkGLcall("glSetFenceNV");
430         }
431     } else if(dwIssueFlags & WINED3DISSUE_BEGIN) {
432         /* Started implicitly at device creation */
433         ERR("Event query issued with START flag - what to do?\n");
434     }
435
436     if(dwIssueFlags & WINED3DISSUE_BEGIN) {
437         This->state = QUERY_BUILDING;
438     } else {
439         This->state = QUERY_SIGNALLED;
440     }
441
442     return WINED3D_OK;
443 }
444
445 static HRESULT  WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface,  DWORD dwIssueFlags) {
446     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
447
448     if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
449         WineD3DContext *ctx = ((WineQueryOcclusionData *)This->extendedData)->ctx;
450
451         if(ctx != This->wineD3DDevice->activeContext || ctx->tid != GetCurrentThreadId()) {
452             WARN("Not the owning context, can't start query\n");
453         } else {
454             /* This is allowed according to msdn and our tests. Reset the query and restart */
455             if (dwIssueFlags & WINED3DISSUE_BEGIN) {
456                 if(This->state == QUERY_BUILDING) {
457                     GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
458                     checkGLcall("glEndQuery()");
459                 }
460
461                 GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, ((WineQueryOcclusionData *)This->extendedData)->queryId));
462                 checkGLcall("glBeginQuery()");
463             }
464             if (dwIssueFlags & WINED3DISSUE_END) {
465                 /* Msdn says _END on a non-building occlusion query returns an error, but
466                  * our tests show that it returns OK. But OpenGL doesn't like it, so avoid
467                  * generating an error
468                  */
469                 if(This->state == QUERY_BUILDING) {
470                     GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
471                     checkGLcall("glEndQuery()");
472                 }
473             }
474         }
475     } else {
476         FIXME("(%p) : Occlusion queries not supported\n", This);
477     }
478
479     if(dwIssueFlags & WINED3DISSUE_BEGIN) {
480         This->state = QUERY_BUILDING;
481     } else {
482         This->state = QUERY_SIGNALLED;
483     }
484     return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
485 }
486
487 static HRESULT  WINAPI IWineD3DQueryImpl_Issue(IWineD3DQuery* iface,  DWORD dwIssueFlags){
488     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
489
490     TRACE("(%p) : dwIssueFlags %#x, type %#x\n", This, dwIssueFlags, This->type);
491
492     /* The fixme is printed when the app asks for the resulting data */
493     WARN("(%p) : Unhandled query type %#x\n", This, This->type);
494
495     if(dwIssueFlags & WINED3DISSUE_BEGIN) {
496         This->state = QUERY_BUILDING;
497     } else {
498         This->state = QUERY_SIGNALLED;
499     }
500
501     return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
502 }
503
504
505 /**********************************************************
506  * IWineD3DQuery VTbl follows
507  **********************************************************/
508
509 const IWineD3DQueryVtbl IWineD3DQuery_Vtbl =
510 {
511     /*** IUnknown methods ***/
512     IWineD3DQueryImpl_QueryInterface,
513     IWineD3DQueryImpl_AddRef,
514     IWineD3DQueryImpl_Release,
515      /*** IWineD3Dquery methods ***/
516     IWineD3DQueryImpl_GetParent,
517     IWineD3DQueryImpl_GetDevice,
518     IWineD3DQueryImpl_GetData,
519     IWineD3DQueryImpl_GetDataSize,
520     IWineD3DQueryImpl_GetType,
521     IWineD3DQueryImpl_Issue
522 };
523
524 const IWineD3DQueryVtbl IWineD3DEventQuery_Vtbl =
525 {
526     /*** IUnknown methods ***/
527     IWineD3DQueryImpl_QueryInterface,
528     IWineD3DQueryImpl_AddRef,
529     IWineD3DQueryImpl_Release,
530     /*** IWineD3Dquery methods ***/
531     IWineD3DQueryImpl_GetParent,
532     IWineD3DQueryImpl_GetDevice,
533     IWineD3DEventQueryImpl_GetData,
534     IWineD3DEventQueryImpl_GetDataSize,
535     IWineD3DQueryImpl_GetType,
536     IWineD3DEventQueryImpl_Issue
537 };
538
539 const IWineD3DQueryVtbl IWineD3DOcclusionQuery_Vtbl =
540 {
541     /*** IUnknown methods ***/
542     IWineD3DQueryImpl_QueryInterface,
543     IWineD3DQueryImpl_AddRef,
544     IWineD3DQueryImpl_Release,
545     /*** IWineD3Dquery methods ***/
546     IWineD3DQueryImpl_GetParent,
547     IWineD3DQueryImpl_GetDevice,
548     IWineD3DOcclusionQueryImpl_GetData,
549     IWineD3DOcclusionQueryImpl_GetDataSize,
550     IWineD3DQueryImpl_GetType,
551     IWineD3DOcclusionQueryImpl_Issue
552 };