d3d11_objects.h revision 14193da589275969be31dbdb3280bb48cd24d0c0
1/**************************************************************************
2 *
3 * Copyright 2010 Luca Barbieri
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27template<typename Base = ID3D11DeviceChild>
28struct GalliumD3D11DeviceChild : public GalliumPrivateDataComObject<Base, dual_refcnt_t>
29{
30	GalliumD3D11Screen* device; // must not be null
31
32
33	// if this is called, the subclass constructor must set device itself
34	GalliumD3D11DeviceChild()
35	: device(0)
36	{}
37
38	GalliumD3D11DeviceChild(GalliumD3D11Screen* p_device)
39	{
40		// we store the reference count minus one in refcnt
41		device = p_device;
42		device->AddRef();
43	}
44
45	virtual ~GalliumD3D11DeviceChild()
46	{
47		if(device)
48			device->Release();
49	}
50
51	/* The purpose of this is to avoid cyclic garbage, since this won't hold
52	 * a pointer to the device if it is only held by a pipeline binding in the immediate context
53	 *
54	 * TODO: we could only manipulate the device refcnt when atomic_refcnt == 0 changes,
55	 * but this requires more complex atomic ops
56	 */
57	inline ULONG add_ref()
58	{
59		return GalliumPrivateDataComObject<Base, dual_refcnt_t>::add_ref();
60	}
61
62	inline ULONG release()
63	{
64		return GalliumPrivateDataComObject<Base, dual_refcnt_t>::release();
65	}
66
67	virtual ULONG STDMETHODCALLTYPE AddRef()
68	{
69		return add_ref();
70	}
71
72	virtual ULONG STDMETHODCALLTYPE Release()
73	{
74		return release();
75	}
76
77	virtual void STDMETHODCALLTYPE GetDevice(
78		ID3D11Device **out_device
79	 )
80	{
81		device->AddRef();
82		*out_device = device;
83	}
84};
85
86template<typename Base = ID3D11DeviceChild, typename Object = void>
87struct GalliumD3D11Object : public GalliumD3D11DeviceChild<Base>
88{
89	Object* object;
90	GalliumD3D11Object(GalliumD3D11Screen* device, Object* object)
91	: GalliumD3D11DeviceChild<Base>(device), object(object)
92	{}
93
94	virtual ~GalliumD3D11Object();
95};
96
97#define IMPLEMENT_OBJECT_DTOR(name, gallium) \
98template<> \
99GalliumD3D11Object<ID3D11##name, void>::~GalliumD3D11Object() \
100{ \
101	DX10_ONLY(device->Unbind##name(this)); \
102	device->immediate_pipe->delete_##gallium##_state(device->immediate_pipe, object); \
103}
104
105#define IMPLEMENT_VIEW_DTOR(name, gallium) \
106template<> \
107GalliumD3D11Object<ID3D11##name, struct pipe_##gallium>::~GalliumD3D11Object() \
108{ \
109	DX10_ONLY(device->Unbind##name(this)); \
110	pipe_##gallium##_reference(&object, 0); \
111}
112
113IMPLEMENT_OBJECT_DTOR(InputLayout, vertex_elements)
114IMPLEMENT_OBJECT_DTOR(DepthStencilState, depth_stencil_alpha)
115IMPLEMENT_OBJECT_DTOR(RasterizerState, rasterizer)
116IMPLEMENT_OBJECT_DTOR(SamplerState, sampler)
117IMPLEMENT_OBJECT_DTOR(BlendState, blend)
118IMPLEMENT_OBJECT_DTOR(VertexShader, vs)
119IMPLEMENT_OBJECT_DTOR(PixelShader, fs)
120IMPLEMENT_OBJECT_DTOR(GeometryShader, gs)
121
122IMPLEMENT_VIEW_DTOR(ShaderResourceView, sampler_view)
123IMPLEMENT_VIEW_DTOR(RenderTargetView, surface)
124IMPLEMENT_VIEW_DTOR(DepthStencilView, surface)
125
126#if API >= 11
127// IMPLEMENT_VIEW_DTOR(UnorderedAccessView, surface);
128// IMPLEMENT_OBJECT_DTOR(HullShader, tcs);
129// IMPLEMENT_OBJECT_DTOR(DomainShader, tes);
130// IMPLEMENT_OBJECT_DTOR(ComputeShader, cs);
131#else
132IMPLEMENT_OBJECT_DTOR(BlendState1, blend)
133IMPLEMENT_VIEW_DTOR(ShaderResourceView1, sampler_view)
134#endif
135
136template<typename Base, typename Desc, typename Object = void>
137struct GalliumD3D11DescribedObject : public GalliumD3D11Object<Base, Object>
138{
139	Desc desc;
140	GalliumD3D11DescribedObject(GalliumD3D11Screen* device, Object* object, const Desc& desc)
141	: GalliumD3D11Object<Base, Object>(device, object), desc(desc)
142	{}
143
144	virtual void STDMETHODCALLTYPE GetDesc(Desc *out_desc)
145	{
146		memcpy(out_desc, &desc, sizeof(desc));
147	}
148};
149
150typedef GalliumD3D11Object<ID3D11InputLayout> GalliumD3D11InputLayout;
151typedef GalliumD3D11DescribedObject<ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC> GalliumD3D11DepthStencilState;
152typedef GalliumD3D11DescribedObject<ID3D11RasterizerState, D3D11_RASTERIZER_DESC> GalliumD3D11RasterizerStateBase;
153typedef GalliumD3D11DescribedObject<ID3D11SamplerState, D3D11_SAMPLER_DESC> GalliumD3D11SamplerState;
154
155#if API >= 11
156typedef GalliumD3D11DescribedObject<ID3D11BlendState, D3D11_BLEND_DESC> GalliumD3D11BlendState;
157#else
158typedef GalliumD3D10DescribedObject<ID3D10BlendState1, D3D10_BLEND_DESC> GalliumD3D10BlendStateBase;
159
160struct GalliumD3D10BlendState : public GalliumD3D10BlendStateBase
161{
162	static D3D10_BLEND_DESC convert_to_d3d10(const D3D10_BLEND_DESC1& desc1)
163	{
164		D3D10_BLEND_DESC desc;
165		desc.AlphaToCoverageEnable = desc1.AlphaToCoverageEnable;
166		desc.SrcBlend = desc1.RenderTarget[0].SrcBlend;
167		desc.DestBlend = desc1.RenderTarget[0].DestBlend;
168		desc.BlendOp = desc1.RenderTarget[0].BlendOp;
169		desc.SrcBlendAlpha = desc1.RenderTarget[0].SrcBlendAlpha;
170		desc.DestBlendAlpha = desc1.RenderTarget[0].DestBlendAlpha;
171		desc.BlendOpAlpha = desc1.RenderTarget[0].BlendOpAlpha;
172		for(unsigned i = 0; i < 8; ++i)
173		{
174			desc.BlendEnable[i] = desc1.RenderTarget[i].BlendEnable;
175			desc.RenderTargetWriteMask[i] = desc1.RenderTarget[i].RenderTargetWriteMask;
176		}
177		return desc;
178	}
179
180	D3D10_BLEND_DESC1 desc1;
181
182	GalliumD3D10BlendState(GalliumD3D10Screen* device, void* object, const D3D10_BLEND_DESC& desc)
183	: GalliumD3D10BlendStateBase(device, object, desc)
184	{
185		memset(&desc1, 0, sizeof(desc1));
186		desc1.AlphaToCoverageEnable = desc.AlphaToCoverageEnable;
187		desc1.RenderTarget[0].SrcBlend = desc.SrcBlend;
188		desc1.RenderTarget[0].DestBlend = desc.DestBlend;
189		desc1.RenderTarget[0].BlendOp = desc.BlendOp;
190		desc1.RenderTarget[0].SrcBlendAlpha = desc.SrcBlendAlpha;
191		desc1.RenderTarget[0].DestBlendAlpha = desc.DestBlendAlpha;
192		desc1.RenderTarget[0].BlendOpAlpha = desc.BlendOpAlpha;
193		for(unsigned i = 0; i < 8; ++i)
194		{
195			desc1.RenderTarget[i].BlendEnable = desc.BlendEnable[i];
196			desc1.RenderTarget[i].RenderTargetWriteMask = desc.RenderTargetWriteMask[i];
197		}
198	}
199
200	GalliumD3D10BlendState(GalliumD3D10Screen* device, void* object, const D3D10_BLEND_DESC1& desc)
201	: GalliumD3D10BlendStateBase(device, object, convert_to_d3d10(desc)), desc1(desc1)
202	{}
203
204	virtual void STDMETHODCALLTYPE GetDesc1(D3D10_BLEND_DESC1 *out_desc)
205	{
206		memcpy(out_desc, &desc1, sizeof(desc1));
207	}
208};
209#endif
210
211struct GalliumD3D11RasterizerState : public GalliumD3D11RasterizerStateBase
212{
213	bool depth_clamp;
214
215	GalliumD3D11RasterizerState(GalliumD3D11Screen* device, void* object, const D3D11_RASTERIZER_DESC& desc, bool depth_clamp)
216	: GalliumD3D11RasterizerStateBase(device, object, desc), depth_clamp(depth_clamp)
217	{}
218};
219
220template<typename Base = ID3D11DeviceChild>
221struct GalliumD3D11Shader : public GalliumD3D11Object<Base>
222{
223	GalliumD3D11Shader(GalliumD3D11Screen* device, void* object)
224	: GalliumD3D11Object<Base>(device, object)
225	{}
226};
227
228typedef GalliumD3D11Shader<ID3D11VertexShader> GalliumD3D11VertexShader;
229typedef GalliumD3D11Shader<ID3D11GeometryShader> GalliumD3D11GeometryShader;
230typedef GalliumD3D11Shader<ID3D11PixelShader> GalliumD3D11PixelShader;
231
232#if API >= 11
233/*
234typedef GalliumD3D11Shader<ID3D11HullShader> GalliumD3D11HullShader;
235typedef GalliumD3D11Shader<ID3D11DomainShader> GalliumD3D11DomainShader;
236typedef GalliumD3D11Shader<ID3D11ComputeShader> GalliumD3D11ComputeShader;
237*/
238#endif
239
240template<typename Base = ID3D11Resource>
241struct GalliumD3D11ResourceBase : public GalliumD3D11DeviceChild<Base>
242{
243	unsigned eviction_priority;
244
245	virtual void STDMETHODCALLTYPE SetEvictionPriority(
246		unsigned new_eviction_priority
247	)
248	{
249		eviction_priority = new_eviction_priority;
250	}
251
252	virtual unsigned STDMETHODCALLTYPE GetEvictionPriority()
253	{
254		return eviction_priority;
255	}
256};
257
258template<typename Real>
259struct GalliumDXGIResource : public IDXGIResource
260{
261	virtual HRESULT STDMETHODCALLTYPE SetEvictionPriority(
262		unsigned new_eviction_priority
263	)
264	{
265		static_cast<Real*>(this)->eviction_priority = new_eviction_priority;
266		return S_OK;
267	}
268
269	virtual HRESULT STDMETHODCALLTYPE GetEvictionPriority(unsigned* out_eviction_priority)
270	{
271	 	*out_eviction_priority = static_cast<Real*>(this)->eviction_priority;
272	 	return S_OK;
273	}
274
275	virtual HRESULT STDMETHODCALLTYPE GetDevice(
276		REFIID riid,
277		void **out_parent)
278	{
279		if(!static_cast<Real*>(this)->device)
280			return E_NOINTERFACE;
281		return static_cast<Real*>(this)->device->QueryInterface(riid, out_parent);
282	}
283
284	virtual HRESULT STDMETHODCALLTYPE GetParent(
285		REFIID riid,
286		void **out_parent)
287	{
288		if(!static_cast<Real*>(this)->device)
289			return E_NOINTERFACE;
290		return static_cast<Real*>(this)->device->QueryInterface(riid, out_parent);
291	}
292};
293
294template<typename T>
295struct com_traits<GalliumDXGIResource<T> > : public com_traits<IDXGIResource>
296{};
297
298template<typename Base = ID3D11Resource>
299struct GalliumD3D11Resource
300	: public GalliumMultiComObject<
301		GalliumMultiPrivateDataComObject<
302			GalliumD3D11ResourceBase<Base>,
303			GalliumDXGIResource<GalliumD3D11Resource<Base> >
304		>,
305		IGalliumResource
306	>
307{
308	struct pipe_resource* resource;
309	std::unordered_map<unsigned, pipe_transfer*> transfers;
310	float min_lod;
311	DXGI_USAGE dxgi_usage;
312
313	GalliumD3D11Resource(GalliumD3D11Screen* device = 0, struct pipe_resource* resource = 0, unsigned dxgi_usage = 0)
314	: resource(resource), min_lod(0), dxgi_usage(dxgi_usage)
315	{
316		this->device = device;
317		if(device)
318			device->AddRef();
319		this->eviction_priority = 0;
320	}
321
322	~GalliumD3D11Resource()
323	{
324		pipe_resource_reference(&resource, 0);
325	}
326
327	virtual HRESULT STDMETHODCALLTYPE GetUsage(
328		DXGI_USAGE *out_usage
329	 )
330	{
331		*out_usage = this->dxgi_usage;
332		return S_OK;
333	}
334
335	virtual HRESULT STDMETHODCALLTYPE GetSharedHandle(HANDLE *out_shared_handle)
336	{
337		return E_NOTIMPL;
338	}
339
340	virtual struct pipe_resource* STDMETHODCALLTYPE GetGalliumResource()
341	{
342		return resource;
343	}
344};
345
346template<typename Base, typename Desc, D3D11_RESOURCE_DIMENSION Dim>
347struct GalliumD3D11TypedResource : public GalliumD3D11Resource<Base>
348{
349	Desc desc;
350	GalliumD3D11TypedResource() {}
351	GalliumD3D11TypedResource(GalliumD3D11Screen* device, struct pipe_resource* resource, const Desc& desc, unsigned dxgi_usage)
352	: GalliumD3D11Resource<Base>(device, resource, dxgi_usage), desc(desc)
353	{}
354	virtual void STDMETHODCALLTYPE GetType(
355		D3D11_RESOURCE_DIMENSION *out_resource_dimension)
356	{
357		*out_resource_dimension = Dim;
358	}
359	virtual void STDMETHODCALLTYPE GetDesc(Desc *out_desc)
360	{
361		memcpy(out_desc, &desc, sizeof(desc));
362	}
363};
364
365typedef GalliumD3D11TypedResource<ID3D11Texture1D, D3D11_TEXTURE1D_DESC, D3D11_RESOURCE_DIMENSION_TEXTURE1D> GalliumD3D11Texture1DBase;
366typedef GalliumD3D11TypedResource<ID3D11Texture2D, D3D11_TEXTURE2D_DESC, D3D11_RESOURCE_DIMENSION_TEXTURE2D> GalliumD3D11Texture2DBase;
367typedef GalliumD3D11TypedResource<ID3D11Texture3D, D3D11_TEXTURE3D_DESC, D3D11_RESOURCE_DIMENSION_TEXTURE3D> GalliumD3D11Texture3DBase;
368typedef GalliumD3D11TypedResource<ID3D11Buffer, D3D11_BUFFER_DESC, D3D11_RESOURCE_DIMENSION_BUFFER> GalliumD3D11BufferBase;
369
370#if API >= 11
371typedef GalliumD3D11Texture1DBase GalliumD3D11Texture1D;
372typedef GalliumD3D11Texture2DBase GalliumD3D11Texture2D;
373typedef GalliumD3D11Texture3DBase GalliumD3D11Texture3D;
374
375struct GalliumD3D11Buffer : public GalliumD3D11BufferBase
376{
377	struct pipe_stream_output_target* so_target;
378
379	GalliumD3D11Buffer(GalliumD3D11Screen* device, struct pipe_resource* resource, const D3D11_BUFFER_DESC& desc, unsigned dxgi_usage)
380	: GalliumD3D11BufferBase(device, resource, desc, dxgi_usage), so_target(0)
381	{
382	}
383
384	~GalliumD3D11Buffer()
385	{
386		if(so_target)
387			pipe_so_target_reference(&so_target, NULL);
388	}
389};
390#else
391struct GalliumD3D10Buffer : public GalliumD3D10BufferBase
392{
393	struct pipe_stream_output_target *so_target;
394
395	GalliumD3D10Buffer(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_BUFFER_DESC& desc, unsigned dxgi_usage)
396	: GalliumD3D10BufferBase(device, resource, desc, dxgi_usage)
397	{
398	}
399
400	~GalliumD3D10Buffer()
401	{
402		if(so_target)
403			pipe_so_target_reference(&so_target, NULL);
404
405		device->UnbindBuffer(this);
406	}
407
408	virtual HRESULT STDMETHODCALLTYPE Map(
409		D3D10_MAP map_type,
410		unsigned map_flags,
411		void **out_data)
412	{
413		D3D10_MAPPED_SUBRESOURCE msr;
414		HRESULT hr = device->Map(this, 0, map_type, map_flags, &msr);
415		if(!SUCCEEDED(hr))
416			return hr;
417		*out_data = msr.pData;
418		return S_OK;
419	}
420
421	virtual void STDMETHODCALLTYPE Unmap()
422	{
423		device->Unmap(this, 0);
424	}
425};
426
427struct GalliumD3D10Texture1D : public GalliumD3D10Texture1DBase
428{
429	GalliumD3D10Texture1D(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_TEXTURE1D_DESC& desc, unsigned dxgi_usage)
430	: GalliumD3D10Texture1DBase(device, resource, desc, dxgi_usage)
431	{}
432
433	virtual HRESULT STDMETHODCALLTYPE Map(
434		unsigned subresource,
435		D3D10_MAP map_type,
436		unsigned map_flags,
437		void **out_data)
438	{
439		D3D10_MAPPED_SUBRESOURCE msr;
440		HRESULT hr = device->Map(this, subresource, map_type, map_flags, &msr);
441		if(!SUCCEEDED(hr))
442			return hr;
443		*out_data = msr.pData;
444		return S_OK;
445	}
446
447	virtual void STDMETHODCALLTYPE Unmap(
448		unsigned subresource
449	)
450	{
451		device->Unmap(this, subresource);
452	}
453};
454
455struct GalliumD3D10Texture2D : public GalliumD3D10Texture2DBase
456{
457	GalliumD3D10Texture2D() {}
458	GalliumD3D10Texture2D(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_TEXTURE2D_DESC& desc, unsigned dxgi_usage)
459	: GalliumD3D10Texture2DBase(device, resource, desc, dxgi_usage)
460	{}
461
462	virtual HRESULT STDMETHODCALLTYPE Map(
463		unsigned subresource,
464		D3D10_MAP map_type,
465		unsigned map_flags,
466		D3D10_MAPPED_TEXTURE2D *out_mapped_subresource)
467	{
468		D3D10_MAPPED_SUBRESOURCE msr;
469		HRESULT hr = device->Map(this, subresource, map_type, map_flags, &msr);
470		if(!SUCCEEDED(hr))
471			return hr;
472		out_mapped_subresource->pData = msr.pData;
473		out_mapped_subresource->RowPitch = msr.RowPitch;
474		return S_OK;
475	}
476
477	virtual void STDMETHODCALLTYPE Unmap(
478		unsigned subresource
479	)
480	{
481		device->Unmap(this, subresource);
482	}
483};
484
485
486struct GalliumD3D10Texture3D : public GalliumD3D10Texture3DBase
487{
488	GalliumD3D10Texture3D(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_TEXTURE3D_DESC& desc, unsigned dxgi_usage)
489	: GalliumD3D10Texture3DBase(device, resource, desc, dxgi_usage)
490	{}
491
492	virtual HRESULT STDMETHODCALLTYPE Map(
493		unsigned subresource,
494		D3D10_MAP map_type,
495		unsigned map_flags,
496		D3D10_MAPPED_TEXTURE3D *out_mapped_subresource)
497	{
498		D3D10_MAPPED_SUBRESOURCE msr;
499		HRESULT hr = device->Map(this, subresource, map_type, map_flags, &msr);
500		if(!SUCCEEDED(hr))
501			return hr;
502		out_mapped_subresource->pData = msr.pData;
503		out_mapped_subresource->RowPitch = msr.RowPitch;
504		out_mapped_subresource->DepthPitch = msr.DepthPitch;
505		return S_OK;
506	}
507
508	virtual void STDMETHODCALLTYPE Unmap(
509		unsigned subresource
510	)
511	{
512		device->Unmap(this, subresource);
513	}
514};
515#endif
516
517struct GalliumD3D11Surface : public GalliumMultiPrivateDataComObject<GalliumD3D11Texture2D, IDXGISurface1>
518{
519	GalliumD3D11Surface(GalliumD3D11Screen* device, struct pipe_resource* resource, const D3D11_TEXTURE2D_DESC& desc, unsigned dxgi_usage)
520	{
521		this->device = device;
522		this->device->AddRef();
523		this->resource = resource;
524		this->desc = desc;
525		this->dxgi_usage = dxgi_usage;
526	}
527
528	virtual HRESULT STDMETHODCALLTYPE GetDesc(
529		DXGI_SURFACE_DESC *out_desc)
530	{
531		out_desc->Format = this->desc.Format;
532		out_desc->Width = this->desc.Width;
533		out_desc->Height = this->desc.Height;
534		out_desc->SampleDesc = this->desc.SampleDesc;
535		return S_OK;
536	}
537
538	virtual HRESULT STDMETHODCALLTYPE GetParent(
539		REFIID riid,
540		void **out_parent)
541	{
542		if(!device)
543			return E_NOINTERFACE;
544		return device->QueryInterface(riid, out_parent);
545	}
546
547	/* TODO: somehow implement these */
548	virtual HRESULT STDMETHODCALLTYPE GetDC(
549		BOOL discard,
550		HDC *out_hdc)
551	{
552		*out_hdc = 0;
553		return E_NOTIMPL;
554	}
555
556	virtual HRESULT STDMETHODCALLTYPE ReleaseDC(
557		RECT *out_dirty_rect)
558	{
559		return E_NOTIMPL;
560	}
561
562	virtual HRESULT STDMETHODCALLTYPE Map(
563		DXGI_MAPPED_RECT *out_locked_rect,
564		unsigned map_flags)
565	{
566		D3D11_MAP d3d_map;
567		if(map_flags & DXGI_MAP_DISCARD)
568			d3d_map = D3D11_MAP_WRITE_DISCARD;
569		else
570		{
571			if(map_flags & DXGI_MAP_READ)
572			{
573				if(map_flags & DXGI_MAP_WRITE)
574					d3d_map = D3D11_MAP_READ_WRITE;
575				else
576					d3d_map = D3D11_MAP_READ;
577			}
578			else
579				d3d_map = D3D11_MAP_WRITE;
580		}
581		D3D11_MAPPED_SUBRESOURCE d3d_mapped;
582		HRESULT hres = this->device->get_immediate_context()->Map(this, 0, d3d_map, 0, &d3d_mapped);
583		out_locked_rect->pBits = (uint8_t*)d3d_mapped.pData;
584		out_locked_rect->Pitch = d3d_mapped.RowPitch;
585		return hres;
586	}
587
588	virtual HRESULT STDMETHODCALLTYPE Unmap(void)
589	{
590		this->device->get_immediate_context()->Unmap(this, 0);
591		return S_OK;
592	}
593
594	virtual HRESULT STDMETHODCALLTYPE GetDevice(
595		REFIID riid,
596		void **out_parent)
597	{
598		if(!device)
599			return E_NOINTERFACE;
600		return device->QueryInterface(riid, out_parent);
601	}
602};
603
604template<typename Base, typename Desc, typename Object>
605struct GalliumD3D11View : public GalliumD3D11DescribedObject<Base, Desc, Object>
606{
607	GalliumD3D11Resource<>* resource;
608	GalliumD3D11View(GalliumD3D11Screen* device, GalliumD3D11Resource<>* resource, Object* object, const Desc& desc)
609	: GalliumD3D11DescribedObject<Base, Desc, Object>(device, object, desc), resource(resource)
610	{
611		resource->AddRef();
612	}
613
614	~GalliumD3D11View()
615	{
616		resource->Release();
617	}
618
619	virtual void STDMETHODCALLTYPE GetResource(ID3D11Resource** out_resource)
620	{
621		resource->AddRef();
622		*out_resource = resource;
623	}
624};
625
626typedef GalliumD3D11View<ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, struct pipe_surface> GalliumD3D11DepthStencilView;
627typedef GalliumD3D11View<ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, struct pipe_surface> GalliumD3D11RenderTargetView;
628
629#if API >= 11
630typedef GalliumD3D11View<ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, struct pipe_sampler_view> GalliumD3D11ShaderResourceView;
631#else
632typedef GalliumD3D10View<ID3D10ShaderResourceView1, D3D10_SHADER_RESOURCE_VIEW_DESC1, struct pipe_sampler_view> GalliumD3D10ShaderResourceViewBase;
633
634struct GalliumD3D10ShaderResourceView : public GalliumD3D10ShaderResourceViewBase
635{
636	GalliumD3D10ShaderResourceView(GalliumD3D10Screen* device, GalliumD3D10Resource<>* resource, struct pipe_sampler_view* view, const D3D10_SHADER_RESOURCE_VIEW_DESC1& desc)
637	: GalliumD3D10ShaderResourceViewBase(device, resource, view, desc)
638	{}
639
640	virtual void STDMETHODCALLTYPE GetDesc1(D3D10_SHADER_RESOURCE_VIEW_DESC1 *out_desc)
641	{
642		memcpy(out_desc, &desc, sizeof(*out_desc));
643	}
644
645	virtual void STDMETHODCALLTYPE GetDesc(D3D10_SHADER_RESOURCE_VIEW_DESC *out_desc)
646	{
647		memcpy(out_desc, &desc, sizeof(*out_desc));
648	}
649};
650#endif
651
652template<typename Base = ID3D11Asynchronous>
653struct GalliumD3D11Asynchronous : public GalliumD3D11DeviceChild<Base>
654{
655	struct pipe_query* query;
656	unsigned data_size;
657
658	GalliumD3D11Asynchronous(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size)
659	: GalliumD3D11DeviceChild<Base>(device), query(query), data_size(data_size)
660	{}
661
662	~GalliumD3D11Asynchronous()
663	{
664		this->device->immediate_pipe->destroy_query(this->device->immediate_pipe, query);
665	}
666
667	virtual unsigned STDMETHODCALLTYPE GetDataSize()
668	{
669		return data_size;
670	}
671
672#if API < 11
673	virtual void STDMETHODCALLTYPE Begin()
674	{
675		this->device->Begin(this);
676	}
677
678	virtual void STDMETHODCALLTYPE End()
679	{
680		this->device->End(this);
681	}
682
683	virtual HRESULT STDMETHODCALLTYPE GetData(
684		void * out_data,
685		unsigned data_size,
686		unsigned get_data_flags)
687	{
688		return this->device->GetData(this, out_data, data_size, get_data_flags);
689	}
690#endif
691};
692
693template<typename Base = ID3D11Asynchronous>
694struct GalliumD3D11QueryOrPredicate : public GalliumD3D11Asynchronous<Base>
695{
696	D3D11_QUERY_DESC desc;
697	GalliumD3D11QueryOrPredicate(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size, const D3D11_QUERY_DESC& desc)
698	: GalliumD3D11Asynchronous<Base>(device, query, data_size), desc(desc)
699	{}
700
701	virtual void STDMETHODCALLTYPE GetDesc(
702		D3D11_QUERY_DESC *out_desc)
703	{
704		*out_desc = desc;
705	}
706};
707
708struct GalliumD3D11Query : public GalliumD3D11QueryOrPredicate<ID3D11Query>
709{
710	GalliumD3D11Query(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size, const D3D11_QUERY_DESC& desc)
711	: GalliumD3D11QueryOrPredicate<ID3D11Query>(device, query, data_size, desc)
712	{}
713};
714
715struct GalliumD3D11Predicate : public GalliumD3D11QueryOrPredicate<ID3D11Predicate>
716{
717	GalliumD3D11Predicate(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size, const D3D11_QUERY_DESC& desc)
718	: GalliumD3D11QueryOrPredicate<ID3D11Predicate>(device, query, data_size, desc)
719	{}
720
721	~GalliumD3D11Predicate()
722	{
723		DX10_ONLY(device->UnbindPredicate(this));
724	}
725};
726
727struct GalliumD3D11Counter : public GalliumD3D11Asynchronous<ID3D11Counter>
728{
729	D3D11_COUNTER_DESC desc;
730	GalliumD3D11Counter(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size, const D3D11_COUNTER_DESC& desc)
731	: GalliumD3D11Asynchronous<ID3D11Counter>(device, query, data_size), desc(desc)
732	{}
733
734	virtual void STDMETHODCALLTYPE GetDesc(
735		D3D11_COUNTER_DESC *out_desc)
736	{
737		*out_desc = desc;
738	}
739};
740