ddraw: Version 1 devices are aggregated by the surface that created them.
[wine] / dlls / d3d10core / view.c
1 /*
2  * Copyright 2009 Henri Verbeet for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  *
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22 #include <assert.h>
23
24 #define NONAMELESSUNION
25 #include "d3d10core_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d10core);
28
29 static struct wined3d_resource *wined3d_resource_from_resource(ID3D10Resource *resource)
30 {
31     D3D10_RESOURCE_DIMENSION dimension;
32
33     ID3D10Resource_GetType(resource, &dimension);
34
35     switch(dimension)
36     {
37         case D3D10_RESOURCE_DIMENSION_BUFFER:
38             return wined3d_buffer_get_resource(((struct d3d10_buffer *)resource)->wined3d_buffer);
39
40         case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
41             return wined3d_surface_get_resource(((struct d3d10_texture2d *)resource)->wined3d_surface);
42
43         default:
44             FIXME("Unhandled resource dimension %#x.\n", dimension);
45             return NULL;
46     }
47 }
48
49 static HRESULT set_rtdesc_from_resource(D3D10_RENDER_TARGET_VIEW_DESC *desc, ID3D10Resource *resource)
50 {
51     D3D10_RESOURCE_DIMENSION dimension;
52     HRESULT hr;
53
54     ID3D10Resource_GetType(resource, &dimension);
55
56     switch(dimension)
57     {
58         case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
59         {
60             ID3D10Texture1D *texture;
61             D3D10_TEXTURE1D_DESC texture_desc;
62
63             hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture1D, (void **)&texture);
64             if (FAILED(hr))
65             {
66                 ERR("Resource of type TEXTURE1D doesn't implement ID3D10Texture1D?\n");
67                 return E_INVALIDARG;
68             }
69
70             ID3D10Texture1D_GetDesc(texture, &texture_desc);
71             ID3D10Texture1D_Release(texture);
72
73             desc->Format = texture_desc.Format;
74             if (texture_desc.ArraySize == 1)
75             {
76                 desc->ViewDimension = D3D10_RTV_DIMENSION_TEXTURE1D;
77                 desc->u.Texture1D.MipSlice = 0;
78             }
79             else
80             {
81                 desc->ViewDimension = D3D10_RTV_DIMENSION_TEXTURE1DARRAY;
82                 desc->u.Texture1DArray.MipSlice = 0;
83                 desc->u.Texture1DArray.FirstArraySlice = 0;
84                 desc->u.Texture1DArray.ArraySize = 1;
85             }
86
87             return S_OK;
88         }
89
90         case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
91         {
92             ID3D10Texture2D *texture;
93             D3D10_TEXTURE2D_DESC texture_desc;
94
95             hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture2D, (void **)&texture);
96             if (FAILED(hr))
97             {
98                 ERR("Resource of type TEXTURE2D doesn't implement ID3D10Texture2D?\n");
99                 return E_INVALIDARG;
100             }
101
102             ID3D10Texture2D_GetDesc(texture, &texture_desc);
103             ID3D10Texture2D_Release(texture);
104
105             desc->Format = texture_desc.Format;
106             if (texture_desc.ArraySize == 1)
107             {
108                 if (texture_desc.SampleDesc.Count == 1)
109                 {
110                     desc->ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
111                     desc->u.Texture2D.MipSlice = 0;
112                 }
113                 else
114                 {
115                     desc->ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2DMS;
116                 }
117             }
118             else
119             {
120                 if (texture_desc.SampleDesc.Count == 1)
121                 {
122                     desc->ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2DARRAY;
123                     desc->u.Texture2DArray.MipSlice = 0;
124                     desc->u.Texture2DArray.FirstArraySlice = 0;
125                     desc->u.Texture2DArray.ArraySize = 1;
126                 }
127                 else
128                 {
129                     desc->ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2DMSARRAY;
130                     desc->u.Texture2DMSArray.FirstArraySlice = 0;
131                     desc->u.Texture2DMSArray.ArraySize = 1;
132                 }
133             }
134
135             return S_OK;
136         }
137
138         case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
139         {
140             ID3D10Texture3D *texture;
141             D3D10_TEXTURE3D_DESC texture_desc;
142
143             hr = ID3D10Resource_QueryInterface(resource, &IID_ID3D10Texture3D, (void **)&texture);
144             if (FAILED(hr))
145             {
146                 ERR("Resource of type TEXTURE3D doesn't implement ID3D10Texture3D?\n");
147                 return E_INVALIDARG;
148             }
149
150             ID3D10Texture3D_GetDesc(texture, &texture_desc);
151             ID3D10Texture3D_Release(texture);
152
153             desc->Format = texture_desc.Format;
154             desc->ViewDimension = D3D10_RTV_DIMENSION_TEXTURE3D;
155             desc->u.Texture3D.MipSlice = 0;
156             desc->u.Texture3D.FirstWSlice = 0;
157             desc->u.Texture3D.WSize = 1;
158
159             return S_OK;
160         }
161
162         default:
163             FIXME("Unhandled resource dimension %#x.\n", dimension);
164             return E_INVALIDARG;
165     }
166 }
167
168 static inline struct d3d10_depthstencil_view *impl_from_ID3D10DepthStencilView(ID3D10DepthStencilView *iface)
169 {
170     return CONTAINING_RECORD(iface, struct d3d10_depthstencil_view, ID3D10DepthStencilView_iface);
171 }
172
173 /* IUnknown methods */
174
175 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_view_QueryInterface(ID3D10DepthStencilView *iface,
176         REFIID riid, void **object)
177 {
178     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
179
180     if (IsEqualGUID(riid, &IID_ID3D10DepthStencilView)
181             || IsEqualGUID(riid, &IID_ID3D10View)
182             || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
183             || IsEqualGUID(riid, &IID_IUnknown))
184     {
185         IUnknown_AddRef(iface);
186         *object = iface;
187         return S_OK;
188     }
189
190     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
191
192     *object = NULL;
193     return E_NOINTERFACE;
194 }
195
196 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_view_AddRef(ID3D10DepthStencilView *iface)
197 {
198     struct d3d10_depthstencil_view *This = impl_from_ID3D10DepthStencilView(iface);
199     ULONG refcount = InterlockedIncrement(&This->refcount);
200
201     TRACE("%p increasing refcount to %u.\n", This, refcount);
202
203     return refcount;
204 }
205
206 static ULONG STDMETHODCALLTYPE d3d10_depthstencil_view_Release(ID3D10DepthStencilView *iface)
207 {
208     struct d3d10_depthstencil_view *This = impl_from_ID3D10DepthStencilView(iface);
209     ULONG refcount = InterlockedDecrement(&This->refcount);
210
211     TRACE("%p decreasing refcount to %u.\n", This, refcount);
212
213     if (!refcount)
214     {
215         HeapFree(GetProcessHeap(), 0, This);
216     }
217
218     return refcount;
219 }
220
221 /* ID3D10DeviceChild methods */
222
223 static void STDMETHODCALLTYPE d3d10_depthstencil_view_GetDevice(ID3D10DepthStencilView *iface, ID3D10Device **device)
224 {
225     FIXME("iface %p, device %p stub!\n", iface, device);
226 }
227
228 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_view_GetPrivateData(ID3D10DepthStencilView *iface,
229         REFGUID guid, UINT *data_size, void *data)
230 {
231     FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
232             iface, debugstr_guid(guid), data_size, data);
233
234     return E_NOTIMPL;
235 }
236
237 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_view_SetPrivateData(ID3D10DepthStencilView *iface,
238         REFGUID guid, UINT data_size, const void *data)
239 {
240     FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
241             iface, debugstr_guid(guid), data_size, data);
242
243     return E_NOTIMPL;
244 }
245
246 static HRESULT STDMETHODCALLTYPE d3d10_depthstencil_view_SetPrivateDataInterface(ID3D10DepthStencilView *iface,
247         REFGUID guid, const IUnknown *data)
248 {
249     FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
250
251     return E_NOTIMPL;
252 }
253
254 /* ID3D10View methods */
255
256 static void STDMETHODCALLTYPE d3d10_depthstencil_view_GetResource(ID3D10DepthStencilView *iface,
257         ID3D10Resource **resource)
258 {
259     FIXME("iface %p, resource %p stub!\n", iface, resource);
260 }
261
262 /* ID3D10DepthStencilView methods */
263
264 static void STDMETHODCALLTYPE d3d10_depthstencil_view_GetDesc(ID3D10DepthStencilView *iface,
265         D3D10_DEPTH_STENCIL_VIEW_DESC *desc)
266 {
267     FIXME("iface %p, desc %p stub!\n", iface, desc);
268 }
269
270 static const struct ID3D10DepthStencilViewVtbl d3d10_depthstencil_view_vtbl =
271 {
272     /* IUnknown methods */
273     d3d10_depthstencil_view_QueryInterface,
274     d3d10_depthstencil_view_AddRef,
275     d3d10_depthstencil_view_Release,
276     /* ID3D10DeviceChild methods */
277     d3d10_depthstencil_view_GetDevice,
278     d3d10_depthstencil_view_GetPrivateData,
279     d3d10_depthstencil_view_SetPrivateData,
280     d3d10_depthstencil_view_SetPrivateDataInterface,
281     /* ID3D10View methods */
282     d3d10_depthstencil_view_GetResource,
283     /* ID3D10DepthStencilView methods */
284     d3d10_depthstencil_view_GetDesc,
285 };
286
287 HRESULT d3d10_depthstencil_view_init(struct d3d10_depthstencil_view *view)
288 {
289     view->ID3D10DepthStencilView_iface.lpVtbl = &d3d10_depthstencil_view_vtbl;
290     view->refcount = 1;
291
292     return S_OK;
293 }
294
295 static inline struct d3d10_rendertarget_view *impl_from_ID3D10RenderTargetView(ID3D10RenderTargetView *iface)
296 {
297     return CONTAINING_RECORD(iface, struct d3d10_rendertarget_view, ID3D10RenderTargetView_iface);
298 }
299
300 /* IUnknown methods */
301
302 static HRESULT STDMETHODCALLTYPE d3d10_rendertarget_view_QueryInterface(ID3D10RenderTargetView *iface,
303         REFIID riid, void **object)
304 {
305     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
306
307     if (IsEqualGUID(riid, &IID_ID3D10RenderTargetView)
308             || IsEqualGUID(riid, &IID_ID3D10View)
309             || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
310             || IsEqualGUID(riid, &IID_IUnknown))
311     {
312         IUnknown_AddRef(iface);
313         *object = iface;
314         return S_OK;
315     }
316
317     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
318
319     *object = NULL;
320     return E_NOINTERFACE;
321 }
322
323 static ULONG STDMETHODCALLTYPE d3d10_rendertarget_view_AddRef(ID3D10RenderTargetView *iface)
324 {
325     struct d3d10_rendertarget_view *This = impl_from_ID3D10RenderTargetView(iface);
326     ULONG refcount = InterlockedIncrement(&This->refcount);
327
328     TRACE("%p increasing refcount to %u\n", This, refcount);
329
330     return refcount;
331 }
332
333 static ULONG STDMETHODCALLTYPE d3d10_rendertarget_view_Release(ID3D10RenderTargetView *iface)
334 {
335     struct d3d10_rendertarget_view *This = impl_from_ID3D10RenderTargetView(iface);
336     ULONG refcount = InterlockedDecrement(&This->refcount);
337
338     TRACE("%p decreasing refcount to %u\n", This, refcount);
339
340     if (!refcount)
341     {
342         wined3d_rendertarget_view_decref(This->wined3d_view);
343         HeapFree(GetProcessHeap(), 0, This);
344     }
345
346     return refcount;
347 }
348
349 /* ID3D10DeviceChild methods */
350
351 static void STDMETHODCALLTYPE d3d10_rendertarget_view_GetDevice(ID3D10RenderTargetView *iface, ID3D10Device **device)
352 {
353     FIXME("iface %p, device %p stub!\n", iface, device);
354 }
355
356 static HRESULT STDMETHODCALLTYPE d3d10_rendertarget_view_GetPrivateData(ID3D10RenderTargetView *iface,
357         REFGUID guid, UINT *data_size, void *data)
358 {
359     FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
360             iface, debugstr_guid(guid), data_size, data);
361
362     return E_NOTIMPL;
363 }
364
365 static HRESULT STDMETHODCALLTYPE d3d10_rendertarget_view_SetPrivateData(ID3D10RenderTargetView *iface,
366         REFGUID guid, UINT data_size, const void *data)
367 {
368     FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
369             iface, debugstr_guid(guid), data_size, data);
370
371     return E_NOTIMPL;
372 }
373
374 static HRESULT STDMETHODCALLTYPE d3d10_rendertarget_view_SetPrivateDataInterface(ID3D10RenderTargetView *iface,
375         REFGUID guid, const IUnknown *data)
376 {
377     FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
378
379     return E_NOTIMPL;
380 }
381
382 /* ID3D10View methods */
383
384 static void STDMETHODCALLTYPE d3d10_rendertarget_view_GetResource(ID3D10RenderTargetView *iface,
385         ID3D10Resource **resource)
386 {
387     struct d3d10_rendertarget_view *This = impl_from_ID3D10RenderTargetView(iface);
388     struct wined3d_resource *wined3d_resource;
389     IUnknown *parent;
390     HRESULT hr;
391
392     TRACE("iface %p, resource %p\n", iface, resource);
393
394     wined3d_resource = wined3d_rendertarget_view_get_resource(This->wined3d_view);
395     if (!wined3d_resource)
396     {
397         ERR("Failed to get wined3d resource.\n");
398         *resource = NULL;
399         return;
400     }
401
402     parent = wined3d_resource_get_parent(wined3d_resource);
403     hr = IUnknown_QueryInterface(parent, &IID_ID3D10Resource, (void **)&resource);
404     if (FAILED(hr))
405     {
406         ERR("Resource parent isn't a d3d10 resource, hr %#x\n", hr);
407         *resource = NULL;
408         return;
409     }
410 }
411
412 /* ID3D10RenderTargetView methods */
413
414 static void STDMETHODCALLTYPE d3d10_rendertarget_view_GetDesc(ID3D10RenderTargetView *iface,
415         D3D10_RENDER_TARGET_VIEW_DESC *desc)
416 {
417     struct d3d10_rendertarget_view *This = impl_from_ID3D10RenderTargetView(iface);
418
419     TRACE("iface %p, desc %p\n", iface, desc);
420
421     *desc = This->desc;
422 }
423
424 static const struct ID3D10RenderTargetViewVtbl d3d10_rendertarget_view_vtbl =
425 {
426     /* IUnknown methods */
427     d3d10_rendertarget_view_QueryInterface,
428     d3d10_rendertarget_view_AddRef,
429     d3d10_rendertarget_view_Release,
430     /* ID3D10DeviceChild methods */
431     d3d10_rendertarget_view_GetDevice,
432     d3d10_rendertarget_view_GetPrivateData,
433     d3d10_rendertarget_view_SetPrivateData,
434     d3d10_rendertarget_view_SetPrivateDataInterface,
435     /* ID3D10View methods */
436     d3d10_rendertarget_view_GetResource,
437     /* ID3D10RenderTargetView methods */
438     d3d10_rendertarget_view_GetDesc,
439 };
440
441 HRESULT d3d10_rendertarget_view_init(struct d3d10_rendertarget_view *view,
442         ID3D10Resource *resource, const D3D10_RENDER_TARGET_VIEW_DESC *desc)
443 {
444     struct wined3d_resource *wined3d_resource;
445     HRESULT hr;
446
447     view->ID3D10RenderTargetView_iface.lpVtbl = &d3d10_rendertarget_view_vtbl;
448     view->refcount = 1;
449
450     if (!desc)
451     {
452         HRESULT hr = set_rtdesc_from_resource(&view->desc, resource);
453         if (FAILED(hr)) return hr;
454     }
455     else
456     {
457         view->desc = *desc;
458     }
459
460     wined3d_resource = wined3d_resource_from_resource(resource);
461     if (!wined3d_resource)
462     {
463         ERR("Failed to get wined3d resource for d3d10 resource %p.\n", resource);
464         return E_FAIL;
465     }
466
467     hr = wined3d_rendertarget_view_create(wined3d_resource, view, &view->wined3d_view);
468     if (FAILED(hr))
469     {
470         WARN("Failed to create a wined3d rendertarget view, hr %#x.\n", hr);
471         return hr;
472     }
473
474     return S_OK;
475 }
476
477 struct d3d10_rendertarget_view *unsafe_impl_from_ID3D10RenderTargetView(ID3D10RenderTargetView *iface)
478 {
479     if (!iface)
480         return NULL;
481     assert(iface->lpVtbl == &d3d10_rendertarget_view_vtbl);
482
483     return impl_from_ID3D10RenderTargetView(iface);
484 }
485
486 static inline struct d3d10_shader_resource_view *impl_from_ID3D10ShaderResourceView(ID3D10ShaderResourceView *iface)
487 {
488     return CONTAINING_RECORD(iface, struct d3d10_shader_resource_view, ID3D10ShaderResourceView_iface);
489 }
490
491 /* IUnknown methods */
492
493 static HRESULT STDMETHODCALLTYPE d3d10_shader_resource_view_QueryInterface(ID3D10ShaderResourceView *iface,
494         REFIID riid, void **object)
495 {
496     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
497
498     if (IsEqualGUID(riid, &IID_ID3D10ShaderResourceView)
499             || IsEqualGUID(riid, &IID_ID3D10View)
500             || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
501             || IsEqualGUID(riid, &IID_IUnknown))
502     {
503         IUnknown_AddRef(iface);
504         *object = iface;
505         return S_OK;
506     }
507
508     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
509
510     *object = NULL;
511     return E_NOINTERFACE;
512 }
513
514 static ULONG STDMETHODCALLTYPE d3d10_shader_resource_view_AddRef(ID3D10ShaderResourceView *iface)
515 {
516     struct d3d10_shader_resource_view *This = impl_from_ID3D10ShaderResourceView(iface);
517     ULONG refcount = InterlockedIncrement(&This->refcount);
518
519     TRACE("%p increasing refcount to %u.\n", This, refcount);
520
521     return refcount;
522 }
523
524 static ULONG STDMETHODCALLTYPE d3d10_shader_resource_view_Release(ID3D10ShaderResourceView *iface)
525 {
526     struct d3d10_shader_resource_view *This = impl_from_ID3D10ShaderResourceView(iface);
527     ULONG refcount = InterlockedDecrement(&This->refcount);
528
529     TRACE("%p decreasing refcount to %u.\n", This, refcount);
530
531     if (!refcount)
532     {
533         HeapFree(GetProcessHeap(), 0, This);
534     }
535
536     return refcount;
537 }
538
539 /* ID3D10DeviceChild methods */
540
541 static void STDMETHODCALLTYPE d3d10_shader_resource_view_GetDevice(ID3D10ShaderResourceView *iface,
542         ID3D10Device **device)
543 {
544     FIXME("iface %p, device %p stub!\n", iface, device);
545 }
546
547 static HRESULT STDMETHODCALLTYPE d3d10_shader_resource_view_GetPrivateData(ID3D10ShaderResourceView *iface,
548         REFGUID guid, UINT *data_size, void *data)
549 {
550     FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
551             iface, debugstr_guid(guid), data_size, data);
552
553     return E_NOTIMPL;
554 }
555
556 static HRESULT STDMETHODCALLTYPE d3d10_shader_resource_view_SetPrivateData(ID3D10ShaderResourceView *iface,
557         REFGUID guid, UINT data_size, const void *data)
558 {
559     FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
560             iface, debugstr_guid(guid), data_size, data);
561
562     return E_NOTIMPL;
563 }
564
565 static HRESULT STDMETHODCALLTYPE d3d10_shader_resource_view_SetPrivateDataInterface(ID3D10ShaderResourceView *iface,
566         REFGUID guid, const IUnknown *data)
567 {
568     FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
569
570     return E_NOTIMPL;
571 }
572
573 /* ID3D10View methods */
574
575 static void STDMETHODCALLTYPE d3d10_shader_resource_view_GetResource(ID3D10ShaderResourceView *iface,
576         ID3D10Resource **resource)
577 {
578     FIXME("iface %p, resource %p stub!\n", iface, resource);
579 }
580
581 /* ID3D10ShaderResourceView methods */
582
583 static void STDMETHODCALLTYPE d3d10_shader_resource_view_GetDesc(ID3D10ShaderResourceView *iface,
584         D3D10_SHADER_RESOURCE_VIEW_DESC *desc)
585 {
586     FIXME("iface %p, desc %p stub!\n", iface, desc);
587 }
588
589 static const struct ID3D10ShaderResourceViewVtbl d3d10_shader_resource_view_vtbl =
590 {
591     /* IUnknown methods */
592     d3d10_shader_resource_view_QueryInterface,
593     d3d10_shader_resource_view_AddRef,
594     d3d10_shader_resource_view_Release,
595     /* ID3D10DeviceChild methods */
596     d3d10_shader_resource_view_GetDevice,
597     d3d10_shader_resource_view_GetPrivateData,
598     d3d10_shader_resource_view_SetPrivateData,
599     d3d10_shader_resource_view_SetPrivateDataInterface,
600     /* ID3D10View methods */
601     d3d10_shader_resource_view_GetResource,
602     /* ID3D10ShaderResourceView methods */
603     d3d10_shader_resource_view_GetDesc,
604 };
605
606 HRESULT d3d10_shader_resource_view_init(struct d3d10_shader_resource_view *view)
607 {
608     view->ID3D10ShaderResourceView_iface.lpVtbl = &d3d10_shader_resource_view_vtbl;
609     view->refcount = 1;
610
611     return S_OK;
612 }