wined3d: Pass the correct mask to shader_glsl_add_src_param() in shader_glsl_callnz().
[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  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/Queries.asp
29  *
30  * Occlusion Queries:
31  * http://www.gris.uni-tuebingen.de/~bartz/Publications/paper/hww98.pdf
32  * http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt
33  */
34
35 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info
37
38 /* *******************************************
39    IWineD3DQuery IUnknown parts follow
40    ******************************************* */
41 static HRESULT  WINAPI IWineD3DQueryImpl_QueryInterface(IWineD3DQuery *iface, REFIID riid, LPVOID *ppobj)
42 {
43     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
44     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
45     if (IsEqualGUID(riid, &IID_IUnknown)
46         || IsEqualGUID(riid, &IID_IWineD3DBase)
47         || IsEqualGUID(riid, &IID_IWineD3DQuery)) {
48         IUnknown_AddRef(iface);
49         *ppobj = This;
50         return S_OK;
51     }
52     *ppobj = NULL;
53     return E_NOINTERFACE;
54 }
55
56 static ULONG  WINAPI IWineD3DQueryImpl_AddRef(IWineD3DQuery *iface) {
57     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
58     TRACE("(%p) : AddRef increasing from %d\n", This, This->ref);
59     return InterlockedIncrement(&This->ref);
60 }
61
62 static ULONG  WINAPI IWineD3DQueryImpl_Release(IWineD3DQuery *iface) {
63     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
64     ULONG ref;
65     TRACE("(%p) : Releasing from %d\n", This, This->ref);
66     ref = InterlockedDecrement(&This->ref);
67     if (ref == 0) {
68         HeapFree(GetProcessHeap(), 0, This->extendedData);
69         HeapFree(GetProcessHeap(), 0, This);
70     }
71     return ref;
72 }
73
74 /* *******************************************
75    IWineD3DQuery IWineD3DQuery parts follow
76    ******************************************* */
77 static HRESULT  WINAPI IWineD3DQueryImpl_GetParent(IWineD3DQuery *iface, IUnknown** parent){
78     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
79
80     *parent= (IUnknown*) parent;
81     IUnknown_AddRef(*parent);
82     TRACE("(%p) : returning %p\n", This, *parent);
83     return WINED3D_OK;
84 }
85
86 static HRESULT  WINAPI IWineD3DQueryImpl_GetDevice(IWineD3DQuery* iface, IWineD3DDevice **pDevice){
87     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
88     IWineD3DDevice_AddRef((IWineD3DDevice *)This->wineD3DDevice);
89     *pDevice = (IWineD3DDevice *)This->wineD3DDevice;
90     TRACE("(%p) returning %p\n", This, *pDevice);
91     return WINED3D_OK;
92 }
93
94
95 static HRESULT  WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags){
96     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
97     HRESULT res = S_OK;
98
99     TRACE("(%p) : type %#x, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, This->type, pData, dwSize, dwGetDataFlags);
100
101     if(dwSize == 0){
102         /*you can use this method to poll the resource for the query status*/
103         /*We return success(S_OK) if we support a feature, and faikure(S_FALSE) if we don't, just return success and fluff it for now*/
104         return S_OK;
105     }else{
106     }
107
108     switch (This->type){
109
110     case WINED3DQUERYTYPE_VCACHE:
111     {
112
113         WINED3DDEVINFO_VCACHE *data = (WINED3DDEVINFO_VCACHE *)pData;
114         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VCACHE\n", This);
115         data->Pattern     = MAKEFOURCC('C','A','C','H');
116         data->OptMethod   = 0; /*0 get longest strips, 1 optimize vertex cache*/
117         data->CacheSize   = 0; /*cache size, only required if OptMethod == 1*/
118         data->MagicNumber = 0; /*only required if OptMethod == 1 (used internally)*/
119
120     }
121     break;
122     case WINED3DQUERYTYPE_RESOURCEMANAGER:
123     {
124         WINED3DDEVINFO_RESOURCEMANAGER *data = (WINED3DDEVINFO_RESOURCEMANAGER *)pData;
125         int i;
126         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_RESOURCEMANAGER\n", This);
127         for(i = 0; i < WINED3DRTYPECOUNT; i++){
128             /*I'm setting the default values to 1 so as to reduce the risk of a div/0 in the caller*/
129             /*  isTextureResident could be used to get some of this infomration  */
130             data->stats[i].bThrashing            = FALSE;
131             data->stats[i].ApproxBytesDownloaded = 1;
132             data->stats[i].NumEvicts             = 1;
133             data->stats[i].NumVidCreates         = 1;
134             data->stats[i].LastPri               = 1;
135             data->stats[i].NumUsed               = 1;
136             data->stats[i].NumUsedInVidMem       = 1;
137             data->stats[i].WorkingSet            = 1;
138             data->stats[i].WorkingSetBytes       = 1;
139             data->stats[i].TotalManaged          = 1;
140             data->stats[i].TotalBytes            = 1;
141         }
142
143     }
144     break;
145     case WINED3DQUERYTYPE_VERTEXSTATS:
146     {
147         WINED3DDEVINFO_VERTEXSTATS *data = (WINED3DDEVINFO_VERTEXSTATS *)pData;
148         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VERTEXSTATS\n", This);
149         data->NumRenderedTriangles      = 1;
150         data->NumExtraClippingTriangles = 1;
151
152     }
153     break;
154     case WINED3DQUERYTYPE_EVENT:
155     {
156         BOOL* data = pData;
157         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_EVENT\n", This);
158         *data = TRUE; /*Don't know what this is supposed to be*/
159     }
160     break;
161     case WINED3DQUERYTYPE_OCCLUSION:
162     {
163         DWORD* data = pData;
164         if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
165             GLuint available;
166             GLuint samples;
167             GLuint queryId = ((WineQueryOcclusionData *)This->extendedData)->queryId;
168
169             GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_AVAILABLE_ARB, &available));
170             checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT_AVAILABLE)\n");
171             TRACE("(%p) : available %d.\n", This, available);
172
173             if (available) {
174                 GL_EXTCALL(glGetQueryObjectuivARB(queryId, GL_QUERY_RESULT_ARB, &samples));
175                 checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)\n");
176                 TRACE("(%p) : Returning %d samples.\n", This, samples);
177                 *data = samples;
178                 res = S_OK;
179             } else {
180                 res = S_FALSE;
181             }
182         } else {
183             FIXME("(%p) : Occlusion queries not supported. Returning 1.\n", This);
184             *data = 1;
185             res = S_OK;
186         }
187     }
188     break;
189     case WINED3DQUERYTYPE_TIMESTAMP:
190     {
191         UINT64* data = pData;
192         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMP\n", This);
193         *data = 1; /*Don't know what this is supposed to be*/
194     }
195     break;
196     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
197     {
198         BOOL* data = pData;
199         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMPDISJOINT\n", This);
200         *data = FALSE; /*Don't know what this is supposed to be*/
201     }
202     break;
203     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
204     {
205         UINT64* data = pData;
206         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_TIMESTAMPFREQ\n", This);
207         *data = 1; /*Don't know what this is supposed to be*/
208     }
209     break;
210     case WINED3DQUERYTYPE_PIPELINETIMINGS:
211     {
212         WINED3DDEVINFO_PIPELINETIMINGS *data = (WINED3DDEVINFO_PIPELINETIMINGS *)pData;
213         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_PIPELINETIMINGS\n", This);
214
215         data->VertexProcessingTimePercent    =   1.0f;
216         data->PixelProcessingTimePercent     =   1.0f;
217         data->OtherGPUProcessingTimePercent  =  97.0f;
218         data->GPUIdleTimePercent             =   1.0f;
219     }
220     break;
221     case WINED3DQUERYTYPE_INTERFACETIMINGS:
222     {
223         WINED3DDEVINFO_INTERFACETIMINGS *data = (WINED3DDEVINFO_INTERFACETIMINGS *)pData;
224         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_INTERFACETIMINGS\n", This);
225
226         data->WaitingForGPUToUseApplicationResourceTimePercent =   1.0f;
227         data->WaitingForGPUToAcceptMoreCommandsTimePercent     =   1.0f;
228         data->WaitingForGPUToStayWithinLatencyTimePercent      =   1.0f;
229         data->WaitingForGPUExclusiveResourceTimePercent        =   1.0f;
230         data->WaitingForGPUOtherTimePercent                    =  96.0f;
231     }
232
233     break;
234     case WINED3DQUERYTYPE_VERTEXTIMINGS:
235     {
236         WINED3DDEVINFO_STAGETIMINGS *data = (WINED3DDEVINFO_STAGETIMINGS *)pData;
237         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_VERTEXTIMINGS\n", This);
238
239         data->MemoryProcessingPercent      = 50.0f;
240         data->ComputationProcessingPercent = 50.0f;
241
242     }
243     break;
244     case WINED3DQUERYTYPE_PIXELTIMINGS:
245     {
246         WINED3DDEVINFO_STAGETIMINGS *data = (WINED3DDEVINFO_STAGETIMINGS *)pData;
247         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_PIXELTIMINGS\n", This);
248
249         data->MemoryProcessingPercent      = 50.0f;
250         data->ComputationProcessingPercent = 50.0f;
251     }
252     break;
253     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
254     {
255         WINED3DDEVINFO_BANDWIDTHTIMINGS *data = (WINED3DDEVINFO_BANDWIDTHTIMINGS *)pData;
256         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_BANDWIDTHTIMINGS\n", This);
257
258         data->MaxBandwidthUtilized                =  1.0f;
259         data->FrontEndUploadMemoryUtilizedPercent =  1.0f;
260         data->VertexRateUtilizedPercent           =  1.0f;
261         data->TriangleSetupRateUtilizedPercent    =  1.0f;
262         data->FillRateUtilizedPercent             = 97.0f;
263     }
264     break;
265     case WINED3DQUERYTYPE_CACHEUTILIZATION:
266     {
267         WINED3DDEVINFO_CACHEUTILIZATION *data = (WINED3DDEVINFO_CACHEUTILIZATION *)pData;
268         FIXME("(%p): Unimplemented query WINED3DQUERYTYPE_CACHEUTILIZATION\n", This);
269
270         data->TextureCacheHitRate             = 1.0f;
271         data->PostTransformVertexCacheHitRate = 1.0f;
272     }
273
274
275     break;
276     default:
277         FIXME("(%p) Unhandled query type %d\n",This , This->type);
278
279     };
280
281     /*dwGetDataFlags = 0 || D3DGETDATA_FLUSH
282     D3DGETDATA_FLUSH may return WINED3DERR_DEVICELOST if the device is lost
283     */
284     return res; /* S_OK if the query data is available*/
285 }
286
287
288 static DWORD  WINAPI IWineD3DQueryImpl_GetDataSize(IWineD3DQuery* iface){
289     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
290     int dataSize = 0;
291     TRACE("(%p) : type %#x\n", This, This->type);
292     switch(This->type){
293     case WINED3DQUERYTYPE_VCACHE:
294         dataSize = sizeof(WINED3DDEVINFO_VCACHE);
295         break;
296     case WINED3DQUERYTYPE_RESOURCEMANAGER:
297         dataSize = sizeof(WINED3DDEVINFO_RESOURCEMANAGER);
298         break;
299     case WINED3DQUERYTYPE_VERTEXSTATS:
300         dataSize = sizeof(WINED3DDEVINFO_VERTEXSTATS);
301         break;
302     case WINED3DQUERYTYPE_EVENT:
303         dataSize = sizeof(BOOL);
304         break;
305     case WINED3DQUERYTYPE_OCCLUSION:
306         dataSize = sizeof(DWORD);
307         break;
308     case WINED3DQUERYTYPE_TIMESTAMP:
309         dataSize = sizeof(UINT64);
310         break;
311     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
312         dataSize = sizeof(BOOL);
313         break;
314     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
315         dataSize = sizeof(UINT64);
316         break;
317     case WINED3DQUERYTYPE_PIPELINETIMINGS:
318         dataSize = sizeof(WINED3DDEVINFO_PIPELINETIMINGS);
319         break;
320     case WINED3DQUERYTYPE_INTERFACETIMINGS:
321         dataSize = sizeof(WINED3DDEVINFO_INTERFACETIMINGS);
322         break;
323     case WINED3DQUERYTYPE_VERTEXTIMINGS:
324         dataSize = sizeof(WINED3DDEVINFO_STAGETIMINGS);
325         break;
326     case WINED3DQUERYTYPE_PIXELTIMINGS:
327         dataSize = sizeof(WINED3DDEVINFO_STAGETIMINGS);
328         break;
329     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
330         dataSize = sizeof(WINED3DQUERYTYPE_BANDWIDTHTIMINGS);
331         break;
332     case WINED3DQUERYTYPE_CACHEUTILIZATION:
333         dataSize = sizeof(WINED3DDEVINFO_CACHEUTILIZATION);
334         break;
335     default:
336        FIXME("(%p) Unhandled query type %d\n",This , This->type);
337        dataSize = 0;
338     }
339     return dataSize;
340 }
341
342
343 static WINED3DQUERYTYPE  WINAPI IWineD3DQueryImpl_GetType(IWineD3DQuery* iface){
344     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
345     return This->type;
346 }
347
348
349 static HRESULT  WINAPI IWineD3DQueryImpl_Issue(IWineD3DQuery* iface,  DWORD dwIssueFlags){
350     IWineD3DQueryImpl *This = (IWineD3DQueryImpl *)iface;
351
352     TRACE("(%p) : dwIssueFlags %#x, type %#x\n", This, dwIssueFlags, This->type);
353
354     switch (This->type) {
355         case WINED3DQUERYTYPE_OCCLUSION:
356             if (GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
357                 if (dwIssueFlags & D3DISSUE_BEGIN) {
358                     GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, ((WineQueryOcclusionData *)This->extendedData)->queryId));
359                     checkGLcall("glBeginQuery()");
360                 }
361                 if (dwIssueFlags & D3DISSUE_END) {
362                     GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB));
363                     checkGLcall("glEndQuery()");
364                 }
365             } else {
366                 FIXME("(%p) : Occlusion queries not supported\n", This);
367             }
368             break;
369
370         default:
371             /* The fixme is printed when the app asks for the resulting data */
372             WARN("(%p) : Unhandled query type %#x\n", This, This->type);
373             break;
374     }
375
376     return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL.    */
377 }
378
379
380 /**********************************************************
381  * IWineD3DQuery VTbl follows
382  **********************************************************/
383
384 const IWineD3DQueryVtbl IWineD3DQuery_Vtbl =
385 {
386     /*** IUnknown methods ***/
387     IWineD3DQueryImpl_QueryInterface,
388     IWineD3DQueryImpl_AddRef,
389     IWineD3DQueryImpl_Release,
390      /*** IWineD3Dquery methods ***/
391     IWineD3DQueryImpl_GetParent,
392     IWineD3DQueryImpl_GetDevice,
393     IWineD3DQueryImpl_GetData,
394     IWineD3DQueryImpl_GetDataSize,
395     IWineD3DQueryImpl_GetType,
396     IWineD3DQueryImpl_Issue
397 };