mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / d3d11 / state.c
blob6b28717653644e071435ad7055733d69a88ef28f
1 /*
2 * Copyright 2009 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "d3d11_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
24 /* ID3D11BlendState methods */
26 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_QueryInterface(ID3D11BlendState *iface,
27 REFIID riid, void **object)
29 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
31 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
33 if (IsEqualGUID(riid, &IID_ID3D11BlendState)
34 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
35 || IsEqualGUID(riid, &IID_IUnknown))
37 ID3D11BlendState_AddRef(iface);
38 *object = iface;
39 return S_OK;
42 if (IsEqualGUID(riid, &IID_ID3D10BlendState1)
43 || IsEqualGUID(riid, &IID_ID3D10BlendState)
44 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
46 ID3D10BlendState1_AddRef(&state->ID3D10BlendState1_iface);
47 *object = &state->ID3D10BlendState1_iface;
48 return S_OK;
51 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
53 *object = NULL;
54 return E_NOINTERFACE;
57 static ULONG STDMETHODCALLTYPE d3d11_blend_state_AddRef(ID3D11BlendState *iface)
59 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
60 ULONG refcount = InterlockedIncrement(&state->refcount);
62 TRACE("%p increasing refcount to %u.\n", state, refcount);
64 if (refcount == 1)
66 ID3D11Device2_AddRef(state->device);
67 wined3d_mutex_lock();
68 wined3d_blend_state_incref(state->wined3d_state);
69 wined3d_mutex_unlock();
72 return refcount;
75 static ULONG STDMETHODCALLTYPE d3d11_blend_state_Release(ID3D11BlendState *iface)
77 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
78 ULONG refcount = InterlockedDecrement(&state->refcount);
80 TRACE("%p decreasing refcount to %u.\n", state, refcount);
82 if (!refcount)
84 ID3D11Device2 *device = state->device;
86 wined3d_mutex_lock();
87 wined3d_blend_state_decref(state->wined3d_state);
88 wined3d_mutex_unlock();
90 ID3D11Device2_Release(device);
93 return refcount;
96 static void STDMETHODCALLTYPE d3d11_blend_state_GetDevice(ID3D11BlendState *iface,
97 ID3D11Device **device)
99 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
101 TRACE("iface %p, device %p.\n", iface, device);
103 *device = (ID3D11Device *)state->device;
104 ID3D11Device_AddRef(*device);
107 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_GetPrivateData(ID3D11BlendState *iface,
108 REFGUID guid, UINT *data_size, void *data)
110 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
112 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
114 return d3d_get_private_data(&state->private_store, guid, data_size, data);
117 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_SetPrivateData(ID3D11BlendState *iface,
118 REFGUID guid, UINT data_size, const void *data)
120 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
122 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
124 return d3d_set_private_data(&state->private_store, guid, data_size, data);
127 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_SetPrivateDataInterface(ID3D11BlendState *iface,
128 REFGUID guid, const IUnknown *data)
130 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
132 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
134 return d3d_set_private_data_interface(&state->private_store, guid, data);
137 static void STDMETHODCALLTYPE d3d11_blend_state_GetDesc(ID3D11BlendState *iface, D3D11_BLEND_DESC *desc)
139 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
141 TRACE("iface %p, desc %p.\n", iface, desc);
143 *desc = state->desc;
146 static const struct ID3D11BlendStateVtbl d3d11_blend_state_vtbl =
148 /* IUnknown methods */
149 d3d11_blend_state_QueryInterface,
150 d3d11_blend_state_AddRef,
151 d3d11_blend_state_Release,
152 /* ID3D11DeviceChild methods */
153 d3d11_blend_state_GetDevice,
154 d3d11_blend_state_GetPrivateData,
155 d3d11_blend_state_SetPrivateData,
156 d3d11_blend_state_SetPrivateDataInterface,
157 /* ID3D11BlendState methods */
158 d3d11_blend_state_GetDesc,
161 /* ID3D10BlendState methods */
163 static inline struct d3d_blend_state *impl_from_ID3D10BlendState(ID3D10BlendState1 *iface)
165 return CONTAINING_RECORD(iface, struct d3d_blend_state, ID3D10BlendState1_iface);
168 /* IUnknown methods */
170 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_QueryInterface(ID3D10BlendState1 *iface,
171 REFIID riid, void **object)
173 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
175 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
177 return d3d11_blend_state_QueryInterface(&state->ID3D11BlendState_iface, riid, object);
180 static ULONG STDMETHODCALLTYPE d3d10_blend_state_AddRef(ID3D10BlendState1 *iface)
182 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
184 TRACE("iface %p.\n", iface);
186 return d3d11_blend_state_AddRef(&state->ID3D11BlendState_iface);
189 static ULONG STDMETHODCALLTYPE d3d10_blend_state_Release(ID3D10BlendState1 *iface)
191 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
193 TRACE("iface %p.\n", iface);
195 return d3d11_blend_state_Release(&state->ID3D11BlendState_iface);
198 /* ID3D10DeviceChild methods */
200 static void STDMETHODCALLTYPE d3d10_blend_state_GetDevice(ID3D10BlendState1 *iface, ID3D10Device **device)
202 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
204 TRACE("iface %p, device %p.\n", iface, device);
206 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
209 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_GetPrivateData(ID3D10BlendState1 *iface,
210 REFGUID guid, UINT *data_size, void *data)
212 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
214 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
215 iface, debugstr_guid(guid), data_size, data);
217 return d3d_get_private_data(&state->private_store, guid, data_size, data);
220 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_SetPrivateData(ID3D10BlendState1 *iface,
221 REFGUID guid, UINT data_size, const void *data)
223 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
225 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
226 iface, debugstr_guid(guid), data_size, data);
228 return d3d_set_private_data(&state->private_store, guid, data_size, data);
231 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_SetPrivateDataInterface(ID3D10BlendState1 *iface,
232 REFGUID guid, const IUnknown *data)
234 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
236 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
238 return d3d_set_private_data_interface(&state->private_store, guid, data);
241 /* ID3D10BlendState methods */
243 static D3D10_BLEND d3d10_blend_from_d3d11(D3D11_BLEND factor)
245 return (D3D10_BLEND)factor;
248 static D3D10_BLEND_OP d3d10_blend_op_from_d3d11(D3D11_BLEND_OP op)
250 return (D3D10_BLEND_OP)op;
253 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc(ID3D10BlendState1 *iface, D3D10_BLEND_DESC *desc)
255 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
256 const D3D11_BLEND_DESC *d3d11_desc = &state->desc;
257 unsigned int i;
259 TRACE("iface %p, desc %p.\n", iface, desc);
261 desc->AlphaToCoverageEnable = d3d11_desc->AlphaToCoverageEnable;
262 desc->SrcBlend = d3d10_blend_from_d3d11(d3d11_desc->RenderTarget[0].SrcBlend);
263 desc->DestBlend = d3d10_blend_from_d3d11(d3d11_desc->RenderTarget[0].DestBlend);
264 desc->BlendOp = d3d10_blend_op_from_d3d11(d3d11_desc->RenderTarget[0].BlendOp);
265 desc->SrcBlendAlpha = d3d10_blend_from_d3d11(d3d11_desc->RenderTarget[0].SrcBlendAlpha);
266 desc->DestBlendAlpha = d3d10_blend_from_d3d11(d3d11_desc->RenderTarget[0].DestBlendAlpha);
267 desc->BlendOpAlpha = d3d10_blend_op_from_d3d11(d3d11_desc->RenderTarget[0].BlendOpAlpha);
268 for (i = 0; i < D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
270 desc->BlendEnable[i] = d3d11_desc->RenderTarget[i].BlendEnable;
271 desc->RenderTargetWriteMask[i] = d3d11_desc->RenderTarget[i].RenderTargetWriteMask;
275 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc1(ID3D10BlendState1 *iface, D3D10_BLEND_DESC1 *desc)
277 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
279 TRACE("iface %p, desc %p.\n", iface, desc);
281 memcpy(desc, &state->desc, sizeof(*desc));
284 static const struct ID3D10BlendState1Vtbl d3d10_blend_state_vtbl =
286 /* IUnknown methods */
287 d3d10_blend_state_QueryInterface,
288 d3d10_blend_state_AddRef,
289 d3d10_blend_state_Release,
290 /* ID3D10DeviceChild methods */
291 d3d10_blend_state_GetDevice,
292 d3d10_blend_state_GetPrivateData,
293 d3d10_blend_state_SetPrivateData,
294 d3d10_blend_state_SetPrivateDataInterface,
295 /* ID3D10BlendState methods */
296 d3d10_blend_state_GetDesc,
297 /* ID3D10BlendState1 methods */
298 d3d10_blend_state_GetDesc1,
301 static void STDMETHODCALLTYPE d3d_blend_state_wined3d_object_destroyed(void *parent)
303 struct d3d_blend_state *state = parent;
304 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
306 wine_rb_remove(&device->blend_states, &state->entry);
307 wined3d_private_store_cleanup(&state->private_store);
308 heap_free(parent);
311 static const struct wined3d_parent_ops d3d_blend_state_wined3d_parent_ops =
313 d3d_blend_state_wined3d_object_destroyed,
316 static enum wined3d_blend wined3d_blend_from_d3d11(D3D11_BLEND factor)
318 return (enum wined3d_blend)factor;
321 static enum wined3d_blend_op wined3d_blend_op_from_d3d11(D3D11_BLEND_OP op)
323 return (enum wined3d_blend_op)op;
326 HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC *desc,
327 struct d3d_blend_state **state)
329 struct wined3d_blend_state_desc wined3d_desc;
330 struct d3d_blend_state *object;
331 struct wine_rb_entry *entry;
332 D3D11_BLEND_DESC tmp_desc;
333 unsigned int i, j;
334 HRESULT hr;
336 if (!desc)
337 return E_INVALIDARG;
339 /* D3D11_RENDER_TARGET_BLEND_DESC has a hole, which is a problem because we use
340 * D3D11_BLEND_DESC as a key in the rbtree. */
341 memset(&tmp_desc, 0, sizeof(tmp_desc));
342 tmp_desc.AlphaToCoverageEnable = desc->AlphaToCoverageEnable;
343 tmp_desc.IndependentBlendEnable = desc->IndependentBlendEnable;
344 for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
346 j = desc->IndependentBlendEnable ? i : 0;
347 tmp_desc.RenderTarget[i].BlendEnable = desc->RenderTarget[j].BlendEnable;
348 if (tmp_desc.RenderTarget[i].BlendEnable)
350 tmp_desc.RenderTarget[i].SrcBlend = desc->RenderTarget[j].SrcBlend;
351 tmp_desc.RenderTarget[i].DestBlend = desc->RenderTarget[j].DestBlend;
352 tmp_desc.RenderTarget[i].BlendOp = desc->RenderTarget[j].BlendOp;
353 tmp_desc.RenderTarget[i].SrcBlendAlpha = desc->RenderTarget[j].SrcBlendAlpha;
354 tmp_desc.RenderTarget[i].DestBlendAlpha = desc->RenderTarget[j].DestBlendAlpha;
355 tmp_desc.RenderTarget[i].BlendOpAlpha = desc->RenderTarget[j].BlendOpAlpha;
357 else
359 tmp_desc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
360 tmp_desc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO;
361 tmp_desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
362 tmp_desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
363 tmp_desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
364 tmp_desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
366 tmp_desc.RenderTarget[i].RenderTargetWriteMask = desc->RenderTarget[j].RenderTargetWriteMask;
369 wined3d_mutex_lock();
370 if ((entry = wine_rb_get(&device->blend_states, &tmp_desc)))
372 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_blend_state, entry);
374 TRACE("Returning existing blend state %p.\n", object);
375 ID3D11BlendState_AddRef(&object->ID3D11BlendState_iface);
376 *state = object;
377 wined3d_mutex_unlock();
379 return S_OK;
382 if (!(object = heap_alloc_zero(sizeof(*object))))
384 wined3d_mutex_unlock();
385 return E_OUTOFMEMORY;
388 object->ID3D11BlendState_iface.lpVtbl = &d3d11_blend_state_vtbl;
389 object->ID3D10BlendState1_iface.lpVtbl = &d3d10_blend_state_vtbl;
390 object->refcount = 1;
391 wined3d_private_store_init(&object->private_store);
392 object->desc = tmp_desc;
394 if (wine_rb_put(&device->blend_states, &tmp_desc, &object->entry) == -1)
396 ERR("Failed to insert blend state entry.\n");
397 wined3d_private_store_cleanup(&object->private_store);
398 heap_free(object);
399 wined3d_mutex_unlock();
400 return E_FAIL;
403 wined3d_desc.alpha_to_coverage = desc->AlphaToCoverageEnable;
404 wined3d_desc.independent = desc->IndependentBlendEnable;
405 for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
407 wined3d_desc.rt[i].enable = desc->RenderTarget[i].BlendEnable;
408 wined3d_desc.rt[i].src = wined3d_blend_from_d3d11(desc->RenderTarget[i].SrcBlend);
409 wined3d_desc.rt[i].dst = wined3d_blend_from_d3d11(desc->RenderTarget[i].DestBlend);
410 wined3d_desc.rt[i].op = wined3d_blend_op_from_d3d11(desc->RenderTarget[i].BlendOp);
411 wined3d_desc.rt[i].src_alpha = wined3d_blend_from_d3d11(desc->RenderTarget[i].SrcBlendAlpha);
412 wined3d_desc.rt[i].dst_alpha = wined3d_blend_from_d3d11(desc->RenderTarget[i].DestBlendAlpha);
413 wined3d_desc.rt[i].op_alpha = wined3d_blend_op_from_d3d11(desc->RenderTarget[i].BlendOpAlpha);
414 wined3d_desc.rt[i].writemask = desc->RenderTarget[i].RenderTargetWriteMask;
417 /* We cannot fail after creating a wined3d_blend_state object. It
418 * would lead to double free. */
419 if (FAILED(hr = wined3d_blend_state_create(device->wined3d_device, &wined3d_desc,
420 object, &d3d_blend_state_wined3d_parent_ops, &object->wined3d_state)))
422 WARN("Failed to create wined3d blend state, hr %#x.\n", hr);
423 wined3d_private_store_cleanup(&object->private_store);
424 wine_rb_remove(&device->blend_states, &object->entry);
425 heap_free(object);
426 wined3d_mutex_unlock();
427 return hr;
429 wined3d_mutex_unlock();
431 ID3D11Device2_AddRef(object->device = &device->ID3D11Device2_iface);
433 TRACE("Created blend state %p.\n", object);
434 *state = object;
436 return S_OK;
439 struct d3d_blend_state *unsafe_impl_from_ID3D11BlendState(ID3D11BlendState *iface)
441 if (!iface)
442 return NULL;
443 assert(iface->lpVtbl == &d3d11_blend_state_vtbl);
445 return impl_from_ID3D11BlendState(iface);
448 struct d3d_blend_state *unsafe_impl_from_ID3D10BlendState(ID3D10BlendState *iface)
450 if (!iface)
451 return NULL;
452 assert(iface->lpVtbl == (ID3D10BlendStateVtbl *)&d3d10_blend_state_vtbl);
454 return impl_from_ID3D10BlendState((ID3D10BlendState1 *)iface);
457 /* ID3D11DepthStencilState methods */
459 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_QueryInterface(ID3D11DepthStencilState *iface,
460 REFIID riid, void **object)
462 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
464 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
466 if (IsEqualGUID(riid, &IID_ID3D11DepthStencilState)
467 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
468 || IsEqualGUID(riid, &IID_IUnknown))
470 ID3D11DepthStencilState_AddRef(iface);
471 *object = iface;
472 return S_OK;
475 if (IsEqualGUID(riid, &IID_ID3D10DepthStencilState)
476 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
478 ID3D10DepthStencilState_AddRef(&state->ID3D10DepthStencilState_iface);
479 *object = &state->ID3D10DepthStencilState_iface;
480 return S_OK;
483 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
485 *object = NULL;
486 return E_NOINTERFACE;
489 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_AddRef(ID3D11DepthStencilState *iface)
491 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
492 ULONG refcount = InterlockedIncrement(&state->refcount);
494 TRACE("%p increasing refcount to %u.\n", state, refcount);
496 if (refcount == 1)
498 ID3D11Device2_AddRef(state->device);
499 wined3d_mutex_lock();
500 wined3d_depth_stencil_state_incref(state->wined3d_state);
501 wined3d_mutex_unlock();
504 return refcount;
507 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_Release(ID3D11DepthStencilState *iface)
509 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
510 ULONG refcount = InterlockedDecrement(&state->refcount);
512 TRACE("%p decreasing refcount to %u.\n", state, refcount);
514 if (!refcount)
516 ID3D11Device2 *device = state->device;
518 wined3d_mutex_lock();
519 wined3d_depth_stencil_state_decref(state->wined3d_state);
520 wined3d_mutex_unlock();
521 ID3D11Device2_Release(device);
524 return refcount;
527 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDevice(ID3D11DepthStencilState *iface,
528 ID3D11Device **device)
530 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
532 TRACE("iface %p, device %p.\n", iface, device);
534 *device = (ID3D11Device *)state->device;
535 ID3D11Device_AddRef(*device);
538 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_GetPrivateData(ID3D11DepthStencilState *iface,
539 REFGUID guid, UINT *data_size, void *data)
541 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
543 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
545 return d3d_get_private_data(&state->private_store, guid, data_size, data);
548 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateData(ID3D11DepthStencilState *iface,
549 REFGUID guid, UINT data_size, const void *data)
551 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
553 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
555 return d3d_set_private_data(&state->private_store, guid, data_size, data);
558 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateDataInterface(ID3D11DepthStencilState *iface,
559 REFGUID guid, const IUnknown *data)
561 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
563 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
565 return d3d_set_private_data_interface(&state->private_store, guid, data);
568 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDesc(ID3D11DepthStencilState *iface,
569 D3D11_DEPTH_STENCIL_DESC *desc)
571 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
573 TRACE("iface %p, desc %p.\n", iface, desc);
575 *desc = state->desc;
578 static const struct ID3D11DepthStencilStateVtbl d3d11_depthstencil_state_vtbl =
580 /* IUnknown methods */
581 d3d11_depthstencil_state_QueryInterface,
582 d3d11_depthstencil_state_AddRef,
583 d3d11_depthstencil_state_Release,
584 /* ID3D11DeviceChild methods */
585 d3d11_depthstencil_state_GetDevice,
586 d3d11_depthstencil_state_GetPrivateData,
587 d3d11_depthstencil_state_SetPrivateData,
588 d3d11_depthstencil_state_SetPrivateDataInterface,
589 /* ID3D11DepthStencilState methods */
590 d3d11_depthstencil_state_GetDesc,
593 /* ID3D10DepthStencilState methods */
595 static inline struct d3d_depthstencil_state *impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
597 return CONTAINING_RECORD(iface, struct d3d_depthstencil_state, ID3D10DepthStencilState_iface);
600 /* IUnknown methods */
602 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_QueryInterface(ID3D10DepthStencilState *iface,
603 REFIID riid, void **object)
605 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
607 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
609 return d3d11_depthstencil_state_QueryInterface(&state->ID3D11DepthStencilState_iface, riid, object);
612 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_AddRef(ID3D10DepthStencilState *iface)
614 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
616 TRACE("iface %p.\n", iface);
618 return d3d11_depthstencil_state_AddRef(&state->ID3D11DepthStencilState_iface);
621 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_Release(ID3D10DepthStencilState *iface)
623 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
625 TRACE("iface %p.\n", iface);
627 return d3d11_depthstencil_state_Release(&state->ID3D11DepthStencilState_iface);
630 /* ID3D10DeviceChild methods */
632 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDevice(ID3D10DepthStencilState *iface, ID3D10Device **device)
634 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
636 TRACE("iface %p, device %p.\n", iface, device);
638 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
641 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_GetPrivateData(ID3D10DepthStencilState *iface,
642 REFGUID guid, UINT *data_size, void *data)
644 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
646 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
647 iface, debugstr_guid(guid), data_size, data);
649 return d3d_get_private_data(&state->private_store, guid, data_size, data);
652 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateData(ID3D10DepthStencilState *iface,
653 REFGUID guid, UINT data_size, const void *data)
655 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
657 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
658 iface, debugstr_guid(guid), data_size, data);
660 return d3d_set_private_data(&state->private_store, guid, data_size, data);
663 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateDataInterface(ID3D10DepthStencilState *iface,
664 REFGUID guid, const IUnknown *data)
666 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
668 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
670 return d3d_set_private_data_interface(&state->private_store, guid, data);
673 /* ID3D10DepthStencilState methods */
675 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDesc(ID3D10DepthStencilState *iface,
676 D3D10_DEPTH_STENCIL_DESC *desc)
678 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
680 TRACE("iface %p, desc %p.\n", iface, desc);
682 memcpy(desc, &state->desc, sizeof(*desc));
685 static const struct ID3D10DepthStencilStateVtbl d3d10_depthstencil_state_vtbl =
687 /* IUnknown methods */
688 d3d10_depthstencil_state_QueryInterface,
689 d3d10_depthstencil_state_AddRef,
690 d3d10_depthstencil_state_Release,
691 /* ID3D10DeviceChild methods */
692 d3d10_depthstencil_state_GetDevice,
693 d3d10_depthstencil_state_GetPrivateData,
694 d3d10_depthstencil_state_SetPrivateData,
695 d3d10_depthstencil_state_SetPrivateDataInterface,
696 /* ID3D10DepthStencilState methods */
697 d3d10_depthstencil_state_GetDesc,
700 static void STDMETHODCALLTYPE d3d_depthstencil_state_wined3d_object_destroyed(void *parent)
702 struct d3d_depthstencil_state *state = parent;
703 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
705 wine_rb_remove(&device->depthstencil_states, &state->entry);
706 wined3d_private_store_cleanup(&state->private_store);
707 heap_free(parent);
710 static const struct wined3d_parent_ops d3d_depthstencil_state_wined3d_parent_ops =
712 d3d_depthstencil_state_wined3d_object_destroyed,
715 HRESULT d3d_depthstencil_state_create(struct d3d_device *device, const D3D11_DEPTH_STENCIL_DESC *desc,
716 struct d3d_depthstencil_state **state)
718 struct wined3d_depth_stencil_state_desc wined3d_desc;
719 struct d3d_depthstencil_state *object;
720 D3D11_DEPTH_STENCIL_DESC tmp_desc;
721 struct wine_rb_entry *entry;
722 HRESULT hr;
724 if (!desc)
725 return E_INVALIDARG;
727 /* D3D11_DEPTH_STENCIL_DESC has a hole, which is a problem because we use
728 * it as a key in the rbtree. */
729 memset(&tmp_desc, 0, sizeof(tmp_desc));
730 tmp_desc.DepthEnable = desc->DepthEnable;
731 if (desc->DepthEnable)
733 tmp_desc.DepthWriteMask = desc->DepthWriteMask;
734 tmp_desc.DepthFunc = desc->DepthFunc;
736 else
738 tmp_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
739 tmp_desc.DepthFunc = D3D11_COMPARISON_LESS;
741 tmp_desc.StencilEnable = desc->StencilEnable;
742 if (desc->StencilEnable)
744 tmp_desc.StencilReadMask = desc->StencilReadMask;
745 tmp_desc.StencilWriteMask = desc->StencilWriteMask;
746 tmp_desc.FrontFace = desc->FrontFace;
747 tmp_desc.BackFace = desc->BackFace;
749 else
751 tmp_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
752 tmp_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
753 tmp_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
754 tmp_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
755 tmp_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
756 tmp_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
757 tmp_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
758 tmp_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
759 tmp_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
760 tmp_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
763 wined3d_mutex_lock();
764 if ((entry = wine_rb_get(&device->depthstencil_states, &tmp_desc)))
766 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_depthstencil_state, entry);
768 TRACE("Returning existing depthstencil state %p.\n", object);
769 ID3D11DepthStencilState_AddRef(&object->ID3D11DepthStencilState_iface);
770 *state = object;
771 wined3d_mutex_unlock();
773 return S_OK;
776 if (!(object = heap_alloc_zero(sizeof(*object))))
778 wined3d_mutex_unlock();
779 return E_OUTOFMEMORY;
782 object->ID3D11DepthStencilState_iface.lpVtbl = &d3d11_depthstencil_state_vtbl;
783 object->ID3D10DepthStencilState_iface.lpVtbl = &d3d10_depthstencil_state_vtbl;
784 object->refcount = 1;
785 wined3d_private_store_init(&object->private_store);
786 object->desc = tmp_desc;
788 if (wine_rb_put(&device->depthstencil_states, &tmp_desc, &object->entry) == -1)
790 ERR("Failed to insert depth/stencil state entry.\n");
791 wined3d_private_store_cleanup(&object->private_store);
792 heap_free(object);
793 wined3d_mutex_unlock();
794 return E_FAIL;
797 wined3d_desc.depth = desc->DepthEnable;
798 wined3d_desc.depth_write = desc->DepthWriteMask;
799 wined3d_desc.depth_func = desc->DepthFunc;
800 wined3d_desc.stencil = desc->StencilEnable;
801 wined3d_desc.stencil_read_mask = desc->StencilReadMask;
802 wined3d_desc.stencil_write_mask = desc->StencilWriteMask;
803 wined3d_desc.front.fail_op = desc->FrontFace.StencilFailOp;
804 wined3d_desc.front.depth_fail_op = desc->FrontFace.StencilDepthFailOp;
805 wined3d_desc.front.pass_op = desc->FrontFace.StencilPassOp;
806 wined3d_desc.front.func = desc->FrontFace.StencilFunc;
807 wined3d_desc.back.fail_op = desc->BackFace.StencilFailOp;
808 wined3d_desc.back.depth_fail_op = desc->BackFace.StencilDepthFailOp;
809 wined3d_desc.back.pass_op = desc->BackFace.StencilPassOp;
810 wined3d_desc.back.func = desc->BackFace.StencilFunc;
812 /* We cannot fail after creating a wined3d_depth_stencil_state object. It
813 * would lead to double free. */
814 if (FAILED(hr = wined3d_depth_stencil_state_create(device->wined3d_device, &wined3d_desc,
815 object, &d3d_depthstencil_state_wined3d_parent_ops, &object->wined3d_state)))
817 WARN("Failed to create wined3d depth/stencil state, hr %#x.\n", hr);
818 wined3d_private_store_cleanup(&object->private_store);
819 wine_rb_remove(&device->depthstencil_states, &object->entry);
820 heap_free(object);
821 wined3d_mutex_unlock();
822 return hr;
824 wined3d_mutex_unlock();
826 ID3D11Device2_AddRef(object->device = &device->ID3D11Device2_iface);
828 TRACE("Created depth/stencil state %p.\n", object);
829 *state = object;
831 return S_OK;
834 struct d3d_depthstencil_state *unsafe_impl_from_ID3D11DepthStencilState(ID3D11DepthStencilState *iface)
836 if (!iface)
837 return NULL;
838 assert(iface->lpVtbl == &d3d11_depthstencil_state_vtbl);
840 return impl_from_ID3D11DepthStencilState(iface);
843 struct d3d_depthstencil_state *unsafe_impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
845 if (!iface)
846 return NULL;
847 assert(iface->lpVtbl == &d3d10_depthstencil_state_vtbl);
849 return impl_from_ID3D10DepthStencilState(iface);
852 /* ID3D11RasterizerState methods */
854 static inline struct d3d_rasterizer_state *impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
856 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D11RasterizerState_iface);
859 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_QueryInterface(ID3D11RasterizerState *iface,
860 REFIID riid, void **object)
862 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
864 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
866 if (IsEqualGUID(riid, &IID_ID3D11RasterizerState)
867 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
868 || IsEqualGUID(riid, &IID_IUnknown))
870 ID3D11RasterizerState_AddRef(iface);
871 *object = iface;
872 return S_OK;
875 if (IsEqualGUID(riid, &IID_ID3D10RasterizerState)
876 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
878 ID3D10RasterizerState_AddRef(&state->ID3D10RasterizerState_iface);
879 *object = &state->ID3D10RasterizerState_iface;
880 return S_OK;
883 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
885 *object = NULL;
886 return E_NOINTERFACE;
889 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_AddRef(ID3D11RasterizerState *iface)
891 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
892 ULONG refcount = InterlockedIncrement(&state->refcount);
894 TRACE("%p increasing refcount to %u.\n", state, refcount);
896 if (refcount == 1)
898 ID3D11Device2_AddRef(state->device);
899 wined3d_mutex_lock();
900 wined3d_rasterizer_state_incref(state->wined3d_state);
901 wined3d_mutex_unlock();
904 return refcount;
907 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_Release(ID3D11RasterizerState *iface)
909 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
910 ULONG refcount = InterlockedDecrement(&state->refcount);
912 TRACE("%p decreasing refcount to %u.\n", state, refcount);
914 if (!refcount)
916 ID3D11Device2 *device = state->device;
918 wined3d_mutex_lock();
919 wined3d_rasterizer_state_decref(state->wined3d_state);
920 wined3d_mutex_unlock();
922 ID3D11Device2_Release(device);
925 return refcount;
928 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDevice(ID3D11RasterizerState *iface,
929 ID3D11Device **device)
931 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
933 TRACE("iface %p, device %p.\n", iface, device);
935 *device = (ID3D11Device *)state->device;
936 ID3D11Device_AddRef(*device);
939 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_GetPrivateData(ID3D11RasterizerState *iface,
940 REFGUID guid, UINT *data_size, void *data)
942 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
944 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
946 return d3d_get_private_data(&state->private_store, guid, data_size, data);
949 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateData(ID3D11RasterizerState *iface,
950 REFGUID guid, UINT data_size, const void *data)
952 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
954 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
956 return d3d_set_private_data(&state->private_store, guid, data_size, data);
959 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateDataInterface(ID3D11RasterizerState *iface,
960 REFGUID guid, const IUnknown *data)
962 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
964 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
966 return d3d_set_private_data_interface(&state->private_store, guid, data);
969 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDesc(ID3D11RasterizerState *iface,
970 D3D11_RASTERIZER_DESC *desc)
972 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
974 TRACE("iface %p, desc %p.\n", iface, desc);
976 *desc = state->desc;
979 static const struct ID3D11RasterizerStateVtbl d3d11_rasterizer_state_vtbl =
981 /* IUnknown methods */
982 d3d11_rasterizer_state_QueryInterface,
983 d3d11_rasterizer_state_AddRef,
984 d3d11_rasterizer_state_Release,
985 /* ID3D11DeviceChild methods */
986 d3d11_rasterizer_state_GetDevice,
987 d3d11_rasterizer_state_GetPrivateData,
988 d3d11_rasterizer_state_SetPrivateData,
989 d3d11_rasterizer_state_SetPrivateDataInterface,
990 /* ID3D11RasterizerState methods */
991 d3d11_rasterizer_state_GetDesc,
994 /* ID3D10RasterizerState methods */
996 static inline struct d3d_rasterizer_state *impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
998 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D10RasterizerState_iface);
1001 /* IUnknown methods */
1003 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_QueryInterface(ID3D10RasterizerState *iface,
1004 REFIID riid, void **object)
1006 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1008 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1010 return d3d11_rasterizer_state_QueryInterface(&state->ID3D11RasterizerState_iface, riid, object);
1013 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_AddRef(ID3D10RasterizerState *iface)
1015 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1017 TRACE("iface %p.\n", iface);
1019 return d3d11_rasterizer_state_AddRef(&state->ID3D11RasterizerState_iface);
1022 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_Release(ID3D10RasterizerState *iface)
1024 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1026 TRACE("iface %p.\n", state);
1028 return d3d11_rasterizer_state_Release(&state->ID3D11RasterizerState_iface);
1031 /* ID3D10DeviceChild methods */
1033 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDevice(ID3D10RasterizerState *iface, ID3D10Device **device)
1035 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1037 TRACE("iface %p, device %p.\n", iface, device);
1039 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
1042 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_GetPrivateData(ID3D10RasterizerState *iface,
1043 REFGUID guid, UINT *data_size, void *data)
1045 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1047 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1048 iface, debugstr_guid(guid), data_size, data);
1050 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1053 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateData(ID3D10RasterizerState *iface,
1054 REFGUID guid, UINT data_size, const void *data)
1056 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1058 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1059 iface, debugstr_guid(guid), data_size, data);
1061 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1064 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateDataInterface(ID3D10RasterizerState *iface,
1065 REFGUID guid, const IUnknown *data)
1067 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1069 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1071 return d3d_set_private_data_interface(&state->private_store, guid, data);
1074 /* ID3D10RasterizerState methods */
1076 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDesc(ID3D10RasterizerState *iface,
1077 D3D10_RASTERIZER_DESC *desc)
1079 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1081 TRACE("iface %p, desc %p.\n", iface, desc);
1083 memcpy(desc, &state->desc, sizeof(*desc));
1086 static const struct ID3D10RasterizerStateVtbl d3d10_rasterizer_state_vtbl =
1088 /* IUnknown methods */
1089 d3d10_rasterizer_state_QueryInterface,
1090 d3d10_rasterizer_state_AddRef,
1091 d3d10_rasterizer_state_Release,
1092 /* ID3D10DeviceChild methods */
1093 d3d10_rasterizer_state_GetDevice,
1094 d3d10_rasterizer_state_GetPrivateData,
1095 d3d10_rasterizer_state_SetPrivateData,
1096 d3d10_rasterizer_state_SetPrivateDataInterface,
1097 /* ID3D10RasterizerState methods */
1098 d3d10_rasterizer_state_GetDesc,
1101 static void STDMETHODCALLTYPE d3d_rasterizer_state_wined3d_object_destroyed(void *parent)
1103 struct d3d_rasterizer_state *state = parent;
1104 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
1106 wine_rb_remove(&device->rasterizer_states, &state->entry);
1107 wined3d_private_store_cleanup(&state->private_store);
1108 heap_free(parent);
1111 static const struct wined3d_parent_ops d3d_rasterizer_state_wined3d_parent_ops =
1113 d3d_rasterizer_state_wined3d_object_destroyed,
1116 static enum wined3d_fill_mode wined3d_fill_mode_from_d3d11(D3D11_FILL_MODE mode)
1118 return (enum wined3d_fill_mode)mode;
1121 static enum wined3d_cull wined3d_cull_from_d3d11(D3D11_CULL_MODE mode)
1123 return (enum wined3d_cull)mode;
1126 static HRESULT d3d_rasterizer_state_init(struct d3d_rasterizer_state *state, struct d3d_device *device,
1127 const D3D11_RASTERIZER_DESC *desc)
1129 struct wined3d_rasterizer_state_desc wined3d_desc;
1130 HRESULT hr;
1132 state->ID3D11RasterizerState_iface.lpVtbl = &d3d11_rasterizer_state_vtbl;
1133 state->ID3D10RasterizerState_iface.lpVtbl = &d3d10_rasterizer_state_vtbl;
1134 state->refcount = 1;
1135 wined3d_private_store_init(&state->private_store);
1136 state->desc = *desc;
1138 if (wine_rb_put(&device->rasterizer_states, desc, &state->entry) == -1)
1140 ERR("Failed to insert rasterizer state entry.\n");
1141 wined3d_private_store_cleanup(&state->private_store);
1142 return E_FAIL;
1145 wined3d_desc.fill_mode = wined3d_fill_mode_from_d3d11(desc->FillMode);
1146 wined3d_desc.cull_mode = wined3d_cull_from_d3d11(desc->CullMode);
1147 wined3d_desc.front_ccw = desc->FrontCounterClockwise;
1148 wined3d_desc.depth_bias = desc->DepthBias;
1149 wined3d_desc.depth_bias_clamp = desc->DepthBiasClamp;
1150 wined3d_desc.scale_bias = desc->SlopeScaledDepthBias;
1151 wined3d_desc.depth_clip = desc->DepthClipEnable;
1152 wined3d_desc.scissor = desc->ScissorEnable;
1153 wined3d_desc.line_antialias = desc->AntialiasedLineEnable;
1155 /* We cannot fail after creating a wined3d_rasterizer_state object. It
1156 * would lead to double free. */
1157 if (FAILED(hr = wined3d_rasterizer_state_create(device->wined3d_device, &wined3d_desc,
1158 state, &d3d_rasterizer_state_wined3d_parent_ops, &state->wined3d_state)))
1160 WARN("Failed to create wined3d rasterizer state, hr %#x.\n", hr);
1161 wined3d_private_store_cleanup(&state->private_store);
1162 wine_rb_remove(&device->rasterizer_states, &state->entry);
1163 return hr;
1166 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
1168 return S_OK;
1171 HRESULT d3d_rasterizer_state_create(struct d3d_device *device, const D3D11_RASTERIZER_DESC *desc,
1172 struct d3d_rasterizer_state **state)
1174 struct d3d_rasterizer_state *object;
1175 struct wine_rb_entry *entry;
1176 HRESULT hr;
1178 if (!desc)
1179 return E_INVALIDARG;
1181 wined3d_mutex_lock();
1182 if ((entry = wine_rb_get(&device->rasterizer_states, desc)))
1184 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_rasterizer_state, entry);
1186 TRACE("Returning existing rasterizer state %p.\n", object);
1187 ID3D11RasterizerState_AddRef(&object->ID3D11RasterizerState_iface);
1188 *state = object;
1189 wined3d_mutex_unlock();
1191 return S_OK;
1194 if (!(object = heap_alloc_zero(sizeof(*object))))
1196 wined3d_mutex_unlock();
1197 return E_OUTOFMEMORY;
1200 hr = d3d_rasterizer_state_init(object, device, desc);
1201 wined3d_mutex_unlock();
1202 if (FAILED(hr))
1204 WARN("Failed to initialize rasterizer state, hr %#x.\n", hr);
1205 heap_free(object);
1206 return hr;
1209 TRACE("Created rasterizer state %p.\n", object);
1210 *state = object;
1212 return S_OK;
1215 struct d3d_rasterizer_state *unsafe_impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
1217 if (!iface)
1218 return NULL;
1219 assert(iface->lpVtbl == &d3d11_rasterizer_state_vtbl);
1221 return impl_from_ID3D11RasterizerState(iface);
1224 struct d3d_rasterizer_state *unsafe_impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
1226 if (!iface)
1227 return NULL;
1228 assert(iface->lpVtbl == &d3d10_rasterizer_state_vtbl);
1230 return impl_from_ID3D10RasterizerState(iface);
1233 /* ID3D11SampleState methods */
1235 static inline struct d3d_sampler_state *impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1237 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D11SamplerState_iface);
1240 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_QueryInterface(ID3D11SamplerState *iface,
1241 REFIID riid, void **object)
1243 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1245 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1247 if (IsEqualGUID(riid, &IID_ID3D11SamplerState)
1248 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1249 || IsEqualGUID(riid, &IID_IUnknown))
1251 ID3D11SamplerState_AddRef(iface);
1252 *object = iface;
1253 return S_OK;
1256 if (IsEqualGUID(riid, &IID_ID3D10SamplerState)
1257 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1259 ID3D10SamplerState_AddRef(&state->ID3D10SamplerState_iface);
1260 *object = &state->ID3D10SamplerState_iface;
1261 return S_OK;
1264 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1266 *object = NULL;
1267 return E_NOINTERFACE;
1270 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_AddRef(ID3D11SamplerState *iface)
1272 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1273 ULONG refcount = InterlockedIncrement(&state->refcount);
1275 TRACE("%p increasing refcount to %u.\n", state, refcount);
1277 if (refcount == 1)
1279 ID3D11Device2_AddRef(state->device);
1280 wined3d_mutex_lock();
1281 wined3d_sampler_incref(state->wined3d_sampler);
1282 wined3d_mutex_unlock();
1285 return refcount;
1288 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_Release(ID3D11SamplerState *iface)
1290 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1291 ULONG refcount = InterlockedDecrement(&state->refcount);
1293 TRACE("%p decreasing refcount to %u.\n", state, refcount);
1295 if (!refcount)
1297 ID3D11Device2 *device = state->device;
1299 wined3d_mutex_lock();
1300 wined3d_sampler_decref(state->wined3d_sampler);
1301 wined3d_mutex_unlock();
1303 ID3D11Device2_Release(device);
1306 return refcount;
1309 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDevice(ID3D11SamplerState *iface,
1310 ID3D11Device **device)
1312 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1314 TRACE("iface %p, device %p.\n", iface, device);
1316 *device = (ID3D11Device *)state->device;
1317 ID3D11Device_AddRef(*device);
1320 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_GetPrivateData(ID3D11SamplerState *iface,
1321 REFGUID guid, UINT *data_size, void *data)
1323 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1325 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1327 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1330 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateData(ID3D11SamplerState *iface,
1331 REFGUID guid, UINT data_size, const void *data)
1333 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1335 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1337 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1340 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateDataInterface(ID3D11SamplerState *iface,
1341 REFGUID guid, const IUnknown *data)
1343 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1345 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1347 return d3d_set_private_data_interface(&state->private_store, guid, data);
1350 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDesc(ID3D11SamplerState *iface,
1351 D3D11_SAMPLER_DESC *desc)
1353 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1355 TRACE("iface %p, desc %p.\n", iface, desc);
1357 *desc = state->desc;
1360 static const struct ID3D11SamplerStateVtbl d3d11_sampler_state_vtbl =
1362 /* IUnknown methods */
1363 d3d11_sampler_state_QueryInterface,
1364 d3d11_sampler_state_AddRef,
1365 d3d11_sampler_state_Release,
1366 /* ID3D11DeviceChild methods */
1367 d3d11_sampler_state_GetDevice,
1368 d3d11_sampler_state_GetPrivateData,
1369 d3d11_sampler_state_SetPrivateData,
1370 d3d11_sampler_state_SetPrivateDataInterface,
1371 /* ID3D11SamplerState methods */
1372 d3d11_sampler_state_GetDesc,
1375 /* ID3D10SamplerState methods */
1377 static inline struct d3d_sampler_state *impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1379 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D10SamplerState_iface);
1382 /* IUnknown methods */
1384 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_QueryInterface(ID3D10SamplerState *iface,
1385 REFIID riid, void **object)
1387 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1389 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1391 return d3d11_sampler_state_QueryInterface(&state->ID3D11SamplerState_iface, riid, object);
1394 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_AddRef(ID3D10SamplerState *iface)
1396 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1398 TRACE("iface %p.\n", iface);
1400 return d3d11_sampler_state_AddRef(&state->ID3D11SamplerState_iface);
1403 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_Release(ID3D10SamplerState *iface)
1405 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1407 TRACE("iface %p.\n", iface);
1409 return d3d11_sampler_state_Release(&state->ID3D11SamplerState_iface);
1412 /* ID3D10DeviceChild methods */
1414 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDevice(ID3D10SamplerState *iface, ID3D10Device **device)
1416 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1418 TRACE("iface %p, device %p.\n", iface, device);
1420 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
1423 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_GetPrivateData(ID3D10SamplerState *iface,
1424 REFGUID guid, UINT *data_size, void *data)
1426 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1428 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1429 iface, debugstr_guid(guid), data_size, data);
1431 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1434 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateData(ID3D10SamplerState *iface,
1435 REFGUID guid, UINT data_size, const void *data)
1437 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1439 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1440 iface, debugstr_guid(guid), data_size, data);
1442 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1445 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateDataInterface(ID3D10SamplerState *iface,
1446 REFGUID guid, const IUnknown *data)
1448 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1450 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1452 return d3d_set_private_data_interface(&state->private_store, guid, data);
1455 /* ID3D10SamplerState methods */
1457 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDesc(ID3D10SamplerState *iface,
1458 D3D10_SAMPLER_DESC *desc)
1460 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1462 TRACE("iface %p, desc %p.\n", iface, desc);
1464 memcpy(desc, &state->desc, sizeof(*desc));
1467 static const struct ID3D10SamplerStateVtbl d3d10_sampler_state_vtbl =
1469 /* IUnknown methods */
1470 d3d10_sampler_state_QueryInterface,
1471 d3d10_sampler_state_AddRef,
1472 d3d10_sampler_state_Release,
1473 /* ID3D10DeviceChild methods */
1474 d3d10_sampler_state_GetDevice,
1475 d3d10_sampler_state_GetPrivateData,
1476 d3d10_sampler_state_SetPrivateData,
1477 d3d10_sampler_state_SetPrivateDataInterface,
1478 /* ID3D10SamplerState methods */
1479 d3d10_sampler_state_GetDesc,
1482 static void STDMETHODCALLTYPE d3d_sampler_wined3d_object_destroyed(void *parent)
1484 struct d3d_sampler_state *state = parent;
1485 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
1487 wine_rb_remove(&device->sampler_states, &state->entry);
1488 wined3d_private_store_cleanup(&state->private_store);
1489 heap_free(parent);
1492 static const struct wined3d_parent_ops d3d_sampler_wined3d_parent_ops =
1494 d3d_sampler_wined3d_object_destroyed,
1497 static enum wined3d_texture_address wined3d_texture_address_from_d3d11(enum D3D11_TEXTURE_ADDRESS_MODE t)
1499 return (enum wined3d_texture_address)t;
1502 static enum wined3d_texture_filter_type wined3d_texture_filter_mip_from_d3d11(enum D3D11_FILTER f)
1504 if (D3D11_DECODE_MIP_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1505 return WINED3D_TEXF_LINEAR;
1506 return WINED3D_TEXF_POINT;
1509 static enum wined3d_texture_filter_type wined3d_texture_filter_mag_from_d3d11(enum D3D11_FILTER f)
1511 if (D3D11_DECODE_MAG_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1512 return WINED3D_TEXF_LINEAR;
1513 return WINED3D_TEXF_POINT;
1516 static enum wined3d_texture_filter_type wined3d_texture_filter_min_from_d3d11(enum D3D11_FILTER f)
1518 if (D3D11_DECODE_MIN_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1519 return WINED3D_TEXF_LINEAR;
1520 return WINED3D_TEXF_POINT;
1523 static BOOL wined3d_texture_compare_from_d3d11(enum D3D11_FILTER f)
1525 return D3D11_DECODE_IS_COMPARISON_FILTER(f);
1528 static enum wined3d_cmp_func wined3d_cmp_func_from_d3d11(D3D11_COMPARISON_FUNC f)
1530 return (enum wined3d_cmp_func)f;
1533 static HRESULT d3d_sampler_state_init(struct d3d_sampler_state *state, struct d3d_device *device,
1534 const D3D11_SAMPLER_DESC *desc)
1536 struct wined3d_sampler_desc wined3d_desc;
1537 HRESULT hr;
1539 state->ID3D11SamplerState_iface.lpVtbl = &d3d11_sampler_state_vtbl;
1540 state->ID3D10SamplerState_iface.lpVtbl = &d3d10_sampler_state_vtbl;
1541 state->refcount = 1;
1542 wined3d_private_store_init(&state->private_store);
1543 state->desc = *desc;
1545 wined3d_desc.address_u = wined3d_texture_address_from_d3d11(desc->AddressU);
1546 wined3d_desc.address_v = wined3d_texture_address_from_d3d11(desc->AddressV);
1547 wined3d_desc.address_w = wined3d_texture_address_from_d3d11(desc->AddressW);
1548 memcpy(wined3d_desc.border_color, desc->BorderColor, sizeof(wined3d_desc.border_color));
1549 wined3d_desc.mag_filter = wined3d_texture_filter_mag_from_d3d11(desc->Filter);
1550 wined3d_desc.min_filter = wined3d_texture_filter_min_from_d3d11(desc->Filter);
1551 wined3d_desc.mip_filter = wined3d_texture_filter_mip_from_d3d11(desc->Filter);
1552 wined3d_desc.lod_bias = desc->MipLODBias;
1553 wined3d_desc.min_lod = desc->MinLOD;
1554 wined3d_desc.max_lod = max(desc->MinLOD, desc->MaxLOD);
1555 wined3d_desc.mip_base_level = 0;
1556 wined3d_desc.max_anisotropy = D3D11_DECODE_IS_ANISOTROPIC_FILTER(desc->Filter) ? desc->MaxAnisotropy : 1;
1557 wined3d_desc.compare = wined3d_texture_compare_from_d3d11(desc->Filter);
1558 wined3d_desc.comparison_func = wined3d_cmp_func_from_d3d11(desc->ComparisonFunc);
1559 wined3d_desc.srgb_decode = TRUE;
1561 if (wine_rb_put(&device->sampler_states, desc, &state->entry) == -1)
1563 ERR("Failed to insert sampler state entry.\n");
1564 wined3d_private_store_cleanup(&state->private_store);
1565 return E_FAIL;
1568 /* We cannot fail after creating a wined3d_sampler object. It would lead to
1569 * double free. */
1570 if (FAILED(hr = wined3d_sampler_create(device->wined3d_device, &wined3d_desc,
1571 state, &d3d_sampler_wined3d_parent_ops, &state->wined3d_sampler)))
1573 WARN("Failed to create wined3d sampler, hr %#x.\n", hr);
1574 wined3d_private_store_cleanup(&state->private_store);
1575 wine_rb_remove(&device->sampler_states, &state->entry);
1576 return hr;
1579 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
1581 return S_OK;
1584 HRESULT d3d_sampler_state_create(struct d3d_device *device, const D3D11_SAMPLER_DESC *desc,
1585 struct d3d_sampler_state **state)
1587 D3D11_SAMPLER_DESC normalized_desc;
1588 struct d3d_sampler_state *object;
1589 struct wine_rb_entry *entry;
1590 HRESULT hr;
1592 if (!desc)
1593 return E_INVALIDARG;
1595 normalized_desc = *desc;
1596 if (!D3D11_DECODE_IS_ANISOTROPIC_FILTER(normalized_desc.Filter))
1597 normalized_desc.MaxAnisotropy = 0;
1598 if (!D3D11_DECODE_IS_COMPARISON_FILTER(normalized_desc.Filter))
1599 normalized_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
1600 if (normalized_desc.AddressU != D3D11_TEXTURE_ADDRESS_BORDER
1601 && normalized_desc.AddressV != D3D11_TEXTURE_ADDRESS_BORDER
1602 && normalized_desc.AddressW != D3D11_TEXTURE_ADDRESS_BORDER)
1603 memset(&normalized_desc.BorderColor, 0, sizeof(normalized_desc.BorderColor));
1605 wined3d_mutex_lock();
1606 if ((entry = wine_rb_get(&device->sampler_states, &normalized_desc)))
1608 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_sampler_state, entry);
1610 TRACE("Returning existing sampler state %p.\n", object);
1611 ID3D11SamplerState_AddRef(&object->ID3D11SamplerState_iface);
1612 *state = object;
1613 wined3d_mutex_unlock();
1615 return S_OK;
1618 if (!(object = heap_alloc_zero(sizeof(*object))))
1620 wined3d_mutex_unlock();
1621 return E_OUTOFMEMORY;
1624 hr = d3d_sampler_state_init(object, device, &normalized_desc);
1625 wined3d_mutex_unlock();
1626 if (FAILED(hr))
1628 WARN("Failed to initialize sampler state, hr %#x.\n", hr);
1629 heap_free(object);
1630 return hr;
1633 TRACE("Created sampler state %p.\n", object);
1634 *state = object;
1636 return S_OK;
1639 struct d3d_sampler_state *unsafe_impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1641 if (!iface)
1642 return NULL;
1643 assert(iface->lpVtbl == &d3d11_sampler_state_vtbl);
1645 return impl_from_ID3D11SamplerState(iface);
1648 struct d3d_sampler_state *unsafe_impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1650 if (!iface)
1651 return NULL;
1652 assert(iface->lpVtbl == &d3d10_sampler_state_vtbl);
1654 return impl_from_ID3D10SamplerState(iface);