gdiplus: Set correct color space flags for grayscale images.
[wine.git] / dlls / d3d11 / state.c
blobb7c9264df47b2e181ea58d365207d873296524e6
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 return refcount;
70 static void d3d_blend_state_cleanup(struct d3d_blend_state *state)
72 wined3d_private_store_cleanup(&state->private_store);
73 ID3D11Device_Release(state->device);
76 static ULONG STDMETHODCALLTYPE d3d11_blend_state_Release(ID3D11BlendState *iface)
78 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
79 ULONG refcount = InterlockedDecrement(&state->refcount);
81 TRACE("%p decreasing refcount to %u.\n", state, refcount);
83 if (!refcount)
85 struct d3d_device *device = impl_from_ID3D11Device(state->device);
86 wined3d_mutex_lock();
87 wine_rb_remove(&device->blend_states, &state->entry);
88 d3d_blend_state_cleanup(state);
89 wined3d_mutex_unlock();
90 HeapFree(GetProcessHeap(), 0, state);
93 return refcount;
96 static void STDMETHODCALLTYPE d3d11_blend_state_GetDevice(ID3D11BlendState *iface,
97 ID3D11Device **device)
99 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
101 TRACE("iface %p, device %p.\n", iface, device);
103 *device = state->device;
104 ID3D11Device_AddRef(*device);
107 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_GetPrivateData(ID3D11BlendState *iface,
108 REFGUID guid, UINT *data_size, void *data)
110 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
112 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
114 return d3d_get_private_data(&state->private_store, guid, data_size, data);
117 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_SetPrivateData(ID3D11BlendState *iface,
118 REFGUID guid, UINT data_size, const void *data)
120 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
122 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
124 return d3d_set_private_data(&state->private_store, guid, data_size, data);
127 static HRESULT STDMETHODCALLTYPE d3d11_blend_state_SetPrivateDataInterface(ID3D11BlendState *iface,
128 REFGUID guid, const IUnknown *data)
130 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
132 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
134 return d3d_set_private_data_interface(&state->private_store, guid, data);
137 static void STDMETHODCALLTYPE d3d11_blend_state_GetDesc(ID3D11BlendState *iface, D3D11_BLEND_DESC *desc)
139 struct d3d_blend_state *state = impl_from_ID3D11BlendState(iface);
141 TRACE("iface %p, desc %p.\n", iface, desc);
143 *desc = state->desc;
146 static const struct ID3D11BlendStateVtbl d3d11_blend_state_vtbl =
148 /* IUnknown methods */
149 d3d11_blend_state_QueryInterface,
150 d3d11_blend_state_AddRef,
151 d3d11_blend_state_Release,
152 /* ID3D11DeviceChild methods */
153 d3d11_blend_state_GetDevice,
154 d3d11_blend_state_GetPrivateData,
155 d3d11_blend_state_SetPrivateData,
156 d3d11_blend_state_SetPrivateDataInterface,
157 /* ID3D11BlendState methods */
158 d3d11_blend_state_GetDesc,
161 /* ID3D10BlendState methods */
163 static inline struct d3d_blend_state *impl_from_ID3D10BlendState(ID3D10BlendState1 *iface)
165 return CONTAINING_RECORD(iface, struct d3d_blend_state, ID3D10BlendState1_iface);
168 /* IUnknown methods */
170 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_QueryInterface(ID3D10BlendState1 *iface,
171 REFIID riid, void **object)
173 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
175 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
177 return d3d11_blend_state_QueryInterface(&state->ID3D11BlendState_iface, riid, object);
180 static ULONG STDMETHODCALLTYPE d3d10_blend_state_AddRef(ID3D10BlendState1 *iface)
182 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
184 TRACE("iface %p.\n", iface);
186 return d3d11_blend_state_AddRef(&state->ID3D11BlendState_iface);
189 static ULONG STDMETHODCALLTYPE d3d10_blend_state_Release(ID3D10BlendState1 *iface)
191 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
193 TRACE("iface %p.\n", iface);
195 return d3d11_blend_state_Release(&state->ID3D11BlendState_iface);
198 /* ID3D10DeviceChild methods */
200 static void STDMETHODCALLTYPE d3d10_blend_state_GetDevice(ID3D10BlendState1 *iface, ID3D10Device **device)
202 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
204 TRACE("iface %p, device %p.\n", iface, device);
206 ID3D11Device_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
209 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_GetPrivateData(ID3D10BlendState1 *iface,
210 REFGUID guid, UINT *data_size, void *data)
212 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
214 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
215 iface, debugstr_guid(guid), data_size, data);
217 return d3d_get_private_data(&state->private_store, guid, data_size, data);
220 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_SetPrivateData(ID3D10BlendState1 *iface,
221 REFGUID guid, UINT data_size, const void *data)
223 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
225 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
226 iface, debugstr_guid(guid), data_size, data);
228 return d3d_set_private_data(&state->private_store, guid, data_size, data);
231 static HRESULT STDMETHODCALLTYPE d3d10_blend_state_SetPrivateDataInterface(ID3D10BlendState1 *iface,
232 REFGUID guid, const IUnknown *data)
234 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
236 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
238 return d3d_set_private_data_interface(&state->private_store, guid, data);
241 /* ID3D10BlendState methods */
243 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc(ID3D10BlendState1 *iface, D3D10_BLEND_DESC *desc)
245 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
246 const D3D11_BLEND_DESC *d3d11_desc = &state->desc;
247 unsigned int i;
249 TRACE("iface %p, desc %p.\n", iface, desc);
251 desc->AlphaToCoverageEnable = d3d11_desc->AlphaToCoverageEnable;
252 desc->SrcBlend = d3d11_desc->RenderTarget[0].SrcBlend;
253 desc->DestBlend = d3d11_desc->RenderTarget[0].DestBlend;
254 desc->BlendOp = d3d11_desc->RenderTarget[0].BlendOp;
255 desc->SrcBlendAlpha = d3d11_desc->RenderTarget[0].SrcBlendAlpha;
256 desc->DestBlendAlpha = d3d11_desc->RenderTarget[0].DestBlendAlpha;
257 desc->BlendOpAlpha = d3d11_desc->RenderTarget[0].BlendOpAlpha;
258 for (i = 0; i < D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
260 desc->BlendEnable[i] = d3d11_desc->RenderTarget[i].BlendEnable;
261 desc->RenderTargetWriteMask[i] = d3d11_desc->RenderTarget[i].RenderTargetWriteMask;
265 static void STDMETHODCALLTYPE d3d10_blend_state_GetDesc1(ID3D10BlendState1 *iface, D3D10_BLEND_DESC1 *desc)
267 struct d3d_blend_state *state = impl_from_ID3D10BlendState(iface);
269 TRACE("iface %p, desc %p.\n", iface, desc);
271 memcpy(desc, &state->desc, sizeof(*desc));
274 static const struct ID3D10BlendState1Vtbl d3d10_blend_state_vtbl =
276 /* IUnknown methods */
277 d3d10_blend_state_QueryInterface,
278 d3d10_blend_state_AddRef,
279 d3d10_blend_state_Release,
280 /* ID3D10DeviceChild methods */
281 d3d10_blend_state_GetDevice,
282 d3d10_blend_state_GetPrivateData,
283 d3d10_blend_state_SetPrivateData,
284 d3d10_blend_state_SetPrivateDataInterface,
285 /* ID3D10BlendState methods */
286 d3d10_blend_state_GetDesc,
287 /* ID3D10BlendState1 methods */
288 d3d10_blend_state_GetDesc1,
291 static HRESULT d3d_blend_state_init(struct d3d_blend_state *state, struct d3d_device *device,
292 const D3D11_BLEND_DESC *desc)
294 state->ID3D11BlendState_iface.lpVtbl = &d3d11_blend_state_vtbl;
295 state->ID3D10BlendState1_iface.lpVtbl = &d3d10_blend_state_vtbl;
296 state->refcount = 1;
297 wined3d_private_store_init(&state->private_store);
298 state->desc = *desc;
300 state->device = &device->ID3D11Device_iface;
301 ID3D11Device_AddRef(state->device);
303 return S_OK;
306 HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC *desc,
307 struct d3d_blend_state **state)
309 struct d3d_blend_state *object;
310 struct wine_rb_entry *entry;
311 D3D11_BLEND_DESC tmp_desc;
312 unsigned int i, j;
313 HRESULT hr;
315 if (!desc)
316 return E_INVALIDARG;
318 /* D3D11_RENDER_TARGET_BLEND_DESC has a hole, which is a problem because we use
319 * D3D11_BLEND_DESC as a key in the rbtree. */
320 memset(&tmp_desc, 0, sizeof(tmp_desc));
321 tmp_desc.AlphaToCoverageEnable = desc->AlphaToCoverageEnable;
322 tmp_desc.IndependentBlendEnable = desc->IndependentBlendEnable;
323 for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
325 j = desc->IndependentBlendEnable ? i : 0;
326 tmp_desc.RenderTarget[i].BlendEnable = desc->RenderTarget[j].BlendEnable;
327 tmp_desc.RenderTarget[i].SrcBlend = desc->RenderTarget[j].SrcBlend;
328 tmp_desc.RenderTarget[i].DestBlend = desc->RenderTarget[j].DestBlend;
329 tmp_desc.RenderTarget[i].BlendOp = desc->RenderTarget[j].BlendOp;
330 tmp_desc.RenderTarget[i].SrcBlendAlpha = desc->RenderTarget[j].SrcBlendAlpha;
331 tmp_desc.RenderTarget[i].DestBlendAlpha = desc->RenderTarget[j].DestBlendAlpha;
332 tmp_desc.RenderTarget[i].BlendOpAlpha = desc->RenderTarget[j].BlendOpAlpha;
333 tmp_desc.RenderTarget[i].RenderTargetWriteMask = desc->RenderTarget[j].RenderTargetWriteMask;
335 if (i > 3 && tmp_desc.RenderTarget[i].RenderTargetWriteMask != D3D11_COLOR_WRITE_ENABLE_ALL)
336 FIXME("Color mask %#x not supported for render target %u.\n",
337 tmp_desc.RenderTarget[i].RenderTargetWriteMask, i);
340 /* glSampleCoverage() */
341 if (tmp_desc.AlphaToCoverageEnable)
342 FIXME("Ignoring AlphaToCoverageEnable %#x.\n", tmp_desc.AlphaToCoverageEnable);
343 /* glEnableIndexedEXT(GL_BLEND, ...) */
344 if (tmp_desc.IndependentBlendEnable)
345 FIXME("Per-rendertarget blend not implemented.\n");
347 wined3d_mutex_lock();
348 if ((entry = wine_rb_get(&device->blend_states, &tmp_desc)))
350 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_blend_state, entry);
352 TRACE("Returning existing blend state %p.\n", object);
353 ID3D11BlendState_AddRef(&object->ID3D11BlendState_iface);
354 *state = object;
355 wined3d_mutex_unlock();
357 return S_OK;
360 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
362 wined3d_mutex_unlock();
363 return E_OUTOFMEMORY;
366 if (FAILED(hr = d3d_blend_state_init(object, device, &tmp_desc)))
368 WARN("Failed to initialize blend state, hr %#x.\n", hr);
369 HeapFree(GetProcessHeap(), 0, object);
370 wined3d_mutex_unlock();
371 return hr;
374 if (wine_rb_put(&device->blend_states, desc, &object->entry) == -1)
376 ERR("Failed to insert blend state entry.\n");
377 d3d_blend_state_cleanup(object);
378 HeapFree(GetProcessHeap(), 0, object);
379 wined3d_mutex_unlock();
380 return E_FAIL;
382 wined3d_mutex_unlock();
384 TRACE("Created blend state %p.\n", object);
385 *state = object;
387 return S_OK;
390 struct d3d_blend_state *unsafe_impl_from_ID3D11BlendState(ID3D11BlendState *iface)
392 if (!iface)
393 return NULL;
394 assert(iface->lpVtbl == &d3d11_blend_state_vtbl);
396 return impl_from_ID3D11BlendState(iface);
399 struct d3d_blend_state *unsafe_impl_from_ID3D10BlendState(ID3D10BlendState *iface)
401 if (!iface)
402 return NULL;
403 assert(iface->lpVtbl == (ID3D10BlendStateVtbl *)&d3d10_blend_state_vtbl);
405 return impl_from_ID3D10BlendState((ID3D10BlendState1 *)iface);
408 /* ID3D11DepthStencilState methods */
410 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_QueryInterface(ID3D11DepthStencilState *iface,
411 REFIID riid, void **object)
413 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
415 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
417 if (IsEqualGUID(riid, &IID_ID3D11DepthStencilState)
418 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
419 || IsEqualGUID(riid, &IID_IUnknown))
421 ID3D11DepthStencilState_AddRef(iface);
422 *object = iface;
423 return S_OK;
426 if (IsEqualGUID(riid, &IID_ID3D10DepthStencilState)
427 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
429 ID3D10DepthStencilState_AddRef(&state->ID3D10DepthStencilState_iface);
430 *object = &state->ID3D10DepthStencilState_iface;
431 return S_OK;
434 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
436 *object = NULL;
437 return E_NOINTERFACE;
440 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_AddRef(ID3D11DepthStencilState *iface)
442 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
443 ULONG refcount = InterlockedIncrement(&state->refcount);
445 TRACE("%p increasing refcount to %u.\n", state, refcount);
447 return refcount;
450 static void d3d_depthstencil_state_cleanup(struct d3d_depthstencil_state *state)
452 wined3d_private_store_cleanup(&state->private_store);
453 ID3D11Device_Release(state->device);
456 static ULONG STDMETHODCALLTYPE d3d11_depthstencil_state_Release(ID3D11DepthStencilState *iface)
458 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
459 ULONG refcount = InterlockedDecrement(&state->refcount);
461 TRACE("%p decreasing refcount to %u.\n", state, refcount);
463 if (!refcount)
465 struct d3d_device *device = impl_from_ID3D11Device(state->device);
466 wined3d_mutex_lock();
467 wine_rb_remove(&device->depthstencil_states, &state->entry);
468 d3d_depthstencil_state_cleanup(state);
469 wined3d_mutex_unlock();
470 HeapFree(GetProcessHeap(), 0, state);
473 return refcount;
476 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDevice(ID3D11DepthStencilState *iface,
477 ID3D11Device **device)
479 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
481 TRACE("iface %p, device %p.\n", iface, device);
483 *device = state->device;
484 ID3D11Device_AddRef(*device);
487 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_GetPrivateData(ID3D11DepthStencilState *iface,
488 REFGUID guid, UINT *data_size, void *data)
490 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
492 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
494 return d3d_get_private_data(&state->private_store, guid, data_size, data);
497 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateData(ID3D11DepthStencilState *iface,
498 REFGUID guid, UINT data_size, const void *data)
500 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
502 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
504 return d3d_set_private_data(&state->private_store, guid, data_size, data);
507 static HRESULT STDMETHODCALLTYPE d3d11_depthstencil_state_SetPrivateDataInterface(ID3D11DepthStencilState *iface,
508 REFGUID guid, const IUnknown *data)
510 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
512 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
514 return d3d_set_private_data_interface(&state->private_store, guid, data);
517 static void STDMETHODCALLTYPE d3d11_depthstencil_state_GetDesc(ID3D11DepthStencilState *iface,
518 D3D11_DEPTH_STENCIL_DESC *desc)
520 struct d3d_depthstencil_state *state = impl_from_ID3D11DepthStencilState(iface);
522 TRACE("iface %p, desc %p.\n", iface, desc);
524 *desc = state->desc;
527 static const struct ID3D11DepthStencilStateVtbl d3d11_depthstencil_state_vtbl =
529 /* IUnknown methods */
530 d3d11_depthstencil_state_QueryInterface,
531 d3d11_depthstencil_state_AddRef,
532 d3d11_depthstencil_state_Release,
533 /* ID3D11DeviceChild methods */
534 d3d11_depthstencil_state_GetDevice,
535 d3d11_depthstencil_state_GetPrivateData,
536 d3d11_depthstencil_state_SetPrivateData,
537 d3d11_depthstencil_state_SetPrivateDataInterface,
538 /* ID3D11DepthStencilState methods */
539 d3d11_depthstencil_state_GetDesc,
542 /* ID3D10DepthStencilState methods */
544 static inline struct d3d_depthstencil_state *impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
546 return CONTAINING_RECORD(iface, struct d3d_depthstencil_state, ID3D10DepthStencilState_iface);
549 /* IUnknown methods */
551 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_QueryInterface(ID3D10DepthStencilState *iface,
552 REFIID riid, void **object)
554 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
556 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
558 return d3d11_depthstencil_state_QueryInterface(&state->ID3D11DepthStencilState_iface, riid, object);
561 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_AddRef(ID3D10DepthStencilState *iface)
563 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
565 TRACE("iface %p.\n", iface);
567 return d3d11_depthstencil_state_AddRef(&state->ID3D11DepthStencilState_iface);
570 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_state_Release(ID3D10DepthStencilState *iface)
572 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
574 TRACE("iface %p.\n", iface);
576 return d3d11_depthstencil_state_Release(&state->ID3D11DepthStencilState_iface);
579 /* ID3D10DeviceChild methods */
581 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDevice(ID3D10DepthStencilState *iface, ID3D10Device **device)
583 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
585 TRACE("iface %p, device %p.\n", iface, device);
587 ID3D11Device_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
590 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_GetPrivateData(ID3D10DepthStencilState *iface,
591 REFGUID guid, UINT *data_size, void *data)
593 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
595 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
596 iface, debugstr_guid(guid), data_size, data);
598 return d3d_get_private_data(&state->private_store, guid, data_size, data);
601 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateData(ID3D10DepthStencilState *iface,
602 REFGUID guid, UINT data_size, const void *data)
604 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
606 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
607 iface, debugstr_guid(guid), data_size, data);
609 return d3d_set_private_data(&state->private_store, guid, data_size, data);
612 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_state_SetPrivateDataInterface(ID3D10DepthStencilState *iface,
613 REFGUID guid, const IUnknown *data)
615 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
617 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
619 return d3d_set_private_data_interface(&state->private_store, guid, data);
622 /* ID3D10DepthStencilState methods */
624 static void STDMETHODCALLTYPE d3d10_depthstencil_state_GetDesc(ID3D10DepthStencilState *iface,
625 D3D10_DEPTH_STENCIL_DESC *desc)
627 struct d3d_depthstencil_state *state = impl_from_ID3D10DepthStencilState(iface);
629 TRACE("iface %p, desc %p.\n", iface, desc);
631 memcpy(desc, &state->desc, sizeof(*desc));
634 static const struct ID3D10DepthStencilStateVtbl d3d10_depthstencil_state_vtbl =
636 /* IUnknown methods */
637 d3d10_depthstencil_state_QueryInterface,
638 d3d10_depthstencil_state_AddRef,
639 d3d10_depthstencil_state_Release,
640 /* ID3D10DeviceChild methods */
641 d3d10_depthstencil_state_GetDevice,
642 d3d10_depthstencil_state_GetPrivateData,
643 d3d10_depthstencil_state_SetPrivateData,
644 d3d10_depthstencil_state_SetPrivateDataInterface,
645 /* ID3D10DepthStencilState methods */
646 d3d10_depthstencil_state_GetDesc,
649 static HRESULT d3d_depthstencil_state_init(struct d3d_depthstencil_state *state, struct d3d_device *device,
650 const D3D11_DEPTH_STENCIL_DESC *desc)
652 state->ID3D11DepthStencilState_iface.lpVtbl = &d3d11_depthstencil_state_vtbl;
653 state->ID3D10DepthStencilState_iface.lpVtbl = &d3d10_depthstencil_state_vtbl;
654 state->refcount = 1;
655 wined3d_private_store_init(&state->private_store);
656 state->desc = *desc;
658 state->device = &device->ID3D11Device_iface;
659 ID3D11Device_AddRef(state->device);
661 return S_OK;
664 HRESULT d3d_depthstencil_state_create(struct d3d_device *device, const D3D11_DEPTH_STENCIL_DESC *desc,
665 struct d3d_depthstencil_state **state)
667 struct d3d_depthstencil_state *object;
668 D3D11_DEPTH_STENCIL_DESC tmp_desc;
669 struct wine_rb_entry *entry;
670 HRESULT hr;
672 if (!desc)
673 return E_INVALIDARG;
675 /* D3D11_DEPTH_STENCIL_DESC has a hole, which is a problem because we use
676 * it as a key in the rbtree. */
677 memset(&tmp_desc, 0, sizeof(tmp_desc));
678 tmp_desc.DepthEnable = desc->DepthEnable;
679 if (desc->DepthEnable)
681 tmp_desc.DepthWriteMask = desc->DepthWriteMask;
682 tmp_desc.DepthFunc = desc->DepthFunc;
684 else
686 tmp_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
687 tmp_desc.DepthFunc = D3D11_COMPARISON_LESS;
689 tmp_desc.StencilEnable = desc->StencilEnable;
690 if (desc->StencilEnable)
692 tmp_desc.StencilReadMask = desc->StencilReadMask;
693 tmp_desc.StencilWriteMask = desc->StencilWriteMask;
694 tmp_desc.FrontFace = desc->FrontFace;
695 tmp_desc.BackFace = desc->BackFace;
697 else
699 tmp_desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
700 tmp_desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
701 tmp_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
702 tmp_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
703 tmp_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
704 tmp_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
705 tmp_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
706 tmp_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
707 tmp_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
708 tmp_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
711 wined3d_mutex_lock();
712 if ((entry = wine_rb_get(&device->depthstencil_states, &tmp_desc)))
714 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_depthstencil_state, entry);
716 TRACE("Returning existing depthstencil state %p.\n", object);
717 ID3D11DepthStencilState_AddRef(&object->ID3D11DepthStencilState_iface);
718 *state = object;
719 wined3d_mutex_unlock();
721 return S_OK;
724 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
726 wined3d_mutex_unlock();
727 return E_OUTOFMEMORY;
730 if (FAILED(hr = d3d_depthstencil_state_init(object, device, &tmp_desc)))
732 WARN("Failed to initialize depthstencil state, hr %#x.\n", hr);
733 HeapFree(GetProcessHeap(), 0, object);
734 wined3d_mutex_unlock();
735 return hr;
738 if (wine_rb_put(&device->depthstencil_states, desc, &object->entry) == -1)
740 ERR("Failed to insert depthstencil state entry.\n");
741 d3d_depthstencil_state_cleanup(object);
742 HeapFree(GetProcessHeap(), 0, object);
743 wined3d_mutex_unlock();
744 return E_FAIL;
746 wined3d_mutex_unlock();
748 TRACE("Created depthstencil state %p.\n", object);
749 *state = object;
751 return S_OK;
754 struct d3d_depthstencil_state *unsafe_impl_from_ID3D11DepthStencilState(ID3D11DepthStencilState *iface)
756 if (!iface)
757 return NULL;
758 assert(iface->lpVtbl == &d3d11_depthstencil_state_vtbl);
760 return impl_from_ID3D11DepthStencilState(iface);
763 struct d3d_depthstencil_state *unsafe_impl_from_ID3D10DepthStencilState(ID3D10DepthStencilState *iface)
765 if (!iface)
766 return NULL;
767 assert(iface->lpVtbl == &d3d10_depthstencil_state_vtbl);
769 return impl_from_ID3D10DepthStencilState(iface);
772 /* ID3D11RasterizerState methods */
774 static inline struct d3d_rasterizer_state *impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
776 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D11RasterizerState_iface);
779 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_QueryInterface(ID3D11RasterizerState *iface,
780 REFIID riid, void **object)
782 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
784 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
786 if (IsEqualGUID(riid, &IID_ID3D11RasterizerState)
787 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
788 || IsEqualGUID(riid, &IID_IUnknown))
790 ID3D11RasterizerState_AddRef(iface);
791 *object = iface;
792 return S_OK;
795 if (IsEqualGUID(riid, &IID_ID3D10RasterizerState)
796 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
798 ID3D10RasterizerState_AddRef(&state->ID3D10RasterizerState_iface);
799 *object = &state->ID3D10RasterizerState_iface;
800 return S_OK;
803 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
805 *object = NULL;
806 return E_NOINTERFACE;
809 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_AddRef(ID3D11RasterizerState *iface)
811 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
812 ULONG refcount = InterlockedIncrement(&state->refcount);
814 TRACE("%p increasing refcount to %u.\n", state, refcount);
816 if (refcount == 1)
818 ID3D11Device_AddRef(state->device);
819 wined3d_mutex_lock();
820 wined3d_rasterizer_state_incref(state->wined3d_state);
821 wined3d_mutex_unlock();
824 return refcount;
827 static ULONG STDMETHODCALLTYPE d3d11_rasterizer_state_Release(ID3D11RasterizerState *iface)
829 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
830 ULONG refcount = InterlockedDecrement(&state->refcount);
832 TRACE("%p decreasing refcount to %u.\n", state, refcount);
834 if (!refcount)
836 ID3D11Device *device = state->device;
838 wined3d_mutex_lock();
839 wined3d_rasterizer_state_decref(state->wined3d_state);
840 wined3d_mutex_unlock();
842 ID3D11Device_Release(device);
845 return refcount;
848 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDevice(ID3D11RasterizerState *iface,
849 ID3D11Device **device)
851 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
853 TRACE("iface %p, device %p.\n", iface, device);
855 *device = state->device;
856 ID3D11Device_AddRef(*device);
859 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_GetPrivateData(ID3D11RasterizerState *iface,
860 REFGUID guid, UINT *data_size, void *data)
862 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
864 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
866 return d3d_get_private_data(&state->private_store, guid, data_size, data);
869 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateData(ID3D11RasterizerState *iface,
870 REFGUID guid, UINT data_size, const void *data)
872 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
874 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
876 return d3d_set_private_data(&state->private_store, guid, data_size, data);
879 static HRESULT STDMETHODCALLTYPE d3d11_rasterizer_state_SetPrivateDataInterface(ID3D11RasterizerState *iface,
880 REFGUID guid, const IUnknown *data)
882 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
884 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
886 return d3d_set_private_data_interface(&state->private_store, guid, data);
889 static void STDMETHODCALLTYPE d3d11_rasterizer_state_GetDesc(ID3D11RasterizerState *iface,
890 D3D11_RASTERIZER_DESC *desc)
892 struct d3d_rasterizer_state *state = impl_from_ID3D11RasterizerState(iface);
894 TRACE("iface %p, desc %p.\n", iface, desc);
896 *desc = state->desc;
899 static const struct ID3D11RasterizerStateVtbl d3d11_rasterizer_state_vtbl =
901 /* IUnknown methods */
902 d3d11_rasterizer_state_QueryInterface,
903 d3d11_rasterizer_state_AddRef,
904 d3d11_rasterizer_state_Release,
905 /* ID3D11DeviceChild methods */
906 d3d11_rasterizer_state_GetDevice,
907 d3d11_rasterizer_state_GetPrivateData,
908 d3d11_rasterizer_state_SetPrivateData,
909 d3d11_rasterizer_state_SetPrivateDataInterface,
910 /* ID3D11RasterizerState methods */
911 d3d11_rasterizer_state_GetDesc,
914 /* ID3D10RasterizerState methods */
916 static inline struct d3d_rasterizer_state *impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
918 return CONTAINING_RECORD(iface, struct d3d_rasterizer_state, ID3D10RasterizerState_iface);
921 /* IUnknown methods */
923 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_QueryInterface(ID3D10RasterizerState *iface,
924 REFIID riid, void **object)
926 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
928 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
930 return d3d11_rasterizer_state_QueryInterface(&state->ID3D11RasterizerState_iface, riid, object);
933 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_AddRef(ID3D10RasterizerState *iface)
935 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
937 TRACE("iface %p.\n", iface);
939 return d3d11_rasterizer_state_AddRef(&state->ID3D11RasterizerState_iface);
942 static ULONG STDMETHODCALLTYPE d3d10_rasterizer_state_Release(ID3D10RasterizerState *iface)
944 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
946 TRACE("iface %p.\n", state);
948 return d3d11_rasterizer_state_Release(&state->ID3D11RasterizerState_iface);
951 /* ID3D10DeviceChild methods */
953 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDevice(ID3D10RasterizerState *iface, ID3D10Device **device)
955 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
957 TRACE("iface %p, device %p.\n", iface, device);
959 ID3D11Device_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
962 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_GetPrivateData(ID3D10RasterizerState *iface,
963 REFGUID guid, UINT *data_size, void *data)
965 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
967 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
968 iface, debugstr_guid(guid), data_size, data);
970 return d3d_get_private_data(&state->private_store, guid, data_size, data);
973 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateData(ID3D10RasterizerState *iface,
974 REFGUID guid, UINT data_size, const void *data)
976 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
978 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
979 iface, debugstr_guid(guid), data_size, data);
981 return d3d_set_private_data(&state->private_store, guid, data_size, data);
984 static HRESULT STDMETHODCALLTYPE d3d10_rasterizer_state_SetPrivateDataInterface(ID3D10RasterizerState *iface,
985 REFGUID guid, const IUnknown *data)
987 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
989 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
991 return d3d_set_private_data_interface(&state->private_store, guid, data);
994 /* ID3D10RasterizerState methods */
996 static void STDMETHODCALLTYPE d3d10_rasterizer_state_GetDesc(ID3D10RasterizerState *iface,
997 D3D10_RASTERIZER_DESC *desc)
999 struct d3d_rasterizer_state *state = impl_from_ID3D10RasterizerState(iface);
1001 TRACE("iface %p, desc %p.\n", iface, desc);
1003 memcpy(desc, &state->desc, sizeof(*desc));
1006 static const struct ID3D10RasterizerStateVtbl d3d10_rasterizer_state_vtbl =
1008 /* IUnknown methods */
1009 d3d10_rasterizer_state_QueryInterface,
1010 d3d10_rasterizer_state_AddRef,
1011 d3d10_rasterizer_state_Release,
1012 /* ID3D10DeviceChild methods */
1013 d3d10_rasterizer_state_GetDevice,
1014 d3d10_rasterizer_state_GetPrivateData,
1015 d3d10_rasterizer_state_SetPrivateData,
1016 d3d10_rasterizer_state_SetPrivateDataInterface,
1017 /* ID3D10RasterizerState methods */
1018 d3d10_rasterizer_state_GetDesc,
1021 static void STDMETHODCALLTYPE d3d_rasterizer_state_wined3d_object_destroyed(void *parent)
1023 struct d3d_rasterizer_state *state = parent;
1024 struct d3d_device *device = impl_from_ID3D11Device(state->device);
1026 wine_rb_remove(&device->rasterizer_states, &state->entry);
1027 wined3d_private_store_cleanup(&state->private_store);
1028 HeapFree(GetProcessHeap(), 0, parent);
1031 static const struct wined3d_parent_ops d3d_rasterizer_state_wined3d_parent_ops =
1033 d3d_rasterizer_state_wined3d_object_destroyed,
1036 static HRESULT d3d_rasterizer_state_init(struct d3d_rasterizer_state *state, struct d3d_device *device,
1037 const D3D11_RASTERIZER_DESC *desc)
1039 struct wined3d_rasterizer_state_desc wined3d_desc;
1040 HRESULT hr;
1042 state->ID3D11RasterizerState_iface.lpVtbl = &d3d11_rasterizer_state_vtbl;
1043 state->ID3D10RasterizerState_iface.lpVtbl = &d3d10_rasterizer_state_vtbl;
1044 state->refcount = 1;
1045 wined3d_private_store_init(&state->private_store);
1046 state->desc = *desc;
1048 if (wine_rb_put(&device->rasterizer_states, desc, &state->entry) == -1)
1050 ERR("Failed to insert rasterizer state entry.\n");
1051 wined3d_private_store_cleanup(&state->private_store);
1052 return E_FAIL;
1055 wined3d_desc.front_ccw = desc->FrontCounterClockwise;
1057 /* We cannot fail after creating a wined3d_rasterizer_state object. It
1058 * would lead to double free. */
1059 if (FAILED(hr = wined3d_rasterizer_state_create(device->wined3d_device, &wined3d_desc,
1060 state, &d3d_rasterizer_state_wined3d_parent_ops, &state->wined3d_state)))
1062 WARN("Failed to create wined3d rasterizer state, hr %#x.\n", hr);
1063 wined3d_private_store_cleanup(&state->private_store);
1064 wine_rb_remove(&device->rasterizer_states, &state->entry);
1065 return hr;
1068 ID3D11Device_AddRef(state->device = &device->ID3D11Device_iface);
1070 return S_OK;
1073 HRESULT d3d_rasterizer_state_create(struct d3d_device *device, const D3D11_RASTERIZER_DESC *desc,
1074 struct d3d_rasterizer_state **state)
1076 struct d3d_rasterizer_state *object;
1077 struct wine_rb_entry *entry;
1078 HRESULT hr;
1080 if (!desc)
1081 return E_INVALIDARG;
1083 wined3d_mutex_lock();
1084 if ((entry = wine_rb_get(&device->rasterizer_states, desc)))
1086 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_rasterizer_state, entry);
1088 TRACE("Returning existing rasterizer state %p.\n", object);
1089 ID3D11RasterizerState_AddRef(&object->ID3D11RasterizerState_iface);
1090 *state = object;
1091 wined3d_mutex_unlock();
1093 return S_OK;
1096 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
1098 wined3d_mutex_unlock();
1099 return E_OUTOFMEMORY;
1102 hr = d3d_rasterizer_state_init(object, device, desc);
1103 wined3d_mutex_unlock();
1104 if (FAILED(hr))
1106 WARN("Failed to initialize rasterizer state, hr %#x.\n", hr);
1107 HeapFree(GetProcessHeap(), 0, object);
1108 return hr;
1111 TRACE("Created rasterizer state %p.\n", object);
1112 *state = object;
1114 return S_OK;
1117 struct d3d_rasterizer_state *unsafe_impl_from_ID3D11RasterizerState(ID3D11RasterizerState *iface)
1119 if (!iface)
1120 return NULL;
1121 assert(iface->lpVtbl == &d3d11_rasterizer_state_vtbl);
1123 return impl_from_ID3D11RasterizerState(iface);
1126 struct d3d_rasterizer_state *unsafe_impl_from_ID3D10RasterizerState(ID3D10RasterizerState *iface)
1128 if (!iface)
1129 return NULL;
1130 assert(iface->lpVtbl == &d3d10_rasterizer_state_vtbl);
1132 return impl_from_ID3D10RasterizerState(iface);
1135 /* ID3D11SampleState methods */
1137 static inline struct d3d_sampler_state *impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1139 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D11SamplerState_iface);
1142 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_QueryInterface(ID3D11SamplerState *iface,
1143 REFIID riid, void **object)
1145 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1147 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1149 if (IsEqualGUID(riid, &IID_ID3D11SamplerState)
1150 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
1151 || IsEqualGUID(riid, &IID_IUnknown))
1153 ID3D11SamplerState_AddRef(iface);
1154 *object = iface;
1155 return S_OK;
1158 if (IsEqualGUID(riid, &IID_ID3D10SamplerState)
1159 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
1161 ID3D10SamplerState_AddRef(&state->ID3D10SamplerState_iface);
1162 *object = &state->ID3D10SamplerState_iface;
1163 return S_OK;
1166 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1168 *object = NULL;
1169 return E_NOINTERFACE;
1172 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_AddRef(ID3D11SamplerState *iface)
1174 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1175 ULONG refcount = InterlockedIncrement(&state->refcount);
1177 TRACE("%p increasing refcount to %u.\n", state, refcount);
1179 if (refcount == 1)
1181 ID3D11Device_AddRef(state->device);
1182 wined3d_mutex_lock();
1183 wined3d_sampler_incref(state->wined3d_sampler);
1184 wined3d_mutex_unlock();
1187 return refcount;
1190 static ULONG STDMETHODCALLTYPE d3d11_sampler_state_Release(ID3D11SamplerState *iface)
1192 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1193 ULONG refcount = InterlockedDecrement(&state->refcount);
1195 TRACE("%p decreasing refcount to %u.\n", state, refcount);
1197 if (!refcount)
1199 ID3D11Device *device = state->device;
1201 wined3d_mutex_lock();
1202 wined3d_sampler_decref(state->wined3d_sampler);
1203 wined3d_mutex_unlock();
1205 ID3D11Device_Release(device);
1208 return refcount;
1211 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDevice(ID3D11SamplerState *iface,
1212 ID3D11Device **device)
1214 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1216 TRACE("iface %p, device %p.\n", iface, device);
1218 *device = state->device;
1219 ID3D11Device_AddRef(*device);
1222 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_GetPrivateData(ID3D11SamplerState *iface,
1223 REFGUID guid, UINT *data_size, void *data)
1225 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1227 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1229 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1232 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateData(ID3D11SamplerState *iface,
1233 REFGUID guid, UINT data_size, const void *data)
1235 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1237 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
1239 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1242 static HRESULT STDMETHODCALLTYPE d3d11_sampler_state_SetPrivateDataInterface(ID3D11SamplerState *iface,
1243 REFGUID guid, const IUnknown *data)
1245 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1247 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1249 return d3d_set_private_data_interface(&state->private_store, guid, data);
1252 static void STDMETHODCALLTYPE d3d11_sampler_state_GetDesc(ID3D11SamplerState *iface,
1253 D3D11_SAMPLER_DESC *desc)
1255 struct d3d_sampler_state *state = impl_from_ID3D11SamplerState(iface);
1257 TRACE("iface %p, desc %p.\n", iface, desc);
1259 *desc = state->desc;
1262 static const struct ID3D11SamplerStateVtbl d3d11_sampler_state_vtbl =
1264 /* IUnknown methods */
1265 d3d11_sampler_state_QueryInterface,
1266 d3d11_sampler_state_AddRef,
1267 d3d11_sampler_state_Release,
1268 /* ID3D11DeviceChild methods */
1269 d3d11_sampler_state_GetDevice,
1270 d3d11_sampler_state_GetPrivateData,
1271 d3d11_sampler_state_SetPrivateData,
1272 d3d11_sampler_state_SetPrivateDataInterface,
1273 /* ID3D11SamplerState methods */
1274 d3d11_sampler_state_GetDesc,
1277 /* ID3D10SamplerState methods */
1279 static inline struct d3d_sampler_state *impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1281 return CONTAINING_RECORD(iface, struct d3d_sampler_state, ID3D10SamplerState_iface);
1284 /* IUnknown methods */
1286 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_QueryInterface(ID3D10SamplerState *iface,
1287 REFIID riid, void **object)
1289 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1291 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1293 return d3d11_sampler_state_QueryInterface(&state->ID3D11SamplerState_iface, riid, object);
1296 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_AddRef(ID3D10SamplerState *iface)
1298 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1300 TRACE("iface %p.\n", iface);
1302 return d3d11_sampler_state_AddRef(&state->ID3D11SamplerState_iface);
1305 static ULONG STDMETHODCALLTYPE d3d10_sampler_state_Release(ID3D10SamplerState *iface)
1307 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1309 TRACE("iface %p.\n", iface);
1311 return d3d11_sampler_state_Release(&state->ID3D11SamplerState_iface);
1314 /* ID3D10DeviceChild methods */
1316 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDevice(ID3D10SamplerState *iface, ID3D10Device **device)
1318 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1320 TRACE("iface %p, device %p.\n", iface, device);
1322 ID3D11Device_QueryInterface(state->device, &IID_ID3D10Device, (void **)device);
1325 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_GetPrivateData(ID3D10SamplerState *iface,
1326 REFGUID guid, UINT *data_size, void *data)
1328 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1330 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
1331 iface, debugstr_guid(guid), data_size, data);
1333 return d3d_get_private_data(&state->private_store, guid, data_size, data);
1336 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateData(ID3D10SamplerState *iface,
1337 REFGUID guid, UINT data_size, const void *data)
1339 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1341 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
1342 iface, debugstr_guid(guid), data_size, data);
1344 return d3d_set_private_data(&state->private_store, guid, data_size, data);
1347 static HRESULT STDMETHODCALLTYPE d3d10_sampler_state_SetPrivateDataInterface(ID3D10SamplerState *iface,
1348 REFGUID guid, const IUnknown *data)
1350 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1352 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
1354 return d3d_set_private_data_interface(&state->private_store, guid, data);
1357 /* ID3D10SamplerState methods */
1359 static void STDMETHODCALLTYPE d3d10_sampler_state_GetDesc(ID3D10SamplerState *iface,
1360 D3D10_SAMPLER_DESC *desc)
1362 struct d3d_sampler_state *state = impl_from_ID3D10SamplerState(iface);
1364 TRACE("iface %p, desc %p.\n", iface, desc);
1366 memcpy(desc, &state->desc, sizeof(*desc));
1369 static const struct ID3D10SamplerStateVtbl d3d10_sampler_state_vtbl =
1371 /* IUnknown methods */
1372 d3d10_sampler_state_QueryInterface,
1373 d3d10_sampler_state_AddRef,
1374 d3d10_sampler_state_Release,
1375 /* ID3D10DeviceChild methods */
1376 d3d10_sampler_state_GetDevice,
1377 d3d10_sampler_state_GetPrivateData,
1378 d3d10_sampler_state_SetPrivateData,
1379 d3d10_sampler_state_SetPrivateDataInterface,
1380 /* ID3D10SamplerState methods */
1381 d3d10_sampler_state_GetDesc,
1384 static void STDMETHODCALLTYPE d3d_sampler_wined3d_object_destroyed(void *parent)
1386 struct d3d_sampler_state *state = parent;
1387 struct d3d_device *device = impl_from_ID3D11Device(state->device);
1389 wine_rb_remove(&device->sampler_states, &state->entry);
1390 wined3d_private_store_cleanup(&state->private_store);
1391 HeapFree(GetProcessHeap(), 0, parent);
1394 static const struct wined3d_parent_ops d3d_sampler_wined3d_parent_ops =
1396 d3d_sampler_wined3d_object_destroyed,
1399 static enum wined3d_texture_address wined3d_texture_address_from_d3d11(enum D3D11_TEXTURE_ADDRESS_MODE t)
1401 return (enum wined3d_texture_address)t;
1404 static enum wined3d_texture_filter_type wined3d_texture_filter_mip_from_d3d11(enum D3D11_FILTER f)
1406 if (D3D11_DECODE_MIP_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1407 return WINED3D_TEXF_LINEAR;
1408 return WINED3D_TEXF_POINT;
1411 static enum wined3d_texture_filter_type wined3d_texture_filter_mag_from_d3d11(enum D3D11_FILTER f)
1413 if (D3D11_DECODE_MAG_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1414 return WINED3D_TEXF_LINEAR;
1415 return WINED3D_TEXF_POINT;
1418 static enum wined3d_texture_filter_type wined3d_texture_filter_min_from_d3d11(enum D3D11_FILTER f)
1420 if (D3D11_DECODE_MIN_FILTER(f) == D3D11_FILTER_TYPE_LINEAR)
1421 return WINED3D_TEXF_LINEAR;
1422 return WINED3D_TEXF_POINT;
1425 static BOOL wined3d_texture_compare_from_d3d11(enum D3D11_FILTER f)
1427 return D3D11_DECODE_IS_COMPARISON_FILTER(f);
1430 static enum wined3d_cmp_func wined3d_cmp_func_from_d3d11(D3D11_COMPARISON_FUNC f)
1432 return (enum wined3d_cmp_func)f;
1435 static HRESULT d3d_sampler_state_init(struct d3d_sampler_state *state, struct d3d_device *device,
1436 const D3D11_SAMPLER_DESC *desc)
1438 struct wined3d_sampler_desc wined3d_desc;
1439 HRESULT hr;
1441 state->ID3D11SamplerState_iface.lpVtbl = &d3d11_sampler_state_vtbl;
1442 state->ID3D10SamplerState_iface.lpVtbl = &d3d10_sampler_state_vtbl;
1443 state->refcount = 1;
1444 wined3d_private_store_init(&state->private_store);
1445 state->desc = *desc;
1447 wined3d_desc.address_u = wined3d_texture_address_from_d3d11(desc->AddressU);
1448 wined3d_desc.address_v = wined3d_texture_address_from_d3d11(desc->AddressV);
1449 wined3d_desc.address_w = wined3d_texture_address_from_d3d11(desc->AddressW);
1450 memcpy(wined3d_desc.border_color, desc->BorderColor, sizeof(wined3d_desc.border_color));
1451 wined3d_desc.mag_filter = wined3d_texture_filter_mag_from_d3d11(desc->Filter);
1452 wined3d_desc.min_filter = wined3d_texture_filter_min_from_d3d11(desc->Filter);
1453 wined3d_desc.mip_filter = wined3d_texture_filter_mip_from_d3d11(desc->Filter);
1454 wined3d_desc.lod_bias = desc->MipLODBias;
1455 wined3d_desc.min_lod = desc->MinLOD;
1456 wined3d_desc.max_lod = desc->MaxLOD;
1457 wined3d_desc.mip_base_level = 0;
1458 wined3d_desc.max_anisotropy = D3D11_DECODE_IS_ANISOTROPIC_FILTER(desc->Filter) ? desc->MaxAnisotropy : 1;
1459 wined3d_desc.compare = wined3d_texture_compare_from_d3d11(desc->Filter);
1460 wined3d_desc.comparison_func = wined3d_cmp_func_from_d3d11(desc->ComparisonFunc);
1461 wined3d_desc.srgb_decode = TRUE;
1463 if (wine_rb_put(&device->sampler_states, desc, &state->entry) == -1)
1465 ERR("Failed to insert sampler state entry.\n");
1466 wined3d_private_store_cleanup(&state->private_store);
1467 return E_FAIL;
1470 /* We cannot fail after creating a wined3d_sampler object. It would lead to
1471 * double free. */
1472 if (FAILED(hr = wined3d_sampler_create(device->wined3d_device, &wined3d_desc,
1473 state, &d3d_sampler_wined3d_parent_ops, &state->wined3d_sampler)))
1475 WARN("Failed to create wined3d sampler, hr %#x.\n", hr);
1476 wined3d_private_store_cleanup(&state->private_store);
1477 wine_rb_remove(&device->sampler_states, &state->entry);
1478 return hr;
1481 state->device = &device->ID3D11Device_iface;
1482 ID3D11Device_AddRef(state->device);
1484 return S_OK;
1487 HRESULT d3d_sampler_state_create(struct d3d_device *device, const D3D11_SAMPLER_DESC *desc,
1488 struct d3d_sampler_state **state)
1490 D3D11_SAMPLER_DESC normalized_desc;
1491 struct d3d_sampler_state *object;
1492 struct wine_rb_entry *entry;
1493 HRESULT hr;
1495 if (!desc)
1496 return E_INVALIDARG;
1498 normalized_desc = *desc;
1499 if (!D3D11_DECODE_IS_ANISOTROPIC_FILTER(normalized_desc.Filter))
1500 normalized_desc.MaxAnisotropy = 0;
1501 if (!D3D11_DECODE_IS_COMPARISON_FILTER(normalized_desc.Filter))
1502 normalized_desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
1503 if (normalized_desc.AddressU != D3D11_TEXTURE_ADDRESS_BORDER
1504 && normalized_desc.AddressV != D3D11_TEXTURE_ADDRESS_BORDER
1505 && normalized_desc.AddressW != D3D11_TEXTURE_ADDRESS_BORDER)
1506 memset(&normalized_desc.BorderColor, 0, sizeof(normalized_desc.BorderColor));
1508 wined3d_mutex_lock();
1509 if ((entry = wine_rb_get(&device->sampler_states, &normalized_desc)))
1511 object = WINE_RB_ENTRY_VALUE(entry, struct d3d_sampler_state, entry);
1513 TRACE("Returning existing sampler state %p.\n", object);
1514 ID3D11SamplerState_AddRef(&object->ID3D11SamplerState_iface);
1515 *state = object;
1516 wined3d_mutex_unlock();
1518 return S_OK;
1521 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
1523 wined3d_mutex_unlock();
1524 return E_OUTOFMEMORY;
1527 hr = d3d_sampler_state_init(object, device, &normalized_desc);
1528 wined3d_mutex_unlock();
1529 if (FAILED(hr))
1531 WARN("Failed to initialize sampler state, hr %#x.\n", hr);
1532 HeapFree(GetProcessHeap(), 0, object);
1533 return hr;
1536 TRACE("Created sampler state %p.\n", object);
1537 *state = object;
1539 return S_OK;
1542 struct d3d_sampler_state *unsafe_impl_from_ID3D11SamplerState(ID3D11SamplerState *iface)
1544 if (!iface)
1545 return NULL;
1546 assert(iface->lpVtbl == &d3d11_sampler_state_vtbl);
1548 return impl_from_ID3D11SamplerState(iface);
1551 struct d3d_sampler_state *unsafe_impl_from_ID3D10SamplerState(ID3D10SamplerState *iface)
1553 if (!iface)
1554 return NULL;
1555 assert(iface->lpVtbl == &d3d10_sampler_state_vtbl);
1557 return impl_from_ID3D10SamplerState(iface);