wined3d: Move the blend enable state to wined3d_blend_state.
[wine.git] / dlls / d3d11 / state.c
blob269ec5eb124c266fd1bc52f8780cb67adb84b0b2
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 void STDMETHODCALLTYPE d3d10_blend_state_GetDesc(ID3D10BlendState1 *iface, D3D10_BLEND_DESC *desc)
245 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
246 const D3D11_BLEND_DESC *d3d11_desc = &state->desc;
247 unsigned int i;
249 TRACE("iface %p, desc %p.\n", iface, desc);
251 desc->AlphaToCoverageEnable = d3d11_desc->AlphaToCoverageEnable;
252 desc->SrcBlend = d3d11_desc->RenderTarget[0].SrcBlend;
253 desc->DestBlend = d3d11_desc->RenderTarget[0].DestBlend;
254 desc->BlendOp = d3d11_desc->RenderTarget[0].BlendOp;
255 desc->SrcBlendAlpha = d3d11_desc->RenderTarget[0].SrcBlendAlpha;
256 desc->DestBlendAlpha = d3d11_desc->RenderTarget[0].DestBlendAlpha;
257 desc->BlendOpAlpha = d3d11_desc->RenderTarget[0].BlendOpAlpha;
258 for (i = 0; i < D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
260 desc->BlendEnable[i] = d3d11_desc->RenderTarget[i].BlendEnable;
261 desc->RenderTargetWriteMask[i] = d3d11_desc->RenderTarget[i].RenderTargetWriteMask;
265 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc1(ID3D10BlendState1 *iface, D3D10_BLEND_DESC1 *desc)
267 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
269 TRACE("iface %p, desc %p.\n", iface, desc);
271 memcpy(desc, &state->desc, sizeof(*desc));
274 static const struct ID3D10BlendState1Vtbl d3d10_blend_state_vtbl =
276 /* IUnknown methods */
277 d3d10_blend_state_QueryInterface,
278 d3d10_blend_state_AddRef,
279 d3d10_blend_state_Release,
280 /* ID3D10DeviceChild methods */
281 d3d10_blend_state_GetDevice,
282 d3d10_blend_state_GetPrivateData,
283 d3d10_blend_state_SetPrivateData,
284 d3d10_blend_state_SetPrivateDataInterface,
285 /* ID3D10BlendState methods */
286 d3d10_blend_state_GetDesc,
287 /* ID3D10BlendState1 methods */
288 d3d10_blend_state_GetDesc1,
291 static void STDMETHODCALLTYPE d3d_blend_state_wined3d_object_destroyed(void *parent)
293 struct d3d_blend_state *state = parent;
294 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
296 wine_rb_remove(&device->blend_states, &state->entry);
297 wined3d_private_store_cleanup(&state->private_store);
298 heap_free(parent);
301 static const struct wined3d_parent_ops d3d_blend_state_wined3d_parent_ops =
303 d3d_blend_state_wined3d_object_destroyed,
306 HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC *desc,
307 struct d3d_blend_state **state)
309 struct wined3d_blend_state_desc wined3d_desc;
310 struct d3d_blend_state *object;
311 struct wine_rb_entry *entry;
312 D3D11_BLEND_DESC tmp_desc;
313 unsigned int i, j;
314 HRESULT hr;
316 if (!desc)
317 return E_INVALIDARG;
319 /* D3D11_RENDER_TARGET_BLEND_DESC has a hole, which is a problem because we use
320 * D3D11_BLEND_DESC as a key in the rbtree. */
321 memset(&tmp_desc, 0, sizeof(tmp_desc));
322 tmp_desc.AlphaToCoverageEnable = desc->AlphaToCoverageEnable;
323 tmp_desc.IndependentBlendEnable = desc->IndependentBlendEnable;
324 for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
326 j = desc->IndependentBlendEnable ? i : 0;
327 tmp_desc.RenderTarget[i].BlendEnable = desc->RenderTarget[j].BlendEnable;
328 if (tmp_desc.RenderTarget[i].BlendEnable)
330 tmp_desc.RenderTarget[i].SrcBlend = desc->RenderTarget[j].SrcBlend;
331 tmp_desc.RenderTarget[i].DestBlend = desc->RenderTarget[j].DestBlend;
332 tmp_desc.RenderTarget[i].BlendOp = desc->RenderTarget[j].BlendOp;
333 tmp_desc.RenderTarget[i].SrcBlendAlpha = desc->RenderTarget[j].SrcBlendAlpha;
334 tmp_desc.RenderTarget[i].DestBlendAlpha = desc->RenderTarget[j].DestBlendAlpha;
335 tmp_desc.RenderTarget[i].BlendOpAlpha = desc->RenderTarget[j].BlendOpAlpha;
337 else
339 tmp_desc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
340 tmp_desc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO;
341 tmp_desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
342 tmp_desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
343 tmp_desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
344 tmp_desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
346 tmp_desc.RenderTarget[i].RenderTargetWriteMask = desc->RenderTarget[j].RenderTargetWriteMask;
348 if (i > 3 && tmp_desc.RenderTarget[i].RenderTargetWriteMask != D3D11_COLOR_WRITE_ENABLE_ALL)
349 FIXME("Color mask %#x not supported for render target %u.\n",
350 tmp_desc.RenderTarget[i].RenderTargetWriteMask, i);
353 /* glEnableIndexedEXT(GL_BLEND, ...) */
354 if (tmp_desc.IndependentBlendEnable)
355 FIXME("Per-rendertarget blend not implemented.\n");
357 wined3d_mutex_lock();
358 if ((entry = wine_rb_get(&device->blend_states, &tmp_desc)))
360 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_blend_state, entry);
362 TRACE("Returning existing blend state %p.\n", object);
363 ID3D11BlendState_AddRef(&object->ID3D11BlendState_iface);
364 *state = object;
365 wined3d_mutex_unlock();
367 return S_OK;
370 if (!(object = heap_alloc_zero(sizeof(*object))))
372 wined3d_mutex_unlock();
373 return E_OUTOFMEMORY;
376 object->ID3D11BlendState_iface.lpVtbl = &d3d11_blend_state_vtbl;
377 object->ID3D10BlendState1_iface.lpVtbl = &d3d10_blend_state_vtbl;
378 object->refcount = 1;
379 wined3d_private_store_init(&object->private_store);
380 object->desc = tmp_desc;
382 if (wine_rb_put(&device->blend_states, &tmp_desc, &object->entry) == -1)
384 ERR("Failed to insert blend state entry.\n");
385 wined3d_private_store_cleanup(&object->private_store);
386 heap_free(object);
387 wined3d_mutex_unlock();
388 return E_FAIL;
391 wined3d_desc.alpha_to_coverage = desc->AlphaToCoverageEnable;
392 wined3d_desc.enable = desc->RenderTarget[0].BlendEnable;
394 /* We cannot fail after creating a wined3d_blend_state object. It
395 * would lead to double free. */
396 if (FAILED(hr = wined3d_blend_state_create(device->wined3d_device, &wined3d_desc,
397 object, &d3d_blend_state_wined3d_parent_ops, &object->wined3d_state)))
399 WARN("Failed to create wined3d blend state, hr %#x.\n", hr);
400 wined3d_private_store_cleanup(&object->private_store);
401 wine_rb_remove(&device->blend_states, &object->entry);
402 heap_free(object);
403 wined3d_mutex_unlock();
404 return hr;
406 wined3d_mutex_unlock();
408 ID3D11Device2_AddRef(object->device = &device->ID3D11Device2_iface);
410 TRACE("Created blend state %p.\n", object);
411 *state = object;
413 return S_OK;
416 struct d3d_blend_state *unsafe_impl_from_ID3D11BlendState(ID3D11BlendState *iface)
418 if (!iface)
419 return NULL;
420 assert(iface->lpVtbl == &d3d11_blend_state_vtbl);
422 return impl_from_ID3D11BlendState(iface);
425 struct d3d_blend_state *unsafe_impl_from_ID3D10BlendState(ID3D10BlendState *iface)
427 if (!iface)
428 return NULL;
429 assert(iface->lpVtbl == (ID3D10BlendStateVtbl *)&d3d10_blend_state_vtbl);
431 return impl_from_ID3D10BlendState((ID3D10BlendState1 *)iface);
434 /* ID3D11DepthStencilState methods */
436 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_QueryInterface(ID3D11DepthStencilState *iface,
437 REFIID riid, void **object)
439 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
441 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
443 if (IsEqualGUID(riid, &IID_ID3D11DepthStencilState)
444 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
445 || IsEqualGUID(riid, &IID_IUnknown))
447 ID3D11DepthStencilState_AddRef(iface);
448 *object = iface;
449 return S_OK;
452 if (IsEqualGUID(riid, &IID_ID3D10DepthStencilState)
453 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
455 ID3D10DepthStencilState_AddRef(&state->ID3D10DepthStencilState_iface);
456 *object = &state->ID3D10DepthStencilState_iface;
457 return S_OK;
460 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
462 *object = NULL;
463 return E_NOINTERFACE;
466 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_AddRef(ID3D11DepthStencilState *iface)
468 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
469 ULONG refcount = InterlockedIncrement(&state->refcount);
471 TRACE("%p increasing refcount to %u.\n", state, refcount);
473 return refcount;
476 static void d3d_depthstencil_state_cleanup(struct d3d_depthstencil_state *state)
478 wined3d_private_store_cleanup(&state->private_store);
479 ID3D11Device2_Release(state->device);
482 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_Release(ID3D11DepthStencilState *iface)
484 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
485 ULONG refcount = InterlockedDecrement(&state->refcount);
487 TRACE("%p decreasing refcount to %u.\n", state, refcount);
489 if (!refcount)
491 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
492 wined3d_mutex_lock();
493 wine_rb_remove(&device->depthstencil_states, &state->entry);
494 d3d_depthstencil_state_cleanup(state);
495 wined3d_mutex_unlock();
496 heap_free(state);
499 return refcount;
502 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDevice(ID3D11DepthStencilState *iface,
503 ID3D11Device **device)
505 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
507 TRACE("iface %p, device %p.\n", iface, device);
509 *device = (ID3D11Device *)state->device;
510 ID3D11Device_AddRef(*device);
513 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_GetPrivateData(ID3D11DepthStencilState *iface,
514 REFGUID guid, UINT *data_size, void *data)
516 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
518 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
520 return d3d_get_private_data(&state->private_store, guid, data_size, data);
523 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateData(ID3D11DepthStencilState *iface,
524 REFGUID guid, UINT data_size, const void *data)
526 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
528 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
530 return d3d_set_private_data(&state->private_store, guid, data_size, data);
533 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateDataInterface(ID3D11DepthStencilState *iface,
534 REFGUID guid, const IUnknown *data)
536 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
538 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
540 return d3d_set_private_data_interface(&state->private_store, guid, data);
543 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDesc(ID3D11DepthStencilState *iface,
544 D3D11_DEPTH_STENCIL_DESC *desc)
546 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
548 TRACE("iface %p, desc %p.\n", iface, desc);
550 *desc = state->desc;
553 static const struct ID3D11DepthStencilStateVtbl d3d11_depthstencil_state_vtbl =
555 /* IUnknown methods */
556 d3d11_depthstencil_state_QueryInterface,
557 d3d11_depthstencil_state_AddRef,
558 d3d11_depthstencil_state_Release,
559 /* ID3D11DeviceChild methods */
560 d3d11_depthstencil_state_GetDevice,
561 d3d11_depthstencil_state_GetPrivateData,
562 d3d11_depthstencil_state_SetPrivateData,
563 d3d11_depthstencil_state_SetPrivateDataInterface,
564 /* ID3D11DepthStencilState methods */
565 d3d11_depthstencil_state_GetDesc,
568 /* ID3D10DepthStencilState methods */
570 static inline struct d3d_depthstencil_state *impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
572 return CONTAINING_RECORD(iface, struct d3d_depthstencil_state, ID3D10DepthStencilState_iface);
575 /* IUnknown methods */
577 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_QueryInterface(ID3D10DepthStencilState *iface,
578 REFIID riid, void **object)
580 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
582 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
584 return d3d11_depthstencil_state_QueryInterface(&state->ID3D11DepthStencilState_iface, riid, object);
587 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_AddRef(ID3D10DepthStencilState *iface)
589 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
591 TRACE("iface %p.\n", iface);
593 return d3d11_depthstencil_state_AddRef(&state->ID3D11DepthStencilState_iface);
596 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_Release(ID3D10DepthStencilState *iface)
598 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
600 TRACE("iface %p.\n", iface);
602 return d3d11_depthstencil_state_Release(&state->ID3D11DepthStencilState_iface);
605 /* ID3D10DeviceChild methods */
607 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDevice(ID3D10DepthStencilState *iface, ID3D10Device **device)
609 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
611 TRACE("iface %p, device %p.\n", iface, device);
613 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
616 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_GetPrivateData(ID3D10DepthStencilState *iface,
617 REFGUID guid, UINT *data_size, void *data)
619 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
621 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
622 iface, debugstr_guid(guid), data_size, data);
624 return d3d_get_private_data(&state->private_store, guid, data_size, data);
627 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateData(ID3D10DepthStencilState *iface,
628 REFGUID guid, UINT data_size, const void *data)
630 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
632 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
633 iface, debugstr_guid(guid), data_size, data);
635 return d3d_set_private_data(&state->private_store, guid, data_size, data);
638 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateDataInterface(ID3D10DepthStencilState *iface,
639 REFGUID guid, const IUnknown *data)
641 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
643 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
645 return d3d_set_private_data_interface(&state->private_store, guid, data);
648 /* ID3D10DepthStencilState methods */
650 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDesc(ID3D10DepthStencilState *iface,
651 D3D10_DEPTH_STENCIL_DESC *desc)
653 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
655 TRACE("iface %p, desc %p.\n", iface, desc);
657 memcpy(desc, &state->desc, sizeof(*desc));
660 static const struct ID3D10DepthStencilStateVtbl d3d10_depthstencil_state_vtbl =
662 /* IUnknown methods */
663 d3d10_depthstencil_state_QueryInterface,
664 d3d10_depthstencil_state_AddRef,
665 d3d10_depthstencil_state_Release,
666 /* ID3D10DeviceChild methods */
667 d3d10_depthstencil_state_GetDevice,
668 d3d10_depthstencil_state_GetPrivateData,
669 d3d10_depthstencil_state_SetPrivateData,
670 d3d10_depthstencil_state_SetPrivateDataInterface,
671 /* ID3D10DepthStencilState methods */
672 d3d10_depthstencil_state_GetDesc,
675 static HRESULT d3d_depthstencil_state_init(struct d3d_depthstencil_state *state, struct d3d_device *device,
676 const D3D11_DEPTH_STENCIL_DESC *desc)
678 state->ID3D11DepthStencilState_iface.lpVtbl = &d3d11_depthstencil_state_vtbl;
679 state->ID3D10DepthStencilState_iface.lpVtbl = &d3d10_depthstencil_state_vtbl;
680 state->refcount = 1;
681 wined3d_private_store_init(&state->private_store);
682 state->desc = *desc;
684 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
686 return S_OK;
689 HRESULT d3d_depthstencil_state_create(struct d3d_device *device, const D3D11_DEPTH_STENCIL_DESC *desc,
690 struct d3d_depthstencil_state **state)
692 struct d3d_depthstencil_state *object;
693 D3D11_DEPTH_STENCIL_DESC tmp_desc;
694 struct wine_rb_entry *entry;
695 HRESULT hr;
697 if (!desc)
698 return E_INVALIDARG;
700 /* D3D11_DEPTH_STENCIL_DESC has a hole, which is a problem because we use
701 * it as a key in the rbtree. */
702 memset(&tmp_desc, 0, sizeof(tmp_desc));
703 tmp_desc.DepthEnable = desc->DepthEnable;
704 if (desc->DepthEnable)
706 tmp_desc.DepthWriteMask = desc->DepthWriteMask;
707 tmp_desc.DepthFunc = desc->DepthFunc;
709 else
711 tmp_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
712 tmp_desc.DepthFunc = D3D11_COMPARISON_LESS;
714 tmp_desc.StencilEnable = desc->StencilEnable;
715 if (desc->StencilEnable)
717 tmp_desc.StencilReadMask = desc->StencilReadMask;
718 tmp_desc.StencilWriteMask = desc->StencilWriteMask;
719 tmp_desc.FrontFace = desc->FrontFace;
720 tmp_desc.BackFace = desc->BackFace;
722 else
724 tmp_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
725 tmp_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
726 tmp_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
727 tmp_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
728 tmp_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
729 tmp_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
730 tmp_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
731 tmp_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
732 tmp_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
733 tmp_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
736 wined3d_mutex_lock();
737 if ((entry = wine_rb_get(&device->depthstencil_states, &tmp_desc)))
739 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_depthstencil_state, entry);
741 TRACE("Returning existing depthstencil state %p.\n", object);
742 ID3D11DepthStencilState_AddRef(&object->ID3D11DepthStencilState_iface);
743 *state = object;
744 wined3d_mutex_unlock();
746 return S_OK;
749 if (!(object = heap_alloc_zero(sizeof(*object))))
751 wined3d_mutex_unlock();
752 return E_OUTOFMEMORY;
755 if (FAILED(hr = d3d_depthstencil_state_init(object, device, &tmp_desc)))
757 WARN("Failed to initialize depthstencil state, hr %#x.\n", hr);
758 heap_free(object);
759 wined3d_mutex_unlock();
760 return hr;
763 if (wine_rb_put(&device->depthstencil_states, &tmp_desc, &object->entry) == -1)
765 ERR("Failed to insert depthstencil state entry.\n");
766 d3d_depthstencil_state_cleanup(object);
767 heap_free(object);
768 wined3d_mutex_unlock();
769 return E_FAIL;
771 wined3d_mutex_unlock();
773 TRACE("Created depthstencil state %p.\n", object);
774 *state = object;
776 return S_OK;
779 struct d3d_depthstencil_state *unsafe_impl_from_ID3D11DepthStencilState(ID3D11DepthStencilState *iface)
781 if (!iface)
782 return NULL;
783 assert(iface->lpVtbl == &d3d11_depthstencil_state_vtbl);
785 return impl_from_ID3D11DepthStencilState(iface);
788 struct d3d_depthstencil_state *unsafe_impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
790 if (!iface)
791 return NULL;
792 assert(iface->lpVtbl == &d3d10_depthstencil_state_vtbl);
794 return impl_from_ID3D10DepthStencilState(iface);
797 /* ID3D11RasterizerState methods */
799 static inline struct d3d_rasterizer_state *impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
801 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D11RasterizerState_iface);
804 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_QueryInterface(ID3D11RasterizerState *iface,
805 REFIID riid, void **object)
807 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
809 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
811 if (IsEqualGUID(riid, &IID_ID3D11RasterizerState)
812 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
813 || IsEqualGUID(riid, &IID_IUnknown))
815 ID3D11RasterizerState_AddRef(iface);
816 *object = iface;
817 return S_OK;
820 if (IsEqualGUID(riid, &IID_ID3D10RasterizerState)
821 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
823 ID3D10RasterizerState_AddRef(&state->ID3D10RasterizerState_iface);
824 *object = &state->ID3D10RasterizerState_iface;
825 return S_OK;
828 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
830 *object = NULL;
831 return E_NOINTERFACE;
834 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_AddRef(ID3D11RasterizerState *iface)
836 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
837 ULONG refcount = InterlockedIncrement(&state->refcount);
839 TRACE("%p increasing refcount to %u.\n", state, refcount);
841 if (refcount == 1)
843 ID3D11Device2_AddRef(state->device);
844 wined3d_mutex_lock();
845 wined3d_rasterizer_state_incref(state->wined3d_state);
846 wined3d_mutex_unlock();
849 return refcount;
852 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_Release(ID3D11RasterizerState *iface)
854 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
855 ULONG refcount = InterlockedDecrement(&state->refcount);
857 TRACE("%p decreasing refcount to %u.\n", state, refcount);
859 if (!refcount)
861 ID3D11Device2 *device = state->device;
863 wined3d_mutex_lock();
864 wined3d_rasterizer_state_decref(state->wined3d_state);
865 wined3d_mutex_unlock();
867 ID3D11Device2_Release(device);
870 return refcount;
873 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDevice(ID3D11RasterizerState *iface,
874 ID3D11Device **device)
876 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
878 TRACE("iface %p, device %p.\n", iface, device);
880 *device = (ID3D11Device *)state->device;
881 ID3D11Device_AddRef(*device);
884 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_GetPrivateData(ID3D11RasterizerState *iface,
885 REFGUID guid, UINT *data_size, void *data)
887 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
889 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
891 return d3d_get_private_data(&state->private_store, guid, data_size, data);
894 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateData(ID3D11RasterizerState *iface,
895 REFGUID guid, UINT data_size, const void *data)
897 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
899 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
901 return d3d_set_private_data(&state->private_store, guid, data_size, data);
904 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateDataInterface(ID3D11RasterizerState *iface,
905 REFGUID guid, const IUnknown *data)
907 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
909 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
911 return d3d_set_private_data_interface(&state->private_store, guid, data);
914 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDesc(ID3D11RasterizerState *iface,
915 D3D11_RASTERIZER_DESC *desc)
917 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
919 TRACE("iface %p, desc %p.\n", iface, desc);
921 *desc = state->desc;
924 static const struct ID3D11RasterizerStateVtbl d3d11_rasterizer_state_vtbl =
926 /* IUnknown methods */
927 d3d11_rasterizer_state_QueryInterface,
928 d3d11_rasterizer_state_AddRef,
929 d3d11_rasterizer_state_Release,
930 /* ID3D11DeviceChild methods */
931 d3d11_rasterizer_state_GetDevice,
932 d3d11_rasterizer_state_GetPrivateData,
933 d3d11_rasterizer_state_SetPrivateData,
934 d3d11_rasterizer_state_SetPrivateDataInterface,
935 /* ID3D11RasterizerState methods */
936 d3d11_rasterizer_state_GetDesc,
939 /* ID3D10RasterizerState methods */
941 static inline struct d3d_rasterizer_state *impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
943 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D10RasterizerState_iface);
946 /* IUnknown methods */
948 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_QueryInterface(ID3D10RasterizerState *iface,
949 REFIID riid, void **object)
951 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
953 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
955 return d3d11_rasterizer_state_QueryInterface(&state->ID3D11RasterizerState_iface, riid, object);
958 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_AddRef(ID3D10RasterizerState *iface)
960 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
962 TRACE("iface %p.\n", iface);
964 return d3d11_rasterizer_state_AddRef(&state->ID3D11RasterizerState_iface);
967 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_Release(ID3D10RasterizerState *iface)
969 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
971 TRACE("iface %p.\n", state);
973 return d3d11_rasterizer_state_Release(&state->ID3D11RasterizerState_iface);
976 /* ID3D10DeviceChild methods */
978 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDevice(ID3D10RasterizerState *iface, ID3D10Device **device)
980 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
982 TRACE("iface %p, device %p.\n", iface, device);
984 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
987 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_GetPrivateData(ID3D10RasterizerState *iface,
988 REFGUID guid, UINT *data_size, void *data)
990 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
992 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
993 iface, debugstr_guid(guid), data_size, data);
995 return d3d_get_private_data(&state->private_store, guid, data_size, data);
998 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateData(ID3D10RasterizerState *iface,
999 REFGUID guid, UINT data_size, const void *data)
1001 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1003 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1004 iface, debugstr_guid(guid), data_size, data);
1006 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1009 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateDataInterface(ID3D10RasterizerState *iface,
1010 REFGUID guid, const IUnknown *data)
1012 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1014 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1016 return d3d_set_private_data_interface(&state->private_store, guid, data);
1019 /* ID3D10RasterizerState methods */
1021 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDesc(ID3D10RasterizerState *iface,
1022 D3D10_RASTERIZER_DESC *desc)
1024 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1026 TRACE("iface %p, desc %p.\n", iface, desc);
1028 memcpy(desc, &state->desc, sizeof(*desc));
1031 static const struct ID3D10RasterizerStateVtbl d3d10_rasterizer_state_vtbl =
1033 /* IUnknown methods */
1034 d3d10_rasterizer_state_QueryInterface,
1035 d3d10_rasterizer_state_AddRef,
1036 d3d10_rasterizer_state_Release,
1037 /* ID3D10DeviceChild methods */
1038 d3d10_rasterizer_state_GetDevice,
1039 d3d10_rasterizer_state_GetPrivateData,
1040 d3d10_rasterizer_state_SetPrivateData,
1041 d3d10_rasterizer_state_SetPrivateDataInterface,
1042 /* ID3D10RasterizerState methods */
1043 d3d10_rasterizer_state_GetDesc,
1046 static void STDMETHODCALLTYPE d3d_rasterizer_state_wined3d_object_destroyed(void *parent)
1048 struct d3d_rasterizer_state *state = parent;
1049 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
1051 wine_rb_remove(&device->rasterizer_states, &state->entry);
1052 wined3d_private_store_cleanup(&state->private_store);
1053 heap_free(parent);
1056 static const struct wined3d_parent_ops d3d_rasterizer_state_wined3d_parent_ops =
1058 d3d_rasterizer_state_wined3d_object_destroyed,
1061 static HRESULT d3d_rasterizer_state_init(struct d3d_rasterizer_state *state, struct d3d_device *device,
1062 const D3D11_RASTERIZER_DESC *desc)
1064 struct wined3d_rasterizer_state_desc wined3d_desc;
1065 HRESULT hr;
1067 state->ID3D11RasterizerState_iface.lpVtbl = &d3d11_rasterizer_state_vtbl;
1068 state->ID3D10RasterizerState_iface.lpVtbl = &d3d10_rasterizer_state_vtbl;
1069 state->refcount = 1;
1070 wined3d_private_store_init(&state->private_store);
1071 state->desc = *desc;
1073 if (wine_rb_put(&device->rasterizer_states, desc, &state->entry) == -1)
1075 ERR("Failed to insert rasterizer state entry.\n");
1076 wined3d_private_store_cleanup(&state->private_store);
1077 return E_FAIL;
1080 wined3d_desc.fill_mode = desc->FillMode;
1081 wined3d_desc.cull_mode = desc->CullMode;
1082 wined3d_desc.front_ccw = desc->FrontCounterClockwise;
1083 wined3d_desc.depth_bias = desc->DepthBias;
1084 wined3d_desc.depth_bias_clamp = desc->DepthBiasClamp;
1085 wined3d_desc.scale_bias = desc->SlopeScaledDepthBias;
1086 wined3d_desc.depth_clip = desc->DepthClipEnable;
1087 wined3d_desc.scissor = desc->ScissorEnable;
1088 wined3d_desc.line_antialias = desc->AntialiasedLineEnable;
1090 /* We cannot fail after creating a wined3d_rasterizer_state object. It
1091 * would lead to double free. */
1092 if (FAILED(hr = wined3d_rasterizer_state_create(device->wined3d_device, &wined3d_desc,
1093 state, &d3d_rasterizer_state_wined3d_parent_ops, &state->wined3d_state)))
1095 WARN("Failed to create wined3d rasterizer state, hr %#x.\n", hr);
1096 wined3d_private_store_cleanup(&state->private_store);
1097 wine_rb_remove(&device->rasterizer_states, &state->entry);
1098 return hr;
1101 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
1103 return S_OK;
1106 HRESULT d3d_rasterizer_state_create(struct d3d_device *device, const D3D11_RASTERIZER_DESC *desc,
1107 struct d3d_rasterizer_state **state)
1109 struct d3d_rasterizer_state *object;
1110 struct wine_rb_entry *entry;
1111 HRESULT hr;
1113 if (!desc)
1114 return E_INVALIDARG;
1116 wined3d_mutex_lock();
1117 if ((entry = wine_rb_get(&device->rasterizer_states, desc)))
1119 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_rasterizer_state, entry);
1121 TRACE("Returning existing rasterizer state %p.\n", object);
1122 ID3D11RasterizerState_AddRef(&object->ID3D11RasterizerState_iface);
1123 *state = object;
1124 wined3d_mutex_unlock();
1126 return S_OK;
1129 if (!(object = heap_alloc_zero(sizeof(*object))))
1131 wined3d_mutex_unlock();
1132 return E_OUTOFMEMORY;
1135 hr = d3d_rasterizer_state_init(object, device, desc);
1136 wined3d_mutex_unlock();
1137 if (FAILED(hr))
1139 WARN("Failed to initialize rasterizer state, hr %#x.\n", hr);
1140 heap_free(object);
1141 return hr;
1144 TRACE("Created rasterizer state %p.\n", object);
1145 *state = object;
1147 return S_OK;
1150 struct d3d_rasterizer_state *unsafe_impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
1152 if (!iface)
1153 return NULL;
1154 assert(iface->lpVtbl == &d3d11_rasterizer_state_vtbl);
1156 return impl_from_ID3D11RasterizerState(iface);
1159 struct d3d_rasterizer_state *unsafe_impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
1161 if (!iface)
1162 return NULL;
1163 assert(iface->lpVtbl == &d3d10_rasterizer_state_vtbl);
1165 return impl_from_ID3D10RasterizerState(iface);
1168 /* ID3D11SampleState methods */
1170 static inline struct d3d_sampler_state *impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1172 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D11SamplerState_iface);
1175 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_QueryInterface(ID3D11SamplerState *iface,
1176 REFIID riid, void **object)
1178 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1180 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1182 if (IsEqualGUID(riid, &IID_ID3D11SamplerState)
1183 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1184 || IsEqualGUID(riid, &IID_IUnknown))
1186 ID3D11SamplerState_AddRef(iface);
1187 *object = iface;
1188 return S_OK;
1191 if (IsEqualGUID(riid, &IID_ID3D10SamplerState)
1192 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1194 ID3D10SamplerState_AddRef(&state->ID3D10SamplerState_iface);
1195 *object = &state->ID3D10SamplerState_iface;
1196 return S_OK;
1199 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1201 *object = NULL;
1202 return E_NOINTERFACE;
1205 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_AddRef(ID3D11SamplerState *iface)
1207 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1208 ULONG refcount = InterlockedIncrement(&state->refcount);
1210 TRACE("%p increasing refcount to %u.\n", state, refcount);
1212 if (refcount == 1)
1214 ID3D11Device2_AddRef(state->device);
1215 wined3d_mutex_lock();
1216 wined3d_sampler_incref(state->wined3d_sampler);
1217 wined3d_mutex_unlock();
1220 return refcount;
1223 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_Release(ID3D11SamplerState *iface)
1225 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1226 ULONG refcount = InterlockedDecrement(&state->refcount);
1228 TRACE("%p decreasing refcount to %u.\n", state, refcount);
1230 if (!refcount)
1232 ID3D11Device2 *device = state->device;
1234 wined3d_mutex_lock();
1235 wined3d_sampler_decref(state->wined3d_sampler);
1236 wined3d_mutex_unlock();
1238 ID3D11Device2_Release(device);
1241 return refcount;
1244 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDevice(ID3D11SamplerState *iface,
1245 ID3D11Device **device)
1247 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1249 TRACE("iface %p, device %p.\n", iface, device);
1251 *device = (ID3D11Device *)state->device;
1252 ID3D11Device_AddRef(*device);
1255 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_GetPrivateData(ID3D11SamplerState *iface,
1256 REFGUID guid, UINT *data_size, void *data)
1258 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1260 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1262 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1265 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateData(ID3D11SamplerState *iface,
1266 REFGUID guid, UINT data_size, const void *data)
1268 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1270 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1272 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1275 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateDataInterface(ID3D11SamplerState *iface,
1276 REFGUID guid, const IUnknown *data)
1278 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1280 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1282 return d3d_set_private_data_interface(&state->private_store, guid, data);
1285 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDesc(ID3D11SamplerState *iface,
1286 D3D11_SAMPLER_DESC *desc)
1288 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1290 TRACE("iface %p, desc %p.\n", iface, desc);
1292 *desc = state->desc;
1295 static const struct ID3D11SamplerStateVtbl d3d11_sampler_state_vtbl =
1297 /* IUnknown methods */
1298 d3d11_sampler_state_QueryInterface,
1299 d3d11_sampler_state_AddRef,
1300 d3d11_sampler_state_Release,
1301 /* ID3D11DeviceChild methods */
1302 d3d11_sampler_state_GetDevice,
1303 d3d11_sampler_state_GetPrivateData,
1304 d3d11_sampler_state_SetPrivateData,
1305 d3d11_sampler_state_SetPrivateDataInterface,
1306 /* ID3D11SamplerState methods */
1307 d3d11_sampler_state_GetDesc,
1310 /* ID3D10SamplerState methods */
1312 static inline struct d3d_sampler_state *impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1314 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D10SamplerState_iface);
1317 /* IUnknown methods */
1319 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_QueryInterface(ID3D10SamplerState *iface,
1320 REFIID riid, void **object)
1322 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1324 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1326 return d3d11_sampler_state_QueryInterface(&state->ID3D11SamplerState_iface, riid, object);
1329 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_AddRef(ID3D10SamplerState *iface)
1331 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1333 TRACE("iface %p.\n", iface);
1335 return d3d11_sampler_state_AddRef(&state->ID3D11SamplerState_iface);
1338 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_Release(ID3D10SamplerState *iface)
1340 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1342 TRACE("iface %p.\n", iface);
1344 return d3d11_sampler_state_Release(&state->ID3D11SamplerState_iface);
1347 /* ID3D10DeviceChild methods */
1349 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDevice(ID3D10SamplerState *iface, ID3D10Device **device)
1351 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1353 TRACE("iface %p, device %p.\n", iface, device);
1355 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
1358 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_GetPrivateData(ID3D10SamplerState *iface,
1359 REFGUID guid, UINT *data_size, void *data)
1361 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1363 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1364 iface, debugstr_guid(guid), data_size, data);
1366 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1369 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateData(ID3D10SamplerState *iface,
1370 REFGUID guid, UINT data_size, const void *data)
1372 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1374 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1375 iface, debugstr_guid(guid), data_size, data);
1377 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1380 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateDataInterface(ID3D10SamplerState *iface,
1381 REFGUID guid, const IUnknown *data)
1383 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1385 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1387 return d3d_set_private_data_interface(&state->private_store, guid, data);
1390 /* ID3D10SamplerState methods */
1392 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDesc(ID3D10SamplerState *iface,
1393 D3D10_SAMPLER_DESC *desc)
1395 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1397 TRACE("iface %p, desc %p.\n", iface, desc);
1399 memcpy(desc, &state->desc, sizeof(*desc));
1402 static const struct ID3D10SamplerStateVtbl d3d10_sampler_state_vtbl =
1404 /* IUnknown methods */
1405 d3d10_sampler_state_QueryInterface,
1406 d3d10_sampler_state_AddRef,
1407 d3d10_sampler_state_Release,
1408 /* ID3D10DeviceChild methods */
1409 d3d10_sampler_state_GetDevice,
1410 d3d10_sampler_state_GetPrivateData,
1411 d3d10_sampler_state_SetPrivateData,
1412 d3d10_sampler_state_SetPrivateDataInterface,
1413 /* ID3D10SamplerState methods */
1414 d3d10_sampler_state_GetDesc,
1417 static void STDMETHODCALLTYPE d3d_sampler_wined3d_object_destroyed(void *parent)
1419 struct d3d_sampler_state *state = parent;
1420 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
1422 wine_rb_remove(&device->sampler_states, &state->entry);
1423 wined3d_private_store_cleanup(&state->private_store);
1424 heap_free(parent);
1427 static const struct wined3d_parent_ops d3d_sampler_wined3d_parent_ops =
1429 d3d_sampler_wined3d_object_destroyed,
1432 static enum wined3d_texture_address wined3d_texture_address_from_d3d11(enum D3D11_TEXTURE_ADDRESS_MODE t)
1434 return (enum wined3d_texture_address)t;
1437 static enum wined3d_texture_filter_type wined3d_texture_filter_mip_from_d3d11(enum D3D11_FILTER f)
1439 if (D3D11_DECODE_MIP_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1440 return WINED3D_TEXF_LINEAR;
1441 return WINED3D_TEXF_POINT;
1444 static enum wined3d_texture_filter_type wined3d_texture_filter_mag_from_d3d11(enum D3D11_FILTER f)
1446 if (D3D11_DECODE_MAG_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1447 return WINED3D_TEXF_LINEAR;
1448 return WINED3D_TEXF_POINT;
1451 static enum wined3d_texture_filter_type wined3d_texture_filter_min_from_d3d11(enum D3D11_FILTER f)
1453 if (D3D11_DECODE_MIN_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1454 return WINED3D_TEXF_LINEAR;
1455 return WINED3D_TEXF_POINT;
1458 static BOOL wined3d_texture_compare_from_d3d11(enum D3D11_FILTER f)
1460 return D3D11_DECODE_IS_COMPARISON_FILTER(f);
1463 static enum wined3d_cmp_func wined3d_cmp_func_from_d3d11(D3D11_COMPARISON_FUNC f)
1465 return (enum wined3d_cmp_func)f;
1468 static HRESULT d3d_sampler_state_init(struct d3d_sampler_state *state, struct d3d_device *device,
1469 const D3D11_SAMPLER_DESC *desc)
1471 struct wined3d_sampler_desc wined3d_desc;
1472 HRESULT hr;
1474 state->ID3D11SamplerState_iface.lpVtbl = &d3d11_sampler_state_vtbl;
1475 state->ID3D10SamplerState_iface.lpVtbl = &d3d10_sampler_state_vtbl;
1476 state->refcount = 1;
1477 wined3d_private_store_init(&state->private_store);
1478 state->desc = *desc;
1480 wined3d_desc.address_u = wined3d_texture_address_from_d3d11(desc->AddressU);
1481 wined3d_desc.address_v = wined3d_texture_address_from_d3d11(desc->AddressV);
1482 wined3d_desc.address_w = wined3d_texture_address_from_d3d11(desc->AddressW);
1483 memcpy(wined3d_desc.border_color, desc->BorderColor, sizeof(wined3d_desc.border_color));
1484 wined3d_desc.mag_filter = wined3d_texture_filter_mag_from_d3d11(desc->Filter);
1485 wined3d_desc.min_filter = wined3d_texture_filter_min_from_d3d11(desc->Filter);
1486 wined3d_desc.mip_filter = wined3d_texture_filter_mip_from_d3d11(desc->Filter);
1487 wined3d_desc.lod_bias = desc->MipLODBias;
1488 wined3d_desc.min_lod = desc->MinLOD;
1489 wined3d_desc.max_lod = desc->MaxLOD;
1490 wined3d_desc.mip_base_level = 0;
1491 wined3d_desc.max_anisotropy = D3D11_DECODE_IS_ANISOTROPIC_FILTER(desc->Filter) ? desc->MaxAnisotropy : 1;
1492 wined3d_desc.compare = wined3d_texture_compare_from_d3d11(desc->Filter);
1493 wined3d_desc.comparison_func = wined3d_cmp_func_from_d3d11(desc->ComparisonFunc);
1494 wined3d_desc.srgb_decode = TRUE;
1496 if (wine_rb_put(&device->sampler_states, desc, &state->entry) == -1)
1498 ERR("Failed to insert sampler state entry.\n");
1499 wined3d_private_store_cleanup(&state->private_store);
1500 return E_FAIL;
1503 /* We cannot fail after creating a wined3d_sampler object. It would lead to
1504 * double free. */
1505 if (FAILED(hr = wined3d_sampler_create(device->wined3d_device, &wined3d_desc,
1506 state, &d3d_sampler_wined3d_parent_ops, &state->wined3d_sampler)))
1508 WARN("Failed to create wined3d sampler, hr %#x.\n", hr);
1509 wined3d_private_store_cleanup(&state->private_store);
1510 wine_rb_remove(&device->sampler_states, &state->entry);
1511 return hr;
1514 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
1516 return S_OK;
1519 HRESULT d3d_sampler_state_create(struct d3d_device *device, const D3D11_SAMPLER_DESC *desc,
1520 struct d3d_sampler_state **state)
1522 D3D11_SAMPLER_DESC normalized_desc;
1523 struct d3d_sampler_state *object;
1524 struct wine_rb_entry *entry;
1525 HRESULT hr;
1527 if (!desc)
1528 return E_INVALIDARG;
1530 normalized_desc = *desc;
1531 if (!D3D11_DECODE_IS_ANISOTROPIC_FILTER(normalized_desc.Filter))
1532 normalized_desc.MaxAnisotropy = 0;
1533 if (!D3D11_DECODE_IS_COMPARISON_FILTER(normalized_desc.Filter))
1534 normalized_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
1535 if (normalized_desc.AddressU != D3D11_TEXTURE_ADDRESS_BORDER
1536 && normalized_desc.AddressV != D3D11_TEXTURE_ADDRESS_BORDER
1537 && normalized_desc.AddressW != D3D11_TEXTURE_ADDRESS_BORDER)
1538 memset(&normalized_desc.BorderColor, 0, sizeof(normalized_desc.BorderColor));
1540 wined3d_mutex_lock();
1541 if ((entry = wine_rb_get(&device->sampler_states, &normalized_desc)))
1543 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_sampler_state, entry);
1545 TRACE("Returning existing sampler state %p.\n", object);
1546 ID3D11SamplerState_AddRef(&object->ID3D11SamplerState_iface);
1547 *state = object;
1548 wined3d_mutex_unlock();
1550 return S_OK;
1553 if (!(object = heap_alloc_zero(sizeof(*object))))
1555 wined3d_mutex_unlock();
1556 return E_OUTOFMEMORY;
1559 hr = d3d_sampler_state_init(object, device, &normalized_desc);
1560 wined3d_mutex_unlock();
1561 if (FAILED(hr))
1563 WARN("Failed to initialize sampler state, hr %#x.\n", hr);
1564 heap_free(object);
1565 return hr;
1568 TRACE("Created sampler state %p.\n", object);
1569 *state = object;
1571 return S_OK;
1574 struct d3d_sampler_state *unsafe_impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1576 if (!iface)
1577 return NULL;
1578 assert(iface->lpVtbl == &d3d11_sampler_state_vtbl);
1580 return impl_from_ID3D11SamplerState(iface);
1583 struct d3d_sampler_state *unsafe_impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1585 if (!iface)
1586 return NULL;
1587 assert(iface->lpVtbl == &d3d10_sampler_state_vtbl);
1589 return impl_from_ID3D10SamplerState(iface);