Release 3.0.2.
[wine.git] / dlls / d3d11 / async.c
blobd37cbdeaf6cd95e64921279d4e45da70948ae858
1 /*
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
21 #include "config.h"
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);
48 *object = iface;
49 return S_OK;
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;
59 return S_OK;
62 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
64 *object = NULL;
65 return E_NOINTERFACE;
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);
75 if (refcount == 1)
77 ID3D11Device_AddRef(query->device);
78 wined3d_mutex_lock();
79 wined3d_query_incref(query->wined3d_query);
80 wined3d_mutex_unlock();
83 return refcount;
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);
93 if (!refcount)
95 ID3D11Device *device = query->device;
97 wined3d_mutex_lock();
98 wined3d_query_decref(query->wined3d_query);
99 wined3d_mutex_unlock();
101 ID3D11Device_Release(device);
104 return refcount;
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();
158 return data_size;
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);
167 *desc = query->desc;
170 static const struct ID3D11QueryVtbl d3d11_query_vtbl =
172 /* IUnknown methods */
173 d3d11_query_QueryInterface,
174 d3d11_query_AddRef,
175 d3d11_query_Release,
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 */
184 d3d11_query_GetDesc,
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)
202 if (!iface)
203 return NULL;
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);
297 HRESULT hr;
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);
310 HRESULT hr;
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;
326 HRESULT hr;
328 TRACE("iface %p, data %p, data_size %u, flags %#x.\n", iface, data, data_size, flags);
330 if (!data && data_size)
331 return E_INVALIDARG;
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;
338 data = &d3d11_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;
350 else
352 WARN("Invalid data size %u.\n", data_size);
353 hr = E_INVALIDARG;
355 wined3d_mutex_unlock();
357 if (d3d10_data_pointer && hr == S_OK)
358 memcpy(d3d10_data_pointer, data, sizeof(D3D10_QUERY_DATA_PIPELINE_STATISTICS));
360 return hr;
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);
377 return data_size;
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,
395 d3d10_query_AddRef,
396 d3d10_query_Release,
397 /* ID3D10DeviceChild methods */
398 d3d10_query_GetDevice,
399 d3d10_query_GetPrivateData,
400 d3d10_query_SetPrivateData,
401 d3d10_query_SetPrivateDataInterface,
402 /* ID3D10Asynchronous methods */
403 d3d10_query_Begin,
404 d3d10_query_End,
405 d3d10_query_GetData,
406 d3d10_query_GetDataSize,
407 /* ID3D10Query methods */
408 d3d10_query_GetDesc,
411 struct d3d_query *unsafe_impl_from_ID3D10Query(ID3D10Query *iface)
413 if (!iface)
414 return NULL;
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)
422 HRESULT hr;
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);
447 return E_INVALIDARG;
450 if (desc->MiscFlags)
451 FIXME("Ignoring MiscFlags %#x.\n", desc->MiscFlags);
453 query->ID3D11Query_iface.lpVtbl = &d3d11_query_vtbl;
454 query->ID3D10Query_iface.lpVtbl = &d3d10_query_vtbl;
455 query->refcount = 1;
457 query->desc = *desc;
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();
468 return hr;
470 wined3d_mutex_unlock();
472 query->predicate = predicate;
473 query->device = &device->ID3D11Device_iface;
474 ID3D11Device_AddRef(query->device);
476 return S_OK;
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;
484 HRESULT hr;
486 if (!desc)
487 return E_INVALIDARG;
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);
499 return E_INVALIDARG;
502 if (is_predicate_type)
503 predicate = TRUE;
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);
512 return hr;
515 TRACE("Created query %p.\n", object);
516 *query = object;
518 return S_OK;