makefiles: Add support for a generic SOURCES variable.
[wine.git] / dlls / d3d11 / state.c
bloba14c9d3cb40deaeb6ca176fc6a104d2a1effae30
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 "config.h"
21 #include "wine/port.h"
23 #include "d3d11_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
27 /* ID3D11BlendState methods */
29 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_QueryInterface(ID3D11BlendState *iface,
30 REFIID riid, void **object)
32 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
34 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
36 if (IsEqualGUID(riid, &IID_ID3D11BlendState)
37 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
38 || IsEqualGUID(riid, &IID_IUnknown))
40 ID3D11BlendState_AddRef(iface);
41 *object = iface;
42 return S_OK;
45 if (IsEqualGUID(riid, &IID_ID3D10BlendState1)
46 || IsEqualGUID(riid, &IID_ID3D10BlendState)
47 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
49 ID3D10BlendState1_AddRef(&state->ID3D10BlendState1_iface);
50 *object = &state->ID3D10BlendState1_iface;
51 return S_OK;
54 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
56 *object = NULL;
57 return E_NOINTERFACE;
60 static ULONG STDMETHODCALLTYPE d3d11_blend_state_AddRef(ID3D11BlendState *iface)
62 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
63 ULONG refcount = InterlockedIncrement(&state->refcount);
65 TRACE("%p increasing refcount to %u.\n", state, refcount);
67 if (refcount == 1)
69 ID3D11Device_AddRef(state->device);
70 wined3d_mutex_lock();
71 wined3d_blend_state_incref(state->wined3d_state);
72 wined3d_mutex_unlock();
75 return refcount;
78 static ULONG STDMETHODCALLTYPE d3d11_blend_state_Release(ID3D11BlendState *iface)
80 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
81 ULONG refcount = InterlockedDecrement(&state->refcount);
83 TRACE("%p decreasing refcount to %u.\n", state, refcount);
85 if (!refcount)
87 ID3D11Device *device = state->device;
89 wined3d_mutex_lock();
90 wined3d_blend_state_decref(state->wined3d_state);
91 wined3d_mutex_unlock();
93 ID3D11Device_Release(device);
96 return refcount;
99 static void STDMETHODCALLTYPE d3d11_blend_state_GetDevice(ID3D11BlendState *iface,
100 ID3D11Device **device)
102 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
104 TRACE("iface %p, device %p.\n", iface, device);
106 *device = state->device;
107 ID3D11Device_AddRef(*device);
110 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_GetPrivateData(ID3D11BlendState *iface,
111 REFGUID guid, UINT *data_size, void *data)
113 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
115 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
117 return d3d_get_private_data(&state->private_store, guid, data_size, data);
120 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_SetPrivateData(ID3D11BlendState *iface,
121 REFGUID guid, UINT data_size, const void *data)
123 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
125 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
127 return d3d_set_private_data(&state->private_store, guid, data_size, data);
130 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_SetPrivateDataInterface(ID3D11BlendState *iface,
131 REFGUID guid, const IUnknown *data)
133 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
135 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
137 return d3d_set_private_data_interface(&state->private_store, guid, data);
140 static void STDMETHODCALLTYPE d3d11_blend_state_GetDesc(ID3D11BlendState *iface, D3D11_BLEND_DESC *desc)
142 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
144 TRACE("iface %p, desc %p.\n", iface, desc);
146 *desc = state->desc;
149 static const struct ID3D11BlendStateVtbl d3d11_blend_state_vtbl =
151 /* IUnknown methods */
152 d3d11_blend_state_QueryInterface,
153 d3d11_blend_state_AddRef,
154 d3d11_blend_state_Release,
155 /* ID3D11DeviceChild methods */
156 d3d11_blend_state_GetDevice,
157 d3d11_blend_state_GetPrivateData,
158 d3d11_blend_state_SetPrivateData,
159 d3d11_blend_state_SetPrivateDataInterface,
160 /* ID3D11BlendState methods */
161 d3d11_blend_state_GetDesc,
164 /* ID3D10BlendState methods */
166 static inline struct d3d_blend_state *impl_from_ID3D10BlendState(ID3D10BlendState1 *iface)
168 return CONTAINING_RECORD(iface, struct d3d_blend_state, ID3D10BlendState1_iface);
171 /* IUnknown methods */
173 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_QueryInterface(ID3D10BlendState1 *iface,
174 REFIID riid, void **object)
176 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
178 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
180 return d3d11_blend_state_QueryInterface(&state->ID3D11BlendState_iface, riid, object);
183 static ULONG STDMETHODCALLTYPE d3d10_blend_state_AddRef(ID3D10BlendState1 *iface)
185 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
187 TRACE("iface %p.\n", iface);
189 return d3d11_blend_state_AddRef(&state->ID3D11BlendState_iface);
192 static ULONG STDMETHODCALLTYPE d3d10_blend_state_Release(ID3D10BlendState1 *iface)
194 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
196 TRACE("iface %p.\n", iface);
198 return d3d11_blend_state_Release(&state->ID3D11BlendState_iface);
201 /* ID3D10DeviceChild methods */
203 static void STDMETHODCALLTYPE d3d10_blend_state_GetDevice(ID3D10BlendState1 *iface, ID3D10Device **device)
205 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
207 TRACE("iface %p, device %p.\n", iface, device);
209 ID3D11Device_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
212 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_GetPrivateData(ID3D10BlendState1 *iface,
213 REFGUID guid, UINT *data_size, void *data)
215 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
217 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
218 iface, debugstr_guid(guid), data_size, data);
220 return d3d_get_private_data(&state->private_store, guid, data_size, data);
223 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_SetPrivateData(ID3D10BlendState1 *iface,
224 REFGUID guid, UINT data_size, const void *data)
226 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
228 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
229 iface, debugstr_guid(guid), data_size, data);
231 return d3d_set_private_data(&state->private_store, guid, data_size, data);
234 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_SetPrivateDataInterface(ID3D10BlendState1 *iface,
235 REFGUID guid, const IUnknown *data)
237 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
239 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
241 return d3d_set_private_data_interface(&state->private_store, guid, data);
244 /* ID3D10BlendState methods */
246 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc(ID3D10BlendState1 *iface, D3D10_BLEND_DESC *desc)
248 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
249 const D3D11_BLEND_DESC *d3d11_desc = &state->desc;
250 unsigned int i;
252 TRACE("iface %p, desc %p.\n", iface, desc);
254 desc->AlphaToCoverageEnable = d3d11_desc->AlphaToCoverageEnable;
255 desc->SrcBlend = d3d11_desc->RenderTarget[0].SrcBlend;
256 desc->DestBlend = d3d11_desc->RenderTarget[0].DestBlend;
257 desc->BlendOp = d3d11_desc->RenderTarget[0].BlendOp;
258 desc->SrcBlendAlpha = d3d11_desc->RenderTarget[0].SrcBlendAlpha;
259 desc->DestBlendAlpha = d3d11_desc->RenderTarget[0].DestBlendAlpha;
260 desc->BlendOpAlpha = d3d11_desc->RenderTarget[0].BlendOpAlpha;
261 for (i = 0; i < D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
263 desc->BlendEnable[i] = d3d11_desc->RenderTarget[i].BlendEnable;
264 desc->RenderTargetWriteMask[i] = d3d11_desc->RenderTarget[i].RenderTargetWriteMask;
268 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc1(ID3D10BlendState1 *iface, D3D10_BLEND_DESC1 *desc)
270 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
272 TRACE("iface %p, desc %p.\n", iface, desc);
274 memcpy(desc, &state->desc, sizeof(*desc));
277 static const struct ID3D10BlendState1Vtbl d3d10_blend_state_vtbl =
279 /* IUnknown methods */
280 d3d10_blend_state_QueryInterface,
281 d3d10_blend_state_AddRef,
282 d3d10_blend_state_Release,
283 /* ID3D10DeviceChild methods */
284 d3d10_blend_state_GetDevice,
285 d3d10_blend_state_GetPrivateData,
286 d3d10_blend_state_SetPrivateData,
287 d3d10_blend_state_SetPrivateDataInterface,
288 /* ID3D10BlendState methods */
289 d3d10_blend_state_GetDesc,
290 /* ID3D10BlendState1 methods */
291 d3d10_blend_state_GetDesc1,
294 static void STDMETHODCALLTYPE d3d_blend_state_wined3d_object_destroyed(void *parent)
296 struct d3d_blend_state *state = parent;
297 struct d3d_device *device = impl_from_ID3D11Device(state->device);
299 wine_rb_remove(&device->blend_states, &state->entry);
300 wined3d_private_store_cleanup(&state->private_store);
301 heap_free(parent);
304 static const struct wined3d_parent_ops d3d_blend_state_wined3d_parent_ops =
306 d3d_blend_state_wined3d_object_destroyed,
309 HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC *desc,
310 struct d3d_blend_state **state)
312 struct wined3d_blend_state_desc wined3d_desc;
313 struct d3d_blend_state *object;
314 struct wine_rb_entry *entry;
315 D3D11_BLEND_DESC tmp_desc;
316 unsigned int i, j;
317 HRESULT hr;
319 if (!desc)
320 return E_INVALIDARG;
322 /* D3D11_RENDER_TARGET_BLEND_DESC has a hole, which is a problem because we use
323 * D3D11_BLEND_DESC as a key in the rbtree. */
324 memset(&tmp_desc, 0, sizeof(tmp_desc));
325 tmp_desc.AlphaToCoverageEnable = desc->AlphaToCoverageEnable;
326 tmp_desc.IndependentBlendEnable = desc->IndependentBlendEnable;
327 for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
329 j = desc->IndependentBlendEnable ? i : 0;
330 tmp_desc.RenderTarget[i].BlendEnable = desc->RenderTarget[j].BlendEnable;
331 tmp_desc.RenderTarget[i].SrcBlend = desc->RenderTarget[j].SrcBlend;
332 tmp_desc.RenderTarget[i].DestBlend = desc->RenderTarget[j].DestBlend;
333 tmp_desc.RenderTarget[i].BlendOp = desc->RenderTarget[j].BlendOp;
334 tmp_desc.RenderTarget[i].SrcBlendAlpha = desc->RenderTarget[j].SrcBlendAlpha;
335 tmp_desc.RenderTarget[i].DestBlendAlpha = desc->RenderTarget[j].DestBlendAlpha;
336 tmp_desc.RenderTarget[i].BlendOpAlpha = desc->RenderTarget[j].BlendOpAlpha;
337 tmp_desc.RenderTarget[i].RenderTargetWriteMask = desc->RenderTarget[j].RenderTargetWriteMask;
339 if (i > 3 && tmp_desc.RenderTarget[i].RenderTargetWriteMask != D3D11_COLOR_WRITE_ENABLE_ALL)
340 FIXME("Color mask %#x not supported for render target %u.\n",
341 tmp_desc.RenderTarget[i].RenderTargetWriteMask, i);
344 /* glEnableIndexedEXT(GL_BLEND, ...) */
345 if (tmp_desc.IndependentBlendEnable)
346 FIXME("Per-rendertarget blend not implemented.\n");
348 wined3d_mutex_lock();
349 if ((entry = wine_rb_get(&device->blend_states, &tmp_desc)))
351 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_blend_state, entry);
353 TRACE("Returning existing blend state %p.\n", object);
354 ID3D11BlendState_AddRef(&object->ID3D11BlendState_iface);
355 *state = object;
356 wined3d_mutex_unlock();
358 return S_OK;
361 if (!(object = heap_alloc_zero(sizeof(*object))))
363 wined3d_mutex_unlock();
364 return E_OUTOFMEMORY;
367 object->ID3D11BlendState_iface.lpVtbl = &d3d11_blend_state_vtbl;
368 object->ID3D10BlendState1_iface.lpVtbl = &d3d10_blend_state_vtbl;
369 object->refcount = 1;
370 wined3d_private_store_init(&object->private_store);
371 object->desc = tmp_desc;
373 if (wine_rb_put(&device->blend_states, &tmp_desc, &object->entry) == -1)
375 ERR("Failed to insert blend state entry.\n");
376 wined3d_private_store_cleanup(&object->private_store);
377 heap_free(object);
378 wined3d_mutex_unlock();
379 return E_FAIL;
382 wined3d_desc.alpha_to_coverage = desc->AlphaToCoverageEnable;
384 /* We cannot fail after creating a wined3d_blend_state object. It
385 * would lead to double free. */
386 if (FAILED(hr = wined3d_blend_state_create(device->wined3d_device, &wined3d_desc,
387 object, &d3d_blend_state_wined3d_parent_ops, &object->wined3d_state)))
389 WARN("Failed to create wined3d blend state, hr %#x.\n", hr);
390 wined3d_private_store_cleanup(&object->private_store);
391 wine_rb_remove(&device->blend_states, &object->entry);
392 heap_free(object);
393 wined3d_mutex_unlock();
394 return hr;
396 wined3d_mutex_unlock();
398 ID3D11Device_AddRef(object->device = &device->ID3D11Device_iface);
400 TRACE("Created blend state %p.\n", object);
401 *state = object;
403 return S_OK;
406 struct d3d_blend_state *unsafe_impl_from_ID3D11BlendState(ID3D11BlendState *iface)
408 if (!iface)
409 return NULL;
410 assert(iface->lpVtbl == &d3d11_blend_state_vtbl);
412 return impl_from_ID3D11BlendState(iface);
415 struct d3d_blend_state *unsafe_impl_from_ID3D10BlendState(ID3D10BlendState *iface)
417 if (!iface)
418 return NULL;
419 assert(iface->lpVtbl == (ID3D10BlendStateVtbl *)&d3d10_blend_state_vtbl);
421 return impl_from_ID3D10BlendState((ID3D10BlendState1 *)iface);
424 /* ID3D11DepthStencilState methods */
426 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_QueryInterface(ID3D11DepthStencilState *iface,
427 REFIID riid, void **object)
429 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
431 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
433 if (IsEqualGUID(riid, &IID_ID3D11DepthStencilState)
434 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
435 || IsEqualGUID(riid, &IID_IUnknown))
437 ID3D11DepthStencilState_AddRef(iface);
438 *object = iface;
439 return S_OK;
442 if (IsEqualGUID(riid, &IID_ID3D10DepthStencilState)
443 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
445 ID3D10DepthStencilState_AddRef(&state->ID3D10DepthStencilState_iface);
446 *object = &state->ID3D10DepthStencilState_iface;
447 return S_OK;
450 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
452 *object = NULL;
453 return E_NOINTERFACE;
456 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_AddRef(ID3D11DepthStencilState *iface)
458 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
459 ULONG refcount = InterlockedIncrement(&state->refcount);
461 TRACE("%p increasing refcount to %u.\n", state, refcount);
463 return refcount;
466 static void d3d_depthstencil_state_cleanup(struct d3d_depthstencil_state *state)
468 wined3d_private_store_cleanup(&state->private_store);
469 ID3D11Device_Release(state->device);
472 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_Release(ID3D11DepthStencilState *iface)
474 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
475 ULONG refcount = InterlockedDecrement(&state->refcount);
477 TRACE("%p decreasing refcount to %u.\n", state, refcount);
479 if (!refcount)
481 struct d3d_device *device = impl_from_ID3D11Device(state->device);
482 wined3d_mutex_lock();
483 wine_rb_remove(&device->depthstencil_states, &state->entry);
484 d3d_depthstencil_state_cleanup(state);
485 wined3d_mutex_unlock();
486 heap_free(state);
489 return refcount;
492 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDevice(ID3D11DepthStencilState *iface,
493 ID3D11Device **device)
495 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
497 TRACE("iface %p, device %p.\n", iface, device);
499 *device = state->device;
500 ID3D11Device_AddRef(*device);
503 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_GetPrivateData(ID3D11DepthStencilState *iface,
504 REFGUID guid, UINT *data_size, void *data)
506 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
508 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
510 return d3d_get_private_data(&state->private_store, guid, data_size, data);
513 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateData(ID3D11DepthStencilState *iface,
514 REFGUID guid, UINT data_size, const void *data)
516 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
518 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
520 return d3d_set_private_data(&state->private_store, guid, data_size, data);
523 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateDataInterface(ID3D11DepthStencilState *iface,
524 REFGUID guid, const IUnknown *data)
526 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
528 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
530 return d3d_set_private_data_interface(&state->private_store, guid, data);
533 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDesc(ID3D11DepthStencilState *iface,
534 D3D11_DEPTH_STENCIL_DESC *desc)
536 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
538 TRACE("iface %p, desc %p.\n", iface, desc);
540 *desc = state->desc;
543 static const struct ID3D11DepthStencilStateVtbl d3d11_depthstencil_state_vtbl =
545 /* IUnknown methods */
546 d3d11_depthstencil_state_QueryInterface,
547 d3d11_depthstencil_state_AddRef,
548 d3d11_depthstencil_state_Release,
549 /* ID3D11DeviceChild methods */
550 d3d11_depthstencil_state_GetDevice,
551 d3d11_depthstencil_state_GetPrivateData,
552 d3d11_depthstencil_state_SetPrivateData,
553 d3d11_depthstencil_state_SetPrivateDataInterface,
554 /* ID3D11DepthStencilState methods */
555 d3d11_depthstencil_state_GetDesc,
558 /* ID3D10DepthStencilState methods */
560 static inline struct d3d_depthstencil_state *impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
562 return CONTAINING_RECORD(iface, struct d3d_depthstencil_state, ID3D10DepthStencilState_iface);
565 /* IUnknown methods */
567 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_QueryInterface(ID3D10DepthStencilState *iface,
568 REFIID riid, void **object)
570 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
572 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
574 return d3d11_depthstencil_state_QueryInterface(&state->ID3D11DepthStencilState_iface, riid, object);
577 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_AddRef(ID3D10DepthStencilState *iface)
579 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
581 TRACE("iface %p.\n", iface);
583 return d3d11_depthstencil_state_AddRef(&state->ID3D11DepthStencilState_iface);
586 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_Release(ID3D10DepthStencilState *iface)
588 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
590 TRACE("iface %p.\n", iface);
592 return d3d11_depthstencil_state_Release(&state->ID3D11DepthStencilState_iface);
595 /* ID3D10DeviceChild methods */
597 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDevice(ID3D10DepthStencilState *iface, ID3D10Device **device)
599 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
601 TRACE("iface %p, device %p.\n", iface, device);
603 ID3D11Device_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
606 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_GetPrivateData(ID3D10DepthStencilState *iface,
607 REFGUID guid, UINT *data_size, void *data)
609 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
611 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
612 iface, debugstr_guid(guid), data_size, data);
614 return d3d_get_private_data(&state->private_store, guid, data_size, data);
617 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateData(ID3D10DepthStencilState *iface,
618 REFGUID guid, UINT data_size, const void *data)
620 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
622 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
623 iface, debugstr_guid(guid), data_size, data);
625 return d3d_set_private_data(&state->private_store, guid, data_size, data);
628 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateDataInterface(ID3D10DepthStencilState *iface,
629 REFGUID guid, const IUnknown *data)
631 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
633 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
635 return d3d_set_private_data_interface(&state->private_store, guid, data);
638 /* ID3D10DepthStencilState methods */
640 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDesc(ID3D10DepthStencilState *iface,
641 D3D10_DEPTH_STENCIL_DESC *desc)
643 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
645 TRACE("iface %p, desc %p.\n", iface, desc);
647 memcpy(desc, &state->desc, sizeof(*desc));
650 static const struct ID3D10DepthStencilStateVtbl d3d10_depthstencil_state_vtbl =
652 /* IUnknown methods */
653 d3d10_depthstencil_state_QueryInterface,
654 d3d10_depthstencil_state_AddRef,
655 d3d10_depthstencil_state_Release,
656 /* ID3D10DeviceChild methods */
657 d3d10_depthstencil_state_GetDevice,
658 d3d10_depthstencil_state_GetPrivateData,
659 d3d10_depthstencil_state_SetPrivateData,
660 d3d10_depthstencil_state_SetPrivateDataInterface,
661 /* ID3D10DepthStencilState methods */
662 d3d10_depthstencil_state_GetDesc,
665 static HRESULT d3d_depthstencil_state_init(struct d3d_depthstencil_state *state, struct d3d_device *device,
666 const D3D11_DEPTH_STENCIL_DESC *desc)
668 state->ID3D11DepthStencilState_iface.lpVtbl = &d3d11_depthstencil_state_vtbl;
669 state->ID3D10DepthStencilState_iface.lpVtbl = &d3d10_depthstencil_state_vtbl;
670 state->refcount = 1;
671 wined3d_private_store_init(&state->private_store);
672 state->desc = *desc;
674 state->device = &device->ID3D11Device_iface;
675 ID3D11Device_AddRef(state->device);
677 return S_OK;
680 HRESULT d3d_depthstencil_state_create(struct d3d_device *device, const D3D11_DEPTH_STENCIL_DESC *desc,
681 struct d3d_depthstencil_state **state)
683 struct d3d_depthstencil_state *object;
684 D3D11_DEPTH_STENCIL_DESC tmp_desc;
685 struct wine_rb_entry *entry;
686 HRESULT hr;
688 if (!desc)
689 return E_INVALIDARG;
691 /* D3D11_DEPTH_STENCIL_DESC has a hole, which is a problem because we use
692 * it as a key in the rbtree. */
693 memset(&tmp_desc, 0, sizeof(tmp_desc));
694 tmp_desc.DepthEnable = desc->DepthEnable;
695 if (desc->DepthEnable)
697 tmp_desc.DepthWriteMask = desc->DepthWriteMask;
698 tmp_desc.DepthFunc = desc->DepthFunc;
700 else
702 tmp_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
703 tmp_desc.DepthFunc = D3D11_COMPARISON_LESS;
705 tmp_desc.StencilEnable = desc->StencilEnable;
706 if (desc->StencilEnable)
708 tmp_desc.StencilReadMask = desc->StencilReadMask;
709 tmp_desc.StencilWriteMask = desc->StencilWriteMask;
710 tmp_desc.FrontFace = desc->FrontFace;
711 tmp_desc.BackFace = desc->BackFace;
713 else
715 tmp_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
716 tmp_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
717 tmp_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
718 tmp_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
719 tmp_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
720 tmp_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
721 tmp_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
722 tmp_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
723 tmp_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
724 tmp_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
727 wined3d_mutex_lock();
728 if ((entry = wine_rb_get(&device->depthstencil_states, &tmp_desc)))
730 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_depthstencil_state, entry);
732 TRACE("Returning existing depthstencil state %p.\n", object);
733 ID3D11DepthStencilState_AddRef(&object->ID3D11DepthStencilState_iface);
734 *state = object;
735 wined3d_mutex_unlock();
737 return S_OK;
740 if (!(object = heap_alloc_zero(sizeof(*object))))
742 wined3d_mutex_unlock();
743 return E_OUTOFMEMORY;
746 if (FAILED(hr = d3d_depthstencil_state_init(object, device, &tmp_desc)))
748 WARN("Failed to initialize depthstencil state, hr %#x.\n", hr);
749 heap_free(object);
750 wined3d_mutex_unlock();
751 return hr;
754 if (wine_rb_put(&device->depthstencil_states, desc, &object->entry) == -1)
756 ERR("Failed to insert depthstencil state entry.\n");
757 d3d_depthstencil_state_cleanup(object);
758 heap_free(object);
759 wined3d_mutex_unlock();
760 return E_FAIL;
762 wined3d_mutex_unlock();
764 TRACE("Created depthstencil state %p.\n", object);
765 *state = object;
767 return S_OK;
770 struct d3d_depthstencil_state *unsafe_impl_from_ID3D11DepthStencilState(ID3D11DepthStencilState *iface)
772 if (!iface)
773 return NULL;
774 assert(iface->lpVtbl == &d3d11_depthstencil_state_vtbl);
776 return impl_from_ID3D11DepthStencilState(iface);
779 struct d3d_depthstencil_state *unsafe_impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
781 if (!iface)
782 return NULL;
783 assert(iface->lpVtbl == &d3d10_depthstencil_state_vtbl);
785 return impl_from_ID3D10DepthStencilState(iface);
788 /* ID3D11RasterizerState methods */
790 static inline struct d3d_rasterizer_state *impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
792 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D11RasterizerState_iface);
795 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_QueryInterface(ID3D11RasterizerState *iface,
796 REFIID riid, void **object)
798 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
800 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
802 if (IsEqualGUID(riid, &IID_ID3D11RasterizerState)
803 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
804 || IsEqualGUID(riid, &IID_IUnknown))
806 ID3D11RasterizerState_AddRef(iface);
807 *object = iface;
808 return S_OK;
811 if (IsEqualGUID(riid, &IID_ID3D10RasterizerState)
812 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
814 ID3D10RasterizerState_AddRef(&state->ID3D10RasterizerState_iface);
815 *object = &state->ID3D10RasterizerState_iface;
816 return S_OK;
819 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
821 *object = NULL;
822 return E_NOINTERFACE;
825 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_AddRef(ID3D11RasterizerState *iface)
827 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
828 ULONG refcount = InterlockedIncrement(&state->refcount);
830 TRACE("%p increasing refcount to %u.\n", state, refcount);
832 if (refcount == 1)
834 ID3D11Device_AddRef(state->device);
835 wined3d_mutex_lock();
836 wined3d_rasterizer_state_incref(state->wined3d_state);
837 wined3d_mutex_unlock();
840 return refcount;
843 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_Release(ID3D11RasterizerState *iface)
845 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
846 ULONG refcount = InterlockedDecrement(&state->refcount);
848 TRACE("%p decreasing refcount to %u.\n", state, refcount);
850 if (!refcount)
852 ID3D11Device *device = state->device;
854 wined3d_mutex_lock();
855 wined3d_rasterizer_state_decref(state->wined3d_state);
856 wined3d_mutex_unlock();
858 ID3D11Device_Release(device);
861 return refcount;
864 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDevice(ID3D11RasterizerState *iface,
865 ID3D11Device **device)
867 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
869 TRACE("iface %p, device %p.\n", iface, device);
871 *device = state->device;
872 ID3D11Device_AddRef(*device);
875 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_GetPrivateData(ID3D11RasterizerState *iface,
876 REFGUID guid, UINT *data_size, void *data)
878 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
880 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
882 return d3d_get_private_data(&state->private_store, guid, data_size, data);
885 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateData(ID3D11RasterizerState *iface,
886 REFGUID guid, UINT data_size, const void *data)
888 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
890 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
892 return d3d_set_private_data(&state->private_store, guid, data_size, data);
895 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateDataInterface(ID3D11RasterizerState *iface,
896 REFGUID guid, const IUnknown *data)
898 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
900 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
902 return d3d_set_private_data_interface(&state->private_store, guid, data);
905 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDesc(ID3D11RasterizerState *iface,
906 D3D11_RASTERIZER_DESC *desc)
908 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
910 TRACE("iface %p, desc %p.\n", iface, desc);
912 *desc = state->desc;
915 static const struct ID3D11RasterizerStateVtbl d3d11_rasterizer_state_vtbl =
917 /* IUnknown methods */
918 d3d11_rasterizer_state_QueryInterface,
919 d3d11_rasterizer_state_AddRef,
920 d3d11_rasterizer_state_Release,
921 /* ID3D11DeviceChild methods */
922 d3d11_rasterizer_state_GetDevice,
923 d3d11_rasterizer_state_GetPrivateData,
924 d3d11_rasterizer_state_SetPrivateData,
925 d3d11_rasterizer_state_SetPrivateDataInterface,
926 /* ID3D11RasterizerState methods */
927 d3d11_rasterizer_state_GetDesc,
930 /* ID3D10RasterizerState methods */
932 static inline struct d3d_rasterizer_state *impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
934 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D10RasterizerState_iface);
937 /* IUnknown methods */
939 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_QueryInterface(ID3D10RasterizerState *iface,
940 REFIID riid, void **object)
942 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
944 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
946 return d3d11_rasterizer_state_QueryInterface(&state->ID3D11RasterizerState_iface, riid, object);
949 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_AddRef(ID3D10RasterizerState *iface)
951 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
953 TRACE("iface %p.\n", iface);
955 return d3d11_rasterizer_state_AddRef(&state->ID3D11RasterizerState_iface);
958 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_Release(ID3D10RasterizerState *iface)
960 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
962 TRACE("iface %p.\n", state);
964 return d3d11_rasterizer_state_Release(&state->ID3D11RasterizerState_iface);
967 /* ID3D10DeviceChild methods */
969 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDevice(ID3D10RasterizerState *iface, ID3D10Device **device)
971 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
973 TRACE("iface %p, device %p.\n", iface, device);
975 ID3D11Device_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
978 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_GetPrivateData(ID3D10RasterizerState *iface,
979 REFGUID guid, UINT *data_size, void *data)
981 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
983 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
984 iface, debugstr_guid(guid), data_size, data);
986 return d3d_get_private_data(&state->private_store, guid, data_size, data);
989 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateData(ID3D10RasterizerState *iface,
990 REFGUID guid, UINT data_size, const void *data)
992 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
994 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
995 iface, debugstr_guid(guid), data_size, data);
997 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1000 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateDataInterface(ID3D10RasterizerState *iface,
1001 REFGUID guid, const IUnknown *data)
1003 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1005 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1007 return d3d_set_private_data_interface(&state->private_store, guid, data);
1010 /* ID3D10RasterizerState methods */
1012 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDesc(ID3D10RasterizerState *iface,
1013 D3D10_RASTERIZER_DESC *desc)
1015 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1017 TRACE("iface %p, desc %p.\n", iface, desc);
1019 memcpy(desc, &state->desc, sizeof(*desc));
1022 static const struct ID3D10RasterizerStateVtbl d3d10_rasterizer_state_vtbl =
1024 /* IUnknown methods */
1025 d3d10_rasterizer_state_QueryInterface,
1026 d3d10_rasterizer_state_AddRef,
1027 d3d10_rasterizer_state_Release,
1028 /* ID3D10DeviceChild methods */
1029 d3d10_rasterizer_state_GetDevice,
1030 d3d10_rasterizer_state_GetPrivateData,
1031 d3d10_rasterizer_state_SetPrivateData,
1032 d3d10_rasterizer_state_SetPrivateDataInterface,
1033 /* ID3D10RasterizerState methods */
1034 d3d10_rasterizer_state_GetDesc,
1037 static void STDMETHODCALLTYPE d3d_rasterizer_state_wined3d_object_destroyed(void *parent)
1039 struct d3d_rasterizer_state *state = parent;
1040 struct d3d_device *device = impl_from_ID3D11Device(state->device);
1042 wine_rb_remove(&device->rasterizer_states, &state->entry);
1043 wined3d_private_store_cleanup(&state->private_store);
1044 heap_free(parent);
1047 static const struct wined3d_parent_ops d3d_rasterizer_state_wined3d_parent_ops =
1049 d3d_rasterizer_state_wined3d_object_destroyed,
1052 static HRESULT d3d_rasterizer_state_init(struct d3d_rasterizer_state *state, struct d3d_device *device,
1053 const D3D11_RASTERIZER_DESC *desc)
1055 struct wined3d_rasterizer_state_desc wined3d_desc;
1056 HRESULT hr;
1058 state->ID3D11RasterizerState_iface.lpVtbl = &d3d11_rasterizer_state_vtbl;
1059 state->ID3D10RasterizerState_iface.lpVtbl = &d3d10_rasterizer_state_vtbl;
1060 state->refcount = 1;
1061 wined3d_private_store_init(&state->private_store);
1062 state->desc = *desc;
1064 if (wine_rb_put(&device->rasterizer_states, desc, &state->entry) == -1)
1066 ERR("Failed to insert rasterizer state entry.\n");
1067 wined3d_private_store_cleanup(&state->private_store);
1068 return E_FAIL;
1071 wined3d_desc.front_ccw = desc->FrontCounterClockwise;
1073 /* We cannot fail after creating a wined3d_rasterizer_state object. It
1074 * would lead to double free. */
1075 if (FAILED(hr = wined3d_rasterizer_state_create(device->wined3d_device, &wined3d_desc,
1076 state, &d3d_rasterizer_state_wined3d_parent_ops, &state->wined3d_state)))
1078 WARN("Failed to create wined3d rasterizer state, hr %#x.\n", hr);
1079 wined3d_private_store_cleanup(&state->private_store);
1080 wine_rb_remove(&device->rasterizer_states, &state->entry);
1081 return hr;
1084 ID3D11Device_AddRef(state->device = &device->ID3D11Device_iface);
1086 return S_OK;
1089 HRESULT d3d_rasterizer_state_create(struct d3d_device *device, const D3D11_RASTERIZER_DESC *desc,
1090 struct d3d_rasterizer_state **state)
1092 struct d3d_rasterizer_state *object;
1093 struct wine_rb_entry *entry;
1094 HRESULT hr;
1096 if (!desc)
1097 return E_INVALIDARG;
1099 wined3d_mutex_lock();
1100 if ((entry = wine_rb_get(&device->rasterizer_states, desc)))
1102 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_rasterizer_state, entry);
1104 TRACE("Returning existing rasterizer state %p.\n", object);
1105 ID3D11RasterizerState_AddRef(&object->ID3D11RasterizerState_iface);
1106 *state = object;
1107 wined3d_mutex_unlock();
1109 return S_OK;
1112 if (!(object = heap_alloc_zero(sizeof(*object))))
1114 wined3d_mutex_unlock();
1115 return E_OUTOFMEMORY;
1118 hr = d3d_rasterizer_state_init(object, device, desc);
1119 wined3d_mutex_unlock();
1120 if (FAILED(hr))
1122 WARN("Failed to initialize rasterizer state, hr %#x.\n", hr);
1123 heap_free(object);
1124 return hr;
1127 TRACE("Created rasterizer state %p.\n", object);
1128 *state = object;
1130 return S_OK;
1133 struct d3d_rasterizer_state *unsafe_impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
1135 if (!iface)
1136 return NULL;
1137 assert(iface->lpVtbl == &d3d11_rasterizer_state_vtbl);
1139 return impl_from_ID3D11RasterizerState(iface);
1142 struct d3d_rasterizer_state *unsafe_impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
1144 if (!iface)
1145 return NULL;
1146 assert(iface->lpVtbl == &d3d10_rasterizer_state_vtbl);
1148 return impl_from_ID3D10RasterizerState(iface);
1151 /* ID3D11SampleState methods */
1153 static inline struct d3d_sampler_state *impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1155 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D11SamplerState_iface);
1158 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_QueryInterface(ID3D11SamplerState *iface,
1159 REFIID riid, void **object)
1161 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1163 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1165 if (IsEqualGUID(riid, &IID_ID3D11SamplerState)
1166 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1167 || IsEqualGUID(riid, &IID_IUnknown))
1169 ID3D11SamplerState_AddRef(iface);
1170 *object = iface;
1171 return S_OK;
1174 if (IsEqualGUID(riid, &IID_ID3D10SamplerState)
1175 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1177 ID3D10SamplerState_AddRef(&state->ID3D10SamplerState_iface);
1178 *object = &state->ID3D10SamplerState_iface;
1179 return S_OK;
1182 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1184 *object = NULL;
1185 return E_NOINTERFACE;
1188 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_AddRef(ID3D11SamplerState *iface)
1190 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1191 ULONG refcount = InterlockedIncrement(&state->refcount);
1193 TRACE("%p increasing refcount to %u.\n", state, refcount);
1195 if (refcount == 1)
1197 ID3D11Device_AddRef(state->device);
1198 wined3d_mutex_lock();
1199 wined3d_sampler_incref(state->wined3d_sampler);
1200 wined3d_mutex_unlock();
1203 return refcount;
1206 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_Release(ID3D11SamplerState *iface)
1208 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1209 ULONG refcount = InterlockedDecrement(&state->refcount);
1211 TRACE("%p decreasing refcount to %u.\n", state, refcount);
1213 if (!refcount)
1215 ID3D11Device *device = state->device;
1217 wined3d_mutex_lock();
1218 wined3d_sampler_decref(state->wined3d_sampler);
1219 wined3d_mutex_unlock();
1221 ID3D11Device_Release(device);
1224 return refcount;
1227 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDevice(ID3D11SamplerState *iface,
1228 ID3D11Device **device)
1230 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1232 TRACE("iface %p, device %p.\n", iface, device);
1234 *device = state->device;
1235 ID3D11Device_AddRef(*device);
1238 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_GetPrivateData(ID3D11SamplerState *iface,
1239 REFGUID guid, UINT *data_size, void *data)
1241 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1243 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1245 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1248 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateData(ID3D11SamplerState *iface,
1249 REFGUID guid, UINT data_size, const void *data)
1251 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1253 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1255 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1258 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateDataInterface(ID3D11SamplerState *iface,
1259 REFGUID guid, const IUnknown *data)
1261 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1263 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1265 return d3d_set_private_data_interface(&state->private_store, guid, data);
1268 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDesc(ID3D11SamplerState *iface,
1269 D3D11_SAMPLER_DESC *desc)
1271 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1273 TRACE("iface %p, desc %p.\n", iface, desc);
1275 *desc = state->desc;
1278 static const struct ID3D11SamplerStateVtbl d3d11_sampler_state_vtbl =
1280 /* IUnknown methods */
1281 d3d11_sampler_state_QueryInterface,
1282 d3d11_sampler_state_AddRef,
1283 d3d11_sampler_state_Release,
1284 /* ID3D11DeviceChild methods */
1285 d3d11_sampler_state_GetDevice,
1286 d3d11_sampler_state_GetPrivateData,
1287 d3d11_sampler_state_SetPrivateData,
1288 d3d11_sampler_state_SetPrivateDataInterface,
1289 /* ID3D11SamplerState methods */
1290 d3d11_sampler_state_GetDesc,
1293 /* ID3D10SamplerState methods */
1295 static inline struct d3d_sampler_state *impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1297 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D10SamplerState_iface);
1300 /* IUnknown methods */
1302 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_QueryInterface(ID3D10SamplerState *iface,
1303 REFIID riid, void **object)
1305 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1307 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1309 return d3d11_sampler_state_QueryInterface(&state->ID3D11SamplerState_iface, riid, object);
1312 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_AddRef(ID3D10SamplerState *iface)
1314 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1316 TRACE("iface %p.\n", iface);
1318 return d3d11_sampler_state_AddRef(&state->ID3D11SamplerState_iface);
1321 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_Release(ID3D10SamplerState *iface)
1323 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1325 TRACE("iface %p.\n", iface);
1327 return d3d11_sampler_state_Release(&state->ID3D11SamplerState_iface);
1330 /* ID3D10DeviceChild methods */
1332 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDevice(ID3D10SamplerState *iface, ID3D10Device **device)
1334 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1336 TRACE("iface %p, device %p.\n", iface, device);
1338 ID3D11Device_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
1341 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_GetPrivateData(ID3D10SamplerState *iface,
1342 REFGUID guid, UINT *data_size, void *data)
1344 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1346 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1347 iface, debugstr_guid(guid), data_size, data);
1349 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1352 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateData(ID3D10SamplerState *iface,
1353 REFGUID guid, UINT data_size, const void *data)
1355 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1357 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1358 iface, debugstr_guid(guid), data_size, data);
1360 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1363 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateDataInterface(ID3D10SamplerState *iface,
1364 REFGUID guid, const IUnknown *data)
1366 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1368 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1370 return d3d_set_private_data_interface(&state->private_store, guid, data);
1373 /* ID3D10SamplerState methods */
1375 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDesc(ID3D10SamplerState *iface,
1376 D3D10_SAMPLER_DESC *desc)
1378 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1380 TRACE("iface %p, desc %p.\n", iface, desc);
1382 memcpy(desc, &state->desc, sizeof(*desc));
1385 static const struct ID3D10SamplerStateVtbl d3d10_sampler_state_vtbl =
1387 /* IUnknown methods */
1388 d3d10_sampler_state_QueryInterface,
1389 d3d10_sampler_state_AddRef,
1390 d3d10_sampler_state_Release,
1391 /* ID3D10DeviceChild methods */
1392 d3d10_sampler_state_GetDevice,
1393 d3d10_sampler_state_GetPrivateData,
1394 d3d10_sampler_state_SetPrivateData,
1395 d3d10_sampler_state_SetPrivateDataInterface,
1396 /* ID3D10SamplerState methods */
1397 d3d10_sampler_state_GetDesc,
1400 static void STDMETHODCALLTYPE d3d_sampler_wined3d_object_destroyed(void *parent)
1402 struct d3d_sampler_state *state = parent;
1403 struct d3d_device *device = impl_from_ID3D11Device(state->device);
1405 wine_rb_remove(&device->sampler_states, &state->entry);
1406 wined3d_private_store_cleanup(&state->private_store);
1407 heap_free(parent);
1410 static const struct wined3d_parent_ops d3d_sampler_wined3d_parent_ops =
1412 d3d_sampler_wined3d_object_destroyed,
1415 static enum wined3d_texture_address wined3d_texture_address_from_d3d11(enum D3D11_TEXTURE_ADDRESS_MODE t)
1417 return (enum wined3d_texture_address)t;
1420 static enum wined3d_texture_filter_type wined3d_texture_filter_mip_from_d3d11(enum D3D11_FILTER f)
1422 if (D3D11_DECODE_MIP_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1423 return WINED3D_TEXF_LINEAR;
1424 return WINED3D_TEXF_POINT;
1427 static enum wined3d_texture_filter_type wined3d_texture_filter_mag_from_d3d11(enum D3D11_FILTER f)
1429 if (D3D11_DECODE_MAG_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1430 return WINED3D_TEXF_LINEAR;
1431 return WINED3D_TEXF_POINT;
1434 static enum wined3d_texture_filter_type wined3d_texture_filter_min_from_d3d11(enum D3D11_FILTER f)
1436 if (D3D11_DECODE_MIN_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1437 return WINED3D_TEXF_LINEAR;
1438 return WINED3D_TEXF_POINT;
1441 static BOOL wined3d_texture_compare_from_d3d11(enum D3D11_FILTER f)
1443 return D3D11_DECODE_IS_COMPARISON_FILTER(f);
1446 static enum wined3d_cmp_func wined3d_cmp_func_from_d3d11(D3D11_COMPARISON_FUNC f)
1448 return (enum wined3d_cmp_func)f;
1451 static HRESULT d3d_sampler_state_init(struct d3d_sampler_state *state, struct d3d_device *device,
1452 const D3D11_SAMPLER_DESC *desc)
1454 struct wined3d_sampler_desc wined3d_desc;
1455 HRESULT hr;
1457 state->ID3D11SamplerState_iface.lpVtbl = &d3d11_sampler_state_vtbl;
1458 state->ID3D10SamplerState_iface.lpVtbl = &d3d10_sampler_state_vtbl;
1459 state->refcount = 1;
1460 wined3d_private_store_init(&state->private_store);
1461 state->desc = *desc;
1463 wined3d_desc.address_u = wined3d_texture_address_from_d3d11(desc->AddressU);
1464 wined3d_desc.address_v = wined3d_texture_address_from_d3d11(desc->AddressV);
1465 wined3d_desc.address_w = wined3d_texture_address_from_d3d11(desc->AddressW);
1466 memcpy(wined3d_desc.border_color, desc->BorderColor, sizeof(wined3d_desc.border_color));
1467 wined3d_desc.mag_filter = wined3d_texture_filter_mag_from_d3d11(desc->Filter);
1468 wined3d_desc.min_filter = wined3d_texture_filter_min_from_d3d11(desc->Filter);
1469 wined3d_desc.mip_filter = wined3d_texture_filter_mip_from_d3d11(desc->Filter);
1470 wined3d_desc.lod_bias = desc->MipLODBias;
1471 wined3d_desc.min_lod = desc->MinLOD;
1472 wined3d_desc.max_lod = desc->MaxLOD;
1473 wined3d_desc.mip_base_level = 0;
1474 wined3d_desc.max_anisotropy = D3D11_DECODE_IS_ANISOTROPIC_FILTER(desc->Filter) ? desc->MaxAnisotropy : 1;
1475 wined3d_desc.compare = wined3d_texture_compare_from_d3d11(desc->Filter);
1476 wined3d_desc.comparison_func = wined3d_cmp_func_from_d3d11(desc->ComparisonFunc);
1477 wined3d_desc.srgb_decode = TRUE;
1479 if (wine_rb_put(&device->sampler_states, desc, &state->entry) == -1)
1481 ERR("Failed to insert sampler state entry.\n");
1482 wined3d_private_store_cleanup(&state->private_store);
1483 return E_FAIL;
1486 /* We cannot fail after creating a wined3d_sampler object. It would lead to
1487 * double free. */
1488 if (FAILED(hr = wined3d_sampler_create(device->wined3d_device, &wined3d_desc,
1489 state, &d3d_sampler_wined3d_parent_ops, &state->wined3d_sampler)))
1491 WARN("Failed to create wined3d sampler, hr %#x.\n", hr);
1492 wined3d_private_store_cleanup(&state->private_store);
1493 wine_rb_remove(&device->sampler_states, &state->entry);
1494 return hr;
1497 state->device = &device->ID3D11Device_iface;
1498 ID3D11Device_AddRef(state->device);
1500 return S_OK;
1503 HRESULT d3d_sampler_state_create(struct d3d_device *device, const D3D11_SAMPLER_DESC *desc,
1504 struct d3d_sampler_state **state)
1506 D3D11_SAMPLER_DESC normalized_desc;
1507 struct d3d_sampler_state *object;
1508 struct wine_rb_entry *entry;
1509 HRESULT hr;
1511 if (!desc)
1512 return E_INVALIDARG;
1514 normalized_desc = *desc;
1515 if (!D3D11_DECODE_IS_ANISOTROPIC_FILTER(normalized_desc.Filter))
1516 normalized_desc.MaxAnisotropy = 0;
1517 if (!D3D11_DECODE_IS_COMPARISON_FILTER(normalized_desc.Filter))
1518 normalized_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
1519 if (normalized_desc.AddressU != D3D11_TEXTURE_ADDRESS_BORDER
1520 && normalized_desc.AddressV != D3D11_TEXTURE_ADDRESS_BORDER
1521 && normalized_desc.AddressW != D3D11_TEXTURE_ADDRESS_BORDER)
1522 memset(&normalized_desc.BorderColor, 0, sizeof(normalized_desc.BorderColor));
1524 wined3d_mutex_lock();
1525 if ((entry = wine_rb_get(&device->sampler_states, &normalized_desc)))
1527 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_sampler_state, entry);
1529 TRACE("Returning existing sampler state %p.\n", object);
1530 ID3D11SamplerState_AddRef(&object->ID3D11SamplerState_iface);
1531 *state = object;
1532 wined3d_mutex_unlock();
1534 return S_OK;
1537 if (!(object = heap_alloc_zero(sizeof(*object))))
1539 wined3d_mutex_unlock();
1540 return E_OUTOFMEMORY;
1543 hr = d3d_sampler_state_init(object, device, &normalized_desc);
1544 wined3d_mutex_unlock();
1545 if (FAILED(hr))
1547 WARN("Failed to initialize sampler state, hr %#x.\n", hr);
1548 heap_free(object);
1549 return hr;
1552 TRACE("Created sampler state %p.\n", object);
1553 *state = object;
1555 return S_OK;
1558 struct d3d_sampler_state *unsafe_impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1560 if (!iface)
1561 return NULL;
1562 assert(iface->lpVtbl == &d3d11_sampler_state_vtbl);
1564 return impl_from_ID3D11SamplerState(iface);
1567 struct d3d_sampler_state *unsafe_impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1569 if (!iface)
1570 return NULL;
1571 assert(iface->lpVtbl == &d3d10_sampler_state_vtbl);
1573 return impl_from_ID3D10SamplerState(iface);