2 * Copyright 2009 Henri Verbeet for CodeWeavers
3 * Copyright 2015-2017 Józef Kucia for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
24 #include "d3d11_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d11
);
28 /* ID3D11Query methods */
30 static inline struct d3d_query
*impl_from_ID3D11Query(ID3D11Query
*iface
)
32 return CONTAINING_RECORD(iface
, struct d3d_query
, ID3D11Query_iface
);
35 static HRESULT STDMETHODCALLTYPE
d3d11_query_QueryInterface(ID3D11Query
*iface
, REFIID riid
, void **object
)
37 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
39 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
41 if ((IsEqualGUID(riid
, &IID_ID3D11Predicate
) && query
->predicate
)
42 || IsEqualGUID(riid
, &IID_ID3D11Query
)
43 || IsEqualGUID(riid
, &IID_ID3D11Asynchronous
)
44 || IsEqualGUID(riid
, &IID_ID3D11DeviceChild
)
45 || IsEqualGUID(riid
, &IID_IUnknown
))
47 ID3D11Query_AddRef(iface
);
52 if ((IsEqualGUID(riid
, &IID_ID3D10Predicate
) && query
->predicate
)
53 || IsEqualGUID(riid
, &IID_ID3D10Query
)
54 || IsEqualGUID(riid
, &IID_ID3D10Asynchronous
)
55 || IsEqualGUID(riid
, &IID_ID3D10DeviceChild
))
57 ID3D10Query_AddRef(&query
->ID3D10Query_iface
);
58 *object
= &query
->ID3D10Query_iface
;
62 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
68 static ULONG STDMETHODCALLTYPE
d3d11_query_AddRef(ID3D11Query
*iface
)
70 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
71 ULONG refcount
= InterlockedIncrement(&query
->refcount
);
73 TRACE("%p increasing refcount to %u.\n", query
, refcount
);
77 ID3D11Device_AddRef(query
->device
);
79 wined3d_query_incref(query
->wined3d_query
);
80 wined3d_mutex_unlock();
86 static ULONG STDMETHODCALLTYPE
d3d11_query_Release(ID3D11Query
*iface
)
88 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
89 ULONG refcount
= InterlockedDecrement(&query
->refcount
);
91 TRACE("%p decreasing refcount to %u.\n", query
, refcount
);
95 ID3D11Device
*device
= query
->device
;
98 wined3d_query_decref(query
->wined3d_query
);
99 wined3d_mutex_unlock();
101 ID3D11Device_Release(device
);
107 static void STDMETHODCALLTYPE
d3d11_query_GetDevice(ID3D11Query
*iface
, ID3D11Device
**device
)
109 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
111 TRACE("iface %p, device %p.\n", iface
, device
);
113 *device
= query
->device
;
114 ID3D11Device_AddRef(*device
);
117 static HRESULT STDMETHODCALLTYPE
d3d11_query_GetPrivateData(ID3D11Query
*iface
,
118 REFGUID guid
, UINT
*data_size
, void *data
)
120 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
122 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
124 return d3d_get_private_data(&query
->private_store
, guid
, data_size
, data
);
127 static HRESULT STDMETHODCALLTYPE
d3d11_query_SetPrivateData(ID3D11Query
*iface
,
128 REFGUID guid
, UINT data_size
, const void *data
)
130 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
132 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface
, debugstr_guid(guid
), data_size
, data
);
134 return d3d_set_private_data(&query
->private_store
, guid
, data_size
, data
);
137 static HRESULT STDMETHODCALLTYPE
d3d11_query_SetPrivateDataInterface(ID3D11Query
*iface
,
138 REFGUID guid
, const IUnknown
*data
)
140 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
142 TRACE("iface %p, guid %s, data %p.\n", iface
, debugstr_guid(guid
), data
);
144 return d3d_set_private_data_interface(&query
->private_store
, guid
, data
);
147 static UINT STDMETHODCALLTYPE
d3d11_query_GetDataSize(ID3D11Query
*iface
)
149 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
150 unsigned int data_size
;
152 TRACE("iface %p.\n", iface
);
154 wined3d_mutex_lock();
155 data_size
= wined3d_query_get_data_size(query
->wined3d_query
);
156 wined3d_mutex_unlock();
161 static void STDMETHODCALLTYPE
d3d11_query_GetDesc(ID3D11Query
*iface
, D3D11_QUERY_DESC
*desc
)
163 struct d3d_query
*query
= impl_from_ID3D11Query(iface
);
165 TRACE("iface %p, desc %p.\n", iface
, desc
);
170 static const struct ID3D11QueryVtbl d3d11_query_vtbl
=
172 /* IUnknown methods */
173 d3d11_query_QueryInterface
,
176 /* ID3D11DeviceChild methods */
177 d3d11_query_GetDevice
,
178 d3d11_query_GetPrivateData
,
179 d3d11_query_SetPrivateData
,
180 d3d11_query_SetPrivateDataInterface
,
181 /* ID3D11Asynchronous methods */
182 d3d11_query_GetDataSize
,
183 /* ID3D11Query methods */
187 static void STDMETHODCALLTYPE
d3d_query_wined3d_object_destroyed(void *parent
)
189 struct d3d_query
*query
= parent
;
191 wined3d_private_store_cleanup(&query
->private_store
);
192 HeapFree(GetProcessHeap(), 0, parent
);
195 static const struct wined3d_parent_ops d3d_query_wined3d_parent_ops
=
197 d3d_query_wined3d_object_destroyed
,
200 struct d3d_query
*unsafe_impl_from_ID3D11Query(ID3D11Query
*iface
)
204 assert(iface
->lpVtbl
== &d3d11_query_vtbl
);
205 return CONTAINING_RECORD(iface
, struct d3d_query
, ID3D11Query_iface
);
208 struct d3d_query
*unsafe_impl_from_ID3D11Asynchronous(ID3D11Asynchronous
*iface
)
210 return unsafe_impl_from_ID3D11Query((ID3D11Query
*)iface
);
213 /* ID3D10Query methods */
215 static inline struct d3d_query
*impl_from_ID3D10Query(ID3D10Query
*iface
)
217 return CONTAINING_RECORD(iface
, struct d3d_query
, ID3D10Query_iface
);
220 /* IUnknown methods */
222 static HRESULT STDMETHODCALLTYPE
d3d10_query_QueryInterface(ID3D10Query
*iface
, REFIID riid
, void **object
)
224 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
226 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
228 return d3d11_query_QueryInterface(&query
->ID3D11Query_iface
, riid
, object
);
231 static ULONG STDMETHODCALLTYPE
d3d10_query_AddRef(ID3D10Query
*iface
)
233 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
235 TRACE("iface %p.\n", iface
);
237 return d3d11_query_AddRef(&query
->ID3D11Query_iface
);
240 static ULONG STDMETHODCALLTYPE
d3d10_query_Release(ID3D10Query
*iface
)
242 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
244 TRACE("iface %p.\n", iface
);
246 return d3d11_query_Release(&query
->ID3D11Query_iface
);
249 /* ID3D10DeviceChild methods */
251 static void STDMETHODCALLTYPE
d3d10_query_GetDevice(ID3D10Query
*iface
, ID3D10Device
**device
)
253 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
255 TRACE("iface %p, device %p.\n", iface
, device
);
257 ID3D11Device_QueryInterface(query
->device
, &IID_ID3D10Device
, (void **)device
);
260 static HRESULT STDMETHODCALLTYPE
d3d10_query_GetPrivateData(ID3D10Query
*iface
,
261 REFGUID guid
, UINT
*data_size
, void *data
)
263 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
265 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
266 iface
, debugstr_guid(guid
), data_size
, data
);
268 return d3d_get_private_data(&query
->private_store
, guid
, data_size
, data
);
271 static HRESULT STDMETHODCALLTYPE
d3d10_query_SetPrivateData(ID3D10Query
*iface
,
272 REFGUID guid
, UINT data_size
, const void *data
)
274 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
276 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
277 iface
, debugstr_guid(guid
), data_size
, data
);
279 return d3d_set_private_data(&query
->private_store
, guid
, data_size
, data
);
282 static HRESULT STDMETHODCALLTYPE
d3d10_query_SetPrivateDataInterface(ID3D10Query
*iface
,
283 REFGUID guid
, const IUnknown
*data
)
285 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
287 TRACE("iface %p, guid %s, data %p.\n", iface
, debugstr_guid(guid
), data
);
289 return d3d_set_private_data_interface(&query
->private_store
, guid
, data
);
292 /* ID3D10Asynchronous methods */
294 static void STDMETHODCALLTYPE
d3d10_query_Begin(ID3D10Query
*iface
)
296 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
299 TRACE("iface %p.\n", iface
);
301 wined3d_mutex_lock();
302 if (FAILED(hr
= wined3d_query_issue(query
->wined3d_query
, WINED3DISSUE_BEGIN
)))
303 ERR("Failed to issue query, hr %#x.\n", hr
);
304 wined3d_mutex_unlock();
307 static void STDMETHODCALLTYPE
d3d10_query_End(ID3D10Query
*iface
)
309 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
312 TRACE("iface %p.\n", iface
);
314 wined3d_mutex_lock();
315 if (FAILED(hr
= wined3d_query_issue(query
->wined3d_query
, WINED3DISSUE_END
)))
316 ERR("Failed to issue query, hr %#x.\n", hr
);
317 wined3d_mutex_unlock();
320 static HRESULT STDMETHODCALLTYPE
d3d10_query_GetData(ID3D10Query
*iface
, void *data
, UINT data_size
, UINT flags
)
322 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
323 D3D11_QUERY_DATA_PIPELINE_STATISTICS d3d11_data
;
324 void *d3d10_data_pointer
= NULL
;
325 unsigned int wined3d_flags
;
328 TRACE("iface %p, data %p, data_size %u, flags %#x.\n", iface
, data
, data_size
, flags
);
330 if (!data
&& data_size
)
333 if (query
->desc
.Query
== D3D11_QUERY_PIPELINE_STATISTICS
334 && data_size
== sizeof(D3D10_QUERY_DATA_PIPELINE_STATISTICS
))
336 data_size
= sizeof(D3D11_QUERY_DATA_PIPELINE_STATISTICS
);
337 d3d10_data_pointer
= data
;
341 wined3d_flags
= wined3d_getdata_flags_from_d3d11_async_getdata_flags(flags
);
343 wined3d_mutex_lock();
344 if (!data_size
|| wined3d_query_get_data_size(query
->wined3d_query
) == data_size
)
346 hr
= wined3d_query_get_data(query
->wined3d_query
, data
, data_size
, wined3d_flags
);
347 if (hr
== WINED3DERR_INVALIDCALL
)
348 hr
= DXGI_ERROR_INVALID_CALL
;
352 WARN("Invalid data size %u.\n", data_size
);
355 wined3d_mutex_unlock();
357 if (d3d10_data_pointer
&& hr
== S_OK
)
358 memcpy(d3d10_data_pointer
, data
, sizeof(D3D10_QUERY_DATA_PIPELINE_STATISTICS
));
363 static UINT STDMETHODCALLTYPE
d3d10_query_GetDataSize(ID3D10Query
*iface
)
365 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
366 unsigned int data_size
;
368 TRACE("iface %p.\n", iface
);
370 wined3d_mutex_lock();
371 data_size
= wined3d_query_get_data_size(query
->wined3d_query
);
372 wined3d_mutex_unlock();
374 if (query
->desc
.Query
== D3D11_QUERY_PIPELINE_STATISTICS
)
375 data_size
= sizeof(D3D10_QUERY_DATA_PIPELINE_STATISTICS
);
380 /* ID3D10Query methods */
382 static void STDMETHODCALLTYPE
d3d10_query_GetDesc(ID3D10Query
*iface
, D3D10_QUERY_DESC
*desc
)
384 struct d3d_query
*query
= impl_from_ID3D10Query(iface
);
386 TRACE("iface %p, desc %p.\n", iface
, desc
);
388 memcpy(desc
, &query
->desc
, sizeof(*desc
));
391 static const struct ID3D10QueryVtbl d3d10_query_vtbl
=
393 /* IUnknown methods */
394 d3d10_query_QueryInterface
,
397 /* ID3D10DeviceChild methods */
398 d3d10_query_GetDevice
,
399 d3d10_query_GetPrivateData
,
400 d3d10_query_SetPrivateData
,
401 d3d10_query_SetPrivateDataInterface
,
402 /* ID3D10Asynchronous methods */
406 d3d10_query_GetDataSize
,
407 /* ID3D10Query methods */
411 struct d3d_query
*unsafe_impl_from_ID3D10Query(ID3D10Query
*iface
)
415 assert(iface
->lpVtbl
== &d3d10_query_vtbl
);
416 return CONTAINING_RECORD(iface
, struct d3d_query
, ID3D10Query_iface
);
419 static HRESULT
d3d_query_init(struct d3d_query
*query
, struct d3d_device
*device
,
420 const D3D11_QUERY_DESC
*desc
, BOOL predicate
)
424 static const enum wined3d_query_type query_type_map
[] =
426 /* D3D11_QUERY_EVENT */ WINED3D_QUERY_TYPE_EVENT
,
427 /* D3D11_QUERY_OCCLUSION */ WINED3D_QUERY_TYPE_OCCLUSION
,
428 /* D3D11_QUERY_TIMESTAMP */ WINED3D_QUERY_TYPE_TIMESTAMP
,
429 /* D3D11_QUERY_TIMESTAMP_DISJOINT */ WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT
,
430 /* D3D11_QUERY_PIPELINE_STATISTICS */ WINED3D_QUERY_TYPE_PIPELINE_STATISTICS
,
431 /* D3D11_QUERY_OCCLUSION_PREDICATE */ WINED3D_QUERY_TYPE_OCCLUSION
,
432 /* D3D11_QUERY_SO_STATISTICS */ WINED3D_QUERY_TYPE_SO_STATISTICS
,
433 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE */ WINED3D_QUERY_TYPE_SO_OVERFLOW
,
434 /* D3D11_QUERY_SO_STATISTICS_STREAM0 */ WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0
,
435 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0 */ WINED3D_QUERY_TYPE_SO_OVERFLOW_STREAM0
,
436 /* D3D11_QUERY_SO_STATISTICS_STREAM1 */ WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1
,
437 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1 */ WINED3D_QUERY_TYPE_SO_OVERFLOW_STREAM1
,
438 /* D3D11_QUERY_SO_STATISTICS_STREAM2 */ WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2
,
439 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2 */ WINED3D_QUERY_TYPE_SO_OVERFLOW_STREAM2
,
440 /* D3D11_QUERY_SO_STATISTICS_STREAM3 */ WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3
,
441 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3 */ WINED3D_QUERY_TYPE_SO_OVERFLOW_STREAM3
,
444 if (desc
->Query
>= ARRAY_SIZE(query_type_map
))
446 FIXME("Unhandled query type %#x.\n", desc
->Query
);
451 FIXME("Ignoring MiscFlags %#x.\n", desc
->MiscFlags
);
453 query
->ID3D11Query_iface
.lpVtbl
= &d3d11_query_vtbl
;
454 query
->ID3D10Query_iface
.lpVtbl
= &d3d10_query_vtbl
;
459 wined3d_mutex_lock();
460 wined3d_private_store_init(&query
->private_store
);
462 if (FAILED(hr
= wined3d_query_create(device
->wined3d_device
, query_type_map
[desc
->Query
],
463 query
, &d3d_query_wined3d_parent_ops
, &query
->wined3d_query
)))
465 WARN("Failed to create wined3d query, hr %#x.\n", hr
);
466 wined3d_private_store_cleanup(&query
->private_store
);
467 wined3d_mutex_unlock();
470 wined3d_mutex_unlock();
472 query
->predicate
= predicate
;
473 query
->device
= &device
->ID3D11Device_iface
;
474 ID3D11Device_AddRef(query
->device
);
479 HRESULT
d3d_query_create(struct d3d_device
*device
, const D3D11_QUERY_DESC
*desc
, BOOL predicate
,
480 struct d3d_query
**query
)
482 struct d3d_query
*object
;
483 BOOL is_predicate_type
;
489 is_predicate_type
= desc
->Query
== D3D11_QUERY_OCCLUSION_PREDICATE
490 || desc
->Query
== D3D11_QUERY_SO_OVERFLOW_PREDICATE
491 || desc
->Query
== D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0
492 || desc
->Query
== D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1
493 || desc
->Query
== D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2
494 || desc
->Query
== D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3
;
496 if (!is_predicate_type
&& predicate
)
498 WARN("Query type %u is not a predicate.\n", desc
->Query
);
502 if (is_predicate_type
)
505 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
506 return E_OUTOFMEMORY
;
508 if (FAILED(hr
= d3d_query_init(object
, device
, desc
, predicate
)))
510 WARN("Failed to initialize predicate, hr %#x.\n", hr
);
511 HeapFree(GetProcessHeap(), 0, object
);
515 TRACE("Created query %p.\n", object
);