wined3d: Pass a wined3d_device_context to wined3d_cs_emit_set_index_buffer().
[wine.git] / dlls / d3d11 / async.c
blobfd83871220d5149e1b2db5cd0388dd42f45ddcff
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 "d3d11_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
25 /* ID3D11Query methods */
27 static inline struct d3d_query *impl_from_ID3D11Query(ID3D11Query *iface)
29 return CONTAINING_RECORD(iface, struct d3d_query, ID3D11Query_iface);
32 static HRESULT STDMETHODCALLTYPE d3d11_query_QueryInterface(ID3D11Query *iface, REFIID riid, void **object)
34 struct d3d_query *query = impl_from_ID3D11Query(iface);
36 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
38 if ((IsEqualGUID(riid, &IID_ID3D11Predicate) && query->predicate)
39 || IsEqualGUID(riid, &IID_ID3D11Query)
40 || IsEqualGUID(riid, &IID_ID3D11Asynchronous)
41 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
42 || IsEqualGUID(riid, &IID_IUnknown))
44 ID3D11Query_AddRef(iface);
45 *object = iface;
46 return S_OK;
49 if ((IsEqualGUID(riid, &IID_ID3D10Predicate) && query->predicate)
50 || IsEqualGUID(riid, &IID_ID3D10Query)
51 || IsEqualGUID(riid, &IID_ID3D10Asynchronous)
52 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
54 ID3D10Query_AddRef(&query->ID3D10Query_iface);
55 *object = &query->ID3D10Query_iface;
56 return S_OK;
59 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
61 *object = NULL;
62 return E_NOINTERFACE;
65 static ULONG STDMETHODCALLTYPE d3d11_query_AddRef(ID3D11Query *iface)
67 struct d3d_query *query = impl_from_ID3D11Query(iface);
68 ULONG refcount = InterlockedIncrement(&query->refcount);
70 TRACE("%p increasing refcount to %u.\n", query, refcount);
72 if (refcount == 1)
74 ID3D11Device2_AddRef(query->device);
75 wined3d_mutex_lock();
76 wined3d_query_incref(query->wined3d_query);
77 wined3d_mutex_unlock();
80 return refcount;
83 static ULONG STDMETHODCALLTYPE d3d11_query_Release(ID3D11Query *iface)
85 struct d3d_query *query = impl_from_ID3D11Query(iface);
86 ULONG refcount = InterlockedDecrement(&query->refcount);
88 TRACE("%p decreasing refcount to %u.\n", query, refcount);
90 if (!refcount)
92 ID3D11Device2 *device = query->device;
94 wined3d_mutex_lock();
95 wined3d_query_decref(query->wined3d_query);
96 wined3d_mutex_unlock();
98 ID3D11Device2_Release(device);
101 return refcount;
104 static void STDMETHODCALLTYPE d3d11_query_GetDevice(ID3D11Query *iface, ID3D11Device **device)
106 struct d3d_query *query = impl_from_ID3D11Query(iface);
108 TRACE("iface %p, device %p.\n", iface, device);
110 *device = (ID3D11Device *)query->device;
111 ID3D11Device_AddRef(*device);
114 static HRESULT STDMETHODCALLTYPE d3d11_query_GetPrivateData(ID3D11Query *iface,
115 REFGUID guid, UINT *data_size, void *data)
117 struct d3d_query *query = impl_from_ID3D11Query(iface);
119 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
121 return d3d_get_private_data(&query->private_store, guid, data_size, data);
124 static HRESULT STDMETHODCALLTYPE d3d11_query_SetPrivateData(ID3D11Query *iface,
125 REFGUID guid, UINT data_size, const void *data)
127 struct d3d_query *query = impl_from_ID3D11Query(iface);
129 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
131 return d3d_set_private_data(&query->private_store, guid, data_size, data);
134 static HRESULT STDMETHODCALLTYPE d3d11_query_SetPrivateDataInterface(ID3D11Query *iface,
135 REFGUID guid, const IUnknown *data)
137 struct d3d_query *query = impl_from_ID3D11Query(iface);
139 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
141 return d3d_set_private_data_interface(&query->private_store, guid, data);
144 static UINT STDMETHODCALLTYPE d3d11_query_GetDataSize(ID3D11Query *iface)
146 struct d3d_query *query = impl_from_ID3D11Query(iface);
147 unsigned int data_size;
149 TRACE("iface %p.\n", iface);
151 wined3d_mutex_lock();
152 data_size = wined3d_query_get_data_size(query->wined3d_query);
153 wined3d_mutex_unlock();
155 return data_size;
158 static void STDMETHODCALLTYPE d3d11_query_GetDesc(ID3D11Query *iface, D3D11_QUERY_DESC *desc)
160 struct d3d_query *query = impl_from_ID3D11Query(iface);
162 TRACE("iface %p, desc %p.\n", iface, desc);
164 *desc = query->desc;
167 static const struct ID3D11QueryVtbl d3d11_query_vtbl =
169 /* IUnknown methods */
170 d3d11_query_QueryInterface,
171 d3d11_query_AddRef,
172 d3d11_query_Release,
173 /* ID3D11DeviceChild methods */
174 d3d11_query_GetDevice,
175 d3d11_query_GetPrivateData,
176 d3d11_query_SetPrivateData,
177 d3d11_query_SetPrivateDataInterface,
178 /* ID3D11Asynchronous methods */
179 d3d11_query_GetDataSize,
180 /* ID3D11Query methods */
181 d3d11_query_GetDesc,
184 static void STDMETHODCALLTYPE d3d_query_wined3d_object_destroyed(void *parent)
186 struct d3d_query *query = parent;
188 wined3d_private_store_cleanup(&query->private_store);
189 heap_free(parent);
192 static const struct wined3d_parent_ops d3d_query_wined3d_parent_ops =
194 d3d_query_wined3d_object_destroyed,
197 struct d3d_query *unsafe_impl_from_ID3D11Query(ID3D11Query *iface)
199 if (!iface)
200 return NULL;
201 assert(iface->lpVtbl == &d3d11_query_vtbl);
202 return CONTAINING_RECORD(iface, struct d3d_query, ID3D11Query_iface);
205 struct d3d_query *unsafe_impl_from_ID3D11Asynchronous(ID3D11Asynchronous *iface)
207 return unsafe_impl_from_ID3D11Query((ID3D11Query *)iface);
210 /* ID3D10Query methods */
212 static inline struct d3d_query *impl_from_ID3D10Query(ID3D10Query *iface)
214 return CONTAINING_RECORD(iface, struct d3d_query, ID3D10Query_iface);
217 /* IUnknown methods */
219 static HRESULT STDMETHODCALLTYPE d3d10_query_QueryInterface(ID3D10Query *iface, REFIID riid, void **object)
221 struct d3d_query *query = impl_from_ID3D10Query(iface);
223 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
225 return d3d11_query_QueryInterface(&query->ID3D11Query_iface, riid, object);
228 static ULONG STDMETHODCALLTYPE d3d10_query_AddRef(ID3D10Query *iface)
230 struct d3d_query *query = impl_from_ID3D10Query(iface);
232 TRACE("iface %p.\n", iface);
234 return d3d11_query_AddRef(&query->ID3D11Query_iface);
237 static ULONG STDMETHODCALLTYPE d3d10_query_Release(ID3D10Query *iface)
239 struct d3d_query *query = impl_from_ID3D10Query(iface);
241 TRACE("iface %p.\n", iface);
243 return d3d11_query_Release(&query->ID3D11Query_iface);
246 /* ID3D10DeviceChild methods */
248 static void STDMETHODCALLTYPE d3d10_query_GetDevice(ID3D10Query *iface, ID3D10Device **device)
250 struct d3d_query *query = impl_from_ID3D10Query(iface);
252 TRACE("iface %p, device %p.\n", iface, device);
254 ID3D11Device2_QueryInterface(query->device, &IID_ID3D10Device, (void **)device);
257 static HRESULT STDMETHODCALLTYPE d3d10_query_GetPrivateData(ID3D10Query *iface,
258 REFGUID guid, UINT *data_size, void *data)
260 struct d3d_query *query = impl_from_ID3D10Query(iface);
262 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
263 iface, debugstr_guid(guid), data_size, data);
265 return d3d_get_private_data(&query->private_store, guid, data_size, data);
268 static HRESULT STDMETHODCALLTYPE d3d10_query_SetPrivateData(ID3D10Query *iface,
269 REFGUID guid, UINT data_size, const void *data)
271 struct d3d_query *query = impl_from_ID3D10Query(iface);
273 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
274 iface, debugstr_guid(guid), data_size, data);
276 return d3d_set_private_data(&query->private_store, guid, data_size, data);
279 static HRESULT STDMETHODCALLTYPE d3d10_query_SetPrivateDataInterface(ID3D10Query *iface,
280 REFGUID guid, const IUnknown *data)
282 struct d3d_query *query = impl_from_ID3D10Query(iface);
284 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
286 return d3d_set_private_data_interface(&query->private_store, guid, data);
289 /* ID3D10Asynchronous methods */
291 static void STDMETHODCALLTYPE d3d10_query_Begin(ID3D10Query *iface)
293 struct d3d_query *query = impl_from_ID3D10Query(iface);
294 HRESULT hr;
296 TRACE("iface %p.\n", iface);
298 wined3d_mutex_lock();
299 if (FAILED(hr = wined3d_query_issue(query->wined3d_query, WINED3DISSUE_BEGIN)))
300 ERR("Failed to issue query, hr %#x.\n", hr);
301 wined3d_mutex_unlock();
304 static void STDMETHODCALLTYPE d3d10_query_End(ID3D10Query *iface)
306 struct d3d_query *query = impl_from_ID3D10Query(iface);
307 HRESULT hr;
309 TRACE("iface %p.\n", iface);
311 wined3d_mutex_lock();
312 if (FAILED(hr = wined3d_query_issue(query->wined3d_query, WINED3DISSUE_END)))
313 ERR("Failed to issue query, hr %#x.\n", hr);
314 wined3d_mutex_unlock();
317 static HRESULT STDMETHODCALLTYPE d3d10_query_GetData(ID3D10Query *iface, void *data, UINT data_size, UINT flags)
319 struct d3d_query *query = impl_from_ID3D10Query(iface);
320 D3D11_QUERY_DATA_PIPELINE_STATISTICS d3d11_data;
321 void *d3d10_data_pointer = NULL;
322 unsigned int wined3d_flags;
323 HRESULT hr;
325 TRACE("iface %p, data %p, data_size %u, flags %#x.\n", iface, data, data_size, flags);
327 if (!data && data_size)
328 return E_INVALIDARG;
330 if (query->desc.Query == D3D11_QUERY_PIPELINE_STATISTICS
331 && data_size == sizeof(D3D10_QUERY_DATA_PIPELINE_STATISTICS))
333 data_size = sizeof(D3D11_QUERY_DATA_PIPELINE_STATISTICS);
334 d3d10_data_pointer = data;
335 data = &d3d11_data;
338 wined3d_flags = wined3d_getdata_flags_from_d3d11_async_getdata_flags(flags);
340 wined3d_mutex_lock();
341 if (!data_size || wined3d_query_get_data_size(query->wined3d_query) == data_size)
343 hr = wined3d_query_get_data(query->wined3d_query, data, data_size, wined3d_flags);
344 if (hr == WINED3DERR_INVALIDCALL)
345 hr = DXGI_ERROR_INVALID_CALL;
347 else
349 WARN("Invalid data size %u.\n", data_size);
350 hr = E_INVALIDARG;
352 wined3d_mutex_unlock();
354 if (d3d10_data_pointer && hr == S_OK)
355 memcpy(d3d10_data_pointer, data, sizeof(D3D10_QUERY_DATA_PIPELINE_STATISTICS));
357 return hr;
360 static UINT STDMETHODCALLTYPE d3d10_query_GetDataSize(ID3D10Query *iface)
362 struct d3d_query *query = impl_from_ID3D10Query(iface);
363 unsigned int data_size;
365 TRACE("iface %p.\n", iface);
367 wined3d_mutex_lock();
368 data_size = wined3d_query_get_data_size(query->wined3d_query);
369 wined3d_mutex_unlock();
371 if (query->desc.Query == D3D11_QUERY_PIPELINE_STATISTICS)
372 data_size = sizeof(D3D10_QUERY_DATA_PIPELINE_STATISTICS);
374 return data_size;
377 /* ID3D10Query methods */
379 static void STDMETHODCALLTYPE d3d10_query_GetDesc(ID3D10Query *iface, D3D10_QUERY_DESC *desc)
381 struct d3d_query *query = impl_from_ID3D10Query(iface);
383 TRACE("iface %p, desc %p.\n", iface, desc);
385 memcpy(desc, &query->desc, sizeof(*desc));
388 static const struct ID3D10QueryVtbl d3d10_query_vtbl =
390 /* IUnknown methods */
391 d3d10_query_QueryInterface,
392 d3d10_query_AddRef,
393 d3d10_query_Release,
394 /* ID3D10DeviceChild methods */
395 d3d10_query_GetDevice,
396 d3d10_query_GetPrivateData,
397 d3d10_query_SetPrivateData,
398 d3d10_query_SetPrivateDataInterface,
399 /* ID3D10Asynchronous methods */
400 d3d10_query_Begin,
401 d3d10_query_End,
402 d3d10_query_GetData,
403 d3d10_query_GetDataSize,
404 /* ID3D10Query methods */
405 d3d10_query_GetDesc,
408 struct d3d_query *unsafe_impl_from_ID3D10Query(ID3D10Query *iface)
410 if (!iface)
411 return NULL;
412 assert(iface->lpVtbl == &d3d10_query_vtbl);
413 return CONTAINING_RECORD(iface, struct d3d_query, ID3D10Query_iface);
416 static HRESULT d3d_query_init(struct d3d_query *query, struct d3d_device *device,
417 const D3D11_QUERY_DESC *desc, BOOL predicate)
419 HRESULT hr;
421 static const enum wined3d_query_type query_type_map[] =
423 /* D3D11_QUERY_EVENT */ WINED3D_QUERY_TYPE_EVENT,
424 /* D3D11_QUERY_OCCLUSION */ WINED3D_QUERY_TYPE_OCCLUSION,
425 /* D3D11_QUERY_TIMESTAMP */ WINED3D_QUERY_TYPE_TIMESTAMP,
426 /* D3D11_QUERY_TIMESTAMP_DISJOINT */ WINED3D_QUERY_TYPE_TIMESTAMP_DISJOINT,
427 /* D3D11_QUERY_PIPELINE_STATISTICS */ WINED3D_QUERY_TYPE_PIPELINE_STATISTICS,
428 /* D3D11_QUERY_OCCLUSION_PREDICATE */ WINED3D_QUERY_TYPE_OCCLUSION,
429 /* D3D11_QUERY_SO_STATISTICS */ WINED3D_QUERY_TYPE_SO_STATISTICS,
430 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE */ WINED3D_QUERY_TYPE_SO_OVERFLOW,
431 /* D3D11_QUERY_SO_STATISTICS_STREAM0 */ WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0,
432 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0 */ WINED3D_QUERY_TYPE_SO_OVERFLOW_STREAM0,
433 /* D3D11_QUERY_SO_STATISTICS_STREAM1 */ WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1,
434 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1 */ WINED3D_QUERY_TYPE_SO_OVERFLOW_STREAM1,
435 /* D3D11_QUERY_SO_STATISTICS_STREAM2 */ WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2,
436 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2 */ WINED3D_QUERY_TYPE_SO_OVERFLOW_STREAM2,
437 /* D3D11_QUERY_SO_STATISTICS_STREAM3 */ WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3,
438 /* D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3 */ WINED3D_QUERY_TYPE_SO_OVERFLOW_STREAM3,
441 if (desc->Query >= ARRAY_SIZE(query_type_map))
443 FIXME("Unhandled query type %#x.\n", desc->Query);
444 return E_INVALIDARG;
447 if (desc->MiscFlags)
448 FIXME("Ignoring MiscFlags %#x.\n", desc->MiscFlags);
450 query->ID3D11Query_iface.lpVtbl = &d3d11_query_vtbl;
451 query->ID3D10Query_iface.lpVtbl = &d3d10_query_vtbl;
452 query->refcount = 1;
454 query->desc = *desc;
456 wined3d_mutex_lock();
457 wined3d_private_store_init(&query->private_store);
459 if (FAILED(hr = wined3d_query_create(device->wined3d_device, query_type_map[desc->Query],
460 query, &d3d_query_wined3d_parent_ops, &query->wined3d_query)))
462 WARN("Failed to create wined3d query, hr %#x.\n", hr);
463 wined3d_private_store_cleanup(&query->private_store);
464 wined3d_mutex_unlock();
465 return hr;
467 wined3d_mutex_unlock();
469 query->predicate = predicate;
470 ID3D11Device2_AddRef(query->device = &device->ID3D11Device2_iface);
472 return S_OK;
475 HRESULT d3d_query_create(struct d3d_device *device, const D3D11_QUERY_DESC *desc, BOOL predicate,
476 struct d3d_query **query)
478 struct d3d_query *object;
479 BOOL is_predicate_type;
480 HRESULT hr;
482 if (!desc)
483 return E_INVALIDARG;
485 is_predicate_type = desc->Query == D3D11_QUERY_OCCLUSION_PREDICATE
486 || desc->Query == D3D11_QUERY_SO_OVERFLOW_PREDICATE
487 || desc->Query == D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM0
488 || desc->Query == D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM1
489 || desc->Query == D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM2
490 || desc->Query == D3D11_QUERY_SO_OVERFLOW_PREDICATE_STREAM3;
492 if (!is_predicate_type && predicate)
494 WARN("Query type %u is not a predicate.\n", desc->Query);
495 return E_INVALIDARG;
498 if (is_predicate_type)
499 predicate = TRUE;
501 if (!(object = heap_alloc_zero(sizeof(*object))))
502 return E_OUTOFMEMORY;
504 if (FAILED(hr = d3d_query_init(object, device, desc, predicate)))
506 WARN("Failed to initialize predicate, hr %#x.\n", hr);
507 heap_free(object);
508 return hr;
511 TRACE("Created query %p.\n", object);
512 *query = object;
514 return S_OK;