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