gdi32: Fix leak in GdiDeleteSpoolFileHandle.
[wine.git] / dlls / d3d11 / buffer.c
blob971fab0533e850c7628e7a91897c0231d42da7fc
1 /*
2 * Copyright 2009 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "d3d11_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
24 /* ID3D11Buffer methods */
26 static inline struct d3d_buffer *impl_from_ID3D11Buffer(ID3D11Buffer *iface)
28 return CONTAINING_RECORD(iface, struct d3d_buffer, ID3D11Buffer_iface);
31 static HRESULT STDMETHODCALLTYPE d3d11_buffer_QueryInterface(ID3D11Buffer *iface, REFIID riid, void **out)
33 struct d3d_buffer *buffer = impl_from_ID3D11Buffer(iface);
34 HRESULT hr;
36 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
38 if (IsEqualGUID(riid, &IID_ID3D11Buffer)
39 || IsEqualGUID(riid, &IID_ID3D11Resource)
40 || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
41 || IsEqualGUID(riid, &IID_IUnknown))
43 ID3D11Buffer_AddRef(iface);
44 *out = iface;
45 return S_OK;
48 if (IsEqualGUID(riid, &IID_ID3D10Buffer)
49 || IsEqualGUID(riid, &IID_ID3D10Resource)
50 || IsEqualGUID(riid, &IID_ID3D10DeviceChild))
52 ID3D10Buffer_AddRef(&buffer->ID3D10Buffer_iface);
53 *out = &buffer->ID3D10Buffer_iface;
54 return S_OK;
57 if (FAILED(hr = IUnknown_QueryInterface(buffer->dxgi_resource, riid, out)))
59 WARN("%s not implemented, returning %#lx.\n", debugstr_guid(riid), hr);
60 *out = NULL;
63 return hr;
66 static ULONG STDMETHODCALLTYPE d3d11_buffer_AddRef(ID3D11Buffer *iface)
68 struct d3d_buffer *buffer = impl_from_ID3D11Buffer(iface);
69 ULONG refcount = InterlockedIncrement(&buffer->refcount);
71 TRACE("%p increasing refcount to %lu.\n", buffer, refcount);
73 if (refcount == 1)
75 ID3D11Device2_AddRef(buffer->device);
76 wined3d_buffer_incref(buffer->wined3d_buffer);
79 return refcount;
82 static ULONG STDMETHODCALLTYPE d3d11_buffer_Release(ID3D11Buffer *iface)
84 struct d3d_buffer *buffer = impl_from_ID3D11Buffer(iface);
85 ULONG refcount = InterlockedDecrement(&buffer->refcount);
87 TRACE("%p decreasing refcount to %lu.\n", buffer, refcount);
89 if (!refcount)
91 ID3D11Device2 *device = buffer->device;
93 wined3d_buffer_decref(buffer->wined3d_buffer);
94 /* Release the device last, it may cause the wined3d device to be
95 * destroyed. */
96 ID3D11Device2_Release(device);
99 return refcount;
102 static void STDMETHODCALLTYPE d3d11_buffer_GetDevice(ID3D11Buffer *iface, ID3D11Device **device)
104 struct d3d_buffer *buffer = impl_from_ID3D11Buffer(iface);
106 TRACE("iface %p, device %p.\n", iface, device);
108 *device = (ID3D11Device *)buffer->device;
109 ID3D11Device_AddRef(*device);
112 static HRESULT STDMETHODCALLTYPE d3d11_buffer_GetPrivateData(ID3D11Buffer *iface,
113 REFGUID guid, UINT *data_size, void *data)
115 struct d3d_buffer *buffer = impl_from_ID3D11Buffer(iface);
116 IDXGIResource *dxgi_resource;
117 HRESULT hr;
119 TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
121 if (SUCCEEDED(hr = IUnknown_QueryInterface(buffer->dxgi_resource, &IID_IDXGIResource, (void **)&dxgi_resource)))
123 hr = IDXGIResource_GetPrivateData(dxgi_resource, guid, data_size, data);
124 IDXGIResource_Release(dxgi_resource);
127 return hr;
130 static HRESULT STDMETHODCALLTYPE d3d11_buffer_SetPrivateData(ID3D11Buffer *iface,
131 REFGUID guid, UINT data_size, const void *data)
133 struct d3d_buffer *buffer = impl_from_ID3D11Buffer(iface);
134 IDXGIResource *dxgi_resource;
135 HRESULT hr;
137 TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
139 if (SUCCEEDED(hr = IUnknown_QueryInterface(buffer->dxgi_resource, &IID_IDXGIResource, (void **)&dxgi_resource)))
141 hr = IDXGIResource_SetPrivateData(dxgi_resource, guid, data_size, data);
142 IDXGIResource_Release(dxgi_resource);
145 return hr;
148 static HRESULT STDMETHODCALLTYPE d3d11_buffer_SetPrivateDataInterface(ID3D11Buffer *iface,
149 REFGUID guid, const IUnknown *data)
151 struct d3d_buffer *buffer = impl_from_ID3D11Buffer(iface);
152 IDXGIResource *dxgi_resource;
153 HRESULT hr;
155 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
157 if (SUCCEEDED(hr = IUnknown_QueryInterface(buffer->dxgi_resource, &IID_IDXGIResource, (void **)&dxgi_resource)))
159 hr = IDXGIResource_SetPrivateDataInterface(dxgi_resource, guid, data);
160 IDXGIResource_Release(dxgi_resource);
163 return hr;
166 static void STDMETHODCALLTYPE d3d11_buffer_GetType(ID3D11Buffer *iface,
167 D3D11_RESOURCE_DIMENSION *resource_dimension)
169 TRACE("iface %p, resource_dimension %p.\n", iface, resource_dimension);
171 *resource_dimension = D3D11_RESOURCE_DIMENSION_BUFFER;
174 static void STDMETHODCALLTYPE d3d11_buffer_SetEvictionPriority(ID3D11Buffer *iface, UINT eviction_priority)
176 FIXME("iface %p, eviction_priority %#x stub!\n", iface, eviction_priority);
179 static UINT STDMETHODCALLTYPE d3d11_buffer_GetEvictionPriority(ID3D11Buffer *iface)
181 FIXME("iface %p stub!\n", iface);
183 return 0;
186 static void STDMETHODCALLTYPE d3d11_buffer_GetDesc(ID3D11Buffer *iface, D3D11_BUFFER_DESC *desc)
188 struct d3d_buffer *buffer = impl_from_ID3D11Buffer(iface);
190 TRACE("iface %p, desc %p.\n", iface, desc);
192 *desc = buffer->desc;
195 static const struct ID3D11BufferVtbl d3d11_buffer_vtbl =
197 /* IUnknown methods */
198 d3d11_buffer_QueryInterface,
199 d3d11_buffer_AddRef,
200 d3d11_buffer_Release,
201 /* ID3D11DeviceChild methods */
202 d3d11_buffer_GetDevice,
203 d3d11_buffer_GetPrivateData,
204 d3d11_buffer_SetPrivateData,
205 d3d11_buffer_SetPrivateDataInterface,
206 /* ID3D11Resource methods */
207 d3d11_buffer_GetType,
208 d3d11_buffer_SetEvictionPriority,
209 d3d11_buffer_GetEvictionPriority,
210 /* ID3D11Buffer methods */
211 d3d11_buffer_GetDesc,
214 struct d3d_buffer *unsafe_impl_from_ID3D11Buffer(ID3D11Buffer *iface)
216 if (!iface)
217 return NULL;
218 assert(iface->lpVtbl == &d3d11_buffer_vtbl);
219 return CONTAINING_RECORD(iface, struct d3d_buffer, ID3D11Buffer_iface);
222 /* ID3D10Buffer methods */
224 static inline struct d3d_buffer *impl_from_ID3D10Buffer(ID3D10Buffer *iface)
226 return CONTAINING_RECORD(iface, struct d3d_buffer, ID3D10Buffer_iface);
229 /* IUnknown methods */
231 static HRESULT STDMETHODCALLTYPE d3d10_buffer_QueryInterface(ID3D10Buffer *iface, REFIID riid, void **out)
233 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
235 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
237 return d3d11_buffer_QueryInterface(&buffer->ID3D11Buffer_iface, riid, out);
240 static ULONG STDMETHODCALLTYPE d3d10_buffer_AddRef(ID3D10Buffer *iface)
242 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
244 TRACE("iface %p.\n", iface);
246 return d3d11_buffer_AddRef(&buffer->ID3D11Buffer_iface);
249 static ULONG STDMETHODCALLTYPE d3d10_buffer_Release(ID3D10Buffer *iface)
251 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
253 TRACE("iface %p.\n", iface);
255 return d3d11_buffer_Release(&buffer->ID3D11Buffer_iface);
258 /* ID3D10DeviceChild methods */
260 static void STDMETHODCALLTYPE d3d10_buffer_GetDevice(ID3D10Buffer *iface, ID3D10Device **device)
262 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
264 TRACE("iface %p, device %p.\n", iface, device);
266 ID3D11Device2_QueryInterface(buffer->device, &IID_ID3D10Device, (void **)device);
269 static HRESULT STDMETHODCALLTYPE d3d10_buffer_GetPrivateData(ID3D10Buffer *iface,
270 REFGUID guid, UINT *data_size, void *data)
272 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
274 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
275 iface, debugstr_guid(guid), data_size, data);
277 return d3d11_buffer_GetPrivateData(&buffer->ID3D11Buffer_iface, guid, data_size, data);
280 static HRESULT STDMETHODCALLTYPE d3d10_buffer_SetPrivateData(ID3D10Buffer *iface,
281 REFGUID guid, UINT data_size, const void *data)
283 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
285 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
286 iface, debugstr_guid(guid), data_size, data);
288 return d3d11_buffer_SetPrivateData(&buffer->ID3D11Buffer_iface, guid, data_size, data);
291 static HRESULT STDMETHODCALLTYPE d3d10_buffer_SetPrivateDataInterface(ID3D10Buffer *iface,
292 REFGUID guid, const IUnknown *data)
294 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
296 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
298 return d3d11_buffer_SetPrivateDataInterface(&buffer->ID3D11Buffer_iface, guid, data);
301 /* ID3D10Resource methods */
303 static void STDMETHODCALLTYPE d3d10_buffer_GetType(ID3D10Buffer *iface, D3D10_RESOURCE_DIMENSION *resource_dimension)
305 TRACE("iface %p, resource_dimension %p\n", iface, resource_dimension);
307 *resource_dimension = D3D10_RESOURCE_DIMENSION_BUFFER;
310 static void STDMETHODCALLTYPE d3d10_buffer_SetEvictionPriority(ID3D10Buffer *iface, UINT eviction_priority)
312 FIXME("iface %p, eviction_priority %u stub!\n", iface, eviction_priority);
315 static UINT STDMETHODCALLTYPE d3d10_buffer_GetEvictionPriority(ID3D10Buffer *iface)
317 FIXME("iface %p stub!\n", iface);
319 return 0;
322 /* ID3D10Buffer methods */
324 static HRESULT STDMETHODCALLTYPE d3d10_buffer_Map(ID3D10Buffer *iface, D3D10_MAP map_type, UINT map_flags, void **data)
326 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
327 struct wined3d_map_desc wined3d_map_desc;
328 HRESULT hr;
330 TRACE("iface %p, map_type %u, map_flags %#x, data %p.\n", iface, map_type, map_flags, data);
332 if (map_flags)
333 FIXME("Ignoring map_flags %#x.\n", map_flags);
335 hr = wined3d_resource_map(wined3d_buffer_get_resource(buffer->wined3d_buffer), 0,
336 &wined3d_map_desc, NULL, wined3d_map_flags_from_d3d10_map_type(map_type));
337 *data = wined3d_map_desc.data;
339 return hr;
342 static void STDMETHODCALLTYPE d3d10_buffer_Unmap(ID3D10Buffer *iface)
344 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
346 TRACE("iface %p.\n", iface);
348 wined3d_resource_unmap(wined3d_buffer_get_resource(buffer->wined3d_buffer), 0);
351 static void STDMETHODCALLTYPE d3d10_buffer_GetDesc(ID3D10Buffer *iface, D3D10_BUFFER_DESC *desc)
353 struct d3d_buffer *buffer = impl_from_ID3D10Buffer(iface);
354 const D3D11_BUFFER_DESC *d3d11_desc = &buffer->desc;
356 TRACE("iface %p, desc %p.\n", iface, desc);
358 desc->ByteWidth = d3d11_desc->ByteWidth;
359 desc->Usage = d3d10_usage_from_d3d11_usage(d3d11_desc->Usage);
360 desc->BindFlags = d3d10_bind_flags_from_d3d11_bind_flags(d3d11_desc->BindFlags);
361 desc->CPUAccessFlags = d3d10_cpu_access_flags_from_d3d11_cpu_access_flags(d3d11_desc->CPUAccessFlags);
362 desc->MiscFlags = d3d10_resource_misc_flags_from_d3d11_resource_misc_flags(d3d11_desc->MiscFlags);
365 static const struct ID3D10BufferVtbl d3d10_buffer_vtbl =
367 /* IUnknown methods */
368 d3d10_buffer_QueryInterface,
369 d3d10_buffer_AddRef,
370 d3d10_buffer_Release,
371 /* ID3D10DeviceChild methods */
372 d3d10_buffer_GetDevice,
373 d3d10_buffer_GetPrivateData,
374 d3d10_buffer_SetPrivateData,
375 d3d10_buffer_SetPrivateDataInterface,
376 /* ID3D10Resource methods */
377 d3d10_buffer_GetType,
378 d3d10_buffer_SetEvictionPriority,
379 d3d10_buffer_GetEvictionPriority,
380 /* ID3D10Buffer methods */
381 d3d10_buffer_Map,
382 d3d10_buffer_Unmap,
383 d3d10_buffer_GetDesc,
386 struct d3d_buffer *unsafe_impl_from_ID3D10Buffer(ID3D10Buffer *iface)
388 if (!iface)
389 return NULL;
390 assert(iface->lpVtbl == &d3d10_buffer_vtbl);
391 return CONTAINING_RECORD(iface, struct d3d_buffer, ID3D10Buffer_iface);
394 static void STDMETHODCALLTYPE d3d_buffer_wined3d_object_released(void *parent)
396 struct d3d_buffer *buffer = parent;
398 if (buffer->dxgi_resource) IUnknown_Release(buffer->dxgi_resource);
399 free(parent);
402 static const struct wined3d_parent_ops d3d_buffer_wined3d_parent_ops =
404 d3d_buffer_wined3d_object_released,
407 static BOOL validate_buffer_desc(D3D11_BUFFER_DESC *desc, D3D_FEATURE_LEVEL feature_level)
409 if (!validate_d3d11_resource_access_flags(D3D11_RESOURCE_DIMENSION_BUFFER,
410 desc->Usage, desc->BindFlags, desc->CPUAccessFlags, feature_level))
411 return FALSE;
413 if (desc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)
415 if (desc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED)
417 WARN("Raw and structure buffers are mutually exclusive.\n");
418 return FALSE;
420 if (!(desc->BindFlags & (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS)))
422 WARN("Invalid bind flags %#x for raw buffer.\n", desc->BindFlags);
423 return FALSE;
427 if (desc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED)
429 if (!desc->StructureByteStride || desc->StructureByteStride % 4)
431 WARN("Invalid structure byte stride %u.\n", desc->StructureByteStride);
432 return FALSE;
434 if (desc->ByteWidth % desc->StructureByteStride)
436 WARN("Byte width %u is not divisible by structure byte stride %u.\n",
437 desc->ByteWidth, desc->StructureByteStride);
438 return FALSE;
441 else
443 desc->StructureByteStride = 0;
446 if (desc->MiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS)
448 WARN("Buffer with the D3D11_RESOURCE_MISC_GENERATE_MIPS flag.\n");
449 return FALSE;
452 return TRUE;
455 static HRESULT d3d_buffer_init(struct d3d_buffer *buffer, struct d3d_device *device,
456 const D3D11_BUFFER_DESC *desc, const D3D11_SUBRESOURCE_DATA *data)
458 struct wined3d_buffer_desc wined3d_desc;
459 HRESULT hr;
461 buffer->ID3D11Buffer_iface.lpVtbl = &d3d11_buffer_vtbl;
462 buffer->ID3D10Buffer_iface.lpVtbl = &d3d10_buffer_vtbl;
463 buffer->refcount = 1;
464 buffer->desc = *desc;
466 if (!validate_buffer_desc(&buffer->desc, device->state->feature_level))
467 return E_INVALIDARG;
469 wined3d_desc.byte_width = buffer->desc.ByteWidth;
470 wined3d_desc.usage = wined3d_usage_from_d3d11(buffer->desc.Usage);
471 wined3d_desc.bind_flags = wined3d_bind_flags_from_d3d11(buffer->desc.BindFlags, buffer->desc.MiscFlags);
472 wined3d_desc.access = wined3d_access_from_d3d11(buffer->desc.Usage, buffer->desc.CPUAccessFlags);
473 wined3d_desc.misc_flags = buffer->desc.MiscFlags;
474 wined3d_desc.structure_byte_stride = buffer->desc.StructureByteStride;
476 wined3d_mutex_lock();
478 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &wined3d_desc,
479 (const struct wined3d_sub_resource_data *)data, buffer,
480 &d3d_buffer_wined3d_parent_ops, &buffer->wined3d_buffer)))
482 WARN("Failed to create wined3d buffer, hr %#lx.\n", hr);
483 wined3d_mutex_unlock();
484 return hr;
487 hr = d3d_device_create_dxgi_resource((IUnknown *)&device->ID3D10Device1_iface,
488 wined3d_buffer_get_resource(buffer->wined3d_buffer), (IUnknown *)&buffer->ID3D10Buffer_iface,
489 FALSE, &buffer->dxgi_resource);
490 if (FAILED(hr))
492 ERR("Failed to create DXGI resource, returning %#.lx\n", hr);
493 wined3d_buffer_decref(buffer->wined3d_buffer);
494 wined3d_mutex_unlock();
495 return hr;
497 wined3d_mutex_unlock();
499 ID3D11Device2_AddRef(buffer->device = &device->ID3D11Device2_iface);
501 return S_OK;
504 HRESULT d3d_buffer_create(struct d3d_device *device, const D3D11_BUFFER_DESC *desc,
505 const D3D11_SUBRESOURCE_DATA *data, struct d3d_buffer **buffer)
507 struct d3d_buffer *object;
508 HRESULT hr;
510 if (!(object = calloc(1, sizeof(*object))))
511 return E_OUTOFMEMORY;
513 if (FAILED(hr = d3d_buffer_init(object, device, desc, data)))
515 WARN("Failed to initialise buffer, hr %#lx.\n", hr);
516 free(object);
517 return hr;
520 TRACE("Created buffer %p.\n", object);
521 *buffer = object;
523 return S_OK;