mf/tests: Test IMediaObject_GetOutputSizeInfo.
[wine.git] / dlls / d3d11 / state.c
blob4f3d9f2bc945476220967772feb1b4651e8e3a40
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 /* ID3D11BlendState1 methods */
26 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_QueryInterface(ID3D11BlendState1 *iface,
27 REFIID riid, void **object)
29 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(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_ID3D11BlendState1)
35 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
36 || IsEqualGUID(riid, &IID_IUnknown))
38 ID3D11BlendState1_AddRef(iface);
39 *object = iface;
40 return S_OK;
43 if (IsEqualGUID(riid, &IID_ID3D10BlendState1)
44 || IsEqualGUID(riid, &IID_ID3D10BlendState)
45 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
47 ID3D10BlendState1_AddRef(&state->ID3D10BlendState1_iface);
48 *object = &state->ID3D10BlendState1_iface;
49 return S_OK;
52 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
54 *object = NULL;
55 return E_NOINTERFACE;
58 static ULONG STDMETHODCALLTYPE d3d11_blend_state_AddRef(ID3D11BlendState1 *iface)
60 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(iface);
61 ULONG refcount = InterlockedIncrement(&state->refcount);
63 TRACE("%p increasing refcount to %lu.\n", state, refcount);
65 if (refcount == 1)
67 ID3D11Device2_AddRef(state->device);
68 wined3d_blend_state_incref(state->wined3d_state);
71 return refcount;
74 static ULONG STDMETHODCALLTYPE d3d11_blend_state_Release(ID3D11BlendState1 *iface)
76 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(iface);
77 ULONG refcount = InterlockedDecrement(&state->refcount);
79 TRACE("%p decreasing refcount to %lu.\n", state, refcount);
81 if (!refcount)
83 ID3D11Device2 *device = state->device;
84 wined3d_blend_state_decref(state->wined3d_state);
85 ID3D11Device2_Release(device);
88 return refcount;
91 static void STDMETHODCALLTYPE d3d11_blend_state_GetDevice(ID3D11BlendState1 *iface,
92 ID3D11Device **device)
94 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(iface);
96 TRACE("iface %p, device %p.\n", iface, device);
98 *device = (ID3D11Device *)state->device;
99 ID3D11Device_AddRef(*device);
102 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_GetPrivateData(ID3D11BlendState1 *iface,
103 REFGUID guid, UINT *data_size, void *data)
105 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(iface);
107 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
109 return d3d_get_private_data(&state->private_store, guid, data_size, data);
112 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_SetPrivateData(ID3D11BlendState1 *iface,
113 REFGUID guid, UINT data_size, const void *data)
115 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(iface);
117 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
119 return d3d_set_private_data(&state->private_store, guid, data_size, data);
122 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_SetPrivateDataInterface(ID3D11BlendState1 *iface,
123 REFGUID guid, const IUnknown *data)
125 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(iface);
127 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
129 return d3d_set_private_data_interface(&state->private_store, guid, data);
132 static void STDMETHODCALLTYPE d3d11_blend_state_GetDesc(ID3D11BlendState1 *iface, D3D11_BLEND_DESC *desc)
134 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(iface);
135 const D3D11_BLEND_DESC1 *d3d11_desc = &state->desc;
136 unsigned int i;
138 TRACE("iface %p, desc %p.\n", iface, desc);
140 desc->AlphaToCoverageEnable = d3d11_desc->AlphaToCoverageEnable;
141 desc->IndependentBlendEnable = d3d11_desc->IndependentBlendEnable;
142 for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
144 desc->RenderTarget[i].BlendEnable = d3d11_desc->RenderTarget[i].BlendEnable;
145 desc->RenderTarget[i].SrcBlend = d3d11_desc->RenderTarget[i].SrcBlend;
146 desc->RenderTarget[i].DestBlend = d3d11_desc->RenderTarget[i].DestBlend;
147 desc->RenderTarget[i].BlendOp = d3d11_desc->RenderTarget[i].BlendOp;
148 desc->RenderTarget[i].SrcBlendAlpha = d3d11_desc->RenderTarget[i].SrcBlendAlpha;
149 desc->RenderTarget[i].DestBlendAlpha = d3d11_desc->RenderTarget[i].DestBlendAlpha;
150 desc->RenderTarget[i].BlendOpAlpha = d3d11_desc->RenderTarget[i].BlendOpAlpha;
151 desc->RenderTarget[i].RenderTargetWriteMask = d3d11_desc->RenderTarget[i].RenderTargetWriteMask;
155 static void STDMETHODCALLTYPE d3d11_blend_state_GetDesc1(ID3D11BlendState1 *iface, D3D11_BLEND_DESC1 *desc)
157 struct d3d_blend_state *state = impl_from_ID3D11BlendState1(iface);
159 TRACE("iface %p, desc %p.\n", iface, desc);
161 *desc = state->desc;
164 static const struct ID3D11BlendState1Vtbl d3d11_blend_state_vtbl =
166 /* IUnknown methods */
167 d3d11_blend_state_QueryInterface,
168 d3d11_blend_state_AddRef,
169 d3d11_blend_state_Release,
170 /* ID3D11DeviceChild methods */
171 d3d11_blend_state_GetDevice,
172 d3d11_blend_state_GetPrivateData,
173 d3d11_blend_state_SetPrivateData,
174 d3d11_blend_state_SetPrivateDataInterface,
175 /* ID3D11BlendState methods */
176 d3d11_blend_state_GetDesc,
177 /* ID3D11BlendState1 methods */
178 d3d11_blend_state_GetDesc1,
181 /* ID3D10BlendState methods */
183 static inline struct d3d_blend_state *impl_from_ID3D10BlendState(ID3D10BlendState1 *iface)
185 return CONTAINING_RECORD(iface, struct d3d_blend_state, ID3D10BlendState1_iface);
188 /* IUnknown methods */
190 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_QueryInterface(ID3D10BlendState1 *iface,
191 REFIID riid, void **object)
193 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
195 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
197 return d3d11_blend_state_QueryInterface(&state->ID3D11BlendState1_iface, riid, object);
200 static ULONG STDMETHODCALLTYPE d3d10_blend_state_AddRef(ID3D10BlendState1 *iface)
202 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
204 TRACE("iface %p.\n", iface);
206 return d3d11_blend_state_AddRef(&state->ID3D11BlendState1_iface);
209 static ULONG STDMETHODCALLTYPE d3d10_blend_state_Release(ID3D10BlendState1 *iface)
211 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
213 TRACE("iface %p.\n", iface);
215 return d3d11_blend_state_Release(&state->ID3D11BlendState1_iface);
218 /* ID3D10DeviceChild methods */
220 static void STDMETHODCALLTYPE d3d10_blend_state_GetDevice(ID3D10BlendState1 *iface, ID3D10Device **device)
222 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
224 TRACE("iface %p, device %p.\n", iface, device);
226 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
229 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_GetPrivateData(ID3D10BlendState1 *iface,
230 REFGUID guid, UINT *data_size, void *data)
232 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
234 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
235 iface, debugstr_guid(guid), data_size, data);
237 return d3d_get_private_data(&state->private_store, guid, data_size, data);
240 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_SetPrivateData(ID3D10BlendState1 *iface,
241 REFGUID guid, UINT data_size, const void *data)
243 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
245 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
246 iface, debugstr_guid(guid), data_size, data);
248 return d3d_set_private_data(&state->private_store, guid, data_size, data);
251 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_SetPrivateDataInterface(ID3D10BlendState1 *iface,
252 REFGUID guid, const IUnknown *data)
254 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
256 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
258 return d3d_set_private_data_interface(&state->private_store, guid, data);
261 /* ID3D10BlendState methods */
263 static D3D10_BLEND d3d10_blend_from_d3d11(D3D11_BLEND factor)
265 return (D3D10_BLEND)factor;
268 static D3D10_BLEND_OP d3d10_blend_op_from_d3d11(D3D11_BLEND_OP op)
270 return (D3D10_BLEND_OP)op;
273 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc(ID3D10BlendState1 *iface, D3D10_BLEND_DESC *desc)
275 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
276 const D3D11_BLEND_DESC1 *d3d11_desc = &state->desc;
277 unsigned int i;
279 TRACE("iface %p, desc %p.\n", iface, desc);
281 desc->AlphaToCoverageEnable = d3d11_desc->AlphaToCoverageEnable;
282 desc->SrcBlend = d3d10_blend_from_d3d11(d3d11_desc->RenderTarget[0].SrcBlend);
283 desc->DestBlend = d3d10_blend_from_d3d11(d3d11_desc->RenderTarget[0].DestBlend);
284 desc->BlendOp = d3d10_blend_op_from_d3d11(d3d11_desc->RenderTarget[0].BlendOp);
285 desc->SrcBlendAlpha = d3d10_blend_from_d3d11(d3d11_desc->RenderTarget[0].SrcBlendAlpha);
286 desc->DestBlendAlpha = d3d10_blend_from_d3d11(d3d11_desc->RenderTarget[0].DestBlendAlpha);
287 desc->BlendOpAlpha = d3d10_blend_op_from_d3d11(d3d11_desc->RenderTarget[0].BlendOpAlpha);
288 for (i = 0; i < D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
290 desc->BlendEnable[i] = d3d11_desc->RenderTarget[i].BlendEnable;
291 desc->RenderTargetWriteMask[i] = d3d11_desc->RenderTarget[i].RenderTargetWriteMask;
295 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc1(ID3D10BlendState1 *iface, D3D10_BLEND_DESC1 *desc)
297 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
299 TRACE("iface %p, desc %p.\n", iface, desc);
301 d3d11_blend_state_GetDesc(&state->ID3D11BlendState1_iface, (D3D11_BLEND_DESC *)desc);
304 static const struct ID3D10BlendState1Vtbl d3d10_blend_state_vtbl =
306 /* IUnknown methods */
307 d3d10_blend_state_QueryInterface,
308 d3d10_blend_state_AddRef,
309 d3d10_blend_state_Release,
310 /* ID3D10DeviceChild methods */
311 d3d10_blend_state_GetDevice,
312 d3d10_blend_state_GetPrivateData,
313 d3d10_blend_state_SetPrivateData,
314 d3d10_blend_state_SetPrivateDataInterface,
315 /* ID3D10BlendState methods */
316 d3d10_blend_state_GetDesc,
317 /* ID3D10BlendState1 methods */
318 d3d10_blend_state_GetDesc1,
321 static void STDMETHODCALLTYPE d3d_blend_state_wined3d_object_destroyed(void *parent)
323 struct d3d_blend_state *state = parent;
324 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
326 wine_rb_remove(&device->blend_states, &state->entry);
327 wined3d_private_store_cleanup(&state->private_store);
328 free(parent);
331 static const struct wined3d_parent_ops d3d_blend_state_wined3d_parent_ops =
333 d3d_blend_state_wined3d_object_destroyed,
336 static enum wined3d_blend wined3d_blend_from_d3d11(D3D11_BLEND factor)
338 return (enum wined3d_blend)factor;
341 static enum wined3d_blend_op wined3d_blend_op_from_d3d11(D3D11_BLEND_OP op)
343 return (enum wined3d_blend_op)op;
346 HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC1 *desc,
347 struct d3d_blend_state **state)
349 struct wined3d_blend_state_desc wined3d_desc;
350 struct d3d_blend_state *object;
351 struct wine_rb_entry *entry;
352 D3D11_BLEND_DESC1 tmp_desc;
353 unsigned int i, j;
354 HRESULT hr;
356 if (!desc)
357 return E_INVALIDARG;
359 /* D3D11_RENDER_TARGET_BLEND_DESC1 has a hole, which is a problem because we use
360 * D3D11_BLEND_DESC1 as a key in the rbtree. */
361 memset(&tmp_desc, 0, sizeof(tmp_desc));
362 tmp_desc.AlphaToCoverageEnable = desc->AlphaToCoverageEnable;
363 tmp_desc.IndependentBlendEnable = desc->IndependentBlendEnable;
364 for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
366 j = desc->IndependentBlendEnable ? i : 0;
367 tmp_desc.RenderTarget[i].BlendEnable = desc->RenderTarget[j].BlendEnable;
368 if (tmp_desc.RenderTarget[i].BlendEnable)
370 tmp_desc.RenderTarget[i].SrcBlend = desc->RenderTarget[j].SrcBlend;
371 tmp_desc.RenderTarget[i].DestBlend = desc->RenderTarget[j].DestBlend;
372 tmp_desc.RenderTarget[i].BlendOp = desc->RenderTarget[j].BlendOp;
373 tmp_desc.RenderTarget[i].SrcBlendAlpha = desc->RenderTarget[j].SrcBlendAlpha;
374 tmp_desc.RenderTarget[i].DestBlendAlpha = desc->RenderTarget[j].DestBlendAlpha;
375 tmp_desc.RenderTarget[i].BlendOpAlpha = desc->RenderTarget[j].BlendOpAlpha;
377 else
379 tmp_desc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
380 tmp_desc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO;
381 tmp_desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
382 tmp_desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
383 tmp_desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
384 tmp_desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
387 tmp_desc.RenderTarget[i].LogicOpEnable = desc->RenderTarget[j].LogicOpEnable;
388 if (tmp_desc.RenderTarget[i].LogicOpEnable)
389 tmp_desc.RenderTarget[i].LogicOp = desc->RenderTarget[j].LogicOp;
390 else
391 tmp_desc.RenderTarget[i].LogicOp = D3D11_LOGIC_OP_NOOP;
393 tmp_desc.RenderTarget[i].RenderTargetWriteMask = desc->RenderTarget[j].RenderTargetWriteMask;
396 wined3d_mutex_lock();
397 if ((entry = wine_rb_get(&device->blend_states, &tmp_desc)))
399 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_blend_state, entry);
401 TRACE("Returning existing blend state %p.\n", object);
402 ID3D11BlendState1_AddRef(&object->ID3D11BlendState1_iface);
403 *state = object;
404 wined3d_mutex_unlock();
406 return S_OK;
409 if (!(object = calloc(1, sizeof(*object))))
411 wined3d_mutex_unlock();
412 return E_OUTOFMEMORY;
415 object->ID3D11BlendState1_iface.lpVtbl = &d3d11_blend_state_vtbl;
416 object->ID3D10BlendState1_iface.lpVtbl = &d3d10_blend_state_vtbl;
417 object->refcount = 1;
418 wined3d_private_store_init(&object->private_store);
419 object->desc = tmp_desc;
421 if (wine_rb_put(&device->blend_states, &tmp_desc, &object->entry) == -1)
423 ERR("Failed to insert blend state entry.\n");
424 wined3d_private_store_cleanup(&object->private_store);
425 free(object);
426 wined3d_mutex_unlock();
427 return E_FAIL;
430 wined3d_desc.alpha_to_coverage = desc->AlphaToCoverageEnable;
431 wined3d_desc.independent = desc->IndependentBlendEnable;
432 for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
434 wined3d_desc.rt[i].enable = desc->RenderTarget[i].BlendEnable;
435 wined3d_desc.rt[i].src = wined3d_blend_from_d3d11(desc->RenderTarget[i].SrcBlend);
436 wined3d_desc.rt[i].dst = wined3d_blend_from_d3d11(desc->RenderTarget[i].DestBlend);
437 wined3d_desc.rt[i].op = wined3d_blend_op_from_d3d11(desc->RenderTarget[i].BlendOp);
438 wined3d_desc.rt[i].src_alpha = wined3d_blend_from_d3d11(desc->RenderTarget[i].SrcBlendAlpha);
439 wined3d_desc.rt[i].dst_alpha = wined3d_blend_from_d3d11(desc->RenderTarget[i].DestBlendAlpha);
440 wined3d_desc.rt[i].op_alpha = wined3d_blend_op_from_d3d11(desc->RenderTarget[i].BlendOpAlpha);
441 wined3d_desc.rt[i].writemask = desc->RenderTarget[i].RenderTargetWriteMask;
444 if (desc->RenderTarget[0].LogicOpEnable && desc->RenderTarget[0].LogicOp != D3D11_LOGIC_OP_NOOP)
445 FIXME("Ignoring logic op %#x.\n", desc->RenderTarget[0].LogicOp);
447 /* We cannot fail after creating a wined3d_blend_state object. It
448 * would lead to double free. */
449 if (FAILED(hr = wined3d_blend_state_create(device->wined3d_device, &wined3d_desc,
450 object, &d3d_blend_state_wined3d_parent_ops, &object->wined3d_state)))
452 WARN("Failed to create wined3d blend state, hr %#lx.\n", hr);
453 wined3d_private_store_cleanup(&object->private_store);
454 wine_rb_remove(&device->blend_states, &object->entry);
455 free(object);
456 wined3d_mutex_unlock();
457 return hr;
459 wined3d_mutex_unlock();
461 ID3D11Device2_AddRef(object->device = &device->ID3D11Device2_iface);
463 TRACE("Created blend state %p.\n", object);
464 *state = object;
466 return S_OK;
469 struct d3d_blend_state *unsafe_impl_from_ID3D11BlendState(ID3D11BlendState *iface)
471 if (!iface)
472 return NULL;
473 assert(iface->lpVtbl == (ID3D11BlendStateVtbl *)&d3d11_blend_state_vtbl);
475 return impl_from_ID3D11BlendState1((ID3D11BlendState1 *)iface);
478 struct d3d_blend_state *unsafe_impl_from_ID3D10BlendState(ID3D10BlendState *iface)
480 if (!iface)
481 return NULL;
482 assert(iface->lpVtbl == (ID3D10BlendStateVtbl *)&d3d10_blend_state_vtbl);
484 return impl_from_ID3D10BlendState((ID3D10BlendState1 *)iface);
487 /* ID3D11DepthStencilState methods */
489 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_QueryInterface(ID3D11DepthStencilState *iface,
490 REFIID riid, void **object)
492 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
494 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
496 if (IsEqualGUID(riid, &IID_ID3D11DepthStencilState)
497 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
498 || IsEqualGUID(riid, &IID_IUnknown))
500 ID3D11DepthStencilState_AddRef(iface);
501 *object = iface;
502 return S_OK;
505 if (IsEqualGUID(riid, &IID_ID3D10DepthStencilState)
506 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
508 ID3D10DepthStencilState_AddRef(&state->ID3D10DepthStencilState_iface);
509 *object = &state->ID3D10DepthStencilState_iface;
510 return S_OK;
513 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
515 *object = NULL;
516 return E_NOINTERFACE;
519 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_AddRef(ID3D11DepthStencilState *iface)
521 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
522 ULONG refcount = InterlockedIncrement(&state->refcount);
524 TRACE("%p increasing refcount to %lu.\n", state, refcount);
526 if (refcount == 1)
528 ID3D11Device2_AddRef(state->device);
529 wined3d_depth_stencil_state_incref(state->wined3d_state);
532 return refcount;
535 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_Release(ID3D11DepthStencilState *iface)
537 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
538 ULONG refcount = InterlockedDecrement(&state->refcount);
540 TRACE("%p decreasing refcount to %lu.\n", state, refcount);
542 if (!refcount)
544 ID3D11Device2 *device = state->device;
546 wined3d_depth_stencil_state_decref(state->wined3d_state);
547 ID3D11Device2_Release(device);
550 return refcount;
553 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDevice(ID3D11DepthStencilState *iface,
554 ID3D11Device **device)
556 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
558 TRACE("iface %p, device %p.\n", iface, device);
560 *device = (ID3D11Device *)state->device;
561 ID3D11Device_AddRef(*device);
564 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_GetPrivateData(ID3D11DepthStencilState *iface,
565 REFGUID guid, UINT *data_size, void *data)
567 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
569 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
571 return d3d_get_private_data(&state->private_store, guid, data_size, data);
574 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateData(ID3D11DepthStencilState *iface,
575 REFGUID guid, UINT data_size, const void *data)
577 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
579 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
581 return d3d_set_private_data(&state->private_store, guid, data_size, data);
584 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateDataInterface(ID3D11DepthStencilState *iface,
585 REFGUID guid, const IUnknown *data)
587 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
589 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
591 return d3d_set_private_data_interface(&state->private_store, guid, data);
594 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDesc(ID3D11DepthStencilState *iface,
595 D3D11_DEPTH_STENCIL_DESC *desc)
597 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
599 TRACE("iface %p, desc %p.\n", iface, desc);
601 *desc = state->desc;
604 static const struct ID3D11DepthStencilStateVtbl d3d11_depthstencil_state_vtbl =
606 /* IUnknown methods */
607 d3d11_depthstencil_state_QueryInterface,
608 d3d11_depthstencil_state_AddRef,
609 d3d11_depthstencil_state_Release,
610 /* ID3D11DeviceChild methods */
611 d3d11_depthstencil_state_GetDevice,
612 d3d11_depthstencil_state_GetPrivateData,
613 d3d11_depthstencil_state_SetPrivateData,
614 d3d11_depthstencil_state_SetPrivateDataInterface,
615 /* ID3D11DepthStencilState methods */
616 d3d11_depthstencil_state_GetDesc,
619 /* ID3D10DepthStencilState methods */
621 static inline struct d3d_depthstencil_state *impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
623 return CONTAINING_RECORD(iface, struct d3d_depthstencil_state, ID3D10DepthStencilState_iface);
626 /* IUnknown methods */
628 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_QueryInterface(ID3D10DepthStencilState *iface,
629 REFIID riid, void **object)
631 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
633 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
635 return d3d11_depthstencil_state_QueryInterface(&state->ID3D11DepthStencilState_iface, riid, object);
638 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_AddRef(ID3D10DepthStencilState *iface)
640 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
642 TRACE("iface %p.\n", iface);
644 return d3d11_depthstencil_state_AddRef(&state->ID3D11DepthStencilState_iface);
647 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_Release(ID3D10DepthStencilState *iface)
649 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
651 TRACE("iface %p.\n", iface);
653 return d3d11_depthstencil_state_Release(&state->ID3D11DepthStencilState_iface);
656 /* ID3D10DeviceChild methods */
658 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDevice(ID3D10DepthStencilState *iface, ID3D10Device **device)
660 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
662 TRACE("iface %p, device %p.\n", iface, device);
664 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
667 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_GetPrivateData(ID3D10DepthStencilState *iface,
668 REFGUID guid, UINT *data_size, void *data)
670 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
672 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
673 iface, debugstr_guid(guid), data_size, data);
675 return d3d_get_private_data(&state->private_store, guid, data_size, data);
678 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateData(ID3D10DepthStencilState *iface,
679 REFGUID guid, UINT data_size, const void *data)
681 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
683 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
684 iface, debugstr_guid(guid), data_size, data);
686 return d3d_set_private_data(&state->private_store, guid, data_size, data);
689 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateDataInterface(ID3D10DepthStencilState *iface,
690 REFGUID guid, const IUnknown *data)
692 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
694 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
696 return d3d_set_private_data_interface(&state->private_store, guid, data);
699 /* ID3D10DepthStencilState methods */
701 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDesc(ID3D10DepthStencilState *iface,
702 D3D10_DEPTH_STENCIL_DESC *desc)
704 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
706 TRACE("iface %p, desc %p.\n", iface, desc);
708 memcpy(desc, &state->desc, sizeof(*desc));
711 static const struct ID3D10DepthStencilStateVtbl d3d10_depthstencil_state_vtbl =
713 /* IUnknown methods */
714 d3d10_depthstencil_state_QueryInterface,
715 d3d10_depthstencil_state_AddRef,
716 d3d10_depthstencil_state_Release,
717 /* ID3D10DeviceChild methods */
718 d3d10_depthstencil_state_GetDevice,
719 d3d10_depthstencil_state_GetPrivateData,
720 d3d10_depthstencil_state_SetPrivateData,
721 d3d10_depthstencil_state_SetPrivateDataInterface,
722 /* ID3D10DepthStencilState methods */
723 d3d10_depthstencil_state_GetDesc,
726 static void STDMETHODCALLTYPE d3d_depthstencil_state_wined3d_object_destroyed(void *parent)
728 struct d3d_depthstencil_state *state = parent;
729 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
731 wine_rb_remove(&device->depthstencil_states, &state->entry);
732 wined3d_private_store_cleanup(&state->private_store);
733 free(parent);
736 static const struct wined3d_parent_ops d3d_depthstencil_state_wined3d_parent_ops =
738 d3d_depthstencil_state_wined3d_object_destroyed,
741 static enum wined3d_cmp_func wined3d_cmp_func_from_d3d11(D3D11_COMPARISON_FUNC func)
743 return (enum wined3d_cmp_func)func;
746 static enum wined3d_stencil_op wined3d_stencil_op_from_d3d11(D3D11_STENCIL_OP stencil_op)
748 return (enum wined3d_stencil_op)stencil_op;
751 HRESULT d3d_depthstencil_state_create(struct d3d_device *device, const D3D11_DEPTH_STENCIL_DESC *desc,
752 struct d3d_depthstencil_state **state)
754 struct wined3d_depth_stencil_state_desc wined3d_desc;
755 struct d3d_depthstencil_state *object;
756 D3D11_DEPTH_STENCIL_DESC tmp_desc;
757 struct wine_rb_entry *entry;
758 HRESULT hr;
760 if (!desc)
761 return E_INVALIDARG;
763 /* D3D11_DEPTH_STENCIL_DESC has a hole, which is a problem because we use
764 * it as a key in the rbtree. */
765 memset(&tmp_desc, 0, sizeof(tmp_desc));
766 tmp_desc.DepthEnable = desc->DepthEnable;
767 if (desc->DepthEnable)
769 tmp_desc.DepthWriteMask = desc->DepthWriteMask;
770 tmp_desc.DepthFunc = desc->DepthFunc;
772 else
774 tmp_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
775 tmp_desc.DepthFunc = D3D11_COMPARISON_LESS;
777 tmp_desc.StencilEnable = desc->StencilEnable;
778 if (desc->StencilEnable)
780 tmp_desc.StencilReadMask = desc->StencilReadMask;
781 tmp_desc.StencilWriteMask = desc->StencilWriteMask;
782 tmp_desc.FrontFace = desc->FrontFace;
783 tmp_desc.BackFace = desc->BackFace;
785 else
787 tmp_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
788 tmp_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
789 tmp_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
790 tmp_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
791 tmp_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
792 tmp_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
793 tmp_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
794 tmp_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
795 tmp_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
796 tmp_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
799 wined3d_mutex_lock();
800 if ((entry = wine_rb_get(&device->depthstencil_states, &tmp_desc)))
802 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_depthstencil_state, entry);
804 TRACE("Returning existing depthstencil state %p.\n", object);
805 ID3D11DepthStencilState_AddRef(&object->ID3D11DepthStencilState_iface);
806 *state = object;
807 wined3d_mutex_unlock();
809 return S_OK;
812 if (!(object = calloc(1, sizeof(*object))))
814 wined3d_mutex_unlock();
815 return E_OUTOFMEMORY;
818 object->ID3D11DepthStencilState_iface.lpVtbl = &d3d11_depthstencil_state_vtbl;
819 object->ID3D10DepthStencilState_iface.lpVtbl = &d3d10_depthstencil_state_vtbl;
820 object->refcount = 1;
821 wined3d_private_store_init(&object->private_store);
822 object->desc = tmp_desc;
824 if (wine_rb_put(&device->depthstencil_states, &tmp_desc, &object->entry) == -1)
826 ERR("Failed to insert depth/stencil state entry.\n");
827 wined3d_private_store_cleanup(&object->private_store);
828 free(object);
829 wined3d_mutex_unlock();
830 return E_FAIL;
833 wined3d_desc.depth = desc->DepthEnable;
834 wined3d_desc.depth_write = desc->DepthWriteMask;
835 wined3d_desc.depth_func = wined3d_cmp_func_from_d3d11(desc->DepthFunc);
836 wined3d_desc.stencil = desc->StencilEnable;
837 wined3d_desc.stencil_read_mask = desc->StencilReadMask;
838 wined3d_desc.stencil_write_mask = desc->StencilWriteMask;
839 wined3d_desc.front.fail_op = wined3d_stencil_op_from_d3d11(desc->FrontFace.StencilFailOp);
840 wined3d_desc.front.depth_fail_op = wined3d_stencil_op_from_d3d11(desc->FrontFace.StencilDepthFailOp);
841 wined3d_desc.front.pass_op = wined3d_stencil_op_from_d3d11(desc->FrontFace.StencilPassOp);
842 wined3d_desc.front.func = wined3d_cmp_func_from_d3d11(desc->FrontFace.StencilFunc);
843 wined3d_desc.back.fail_op = wined3d_stencil_op_from_d3d11(desc->BackFace.StencilFailOp);
844 wined3d_desc.back.depth_fail_op = wined3d_stencil_op_from_d3d11(desc->BackFace.StencilDepthFailOp);
845 wined3d_desc.back.pass_op = wined3d_stencil_op_from_d3d11(desc->BackFace.StencilPassOp);
846 wined3d_desc.back.func = wined3d_cmp_func_from_d3d11(desc->BackFace.StencilFunc);
848 /* We cannot fail after creating a wined3d_depth_stencil_state object. It
849 * would lead to double free. */
850 if (FAILED(hr = wined3d_depth_stencil_state_create(device->wined3d_device, &wined3d_desc,
851 object, &d3d_depthstencil_state_wined3d_parent_ops, &object->wined3d_state)))
853 WARN("Failed to create wined3d depth/stencil state, hr %#lx.\n", hr);
854 wined3d_private_store_cleanup(&object->private_store);
855 wine_rb_remove(&device->depthstencil_states, &object->entry);
856 free(object);
857 wined3d_mutex_unlock();
858 return hr;
860 wined3d_mutex_unlock();
862 ID3D11Device2_AddRef(object->device = &device->ID3D11Device2_iface);
864 TRACE("Created depth/stencil state %p.\n", object);
865 *state = object;
867 return S_OK;
870 struct d3d_depthstencil_state *unsafe_impl_from_ID3D11DepthStencilState(ID3D11DepthStencilState *iface)
872 if (!iface)
873 return NULL;
874 assert(iface->lpVtbl == &d3d11_depthstencil_state_vtbl);
876 return impl_from_ID3D11DepthStencilState(iface);
879 struct d3d_depthstencil_state *unsafe_impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
881 if (!iface)
882 return NULL;
883 assert(iface->lpVtbl == &d3d10_depthstencil_state_vtbl);
885 return impl_from_ID3D10DepthStencilState(iface);
888 /* ID3D11RasterizerState methods */
890 static inline struct d3d_rasterizer_state *impl_from_ID3D11RasterizerState1(ID3D11RasterizerState1 *iface)
892 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D11RasterizerState1_iface);
895 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_QueryInterface(ID3D11RasterizerState1 *iface,
896 REFIID riid, void **object)
898 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
900 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
902 if (IsEqualGUID(riid, &IID_ID3D11RasterizerState)
903 || IsEqualGUID(riid, &IID_ID3D11RasterizerState1)
904 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
905 || IsEqualGUID(riid, &IID_IUnknown))
907 ID3D11RasterizerState1_AddRef(iface);
908 *object = iface;
909 return S_OK;
912 if (IsEqualGUID(riid, &IID_ID3D10RasterizerState)
913 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
915 ID3D10RasterizerState_AddRef(&state->ID3D10RasterizerState_iface);
916 *object = &state->ID3D10RasterizerState_iface;
917 return S_OK;
920 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
922 *object = NULL;
923 return E_NOINTERFACE;
926 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_AddRef(ID3D11RasterizerState1 *iface)
928 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
929 ULONG refcount = InterlockedIncrement(&state->refcount);
931 TRACE("%p increasing refcount to %lu.\n", state, refcount);
933 if (refcount == 1)
935 ID3D11Device2_AddRef(state->device);
936 wined3d_rasterizer_state_incref(state->wined3d_state);
939 return refcount;
942 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_Release(ID3D11RasterizerState1 *iface)
944 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
945 ULONG refcount = InterlockedDecrement(&state->refcount);
947 TRACE("%p decreasing refcount to %lu.\n", state, refcount);
949 if (!refcount)
951 ID3D11Device2 *device = state->device;
952 wined3d_rasterizer_state_decref(state->wined3d_state);
953 ID3D11Device2_Release(device);
956 return refcount;
959 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDevice(ID3D11RasterizerState1 *iface,
960 ID3D11Device **device)
962 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
964 TRACE("iface %p, device %p.\n", iface, device);
966 *device = (ID3D11Device *)state->device;
967 ID3D11Device_AddRef(*device);
970 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_GetPrivateData(ID3D11RasterizerState1 *iface,
971 REFGUID guid, UINT *data_size, void *data)
973 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
975 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
977 return d3d_get_private_data(&state->private_store, guid, data_size, data);
980 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateData(ID3D11RasterizerState1 *iface,
981 REFGUID guid, UINT data_size, const void *data)
983 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
985 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
987 return d3d_set_private_data(&state->private_store, guid, data_size, data);
990 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateDataInterface(ID3D11RasterizerState1 *iface,
991 REFGUID guid, const IUnknown *data)
993 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
995 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
997 return d3d_set_private_data_interface(&state->private_store, guid, data);
1000 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDesc(ID3D11RasterizerState1 *iface,
1001 D3D11_RASTERIZER_DESC *desc)
1003 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
1005 TRACE("iface %p, desc %p.\n", iface, desc);
1007 memcpy(desc, &state->desc, sizeof(*desc));
1010 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDesc1(ID3D11RasterizerState1 *iface,
1011 D3D11_RASTERIZER_DESC1 *desc)
1013 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState1(iface);
1015 TRACE("iface %p, desc %p.\n", iface, desc);
1017 *desc = state->desc;
1020 static const struct ID3D11RasterizerState1Vtbl d3d11_rasterizer_state_vtbl =
1022 /* IUnknown methods */
1023 d3d11_rasterizer_state_QueryInterface,
1024 d3d11_rasterizer_state_AddRef,
1025 d3d11_rasterizer_state_Release,
1026 /* ID3D11DeviceChild methods */
1027 d3d11_rasterizer_state_GetDevice,
1028 d3d11_rasterizer_state_GetPrivateData,
1029 d3d11_rasterizer_state_SetPrivateData,
1030 d3d11_rasterizer_state_SetPrivateDataInterface,
1031 /* ID3D11RasterizerState methods */
1032 d3d11_rasterizer_state_GetDesc,
1033 /* ID3D11RasterizerState1 methods */
1034 d3d11_rasterizer_state_GetDesc1,
1037 /* ID3D10RasterizerState methods */
1039 static inline struct d3d_rasterizer_state *impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
1041 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D10RasterizerState_iface);
1044 /* IUnknown methods */
1046 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_QueryInterface(ID3D10RasterizerState *iface,
1047 REFIID riid, void **object)
1049 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1051 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1053 return d3d11_rasterizer_state_QueryInterface(&state->ID3D11RasterizerState1_iface, riid, object);
1056 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_AddRef(ID3D10RasterizerState *iface)
1058 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1060 TRACE("iface %p.\n", iface);
1062 return d3d11_rasterizer_state_AddRef(&state->ID3D11RasterizerState1_iface);
1065 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_Release(ID3D10RasterizerState *iface)
1067 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1069 TRACE("iface %p.\n", state);
1071 return d3d11_rasterizer_state_Release(&state->ID3D11RasterizerState1_iface);
1074 /* ID3D10DeviceChild methods */
1076 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDevice(ID3D10RasterizerState *iface, ID3D10Device **device)
1078 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1080 TRACE("iface %p, device %p.\n", iface, device);
1082 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
1085 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_GetPrivateData(ID3D10RasterizerState *iface,
1086 REFGUID guid, UINT *data_size, void *data)
1088 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1090 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1091 iface, debugstr_guid(guid), data_size, data);
1093 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1096 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateData(ID3D10RasterizerState *iface,
1097 REFGUID guid, UINT data_size, const void *data)
1099 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1101 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1102 iface, debugstr_guid(guid), data_size, data);
1104 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1107 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateDataInterface(ID3D10RasterizerState *iface,
1108 REFGUID guid, const IUnknown *data)
1110 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1112 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1114 return d3d_set_private_data_interface(&state->private_store, guid, data);
1117 /* ID3D10RasterizerState methods */
1119 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDesc(ID3D10RasterizerState *iface,
1120 D3D10_RASTERIZER_DESC *desc)
1122 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1124 TRACE("iface %p, desc %p.\n", iface, desc);
1126 memcpy(desc, &state->desc, sizeof(*desc));
1129 static const struct ID3D10RasterizerStateVtbl d3d10_rasterizer_state_vtbl =
1131 /* IUnknown methods */
1132 d3d10_rasterizer_state_QueryInterface,
1133 d3d10_rasterizer_state_AddRef,
1134 d3d10_rasterizer_state_Release,
1135 /* ID3D10DeviceChild methods */
1136 d3d10_rasterizer_state_GetDevice,
1137 d3d10_rasterizer_state_GetPrivateData,
1138 d3d10_rasterizer_state_SetPrivateData,
1139 d3d10_rasterizer_state_SetPrivateDataInterface,
1140 /* ID3D10RasterizerState methods */
1141 d3d10_rasterizer_state_GetDesc,
1144 static void STDMETHODCALLTYPE d3d_rasterizer_state_wined3d_object_destroyed(void *parent)
1146 struct d3d_rasterizer_state *state = parent;
1147 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
1149 wine_rb_remove(&device->rasterizer_states, &state->entry);
1150 wined3d_private_store_cleanup(&state->private_store);
1151 free(parent);
1154 static const struct wined3d_parent_ops d3d_rasterizer_state_wined3d_parent_ops =
1156 d3d_rasterizer_state_wined3d_object_destroyed,
1159 static enum wined3d_fill_mode wined3d_fill_mode_from_d3d11(D3D11_FILL_MODE mode)
1161 return (enum wined3d_fill_mode)mode;
1164 static enum wined3d_cull wined3d_cull_from_d3d11(D3D11_CULL_MODE mode)
1166 return (enum wined3d_cull)mode;
1169 static HRESULT d3d_rasterizer_state_init(struct d3d_rasterizer_state *state, struct d3d_device *device,
1170 const D3D11_RASTERIZER_DESC1 *desc)
1172 struct wined3d_rasterizer_state_desc wined3d_desc;
1173 HRESULT hr;
1175 state->ID3D11RasterizerState1_iface.lpVtbl = &d3d11_rasterizer_state_vtbl;
1176 state->ID3D10RasterizerState_iface.lpVtbl = &d3d10_rasterizer_state_vtbl;
1177 state->refcount = 1;
1178 wined3d_private_store_init(&state->private_store);
1179 state->desc = *desc;
1181 if (wine_rb_put(&device->rasterizer_states, desc, &state->entry) == -1)
1183 ERR("Failed to insert rasterizer state entry.\n");
1184 wined3d_private_store_cleanup(&state->private_store);
1185 return E_FAIL;
1188 wined3d_desc.fill_mode = wined3d_fill_mode_from_d3d11(desc->FillMode);
1189 wined3d_desc.cull_mode = wined3d_cull_from_d3d11(desc->CullMode);
1190 wined3d_desc.front_ccw = desc->FrontCounterClockwise;
1191 wined3d_desc.depth_bias = desc->DepthBias;
1192 wined3d_desc.depth_bias_clamp = desc->DepthBiasClamp;
1193 wined3d_desc.scale_bias = desc->SlopeScaledDepthBias;
1194 wined3d_desc.depth_clip = desc->DepthClipEnable;
1195 wined3d_desc.scissor = desc->ScissorEnable;
1196 wined3d_desc.line_antialias = desc->AntialiasedLineEnable;
1198 if (desc->MultisampleEnable)
1200 static unsigned int once;
1201 if (!once++)
1202 FIXME("Ignoring MultisampleEnable %#x.\n", desc->MultisampleEnable);
1205 if (desc->ForcedSampleCount)
1207 static unsigned int once;
1208 if (!once++)
1209 FIXME("Ignoring ForcedSampleCount %#x.\n", desc->ForcedSampleCount);
1212 /* We cannot fail after creating a wined3d_rasterizer_state object. It
1213 * would lead to double free. */
1214 if (FAILED(hr = wined3d_rasterizer_state_create(device->wined3d_device, &wined3d_desc,
1215 state, &d3d_rasterizer_state_wined3d_parent_ops, &state->wined3d_state)))
1217 WARN("Failed to create wined3d rasteriser state, hr %#lx.\n", hr);
1218 wined3d_private_store_cleanup(&state->private_store);
1219 wine_rb_remove(&device->rasterizer_states, &state->entry);
1220 return hr;
1223 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
1225 return S_OK;
1228 HRESULT d3d_rasterizer_state_create(struct d3d_device *device, const D3D11_RASTERIZER_DESC1 *desc,
1229 struct d3d_rasterizer_state **state)
1231 struct d3d_rasterizer_state *object;
1232 struct wine_rb_entry *entry;
1233 HRESULT hr;
1235 wined3d_mutex_lock();
1236 if ((entry = wine_rb_get(&device->rasterizer_states, desc)))
1238 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_rasterizer_state, entry);
1240 TRACE("Returning existing rasterizer state %p.\n", object);
1241 ID3D11RasterizerState1_AddRef(&object->ID3D11RasterizerState1_iface);
1242 *state = object;
1243 wined3d_mutex_unlock();
1245 return S_OK;
1248 if (!(object = calloc(1, sizeof(*object))))
1250 wined3d_mutex_unlock();
1251 return E_OUTOFMEMORY;
1254 hr = d3d_rasterizer_state_init(object, device, desc);
1255 wined3d_mutex_unlock();
1256 if (FAILED(hr))
1258 WARN("Failed to initialise rasterizer state, hr %#lx.\n", hr);
1259 free(object);
1260 return hr;
1263 TRACE("Created rasterizer state %p.\n", object);
1264 *state = object;
1266 return S_OK;
1269 struct d3d_rasterizer_state *unsafe_impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
1271 if (!iface)
1272 return NULL;
1273 assert(iface->lpVtbl == (ID3D11RasterizerStateVtbl *)&d3d11_rasterizer_state_vtbl);
1275 return impl_from_ID3D11RasterizerState1((ID3D11RasterizerState1 *)iface);
1278 struct d3d_rasterizer_state *unsafe_impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
1280 if (!iface)
1281 return NULL;
1282 assert(iface->lpVtbl == &d3d10_rasterizer_state_vtbl);
1284 return impl_from_ID3D10RasterizerState(iface);
1287 /* ID3D11SampleState methods */
1289 static inline struct d3d_sampler_state *impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1291 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D11SamplerState_iface);
1294 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_QueryInterface(ID3D11SamplerState *iface,
1295 REFIID riid, void **object)
1297 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1299 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1301 if (IsEqualGUID(riid, &IID_ID3D11SamplerState)
1302 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1303 || IsEqualGUID(riid, &IID_IUnknown))
1305 ID3D11SamplerState_AddRef(iface);
1306 *object = iface;
1307 return S_OK;
1310 if (IsEqualGUID(riid, &IID_ID3D10SamplerState)
1311 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1313 ID3D10SamplerState_AddRef(&state->ID3D10SamplerState_iface);
1314 *object = &state->ID3D10SamplerState_iface;
1315 return S_OK;
1318 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1320 *object = NULL;
1321 return E_NOINTERFACE;
1324 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_AddRef(ID3D11SamplerState *iface)
1326 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1327 ULONG refcount = InterlockedIncrement(&state->refcount);
1329 TRACE("%p increasing refcount to %lu.\n", state, refcount);
1331 if (refcount == 1)
1333 ID3D11Device2_AddRef(state->device);
1334 wined3d_sampler_incref(state->wined3d_sampler);
1337 return refcount;
1340 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_Release(ID3D11SamplerState *iface)
1342 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1343 ULONG refcount = InterlockedDecrement(&state->refcount);
1345 TRACE("%p decreasing refcount to %lu.\n", state, refcount);
1347 if (!refcount)
1349 ID3D11Device2 *device = state->device;
1350 wined3d_sampler_decref(state->wined3d_sampler);
1351 ID3D11Device2_Release(device);
1354 return refcount;
1357 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDevice(ID3D11SamplerState *iface,
1358 ID3D11Device **device)
1360 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1362 TRACE("iface %p, device %p.\n", iface, device);
1364 *device = (ID3D11Device *)state->device;
1365 ID3D11Device_AddRef(*device);
1368 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_GetPrivateData(ID3D11SamplerState *iface,
1369 REFGUID guid, UINT *data_size, void *data)
1371 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1373 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1375 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1378 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateData(ID3D11SamplerState *iface,
1379 REFGUID guid, UINT data_size, const void *data)
1381 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1383 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1385 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1388 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateDataInterface(ID3D11SamplerState *iface,
1389 REFGUID guid, const IUnknown *data)
1391 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1393 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1395 return d3d_set_private_data_interface(&state->private_store, guid, data);
1398 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDesc(ID3D11SamplerState *iface,
1399 D3D11_SAMPLER_DESC *desc)
1401 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1403 TRACE("iface %p, desc %p.\n", iface, desc);
1405 *desc = state->desc;
1408 static const struct ID3D11SamplerStateVtbl d3d11_sampler_state_vtbl =
1410 /* IUnknown methods */
1411 d3d11_sampler_state_QueryInterface,
1412 d3d11_sampler_state_AddRef,
1413 d3d11_sampler_state_Release,
1414 /* ID3D11DeviceChild methods */
1415 d3d11_sampler_state_GetDevice,
1416 d3d11_sampler_state_GetPrivateData,
1417 d3d11_sampler_state_SetPrivateData,
1418 d3d11_sampler_state_SetPrivateDataInterface,
1419 /* ID3D11SamplerState methods */
1420 d3d11_sampler_state_GetDesc,
1423 /* ID3D10SamplerState methods */
1425 static inline struct d3d_sampler_state *impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1427 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D10SamplerState_iface);
1430 /* IUnknown methods */
1432 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_QueryInterface(ID3D10SamplerState *iface,
1433 REFIID riid, void **object)
1435 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1437 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1439 return d3d11_sampler_state_QueryInterface(&state->ID3D11SamplerState_iface, riid, object);
1442 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_AddRef(ID3D10SamplerState *iface)
1444 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1446 TRACE("iface %p.\n", iface);
1448 return d3d11_sampler_state_AddRef(&state->ID3D11SamplerState_iface);
1451 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_Release(ID3D10SamplerState *iface)
1453 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1455 TRACE("iface %p.\n", iface);
1457 return d3d11_sampler_state_Release(&state->ID3D11SamplerState_iface);
1460 /* ID3D10DeviceChild methods */
1462 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDevice(ID3D10SamplerState *iface, ID3D10Device **device)
1464 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1466 TRACE("iface %p, device %p.\n", iface, device);
1468 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
1471 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_GetPrivateData(ID3D10SamplerState *iface,
1472 REFGUID guid, UINT *data_size, void *data)
1474 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1476 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1477 iface, debugstr_guid(guid), data_size, data);
1479 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1482 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateData(ID3D10SamplerState *iface,
1483 REFGUID guid, UINT data_size, const void *data)
1485 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1487 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1488 iface, debugstr_guid(guid), data_size, data);
1490 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1493 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateDataInterface(ID3D10SamplerState *iface,
1494 REFGUID guid, const IUnknown *data)
1496 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1498 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1500 return d3d_set_private_data_interface(&state->private_store, guid, data);
1503 /* ID3D10SamplerState methods */
1505 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDesc(ID3D10SamplerState *iface,
1506 D3D10_SAMPLER_DESC *desc)
1508 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1510 TRACE("iface %p, desc %p.\n", iface, desc);
1512 memcpy(desc, &state->desc, sizeof(*desc));
1515 static const struct ID3D10SamplerStateVtbl d3d10_sampler_state_vtbl =
1517 /* IUnknown methods */
1518 d3d10_sampler_state_QueryInterface,
1519 d3d10_sampler_state_AddRef,
1520 d3d10_sampler_state_Release,
1521 /* ID3D10DeviceChild methods */
1522 d3d10_sampler_state_GetDevice,
1523 d3d10_sampler_state_GetPrivateData,
1524 d3d10_sampler_state_SetPrivateData,
1525 d3d10_sampler_state_SetPrivateDataInterface,
1526 /* ID3D10SamplerState methods */
1527 d3d10_sampler_state_GetDesc,
1530 static void STDMETHODCALLTYPE d3d_sampler_wined3d_object_destroyed(void *parent)
1532 struct d3d_sampler_state *state = parent;
1533 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
1535 wine_rb_remove(&device->sampler_states, &state->entry);
1536 wined3d_private_store_cleanup(&state->private_store);
1537 free(parent);
1540 static const struct wined3d_parent_ops d3d_sampler_wined3d_parent_ops =
1542 d3d_sampler_wined3d_object_destroyed,
1545 static enum wined3d_texture_address wined3d_texture_address_from_d3d11(enum D3D11_TEXTURE_ADDRESS_MODE t)
1547 return (enum wined3d_texture_address)t;
1550 static enum wined3d_texture_filter_type wined3d_texture_filter_mip_from_d3d11(enum D3D11_FILTER f)
1552 if (D3D11_DECODE_MIP_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1553 return WINED3D_TEXF_LINEAR;
1554 return WINED3D_TEXF_POINT;
1557 static enum wined3d_texture_filter_type wined3d_texture_filter_mag_from_d3d11(enum D3D11_FILTER f)
1559 if (D3D11_DECODE_MAG_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1560 return WINED3D_TEXF_LINEAR;
1561 return WINED3D_TEXF_POINT;
1564 static enum wined3d_texture_filter_type wined3d_texture_filter_min_from_d3d11(enum D3D11_FILTER f)
1566 if (D3D11_DECODE_MIN_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1567 return WINED3D_TEXF_LINEAR;
1568 return WINED3D_TEXF_POINT;
1571 static BOOL wined3d_texture_compare_from_d3d11(enum D3D11_FILTER f)
1573 return D3D11_DECODE_IS_COMPARISON_FILTER(f);
1576 static HRESULT d3d_sampler_state_init(struct d3d_sampler_state *state, struct d3d_device *device,
1577 const D3D11_SAMPLER_DESC *desc)
1579 struct wined3d_sampler_desc wined3d_desc;
1580 HRESULT hr;
1582 state->ID3D11SamplerState_iface.lpVtbl = &d3d11_sampler_state_vtbl;
1583 state->ID3D10SamplerState_iface.lpVtbl = &d3d10_sampler_state_vtbl;
1584 state->refcount = 1;
1585 wined3d_private_store_init(&state->private_store);
1586 state->desc = *desc;
1588 wined3d_desc.address_u = wined3d_texture_address_from_d3d11(desc->AddressU);
1589 wined3d_desc.address_v = wined3d_texture_address_from_d3d11(desc->AddressV);
1590 wined3d_desc.address_w = wined3d_texture_address_from_d3d11(desc->AddressW);
1591 memcpy(wined3d_desc.border_color, desc->BorderColor, sizeof(wined3d_desc.border_color));
1592 wined3d_desc.mag_filter = wined3d_texture_filter_mag_from_d3d11(desc->Filter);
1593 wined3d_desc.min_filter = wined3d_texture_filter_min_from_d3d11(desc->Filter);
1594 wined3d_desc.mip_filter = wined3d_texture_filter_mip_from_d3d11(desc->Filter);
1595 wined3d_desc.lod_bias = desc->MipLODBias;
1596 wined3d_desc.min_lod = desc->MinLOD;
1597 wined3d_desc.max_lod = max(desc->MinLOD, desc->MaxLOD);
1598 wined3d_desc.mip_base_level = 0;
1599 wined3d_desc.max_anisotropy = D3D11_DECODE_IS_ANISOTROPIC_FILTER(desc->Filter) ? desc->MaxAnisotropy : 1;
1600 wined3d_desc.compare = wined3d_texture_compare_from_d3d11(desc->Filter);
1601 wined3d_desc.comparison_func = wined3d_cmp_func_from_d3d11(desc->ComparisonFunc);
1602 wined3d_desc.srgb_decode = TRUE;
1604 if (wine_rb_put(&device->sampler_states, desc, &state->entry) == -1)
1606 ERR("Failed to insert sampler state entry.\n");
1607 wined3d_private_store_cleanup(&state->private_store);
1608 return E_FAIL;
1611 /* We cannot fail after creating a wined3d_sampler object. It would lead to
1612 * double free. */
1613 if (FAILED(hr = wined3d_sampler_create(device->wined3d_device, &wined3d_desc,
1614 state, &d3d_sampler_wined3d_parent_ops, &state->wined3d_sampler)))
1616 WARN("Failed to create wined3d sampler, hr %#lx.\n", hr);
1617 wined3d_private_store_cleanup(&state->private_store);
1618 wine_rb_remove(&device->sampler_states, &state->entry);
1619 return hr;
1622 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
1624 return S_OK;
1627 HRESULT d3d_sampler_state_create(struct d3d_device *device, const D3D11_SAMPLER_DESC *desc,
1628 struct d3d_sampler_state **state)
1630 D3D11_SAMPLER_DESC normalized_desc;
1631 struct d3d_sampler_state *object;
1632 struct wine_rb_entry *entry;
1633 HRESULT hr;
1635 if (!desc)
1636 return E_INVALIDARG;
1638 normalized_desc = *desc;
1639 if (!D3D11_DECODE_IS_ANISOTROPIC_FILTER(normalized_desc.Filter))
1640 normalized_desc.MaxAnisotropy = 0;
1641 if (!D3D11_DECODE_IS_COMPARISON_FILTER(normalized_desc.Filter))
1642 normalized_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
1643 if (normalized_desc.AddressU != D3D11_TEXTURE_ADDRESS_BORDER
1644 && normalized_desc.AddressV != D3D11_TEXTURE_ADDRESS_BORDER
1645 && normalized_desc.AddressW != D3D11_TEXTURE_ADDRESS_BORDER)
1646 memset(&normalized_desc.BorderColor, 0, sizeof(normalized_desc.BorderColor));
1648 wined3d_mutex_lock();
1649 if ((entry = wine_rb_get(&device->sampler_states, &normalized_desc)))
1651 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_sampler_state, entry);
1653 TRACE("Returning existing sampler state %p.\n", object);
1654 ID3D11SamplerState_AddRef(&object->ID3D11SamplerState_iface);
1655 *state = object;
1656 wined3d_mutex_unlock();
1658 return S_OK;
1661 if (!(object = calloc(1, sizeof(*object))))
1663 wined3d_mutex_unlock();
1664 return E_OUTOFMEMORY;
1667 hr = d3d_sampler_state_init(object, device, &normalized_desc);
1668 wined3d_mutex_unlock();
1669 if (FAILED(hr))
1671 WARN("Failed to initialise sampler state, hr %#lx.\n", hr);
1672 free(object);
1673 return hr;
1676 TRACE("Created sampler state %p.\n", object);
1677 *state = object;
1679 return S_OK;
1682 struct d3d_sampler_state *unsafe_impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1684 if (!iface)
1685 return NULL;
1686 assert(iface->lpVtbl == &d3d11_sampler_state_vtbl);
1688 return impl_from_ID3D11SamplerState(iface);
1691 struct d3d_sampler_state *unsafe_impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1693 if (!iface)
1694 return NULL;
1695 assert(iface->lpVtbl == &d3d10_sampler_state_vtbl);
1697 return impl_from_ID3D10SamplerState(iface);