server: Create the initial thread as a separate request.
[wine.git] / dlls / d3d11 / state.c
blobc36b87fbbd39984540dfddf8bdcf210dd1c9a0b7
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 ID3D11Device2_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 ID3D11Device2 *device = state->device;
89 wined3d_mutex_lock();
90 wined3d_blend_state_decref(state->wined3d_state);
91 wined3d_mutex_unlock();
93 ID3D11Device2_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 = (ID3D11Device *)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 ID3D11Device2_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_ID3D11Device2(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 if (tmp_desc.RenderTarget[i].BlendEnable)
333 tmp_desc.RenderTarget[i].SrcBlend = desc->RenderTarget[j].SrcBlend;
334 tmp_desc.RenderTarget[i].DestBlend = desc->RenderTarget[j].DestBlend;
335 tmp_desc.RenderTarget[i].BlendOp = desc->RenderTarget[j].BlendOp;
336 tmp_desc.RenderTarget[i].SrcBlendAlpha = desc->RenderTarget[j].SrcBlendAlpha;
337 tmp_desc.RenderTarget[i].DestBlendAlpha = desc->RenderTarget[j].DestBlendAlpha;
338 tmp_desc.RenderTarget[i].BlendOpAlpha = desc->RenderTarget[j].BlendOpAlpha;
340 else
342 tmp_desc.RenderTarget[i].SrcBlend = D3D11_BLEND_ONE;
343 tmp_desc.RenderTarget[i].DestBlend = D3D11_BLEND_ZERO;
344 tmp_desc.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD;
345 tmp_desc.RenderTarget[i].SrcBlendAlpha = D3D11_BLEND_ONE;
346 tmp_desc.RenderTarget[i].DestBlendAlpha = D3D11_BLEND_ZERO;
347 tmp_desc.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD;
349 tmp_desc.RenderTarget[i].RenderTargetWriteMask = desc->RenderTarget[j].RenderTargetWriteMask;
351 if (i > 3 && tmp_desc.RenderTarget[i].RenderTargetWriteMask != D3D11_COLOR_WRITE_ENABLE_ALL)
352 FIXME("Color mask %#x not supported for render target %u.\n",
353 tmp_desc.RenderTarget[i].RenderTargetWriteMask, i);
356 /* glEnableIndexedEXT(GL_BLEND, ...) */
357 if (tmp_desc.IndependentBlendEnable)
358 FIXME("Per-rendertarget blend not implemented.\n");
360 wined3d_mutex_lock();
361 if ((entry = wine_rb_get(&device->blend_states, &tmp_desc)))
363 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_blend_state, entry);
365 TRACE("Returning existing blend state %p.\n", object);
366 ID3D11BlendState_AddRef(&object->ID3D11BlendState_iface);
367 *state = object;
368 wined3d_mutex_unlock();
370 return S_OK;
373 if (!(object = heap_alloc_zero(sizeof(*object))))
375 wined3d_mutex_unlock();
376 return E_OUTOFMEMORY;
379 object->ID3D11BlendState_iface.lpVtbl = &d3d11_blend_state_vtbl;
380 object->ID3D10BlendState1_iface.lpVtbl = &d3d10_blend_state_vtbl;
381 object->refcount = 1;
382 wined3d_private_store_init(&object->private_store);
383 object->desc = tmp_desc;
385 if (wine_rb_put(&device->blend_states, &tmp_desc, &object->entry) == -1)
387 ERR("Failed to insert blend state entry.\n");
388 wined3d_private_store_cleanup(&object->private_store);
389 heap_free(object);
390 wined3d_mutex_unlock();
391 return E_FAIL;
394 wined3d_desc.alpha_to_coverage = desc->AlphaToCoverageEnable;
396 /* We cannot fail after creating a wined3d_blend_state object. It
397 * would lead to double free. */
398 if (FAILED(hr = wined3d_blend_state_create(device->wined3d_device, &wined3d_desc,
399 object, &d3d_blend_state_wined3d_parent_ops, &object->wined3d_state)))
401 WARN("Failed to create wined3d blend state, hr %#x.\n", hr);
402 wined3d_private_store_cleanup(&object->private_store);
403 wine_rb_remove(&device->blend_states, &object->entry);
404 heap_free(object);
405 wined3d_mutex_unlock();
406 return hr;
408 wined3d_mutex_unlock();
410 ID3D11Device2_AddRef(object->device = &device->ID3D11Device2_iface);
412 TRACE("Created blend state %p.\n", object);
413 *state = object;
415 return S_OK;
418 struct d3d_blend_state *unsafe_impl_from_ID3D11BlendState(ID3D11BlendState *iface)
420 if (!iface)
421 return NULL;
422 assert(iface->lpVtbl == &d3d11_blend_state_vtbl);
424 return impl_from_ID3D11BlendState(iface);
427 struct d3d_blend_state *unsafe_impl_from_ID3D10BlendState(ID3D10BlendState *iface)
429 if (!iface)
430 return NULL;
431 assert(iface->lpVtbl == (ID3D10BlendStateVtbl *)&d3d10_blend_state_vtbl);
433 return impl_from_ID3D10BlendState((ID3D10BlendState1 *)iface);
436 /* ID3D11DepthStencilState methods */
438 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_QueryInterface(ID3D11DepthStencilState *iface,
439 REFIID riid, void **object)
441 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
443 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
445 if (IsEqualGUID(riid, &IID_ID3D11DepthStencilState)
446 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
447 || IsEqualGUID(riid, &IID_IUnknown))
449 ID3D11DepthStencilState_AddRef(iface);
450 *object = iface;
451 return S_OK;
454 if (IsEqualGUID(riid, &IID_ID3D10DepthStencilState)
455 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
457 ID3D10DepthStencilState_AddRef(&state->ID3D10DepthStencilState_iface);
458 *object = &state->ID3D10DepthStencilState_iface;
459 return S_OK;
462 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
464 *object = NULL;
465 return E_NOINTERFACE;
468 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_AddRef(ID3D11DepthStencilState *iface)
470 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
471 ULONG refcount = InterlockedIncrement(&state->refcount);
473 TRACE("%p increasing refcount to %u.\n", state, refcount);
475 return refcount;
478 static void d3d_depthstencil_state_cleanup(struct d3d_depthstencil_state *state)
480 wined3d_private_store_cleanup(&state->private_store);
481 ID3D11Device2_Release(state->device);
484 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_Release(ID3D11DepthStencilState *iface)
486 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
487 ULONG refcount = InterlockedDecrement(&state->refcount);
489 TRACE("%p decreasing refcount to %u.\n", state, refcount);
491 if (!refcount)
493 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
494 wined3d_mutex_lock();
495 wine_rb_remove(&device->depthstencil_states, &state->entry);
496 d3d_depthstencil_state_cleanup(state);
497 wined3d_mutex_unlock();
498 heap_free(state);
501 return refcount;
504 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDevice(ID3D11DepthStencilState *iface,
505 ID3D11Device **device)
507 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
509 TRACE("iface %p, device %p.\n", iface, device);
511 *device = (ID3D11Device *)state->device;
512 ID3D11Device_AddRef(*device);
515 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_GetPrivateData(ID3D11DepthStencilState *iface,
516 REFGUID guid, UINT *data_size, void *data)
518 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
520 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
522 return d3d_get_private_data(&state->private_store, guid, data_size, data);
525 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateData(ID3D11DepthStencilState *iface,
526 REFGUID guid, UINT data_size, const void *data)
528 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
530 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
532 return d3d_set_private_data(&state->private_store, guid, data_size, data);
535 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateDataInterface(ID3D11DepthStencilState *iface,
536 REFGUID guid, const IUnknown *data)
538 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
540 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
542 return d3d_set_private_data_interface(&state->private_store, guid, data);
545 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDesc(ID3D11DepthStencilState *iface,
546 D3D11_DEPTH_STENCIL_DESC *desc)
548 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
550 TRACE("iface %p, desc %p.\n", iface, desc);
552 *desc = state->desc;
555 static const struct ID3D11DepthStencilStateVtbl d3d11_depthstencil_state_vtbl =
557 /* IUnknown methods */
558 d3d11_depthstencil_state_QueryInterface,
559 d3d11_depthstencil_state_AddRef,
560 d3d11_depthstencil_state_Release,
561 /* ID3D11DeviceChild methods */
562 d3d11_depthstencil_state_GetDevice,
563 d3d11_depthstencil_state_GetPrivateData,
564 d3d11_depthstencil_state_SetPrivateData,
565 d3d11_depthstencil_state_SetPrivateDataInterface,
566 /* ID3D11DepthStencilState methods */
567 d3d11_depthstencil_state_GetDesc,
570 /* ID3D10DepthStencilState methods */
572 static inline struct d3d_depthstencil_state *impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
574 return CONTAINING_RECORD(iface, struct d3d_depthstencil_state, ID3D10DepthStencilState_iface);
577 /* IUnknown methods */
579 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_QueryInterface(ID3D10DepthStencilState *iface,
580 REFIID riid, void **object)
582 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
584 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
586 return d3d11_depthstencil_state_QueryInterface(&state->ID3D11DepthStencilState_iface, riid, object);
589 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_AddRef(ID3D10DepthStencilState *iface)
591 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
593 TRACE("iface %p.\n", iface);
595 return d3d11_depthstencil_state_AddRef(&state->ID3D11DepthStencilState_iface);
598 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_Release(ID3D10DepthStencilState *iface)
600 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
602 TRACE("iface %p.\n", iface);
604 return d3d11_depthstencil_state_Release(&state->ID3D11DepthStencilState_iface);
607 /* ID3D10DeviceChild methods */
609 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDevice(ID3D10DepthStencilState *iface, ID3D10Device **device)
611 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
613 TRACE("iface %p, device %p.\n", iface, device);
615 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
618 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_GetPrivateData(ID3D10DepthStencilState *iface,
619 REFGUID guid, UINT *data_size, void *data)
621 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
623 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
624 iface, debugstr_guid(guid), data_size, data);
626 return d3d_get_private_data(&state->private_store, guid, data_size, data);
629 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateData(ID3D10DepthStencilState *iface,
630 REFGUID guid, UINT data_size, const void *data)
632 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
634 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
635 iface, debugstr_guid(guid), data_size, data);
637 return d3d_set_private_data(&state->private_store, guid, data_size, data);
640 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateDataInterface(ID3D10DepthStencilState *iface,
641 REFGUID guid, const IUnknown *data)
643 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
645 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
647 return d3d_set_private_data_interface(&state->private_store, guid, data);
650 /* ID3D10DepthStencilState methods */
652 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDesc(ID3D10DepthStencilState *iface,
653 D3D10_DEPTH_STENCIL_DESC *desc)
655 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
657 TRACE("iface %p, desc %p.\n", iface, desc);
659 memcpy(desc, &state->desc, sizeof(*desc));
662 static const struct ID3D10DepthStencilStateVtbl d3d10_depthstencil_state_vtbl =
664 /* IUnknown methods */
665 d3d10_depthstencil_state_QueryInterface,
666 d3d10_depthstencil_state_AddRef,
667 d3d10_depthstencil_state_Release,
668 /* ID3D10DeviceChild methods */
669 d3d10_depthstencil_state_GetDevice,
670 d3d10_depthstencil_state_GetPrivateData,
671 d3d10_depthstencil_state_SetPrivateData,
672 d3d10_depthstencil_state_SetPrivateDataInterface,
673 /* ID3D10DepthStencilState methods */
674 d3d10_depthstencil_state_GetDesc,
677 static HRESULT d3d_depthstencil_state_init(struct d3d_depthstencil_state *state, struct d3d_device *device,
678 const D3D11_DEPTH_STENCIL_DESC *desc)
680 state->ID3D11DepthStencilState_iface.lpVtbl = &d3d11_depthstencil_state_vtbl;
681 state->ID3D10DepthStencilState_iface.lpVtbl = &d3d10_depthstencil_state_vtbl;
682 state->refcount = 1;
683 wined3d_private_store_init(&state->private_store);
684 state->desc = *desc;
686 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
688 return S_OK;
691 HRESULT d3d_depthstencil_state_create(struct d3d_device *device, const D3D11_DEPTH_STENCIL_DESC *desc,
692 struct d3d_depthstencil_state **state)
694 struct d3d_depthstencil_state *object;
695 D3D11_DEPTH_STENCIL_DESC tmp_desc;
696 struct wine_rb_entry *entry;
697 HRESULT hr;
699 if (!desc)
700 return E_INVALIDARG;
702 /* D3D11_DEPTH_STENCIL_DESC has a hole, which is a problem because we use
703 * it as a key in the rbtree. */
704 memset(&tmp_desc, 0, sizeof(tmp_desc));
705 tmp_desc.DepthEnable = desc->DepthEnable;
706 if (desc->DepthEnable)
708 tmp_desc.DepthWriteMask = desc->DepthWriteMask;
709 tmp_desc.DepthFunc = desc->DepthFunc;
711 else
713 tmp_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
714 tmp_desc.DepthFunc = D3D11_COMPARISON_LESS;
716 tmp_desc.StencilEnable = desc->StencilEnable;
717 if (desc->StencilEnable)
719 tmp_desc.StencilReadMask = desc->StencilReadMask;
720 tmp_desc.StencilWriteMask = desc->StencilWriteMask;
721 tmp_desc.FrontFace = desc->FrontFace;
722 tmp_desc.BackFace = desc->BackFace;
724 else
726 tmp_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
727 tmp_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
728 tmp_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
729 tmp_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
730 tmp_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
731 tmp_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
732 tmp_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
733 tmp_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
734 tmp_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
735 tmp_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
738 wined3d_mutex_lock();
739 if ((entry = wine_rb_get(&device->depthstencil_states, &tmp_desc)))
741 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_depthstencil_state, entry);
743 TRACE("Returning existing depthstencil state %p.\n", object);
744 ID3D11DepthStencilState_AddRef(&object->ID3D11DepthStencilState_iface);
745 *state = object;
746 wined3d_mutex_unlock();
748 return S_OK;
751 if (!(object = heap_alloc_zero(sizeof(*object))))
753 wined3d_mutex_unlock();
754 return E_OUTOFMEMORY;
757 if (FAILED(hr = d3d_depthstencil_state_init(object, device, &tmp_desc)))
759 WARN("Failed to initialize depthstencil state, hr %#x.\n", hr);
760 heap_free(object);
761 wined3d_mutex_unlock();
762 return hr;
765 if (wine_rb_put(&device->depthstencil_states, &tmp_desc, &object->entry) == -1)
767 ERR("Failed to insert depthstencil state entry.\n");
768 d3d_depthstencil_state_cleanup(object);
769 heap_free(object);
770 wined3d_mutex_unlock();
771 return E_FAIL;
773 wined3d_mutex_unlock();
775 TRACE("Created depthstencil state %p.\n", object);
776 *state = object;
778 return S_OK;
781 struct d3d_depthstencil_state *unsafe_impl_from_ID3D11DepthStencilState(ID3D11DepthStencilState *iface)
783 if (!iface)
784 return NULL;
785 assert(iface->lpVtbl == &d3d11_depthstencil_state_vtbl);
787 return impl_from_ID3D11DepthStencilState(iface);
790 struct d3d_depthstencil_state *unsafe_impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
792 if (!iface)
793 return NULL;
794 assert(iface->lpVtbl == &d3d10_depthstencil_state_vtbl);
796 return impl_from_ID3D10DepthStencilState(iface);
799 /* ID3D11RasterizerState methods */
801 static inline struct d3d_rasterizer_state *impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
803 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D11RasterizerState_iface);
806 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_QueryInterface(ID3D11RasterizerState *iface,
807 REFIID riid, void **object)
809 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
811 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
813 if (IsEqualGUID(riid, &IID_ID3D11RasterizerState)
814 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
815 || IsEqualGUID(riid, &IID_IUnknown))
817 ID3D11RasterizerState_AddRef(iface);
818 *object = iface;
819 return S_OK;
822 if (IsEqualGUID(riid, &IID_ID3D10RasterizerState)
823 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
825 ID3D10RasterizerState_AddRef(&state->ID3D10RasterizerState_iface);
826 *object = &state->ID3D10RasterizerState_iface;
827 return S_OK;
830 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
832 *object = NULL;
833 return E_NOINTERFACE;
836 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_AddRef(ID3D11RasterizerState *iface)
838 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
839 ULONG refcount = InterlockedIncrement(&state->refcount);
841 TRACE("%p increasing refcount to %u.\n", state, refcount);
843 if (refcount == 1)
845 ID3D11Device2_AddRef(state->device);
846 wined3d_mutex_lock();
847 wined3d_rasterizer_state_incref(state->wined3d_state);
848 wined3d_mutex_unlock();
851 return refcount;
854 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_Release(ID3D11RasterizerState *iface)
856 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
857 ULONG refcount = InterlockedDecrement(&state->refcount);
859 TRACE("%p decreasing refcount to %u.\n", state, refcount);
861 if (!refcount)
863 ID3D11Device2 *device = state->device;
865 wined3d_mutex_lock();
866 wined3d_rasterizer_state_decref(state->wined3d_state);
867 wined3d_mutex_unlock();
869 ID3D11Device2_Release(device);
872 return refcount;
875 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDevice(ID3D11RasterizerState *iface,
876 ID3D11Device **device)
878 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
880 TRACE("iface %p, device %p.\n", iface, device);
882 *device = (ID3D11Device *)state->device;
883 ID3D11Device_AddRef(*device);
886 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_GetPrivateData(ID3D11RasterizerState *iface,
887 REFGUID guid, UINT *data_size, void *data)
889 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
891 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
893 return d3d_get_private_data(&state->private_store, guid, data_size, data);
896 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateData(ID3D11RasterizerState *iface,
897 REFGUID guid, UINT data_size, const void *data)
899 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
901 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
903 return d3d_set_private_data(&state->private_store, guid, data_size, data);
906 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateDataInterface(ID3D11RasterizerState *iface,
907 REFGUID guid, const IUnknown *data)
909 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
911 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
913 return d3d_set_private_data_interface(&state->private_store, guid, data);
916 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDesc(ID3D11RasterizerState *iface,
917 D3D11_RASTERIZER_DESC *desc)
919 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
921 TRACE("iface %p, desc %p.\n", iface, desc);
923 *desc = state->desc;
926 static const struct ID3D11RasterizerStateVtbl d3d11_rasterizer_state_vtbl =
928 /* IUnknown methods */
929 d3d11_rasterizer_state_QueryInterface,
930 d3d11_rasterizer_state_AddRef,
931 d3d11_rasterizer_state_Release,
932 /* ID3D11DeviceChild methods */
933 d3d11_rasterizer_state_GetDevice,
934 d3d11_rasterizer_state_GetPrivateData,
935 d3d11_rasterizer_state_SetPrivateData,
936 d3d11_rasterizer_state_SetPrivateDataInterface,
937 /* ID3D11RasterizerState methods */
938 d3d11_rasterizer_state_GetDesc,
941 /* ID3D10RasterizerState methods */
943 static inline struct d3d_rasterizer_state *impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
945 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D10RasterizerState_iface);
948 /* IUnknown methods */
950 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_QueryInterface(ID3D10RasterizerState *iface,
951 REFIID riid, void **object)
953 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
955 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
957 return d3d11_rasterizer_state_QueryInterface(&state->ID3D11RasterizerState_iface, riid, object);
960 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_AddRef(ID3D10RasterizerState *iface)
962 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
964 TRACE("iface %p.\n", iface);
966 return d3d11_rasterizer_state_AddRef(&state->ID3D11RasterizerState_iface);
969 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_Release(ID3D10RasterizerState *iface)
971 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
973 TRACE("iface %p.\n", state);
975 return d3d11_rasterizer_state_Release(&state->ID3D11RasterizerState_iface);
978 /* ID3D10DeviceChild methods */
980 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDevice(ID3D10RasterizerState *iface, ID3D10Device **device)
982 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
984 TRACE("iface %p, device %p.\n", iface, device);
986 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
989 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_GetPrivateData(ID3D10RasterizerState *iface,
990 REFGUID guid, UINT *data_size, void *data)
992 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
994 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
995 iface, debugstr_guid(guid), data_size, data);
997 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1000 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateData(ID3D10RasterizerState *iface,
1001 REFGUID guid, UINT data_size, const void *data)
1003 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1005 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1006 iface, debugstr_guid(guid), data_size, data);
1008 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1011 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateDataInterface(ID3D10RasterizerState *iface,
1012 REFGUID guid, const IUnknown *data)
1014 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1016 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1018 return d3d_set_private_data_interface(&state->private_store, guid, data);
1021 /* ID3D10RasterizerState methods */
1023 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDesc(ID3D10RasterizerState *iface,
1024 D3D10_RASTERIZER_DESC *desc)
1026 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1028 TRACE("iface %p, desc %p.\n", iface, desc);
1030 memcpy(desc, &state->desc, sizeof(*desc));
1033 static const struct ID3D10RasterizerStateVtbl d3d10_rasterizer_state_vtbl =
1035 /* IUnknown methods */
1036 d3d10_rasterizer_state_QueryInterface,
1037 d3d10_rasterizer_state_AddRef,
1038 d3d10_rasterizer_state_Release,
1039 /* ID3D10DeviceChild methods */
1040 d3d10_rasterizer_state_GetDevice,
1041 d3d10_rasterizer_state_GetPrivateData,
1042 d3d10_rasterizer_state_SetPrivateData,
1043 d3d10_rasterizer_state_SetPrivateDataInterface,
1044 /* ID3D10RasterizerState methods */
1045 d3d10_rasterizer_state_GetDesc,
1048 static void STDMETHODCALLTYPE d3d_rasterizer_state_wined3d_object_destroyed(void *parent)
1050 struct d3d_rasterizer_state *state = parent;
1051 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
1053 wine_rb_remove(&device->rasterizer_states, &state->entry);
1054 wined3d_private_store_cleanup(&state->private_store);
1055 heap_free(parent);
1058 static const struct wined3d_parent_ops d3d_rasterizer_state_wined3d_parent_ops =
1060 d3d_rasterizer_state_wined3d_object_destroyed,
1063 static HRESULT d3d_rasterizer_state_init(struct d3d_rasterizer_state *state, struct d3d_device *device,
1064 const D3D11_RASTERIZER_DESC *desc)
1066 struct wined3d_rasterizer_state_desc wined3d_desc;
1067 HRESULT hr;
1069 state->ID3D11RasterizerState_iface.lpVtbl = &d3d11_rasterizer_state_vtbl;
1070 state->ID3D10RasterizerState_iface.lpVtbl = &d3d10_rasterizer_state_vtbl;
1071 state->refcount = 1;
1072 wined3d_private_store_init(&state->private_store);
1073 state->desc = *desc;
1075 if (wine_rb_put(&device->rasterizer_states, desc, &state->entry) == -1)
1077 ERR("Failed to insert rasterizer state entry.\n");
1078 wined3d_private_store_cleanup(&state->private_store);
1079 return E_FAIL;
1082 wined3d_desc.front_ccw = desc->FrontCounterClockwise;
1083 wined3d_desc.depth_clip = desc->DepthClipEnable;
1085 /* We cannot fail after creating a wined3d_rasterizer_state object. It
1086 * would lead to double free. */
1087 if (FAILED(hr = wined3d_rasterizer_state_create(device->wined3d_device, &wined3d_desc,
1088 state, &d3d_rasterizer_state_wined3d_parent_ops, &state->wined3d_state)))
1090 WARN("Failed to create wined3d rasterizer state, hr %#x.\n", hr);
1091 wined3d_private_store_cleanup(&state->private_store);
1092 wine_rb_remove(&device->rasterizer_states, &state->entry);
1093 return hr;
1096 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
1098 return S_OK;
1101 HRESULT d3d_rasterizer_state_create(struct d3d_device *device, const D3D11_RASTERIZER_DESC *desc,
1102 struct d3d_rasterizer_state **state)
1104 struct d3d_rasterizer_state *object;
1105 struct wine_rb_entry *entry;
1106 HRESULT hr;
1108 if (!desc)
1109 return E_INVALIDARG;
1111 wined3d_mutex_lock();
1112 if ((entry = wine_rb_get(&device->rasterizer_states, desc)))
1114 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_rasterizer_state, entry);
1116 TRACE("Returning existing rasterizer state %p.\n", object);
1117 ID3D11RasterizerState_AddRef(&object->ID3D11RasterizerState_iface);
1118 *state = object;
1119 wined3d_mutex_unlock();
1121 return S_OK;
1124 if (!(object = heap_alloc_zero(sizeof(*object))))
1126 wined3d_mutex_unlock();
1127 return E_OUTOFMEMORY;
1130 hr = d3d_rasterizer_state_init(object, device, desc);
1131 wined3d_mutex_unlock();
1132 if (FAILED(hr))
1134 WARN("Failed to initialize rasterizer state, hr %#x.\n", hr);
1135 heap_free(object);
1136 return hr;
1139 TRACE("Created rasterizer state %p.\n", object);
1140 *state = object;
1142 return S_OK;
1145 struct d3d_rasterizer_state *unsafe_impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
1147 if (!iface)
1148 return NULL;
1149 assert(iface->lpVtbl == &d3d11_rasterizer_state_vtbl);
1151 return impl_from_ID3D11RasterizerState(iface);
1154 struct d3d_rasterizer_state *unsafe_impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
1156 if (!iface)
1157 return NULL;
1158 assert(iface->lpVtbl == &d3d10_rasterizer_state_vtbl);
1160 return impl_from_ID3D10RasterizerState(iface);
1163 /* ID3D11SampleState methods */
1165 static inline struct d3d_sampler_state *impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1167 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D11SamplerState_iface);
1170 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_QueryInterface(ID3D11SamplerState *iface,
1171 REFIID riid, void **object)
1173 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1175 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1177 if (IsEqualGUID(riid, &IID_ID3D11SamplerState)
1178 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1179 || IsEqualGUID(riid, &IID_IUnknown))
1181 ID3D11SamplerState_AddRef(iface);
1182 *object = iface;
1183 return S_OK;
1186 if (IsEqualGUID(riid, &IID_ID3D10SamplerState)
1187 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1189 ID3D10SamplerState_AddRef(&state->ID3D10SamplerState_iface);
1190 *object = &state->ID3D10SamplerState_iface;
1191 return S_OK;
1194 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1196 *object = NULL;
1197 return E_NOINTERFACE;
1200 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_AddRef(ID3D11SamplerState *iface)
1202 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1203 ULONG refcount = InterlockedIncrement(&state->refcount);
1205 TRACE("%p increasing refcount to %u.\n", state, refcount);
1207 if (refcount == 1)
1209 ID3D11Device2_AddRef(state->device);
1210 wined3d_mutex_lock();
1211 wined3d_sampler_incref(state->wined3d_sampler);
1212 wined3d_mutex_unlock();
1215 return refcount;
1218 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_Release(ID3D11SamplerState *iface)
1220 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1221 ULONG refcount = InterlockedDecrement(&state->refcount);
1223 TRACE("%p decreasing refcount to %u.\n", state, refcount);
1225 if (!refcount)
1227 ID3D11Device2 *device = state->device;
1229 wined3d_mutex_lock();
1230 wined3d_sampler_decref(state->wined3d_sampler);
1231 wined3d_mutex_unlock();
1233 ID3D11Device2_Release(device);
1236 return refcount;
1239 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDevice(ID3D11SamplerState *iface,
1240 ID3D11Device **device)
1242 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1244 TRACE("iface %p, device %p.\n", iface, device);
1246 *device = (ID3D11Device *)state->device;
1247 ID3D11Device_AddRef(*device);
1250 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_GetPrivateData(ID3D11SamplerState *iface,
1251 REFGUID guid, UINT *data_size, void *data)
1253 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1255 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1257 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1260 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateData(ID3D11SamplerState *iface,
1261 REFGUID guid, UINT data_size, const void *data)
1263 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1265 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1267 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1270 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateDataInterface(ID3D11SamplerState *iface,
1271 REFGUID guid, const IUnknown *data)
1273 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1275 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1277 return d3d_set_private_data_interface(&state->private_store, guid, data);
1280 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDesc(ID3D11SamplerState *iface,
1281 D3D11_SAMPLER_DESC *desc)
1283 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1285 TRACE("iface %p, desc %p.\n", iface, desc);
1287 *desc = state->desc;
1290 static const struct ID3D11SamplerStateVtbl d3d11_sampler_state_vtbl =
1292 /* IUnknown methods */
1293 d3d11_sampler_state_QueryInterface,
1294 d3d11_sampler_state_AddRef,
1295 d3d11_sampler_state_Release,
1296 /* ID3D11DeviceChild methods */
1297 d3d11_sampler_state_GetDevice,
1298 d3d11_sampler_state_GetPrivateData,
1299 d3d11_sampler_state_SetPrivateData,
1300 d3d11_sampler_state_SetPrivateDataInterface,
1301 /* ID3D11SamplerState methods */
1302 d3d11_sampler_state_GetDesc,
1305 /* ID3D10SamplerState methods */
1307 static inline struct d3d_sampler_state *impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1309 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D10SamplerState_iface);
1312 /* IUnknown methods */
1314 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_QueryInterface(ID3D10SamplerState *iface,
1315 REFIID riid, void **object)
1317 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1319 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1321 return d3d11_sampler_state_QueryInterface(&state->ID3D11SamplerState_iface, riid, object);
1324 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_AddRef(ID3D10SamplerState *iface)
1326 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1328 TRACE("iface %p.\n", iface);
1330 return d3d11_sampler_state_AddRef(&state->ID3D11SamplerState_iface);
1333 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_Release(ID3D10SamplerState *iface)
1335 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1337 TRACE("iface %p.\n", iface);
1339 return d3d11_sampler_state_Release(&state->ID3D11SamplerState_iface);
1342 /* ID3D10DeviceChild methods */
1344 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDevice(ID3D10SamplerState *iface, ID3D10Device **device)
1346 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1348 TRACE("iface %p, device %p.\n", iface, device);
1350 ID3D11Device2_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
1353 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_GetPrivateData(ID3D10SamplerState *iface,
1354 REFGUID guid, UINT *data_size, void *data)
1356 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1358 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1359 iface, debugstr_guid(guid), data_size, data);
1361 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1364 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateData(ID3D10SamplerState *iface,
1365 REFGUID guid, UINT data_size, const void *data)
1367 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1369 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1370 iface, debugstr_guid(guid), data_size, data);
1372 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1375 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateDataInterface(ID3D10SamplerState *iface,
1376 REFGUID guid, const IUnknown *data)
1378 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1380 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1382 return d3d_set_private_data_interface(&state->private_store, guid, data);
1385 /* ID3D10SamplerState methods */
1387 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDesc(ID3D10SamplerState *iface,
1388 D3D10_SAMPLER_DESC *desc)
1390 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1392 TRACE("iface %p, desc %p.\n", iface, desc);
1394 memcpy(desc, &state->desc, sizeof(*desc));
1397 static const struct ID3D10SamplerStateVtbl d3d10_sampler_state_vtbl =
1399 /* IUnknown methods */
1400 d3d10_sampler_state_QueryInterface,
1401 d3d10_sampler_state_AddRef,
1402 d3d10_sampler_state_Release,
1403 /* ID3D10DeviceChild methods */
1404 d3d10_sampler_state_GetDevice,
1405 d3d10_sampler_state_GetPrivateData,
1406 d3d10_sampler_state_SetPrivateData,
1407 d3d10_sampler_state_SetPrivateDataInterface,
1408 /* ID3D10SamplerState methods */
1409 d3d10_sampler_state_GetDesc,
1412 static void STDMETHODCALLTYPE d3d_sampler_wined3d_object_destroyed(void *parent)
1414 struct d3d_sampler_state *state = parent;
1415 struct d3d_device *device = impl_from_ID3D11Device2(state->device);
1417 wine_rb_remove(&device->sampler_states, &state->entry);
1418 wined3d_private_store_cleanup(&state->private_store);
1419 heap_free(parent);
1422 static const struct wined3d_parent_ops d3d_sampler_wined3d_parent_ops =
1424 d3d_sampler_wined3d_object_destroyed,
1427 static enum wined3d_texture_address wined3d_texture_address_from_d3d11(enum D3D11_TEXTURE_ADDRESS_MODE t)
1429 return (enum wined3d_texture_address)t;
1432 static enum wined3d_texture_filter_type wined3d_texture_filter_mip_from_d3d11(enum D3D11_FILTER f)
1434 if (D3D11_DECODE_MIP_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1435 return WINED3D_TEXF_LINEAR;
1436 return WINED3D_TEXF_POINT;
1439 static enum wined3d_texture_filter_type wined3d_texture_filter_mag_from_d3d11(enum D3D11_FILTER f)
1441 if (D3D11_DECODE_MAG_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1442 return WINED3D_TEXF_LINEAR;
1443 return WINED3D_TEXF_POINT;
1446 static enum wined3d_texture_filter_type wined3d_texture_filter_min_from_d3d11(enum D3D11_FILTER f)
1448 if (D3D11_DECODE_MIN_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1449 return WINED3D_TEXF_LINEAR;
1450 return WINED3D_TEXF_POINT;
1453 static BOOL wined3d_texture_compare_from_d3d11(enum D3D11_FILTER f)
1455 return D3D11_DECODE_IS_COMPARISON_FILTER(f);
1458 static enum wined3d_cmp_func wined3d_cmp_func_from_d3d11(D3D11_COMPARISON_FUNC f)
1460 return (enum wined3d_cmp_func)f;
1463 static HRESULT d3d_sampler_state_init(struct d3d_sampler_state *state, struct d3d_device *device,
1464 const D3D11_SAMPLER_DESC *desc)
1466 struct wined3d_sampler_desc wined3d_desc;
1467 HRESULT hr;
1469 state->ID3D11SamplerState_iface.lpVtbl = &d3d11_sampler_state_vtbl;
1470 state->ID3D10SamplerState_iface.lpVtbl = &d3d10_sampler_state_vtbl;
1471 state->refcount = 1;
1472 wined3d_private_store_init(&state->private_store);
1473 state->desc = *desc;
1475 wined3d_desc.address_u = wined3d_texture_address_from_d3d11(desc->AddressU);
1476 wined3d_desc.address_v = wined3d_texture_address_from_d3d11(desc->AddressV);
1477 wined3d_desc.address_w = wined3d_texture_address_from_d3d11(desc->AddressW);
1478 memcpy(wined3d_desc.border_color, desc->BorderColor, sizeof(wined3d_desc.border_color));
1479 wined3d_desc.mag_filter = wined3d_texture_filter_mag_from_d3d11(desc->Filter);
1480 wined3d_desc.min_filter = wined3d_texture_filter_min_from_d3d11(desc->Filter);
1481 wined3d_desc.mip_filter = wined3d_texture_filter_mip_from_d3d11(desc->Filter);
1482 wined3d_desc.lod_bias = desc->MipLODBias;
1483 wined3d_desc.min_lod = desc->MinLOD;
1484 wined3d_desc.max_lod = desc->MaxLOD;
1485 wined3d_desc.mip_base_level = 0;
1486 wined3d_desc.max_anisotropy = D3D11_DECODE_IS_ANISOTROPIC_FILTER(desc->Filter) ? desc->MaxAnisotropy : 1;
1487 wined3d_desc.compare = wined3d_texture_compare_from_d3d11(desc->Filter);
1488 wined3d_desc.comparison_func = wined3d_cmp_func_from_d3d11(desc->ComparisonFunc);
1489 wined3d_desc.srgb_decode = TRUE;
1491 if (wine_rb_put(&device->sampler_states, desc, &state->entry) == -1)
1493 ERR("Failed to insert sampler state entry.\n");
1494 wined3d_private_store_cleanup(&state->private_store);
1495 return E_FAIL;
1498 /* We cannot fail after creating a wined3d_sampler object. It would lead to
1499 * double free. */
1500 if (FAILED(hr = wined3d_sampler_create(device->wined3d_device, &wined3d_desc,
1501 state, &d3d_sampler_wined3d_parent_ops, &state->wined3d_sampler)))
1503 WARN("Failed to create wined3d sampler, hr %#x.\n", hr);
1504 wined3d_private_store_cleanup(&state->private_store);
1505 wine_rb_remove(&device->sampler_states, &state->entry);
1506 return hr;
1509 ID3D11Device2_AddRef(state->device = &device->ID3D11Device2_iface);
1511 return S_OK;
1514 HRESULT d3d_sampler_state_create(struct d3d_device *device, const D3D11_SAMPLER_DESC *desc,
1515 struct d3d_sampler_state **state)
1517 D3D11_SAMPLER_DESC normalized_desc;
1518 struct d3d_sampler_state *object;
1519 struct wine_rb_entry *entry;
1520 HRESULT hr;
1522 if (!desc)
1523 return E_INVALIDARG;
1525 normalized_desc = *desc;
1526 if (!D3D11_DECODE_IS_ANISOTROPIC_FILTER(normalized_desc.Filter))
1527 normalized_desc.MaxAnisotropy = 0;
1528 if (!D3D11_DECODE_IS_COMPARISON_FILTER(normalized_desc.Filter))
1529 normalized_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
1530 if (normalized_desc.AddressU != D3D11_TEXTURE_ADDRESS_BORDER
1531 && normalized_desc.AddressV != D3D11_TEXTURE_ADDRESS_BORDER
1532 && normalized_desc.AddressW != D3D11_TEXTURE_ADDRESS_BORDER)
1533 memset(&normalized_desc.BorderColor, 0, sizeof(normalized_desc.BorderColor));
1535 wined3d_mutex_lock();
1536 if ((entry = wine_rb_get(&device->sampler_states, &normalized_desc)))
1538 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_sampler_state, entry);
1540 TRACE("Returning existing sampler state %p.\n", object);
1541 ID3D11SamplerState_AddRef(&object->ID3D11SamplerState_iface);
1542 *state = object;
1543 wined3d_mutex_unlock();
1545 return S_OK;
1548 if (!(object = heap_alloc_zero(sizeof(*object))))
1550 wined3d_mutex_unlock();
1551 return E_OUTOFMEMORY;
1554 hr = d3d_sampler_state_init(object, device, &normalized_desc);
1555 wined3d_mutex_unlock();
1556 if (FAILED(hr))
1558 WARN("Failed to initialize sampler state, hr %#x.\n", hr);
1559 heap_free(object);
1560 return hr;
1563 TRACE("Created sampler state %p.\n", object);
1564 *state = object;
1566 return S_OK;
1569 struct d3d_sampler_state *unsafe_impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1571 if (!iface)
1572 return NULL;
1573 assert(iface->lpVtbl == &d3d11_sampler_state_vtbl);
1575 return impl_from_ID3D11SamplerState(iface);
1578 struct d3d_sampler_state *unsafe_impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1580 if (!iface)
1581 return NULL;
1582 assert(iface->lpVtbl == &d3d10_sampler_state_vtbl);
1584 return impl_from_ID3D10SamplerState(iface);