d3d11_screen.h revision 8224256946619fb25278718bbf4703e3b9d60c93
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
27/* These cap sets are much more correct than the ones in u_caps.c */
28/* TODO: it seems cube levels should be the same as 2D levels */
29
30/* DX 9_1 */
31static unsigned caps_dx_9_1[] = {
32	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
33	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12),	/* 2048 */
34	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 8),	 /* 256 */
35	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
36	UTIL_CHECK_TERMINATE
37};
38
39/* DX 9_2 */
40static unsigned caps_dx_9_2[] = {
41	UTIL_CHECK_CAP(OCCLUSION_QUERY),
42	UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
43	UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
44	UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
45	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
46	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12),	/* 2048 */
47	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),	 /* 256 */
48	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
49	UTIL_CHECK_TERMINATE
50};
51
52/* DX 9_3 */
53static unsigned caps_dx_9_3[] = {
54	UTIL_CHECK_CAP(OCCLUSION_QUERY),
55	UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
56	UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
57	UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
58	UTIL_CHECK_CAP(SM3),
59	//UTIL_CHECK_CAP(INSTANCING),
60	UTIL_CHECK_CAP(OCCLUSION_QUERY),
61	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4),
62	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13),	/* 4096 */
63	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),	 /* 256 */
64	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
65	UTIL_CHECK_TERMINATE
66};
67
68
69// this is called "screen" because in the D3D10 case it's only part of the device
70template<bool threadsafe>
71struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
72{
73	D3D_FEATURE_LEVEL feature_level;
74	int format_support[PIPE_FORMAT_COUNT];
75	unsigned creation_flags;
76	unsigned exception_mode;
77	maybe_mutex_t<threadsafe> mutex;
78
79/* TODO: Direct3D 11 specifies that fine-grained locking should be used if the driver supports it.
80 * Right now, I don't trust Gallium drivers to get this right.
81 */
82#define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(mutex)
83
84	GalliumD3D11ScreenImpl(struct pipe_screen* screen, struct pipe_context* immediate_pipe, BOOL owns_immediate_pipe,unsigned creation_flags, IDXGIAdapter* adapter)
85	: GalliumD3D11Screen(screen, immediate_pipe, adapter), creation_flags(creation_flags)
86	{
87		memset(&screen_caps, 0, sizeof(screen_caps));
88		screen_caps.gs = screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
89		screen_caps.so = !!screen->get_param(screen, PIPE_CAP_STREAM_OUTPUT);
90		screen_caps.queries = screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY);
91		screen_caps.render_condition = screen_caps.queries;
92		for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
93			screen_caps.constant_buffers[i] = screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
94		screen_caps.stages = 0;
95		for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
96		{
97			if(!screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
98				break;
99			screen_caps.stages = i + 1;
100		}
101
102		memset(format_support, 0xff, sizeof(format_support));
103
104		float default_level;
105		/* don't even attempt to autodetect D3D10 level support, since it's just not fully implemented yet */
106		if(util_check_caps(screen, caps_dx_9_3))
107			default_level = 9.3;
108		else if(util_check_caps(screen, caps_dx_9_2))
109			default_level = 9.2;
110		else if(util_check_caps(screen, caps_dx_9_1))
111			default_level = 9.1;
112		else
113		{
114			_debug_printf("Warning: driver does not even meet D3D_FEATURE_LEVEL_9_1 features, advertising it anyway!\n");
115			default_level = 9.1;
116		}
117
118		char default_level_name[64];
119		sprintf(default_level_name, "%.1f", default_level);
120		float feature_level_number = atof(debug_get_option("D3D11_FEATURE_LEVEL", default_level_name));
121		if(!feature_level_number)
122			feature_level_number = default_level;
123
124#if API >= 11
125		if(feature_level_number >= 11.0f)
126			feature_level = D3D_FEATURE_LEVEL_11_0;
127		else
128#endif
129		if(feature_level_number >= 10.1f)
130			feature_level = D3D_FEATURE_LEVEL_10_1;
131		else if(feature_level_number >= 10.0f)
132			feature_level = D3D_FEATURE_LEVEL_10_0;
133		else if(feature_level_number >= 9.3f)
134			feature_level = D3D_FEATURE_LEVEL_9_3;
135		else if(feature_level_number >= 9.2f)
136			feature_level = D3D_FEATURE_LEVEL_9_2;
137		else
138			feature_level = D3D_FEATURE_LEVEL_9_1;
139
140#if API >= 11
141		immediate_context = GalliumD3D11ImmediateDeviceContext_Create(this, immediate_pipe, owns_immediate_pipe);
142#endif
143	}
144
145	~GalliumD3D11ScreenImpl()
146	{
147#if API >= 11
148		GalliumD3D11ImmediateDeviceContext_Destroy(immediate_context);
149#endif
150	}
151
152	virtual D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(void)
153	{
154		return feature_level;
155	}
156
157	virtual unsigned STDMETHODCALLTYPE GetCreationFlags(void)
158	{
159		return creation_flags;
160	}
161
162	virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(void)
163	{
164		return S_OK;
165	}
166
167#if API >= 11
168	virtual void STDMETHODCALLTYPE GetImmediateContext(
169		ID3D11DeviceContext **ppImmediateContext)
170	{
171		immediate_context->AddRef();
172		*ppImmediateContext = immediate_context;
173	}
174#endif
175
176	virtual HRESULT STDMETHODCALLTYPE SetExceptionMode(unsigned RaiseFlags)
177	{
178		exception_mode = RaiseFlags;
179		return S_OK;
180	}
181
182	virtual unsigned STDMETHODCALLTYPE GetExceptionMode(void)
183	{
184		return exception_mode;
185	}
186
187	virtual HRESULT STDMETHODCALLTYPE CheckCounter(
188		const D3D11_COUNTER_DESC *pDesc,
189		D3D11_COUNTER_TYPE *pType,
190		unsigned *pActiveCounters,
191		LPSTR szName,
192		unsigned *pNameLength,
193		LPSTR szUnits,
194		unsigned *pUnitsLength,
195		LPSTR szDescription,
196		unsigned *pDescriptionLength)
197	{
198		return E_NOTIMPL;
199	}
200
201	virtual void STDMETHODCALLTYPE CheckCounterInfo(
202		D3D11_COUNTER_INFO *pCounterInfo)
203	{
204		/* none supported at the moment */
205		pCounterInfo->LastDeviceDependentCounter = (D3D11_COUNTER)0;
206		pCounterInfo->NumSimultaneousCounters = 0;
207		pCounterInfo->NumDetectableParallelUnits = 1;
208	}
209
210#if API >= 11
211	virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport(
212		D3D11_FEATURE Feature,
213		void *pFeatureSupportData,
214		unsigned FeatureSupportDataSize)
215	{
216		SYNCHRONIZED;
217
218		switch(Feature)
219		{
220			case D3D11_FEATURE_THREADING:
221			{
222				D3D11_FEATURE_DATA_THREADING* data = (D3D11_FEATURE_DATA_THREADING*)pFeatureSupportData;
223				if(FeatureSupportDataSize != sizeof(*data))
224					return E_INVALIDARG;
225
226				data->DriverCommandLists = FALSE;
227				data->DriverConcurrentCreates = FALSE;
228				return S_OK;
229			}
230			case D3D11_FEATURE_DOUBLES:
231			{
232				D3D11_FEATURE_DATA_DOUBLES* data = (D3D11_FEATURE_DATA_DOUBLES*)pFeatureSupportData;
233				if(FeatureSupportDataSize != sizeof(*data))
234					return E_INVALIDARG;
235
236				data->DoublePrecisionFloatShaderOps = FALSE;
237				return S_OK;
238			}
239			case D3D11_FEATURE_FORMAT_SUPPORT:
240			{
241				D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)pFeatureSupportData;
242				if(FeatureSupportDataSize != sizeof(*data))
243					return E_INVALIDARG;
244
245				return this->CheckFormatSupport(data->InFormat, &data->OutFormatSupport);
246			}
247			case D3D11_FEATURE_FORMAT_SUPPORT2:
248			{
249				D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)pFeatureSupportData;
250				if(FeatureSupportDataSize != sizeof(*data))
251					return E_INVALIDARG;
252
253				data->OutFormatSupport = 0;
254				/* TODO: should this be S_OK? */
255				return E_INVALIDARG;
256			}
257			case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS:
258			{
259				D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS* data = (D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS*)pFeatureSupportData;
260				if(FeatureSupportDataSize != sizeof(*data))
261					return E_INVALIDARG;
262
263				data->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = FALSE;
264				return S_OK;
265			}
266			default:
267				return E_INVALIDARG;
268		}
269	}
270#endif
271
272	virtual HRESULT STDMETHODCALLTYPE CheckFormatSupport(
273		DXGI_FORMAT Format,
274		unsigned *pFormatSupport
275	)
276	{
277		SYNCHRONIZED;
278
279		/* TODO: MSAA, advanced features */
280		pipe_format format = dxgi_to_pipe_format[Format];
281		if(!format)
282			return E_INVALIDARG;
283
284		int support = format_support[format];
285		if(support < 0)
286		{
287			support = 0;
288			unsigned buffer = D3D11_FORMAT_SUPPORT_BUFFER | D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER | D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER;
289			unsigned sampler_view = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
290			if(util_format_is_depth_or_stencil(format))
291				sampler_view |= D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON;
292
293			/* TODO: do this properly when Gallium drivers actually support index/vertex format queries */
294			if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER, 0)
295				|| (screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_INDEX_BUFFER, 0)
296				|| format == PIPE_FORMAT_R8_UNORM))
297				support |= buffer;
298			if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_STREAM_OUTPUT, 0))
299				support |= buffer | D3D11_FORMAT_SUPPORT_SO_BUFFER;
300			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_1D, 0, PIPE_BIND_SAMPLER_VIEW, 0))
301				support |= D3D11_FORMAT_SUPPORT_TEXTURE1D | sampler_view;
302			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0))
303				support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | sampler_view;
304			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_CUBE, 0, PIPE_BIND_SAMPLER_VIEW, 0))
305				support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | sampler_view;
306			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_3D, 0, PIPE_BIND_SAMPLER_VIEW, 0))
307				support |= D3D11_FORMAT_SUPPORT_TEXTURE3D | sampler_view;
308			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, 0))
309				support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_BLENDABLE;
310			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0))
311				support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DEPTH_STENCIL;
312			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DISPLAY_TARGET, 0))
313				support |= D3D11_FORMAT_SUPPORT_DISPLAY;
314			format_support[format] = support;
315		}
316		*pFormatSupport = support;
317		return S_OK;
318	}
319
320	virtual HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels(
321		DXGI_FORMAT Format,
322		unsigned SampleCount,
323		unsigned *pNumQualityLevels
324	)
325	{
326		SYNCHRONIZED;
327
328		*pNumQualityLevels = 0;
329		return S_OK;
330	}
331
332	template<typename T, typename U>
333	bool convert_blend_state(T& to, const U& from, unsigned BlendEnable, unsigned RenderTargetWriteMask)
334	{
335		if(invalid(0
336			|| from.SrcBlend >= D3D11_BLEND_COUNT
337			|| from.SrcBlendAlpha >= D3D11_BLEND_COUNT
338			|| from.DestBlend >= D3D11_BLEND_COUNT
339			|| from.DestBlendAlpha >= D3D11_BLEND_COUNT
340			|| from.BlendOp >= 6
341			|| from.BlendOpAlpha >= 6
342			|| !from.BlendOp
343			|| !from.BlendOpAlpha
344		))
345			return false;
346
347		to.blend_enable = BlendEnable;
348
349		to.rgb_func = from.BlendOp - 1;
350		to.alpha_func = from.BlendOpAlpha - 1;
351
352		to.rgb_src_factor = d3d11_to_pipe_blend[from.SrcBlend];
353		to.alpha_src_factor = d3d11_to_pipe_blend[from.SrcBlendAlpha];
354		to.rgb_dst_factor = d3d11_to_pipe_blend[from.DestBlend];
355		to.alpha_dst_factor = d3d11_to_pipe_blend[from.DestBlendAlpha];
356
357		to.colormask = RenderTargetWriteMask & 0xf;
358		return true;
359	}
360
361#if API >= 11
362	virtual HRESULT STDMETHODCALLTYPE CreateBlendState(
363		const D3D11_BLEND_DESC *pBlendStateDesc,
364		ID3D11BlendState **ppBlendState
365	)
366#else
367	virtual HRESULT STDMETHODCALLTYPE CreateBlendState1(
368		const D3D10_BLEND_DESC1 *pBlendStateDesc,
369		ID3D10BlendState1 **ppBlendState
370	)
371#endif
372	{
373		SYNCHRONIZED;
374
375		pipe_blend_state state;
376		memset(&state, 0, sizeof(state));
377		state.alpha_to_coverage = !!pBlendStateDesc->AlphaToCoverageEnable;
378		state.independent_blend_enable = !!pBlendStateDesc->IndependentBlendEnable;
379		assert(PIPE_MAX_COLOR_BUFS >= 8);
380		for(unsigned i = 0; i < 8; ++i)
381		{
382			 if(!convert_blend_state(
383					 state.rt[i],
384					 pBlendStateDesc->RenderTarget[i],
385					 pBlendStateDesc->RenderTarget[i].BlendEnable,
386					 pBlendStateDesc->RenderTarget[i].RenderTargetWriteMask))
387				 return E_INVALIDARG;
388		}
389
390		if(!ppBlendState)
391			return S_FALSE;
392
393		void* object = immediate_pipe->create_blend_state(immediate_pipe, &state);
394		if(!object)
395			return E_FAIL;
396
397		*ppBlendState = new GalliumD3D11BlendState(this, object, *pBlendStateDesc);
398		return S_OK;
399	}
400
401#if API < 11
402	virtual HRESULT STDMETHODCALLTYPE CreateBlendState(
403		const D3D10_BLEND_DESC *pBlendStateDesc,
404		ID3D10BlendState **ppBlendState
405	)
406	{
407		SYNCHRONIZED;
408
409		pipe_blend_state state;
410		memset(&state, 0, sizeof(state));
411		state.alpha_to_coverage = !!pBlendStateDesc->AlphaToCoverageEnable;
412		assert(PIPE_MAX_COLOR_BUFS >= 8);
413		for(unsigned i = 0; i < 8; ++i)
414		{
415			if(!convert_blend_state(
416				state.rt[i],
417				*pBlendStateDesc,
418				pBlendStateDesc->BlendEnable[i],
419				pBlendStateDesc->RenderTargetWriteMask[i]))
420				return E_INVALIDARG;
421		}
422
423		for(unsigned i = 1; i < 8; ++i)
424		{
425			if(memcmp(&state.rt[0], &state.rt[i], sizeof(state.rt[0])))
426			{
427				state.independent_blend_enable = TRUE;
428				break;
429			}
430		}
431
432		void* object = immediate_pipe->create_blend_state(immediate_pipe, &state);
433		if(!object)
434			return E_FAIL;
435
436		*ppBlendState = new GalliumD3D11BlendState(this, object, *pBlendStateDesc);
437		return S_OK;
438	}
439#endif
440
441	virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilState(
442		const D3D11_DEPTH_STENCIL_DESC *pDepthStencilStateDesc,
443		ID3D11DepthStencilState **ppDepthStencilState
444	)
445	{
446		SYNCHRONIZED;
447
448		pipe_depth_stencil_alpha_state state;
449		memset(&state, 0, sizeof(state));
450		state.depth.enabled = !!pDepthStencilStateDesc->DepthEnable;
451		state.depth.writemask = pDepthStencilStateDesc->DepthWriteMask;
452		state.depth.func = pDepthStencilStateDesc->DepthFunc - 1;
453		state.stencil[0].enabled = !!pDepthStencilStateDesc->StencilEnable;
454		state.stencil[0].writemask = pDepthStencilStateDesc->StencilWriteMask;
455		state.stencil[0].valuemask = pDepthStencilStateDesc->StencilReadMask;
456		state.stencil[0].zpass_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilPassOp];
457		state.stencil[0].fail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilFailOp];
458		state.stencil[0].zfail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilDepthFailOp];
459		state.stencil[0].func = pDepthStencilStateDesc->FrontFace.StencilFunc - 1;
460		state.stencil[1].enabled = !!pDepthStencilStateDesc->StencilEnable;
461		state.stencil[1].writemask = pDepthStencilStateDesc->StencilWriteMask;
462		state.stencil[1].valuemask = pDepthStencilStateDesc->StencilReadMask;
463		state.stencil[1].zpass_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilPassOp];
464		state.stencil[1].fail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilFailOp];
465		state.stencil[1].zfail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilDepthFailOp];
466		state.stencil[1].func = pDepthStencilStateDesc->BackFace.StencilFunc - 1;
467
468		if(!ppDepthStencilState)
469			return S_FALSE;
470
471		void* object = immediate_pipe->create_depth_stencil_alpha_state(immediate_pipe, &state);
472		if(!object)
473			return E_FAIL;
474
475		*ppDepthStencilState = new GalliumD3D11DepthStencilState(this, object, *pDepthStencilStateDesc);
476		return S_OK;
477	}
478
479	virtual HRESULT STDMETHODCALLTYPE CreateRasterizerState(
480		const D3D11_RASTERIZER_DESC *pRasterizerDesc,
481		ID3D11RasterizerState **ppRasterizerState)
482	{
483		SYNCHRONIZED;
484
485		pipe_rasterizer_state state;
486		memset(&state, 0, sizeof(state));
487		state.gl_rasterization_rules = 1; /* D3D10/11 use GL rules */
488		state.fill_front = state.fill_back = (pRasterizerDesc->FillMode == D3D11_FILL_WIREFRAME) ? PIPE_POLYGON_MODE_LINE : PIPE_POLYGON_MODE_FILL;
489		if(pRasterizerDesc->CullMode == D3D11_CULL_FRONT)
490			state.cull_face = PIPE_FACE_FRONT;
491		else if(pRasterizerDesc->CullMode == D3D11_CULL_BACK)
492			state.cull_face = PIPE_FACE_BACK;
493		else
494			state.cull_face = PIPE_FACE_NONE;
495		state.front_ccw = !!pRasterizerDesc->FrontCounterClockwise;
496		/* TODO: is this correct? */
497		/* TODO: we are ignoring DepthBiasClamp! */
498		state.offset_tri = state.offset_line = state.offset_point = pRasterizerDesc->SlopeScaledDepthBias || pRasterizerDesc->DepthBias;
499		state.offset_scale = pRasterizerDesc->SlopeScaledDepthBias;
500		state.offset_units = pRasterizerDesc->DepthBias;
501		state.scissor = !!pRasterizerDesc->ScissorEnable;
502		state.multisample = !!pRasterizerDesc->MultisampleEnable;
503		state.line_smooth = !!pRasterizerDesc->AntialiasedLineEnable;
504
505		/* TODO: is this correct? */
506		state.point_quad_rasterization = 1;
507
508		if(!ppRasterizerState)
509			return S_FALSE;
510
511		void* object = immediate_pipe->create_rasterizer_state(immediate_pipe, &state);
512		if(!object)
513			return E_FAIL;
514
515		*ppRasterizerState = new GalliumD3D11RasterizerState(this, object, *pRasterizerDesc, !pRasterizerDesc->DepthClipEnable);
516		return S_OK;
517	}
518
519	virtual HRESULT STDMETHODCALLTYPE CreateSamplerState(
520		const D3D11_SAMPLER_DESC *pSamplerDesc,
521		ID3D11SamplerState **ppSamplerState)
522	{
523		SYNCHRONIZED;
524
525		pipe_sampler_state state;
526		memset(&state, 0, sizeof(state));
527		state.normalized_coords = 1;
528		state.min_mip_filter = (pSamplerDesc->Filter & 1);
529		state.mag_img_filter = ((pSamplerDesc->Filter >> 2) & 1);
530		state.min_img_filter = ((pSamplerDesc->Filter >> 4) & 1);
531		if(pSamplerDesc->Filter & 0x40)
532			state.max_anisotropy = pSamplerDesc->MaxAnisotropy;
533		if(pSamplerDesc->Filter & 0x80)
534		{
535			state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
536			state.compare_func = pSamplerDesc->ComparisonFunc;
537		}
538		state.wrap_s = d3d11_to_pipe_wrap[pSamplerDesc->AddressU];
539		state.wrap_t = d3d11_to_pipe_wrap[pSamplerDesc->AddressV];
540		state.wrap_r = d3d11_to_pipe_wrap[pSamplerDesc->AddressW];
541		state.lod_bias = pSamplerDesc->MipLODBias;
542		memcpy(state.border_color, pSamplerDesc->BorderColor, sizeof(state.border_color));
543		state.min_lod = pSamplerDesc->MinLOD;
544		state.max_lod = pSamplerDesc->MaxLOD;
545
546		if(!ppSamplerState)
547			return S_FALSE;
548
549		void* object = immediate_pipe->create_sampler_state(immediate_pipe, &state);
550		if(!object)
551			return E_FAIL;
552
553		*ppSamplerState = new GalliumD3D11SamplerState(this, object, *pSamplerDesc);
554		return S_OK;
555	}
556
557	virtual HRESULT STDMETHODCALLTYPE CreateInputLayout(
558		const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
559		unsigned NumElements,
560		const void *pShaderBytecodeWithInputSignature,
561		SIZE_T BytecodeLength,
562		ID3D11InputLayout **ppInputLayout)
563	{
564		SYNCHRONIZED;
565
566		if(NumElements > D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT)
567			return E_INVALIDARG;
568		assert(D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT <= PIPE_MAX_ATTRIBS);
569
570		// putting semantics matching in the core API seems to be a (minor) design mistake
571
572		struct dxbc_chunk_signature* sig = dxbc_find_signature(pShaderBytecodeWithInputSignature, BytecodeLength, false);
573		D3D11_SIGNATURE_PARAMETER_DESC* params;
574		unsigned num_params = dxbc_parse_signature(sig, &params);
575
576		typedef std::unordered_map<std::pair<c_string, unsigned>, unsigned> semantic_to_idx_map_t;
577		semantic_to_idx_map_t semantic_to_idx_map;
578		for(unsigned i = 0; i < NumElements; ++i)
579			semantic_to_idx_map[std::make_pair(c_string(pInputElementDescs[i].SemanticName), pInputElementDescs[i].SemanticIndex)] = i;
580
581		struct pipe_vertex_element elements[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
582
583		unsigned num_params_to_use = std::min(num_params, (unsigned)D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT);
584		for(unsigned i = 0; i < num_params_to_use; ++i)
585		{
586			int idx = -1;
587			semantic_to_idx_map_t::iterator iter = semantic_to_idx_map.find(std::make_pair(c_string(params[i].SemanticName), params[i].SemanticIndex));
588			if(iter != semantic_to_idx_map.end())
589				idx = iter->second;
590
591			// TODO: I kind of doubt Gallium drivers will like null elements; should we do something about it, either here, in the interface, or in the drivers?
592			// TODO: also, in which cases should we return errors? (i.e. duplicate semantics in vs, duplicate semantics in layout, unmatched semantic in vs, unmatched semantic in layout)
593			memset(&elements[i], 0, sizeof(elements[i]));
594			if(idx >= 0)
595			{
596				elements[i].src_format = dxgi_to_pipe_format[pInputElementDescs[idx].Format];
597				elements[i].src_offset = pInputElementDescs[idx].AlignedByteOffset;
598				elements[i].vertex_buffer_index = pInputElementDescs[idx].InputSlot;
599				elements[i].instance_divisor = pInputElementDescs[idx].InstanceDataStepRate;
600			}
601		}
602
603		free(params);
604
605		if(!ppInputLayout)
606			return S_FALSE;
607
608		void* object = immediate_pipe->create_vertex_elements_state(immediate_pipe, num_params_to_use, elements);
609		if(!object)
610			return E_FAIL;
611
612		*ppInputLayout = new GalliumD3D11InputLayout(this, object);
613		return S_OK;
614	}
615
616	static unsigned d3d11_to_pipe_bind_flags(unsigned BindFlags)
617	{
618		unsigned bind = 0;
619		if(BindFlags & D3D11_BIND_VERTEX_BUFFER)
620			bind |= PIPE_BIND_VERTEX_BUFFER;
621		if(BindFlags & D3D11_BIND_INDEX_BUFFER)
622			bind |= PIPE_BIND_INDEX_BUFFER;
623		if(BindFlags & D3D11_BIND_CONSTANT_BUFFER)
624			bind |= PIPE_BIND_CONSTANT_BUFFER;
625		if(BindFlags & D3D11_BIND_SHADER_RESOURCE)
626			bind |= PIPE_BIND_SAMPLER_VIEW;
627		if(BindFlags & D3D11_BIND_STREAM_OUTPUT)
628			bind |= PIPE_BIND_STREAM_OUTPUT;
629		if(BindFlags & D3D11_BIND_RENDER_TARGET)
630			bind |= PIPE_BIND_RENDER_TARGET;
631		if(BindFlags & D3D11_BIND_DEPTH_STENCIL)
632			bind |= PIPE_BIND_DEPTH_STENCIL;
633		return bind;
634	}
635
636	inline HRESULT create_resource(
637		pipe_texture_target target,
638		unsigned Width,
639		unsigned Height,
640		unsigned Depth,
641		unsigned MipLevels,
642		unsigned ArraySize,
643		DXGI_FORMAT Format,
644		const DXGI_SAMPLE_DESC* SampleDesc,
645		D3D11_USAGE Usage,
646		unsigned BindFlags,
647		unsigned CPUAccessFlags,
648		unsigned MiscFlags,
649		const D3D11_SUBRESOURCE_DATA *pInitialData,
650		DXGI_USAGE dxgi_usage,
651		struct pipe_resource** ppresource
652	)
653	{
654		if(invalid(Format >= DXGI_FORMAT_COUNT))
655			return E_INVALIDARG;
656		if(MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
657		{
658			if(target != PIPE_TEXTURE_2D)
659				return E_INVALIDARG;
660			target = PIPE_TEXTURE_CUBE;
661
662			if(ArraySize != 6)
663				return E_NOTIMPL;
664		}
665		else
666		{
667			if(ArraySize > 1)
668				return E_NOTIMPL;
669			ArraySize = 1;
670		}
671		/* TODO: msaa */
672		struct pipe_resource templat;
673		memset(&templat, 0, sizeof(templat));
674		templat.target = target;
675		templat.width0 = Width;
676		templat.height0 = Height;
677		templat.depth0 = Depth;
678		templat.last_level = MipLevels ? (MipLevels - 1) : 0;
679		templat.format = dxgi_to_pipe_format[Format];
680		templat.bind = d3d11_to_pipe_bind_flags(BindFlags);
681		if(CPUAccessFlags & D3D11_CPU_ACCESS_READ)
682			templat.bind |= PIPE_BIND_TRANSFER_READ;
683		if(CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
684			templat.bind |= PIPE_BIND_TRANSFER_WRITE;
685		if(MiscFlags & D3D11_RESOURCE_MISC_SHARED)
686			templat.bind |= PIPE_BIND_SHARED;
687		if(MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE)
688			templat.bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE;
689		if(dxgi_usage & DXGI_USAGE_BACK_BUFFER)
690			templat.bind |= PIPE_BIND_DISPLAY_TARGET;
691		templat.usage = d3d11_to_pipe_usage[Usage];
692		if(invalid(!templat.format))
693			return E_NOTIMPL;
694
695		if(!ppresource)
696			return S_FALSE;
697
698		struct pipe_resource* resource = screen->resource_create(screen, &templat);
699		if(!resource)
700			return E_FAIL;
701		if(pInitialData)
702		{
703			for(unsigned slice = 0; slice < ArraySize; ++slice)
704			{
705				for(unsigned level = 0; level <= templat.last_level; ++level)
706				{
707					struct pipe_subresource sr;
708					sr.level = level;
709					sr.face = slice;
710					struct pipe_box box;
711					box.x = box.y = box.z = 0;
712					box.width = u_minify(Width, level);
713					box.height = u_minify(Height, level);
714					box.depth = u_minify(Depth, level);
715					immediate_pipe->transfer_inline_write(immediate_pipe, resource, sr, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_UNSYNCHRONIZED, &box, pInitialData->pSysMem, pInitialData->SysMemPitch, pInitialData->SysMemSlicePitch);
716					++pInitialData;
717				}
718			}
719		}
720		*ppresource = resource;
721		return S_OK;
722	}
723
724	static unsigned d3d_to_dxgi_usage(unsigned bind, unsigned misc)
725	{
726		unsigned dxgi_usage = 0;
727		if(bind |= D3D11_BIND_RENDER_TARGET)
728			dxgi_usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
729		if(bind & D3D11_BIND_SHADER_RESOURCE)
730			dxgi_usage |= DXGI_USAGE_SHADER_INPUT;
731#if API >= 11
732		if(bind & D3D11_BIND_UNORDERED_ACCESS)
733			dxgi_usage |= DXGI_USAGE_UNORDERED_ACCESS;
734#endif
735		if(misc & D3D11_RESOURCE_MISC_SHARED)
736			dxgi_usage |= DXGI_USAGE_SHARED;
737		return dxgi_usage;
738	}
739
740	virtual HRESULT STDMETHODCALLTYPE CreateTexture1D(
741		const D3D11_TEXTURE1D_DESC *pDesc,
742		const D3D11_SUBRESOURCE_DATA *pInitialData,
743		ID3D11Texture1D **ppTexture1D)
744	{
745		SYNCHRONIZED;
746
747		struct pipe_resource* resource;
748		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags);
749		HRESULT hr = create_resource(PIPE_TEXTURE_1D, pDesc->Width, 1, 1, pDesc->MipLevels, pDesc->ArraySize, pDesc->Format, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture1D ? &resource : 0);
750		if(hr != S_OK)
751			return hr;
752		*ppTexture1D = new GalliumD3D11Texture1D(this, resource, *pDesc, dxgi_usage);
753		return S_OK;
754	}
755
756	virtual HRESULT STDMETHODCALLTYPE CreateTexture2D(
757		const D3D11_TEXTURE2D_DESC *pDesc,
758		const D3D11_SUBRESOURCE_DATA *pInitialData,
759		ID3D11Texture2D **ppTexture2D)
760	{
761		SYNCHRONIZED;
762
763		struct pipe_resource* resource;
764		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags);
765		HRESULT hr = create_resource(PIPE_TEXTURE_2D, pDesc->Width, pDesc->Height, 1, pDesc->MipLevels, pDesc->ArraySize, pDesc->Format, &pDesc->SampleDesc, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture2D ? &resource : 0);
766		if(hr != S_OK)
767			return hr;
768		if(pDesc->MipLevels == 1 && pDesc->ArraySize == 1)
769			*ppTexture2D = new GalliumD3D11Surface(this, resource, *pDesc, dxgi_usage);
770		else
771			*ppTexture2D = new GalliumD3D11Texture2D(this, resource, *pDesc, dxgi_usage);
772		return S_OK;
773	}
774
775	virtual HRESULT STDMETHODCALLTYPE CreateTexture3D(
776		const D3D11_TEXTURE3D_DESC *pDesc,
777		const D3D11_SUBRESOURCE_DATA *pInitialData,
778		ID3D11Texture3D **ppTexture3D)
779	{
780		SYNCHRONIZED;
781
782		struct pipe_resource* resource;
783		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags);
784		HRESULT hr = create_resource(PIPE_TEXTURE_3D, pDesc->Width, pDesc->Height, pDesc->Depth, pDesc->MipLevels, 1, pDesc->Format, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture3D ? &resource : 0);
785		if(hr != S_OK)
786			return hr;
787		*ppTexture3D = new GalliumD3D11Texture3D(this, resource, *pDesc, dxgi_usage);
788		return S_OK;
789	}
790
791	virtual HRESULT STDMETHODCALLTYPE CreateBuffer(
792		const D3D11_BUFFER_DESC *pDesc,
793		const D3D11_SUBRESOURCE_DATA *pInitialData,
794		ID3D11Buffer **ppBuffer)
795	{
796		SYNCHRONIZED;
797
798#if API >= 11
799		if(pDesc->StructureByteStride > 1)
800			return E_NOTIMPL;
801#endif
802		struct pipe_resource* resource;
803		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags);
804		HRESULT hr = create_resource(PIPE_BUFFER, pDesc->ByteWidth, 1, 1, 1, 1, DXGI_FORMAT_R8_UNORM, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppBuffer ? &resource : 0);
805		if(hr != S_OK)
806			return hr;
807		*ppBuffer = new GalliumD3D11Buffer(this, resource, *pDesc, dxgi_usage);
808		return S_OK;
809	}
810
811	virtual HRESULT STDMETHODCALLTYPE OpenGalliumResource(
812		struct pipe_resource* resource,
813		IUnknown** dxgi_resource)
814	{
815		SYNCHRONIZED;
816
817		/* TODO: maybe support others */
818		assert(resource->target == PIPE_TEXTURE_2D);
819		*dxgi_resource = 0;
820		D3D11_TEXTURE2D_DESC desc;
821		memset(&desc, 0, sizeof(desc));
822		desc.Width = resource->width0;
823		desc.Height = resource->height0;
824		init_pipe_to_dxgi_format();
825		desc.Format = pipe_to_dxgi_format[resource->format];
826		desc.SampleDesc.Count = resource->nr_samples;
827		desc.SampleDesc.Quality = 0;
828		desc.ArraySize = 1;
829		desc.MipLevels = resource->last_level + 1;
830		desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
831		if(resource->bind & PIPE_BIND_RENDER_TARGET)
832			desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
833		if(resource->bind & PIPE_BIND_DEPTH_STENCIL)
834			desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
835		if(resource->bind & PIPE_BIND_SAMPLER_VIEW)
836			desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
837		if(resource->bind & PIPE_BIND_SHARED)
838			desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
839		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc.BindFlags, desc.MiscFlags);
840		if(desc.MipLevels == 1 && desc.ArraySize == 1)
841			*dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Surface(this, resource, desc, dxgi_usage);
842		else
843			*dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Texture2D(this, resource, desc, dxgi_usage);
844		return S_OK;
845	}
846
847	virtual HRESULT STDMETHODCALLTYPE CreateSurface(
848		const DXGI_SURFACE_DESC *pDesc,
849		unsigned NumSurfaces,
850		DXGI_USAGE Usage,
851		const DXGI_SHARED_RESOURCE *pSharedResource,
852		IDXGISurface **ppSurface)
853	{
854		SYNCHRONIZED;
855
856		D3D11_TEXTURE2D_DESC desc;
857		memset(&desc, 0, sizeof(desc));
858
859		struct pipe_resource* resource;
860		desc.Width = pDesc->Width;
861		desc.Height = pDesc->Height;
862		desc.Format = pDesc->Format;
863		desc.SampleDesc = pDesc->SampleDesc;
864		desc.ArraySize = NumSurfaces;
865		desc.MipLevels = 1;
866		desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
867		if(Usage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
868			desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
869		if(Usage & DXGI_USAGE_SHADER_INPUT)
870			desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
871#if API >= 11
872		if(Usage & DXGI_USAGE_UNORDERED_ACCESS)
873			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
874#endif
875		if(Usage & DXGI_USAGE_SHARED)
876			desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
877		HRESULT hr = create_resource(PIPE_TEXTURE_2D, pDesc->Width, pDesc->Height, 1, 1, NumSurfaces, pDesc->Format, &pDesc->SampleDesc, D3D11_USAGE_DEFAULT, desc.BindFlags, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE, desc.MiscFlags, 0, Usage, &resource);
878		if(hr != S_OK)
879			return hr;
880		*ppSurface = new GalliumD3D11Surface(this, resource, desc, Usage);
881		return S_OK;
882	}
883
884	virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView(
885		ID3D11Resource *pResource,
886		const D3D11_SHADER_RESOURCE_VIEW_DESC *pDesc,
887		ID3D11ShaderResourceView **ppSRView)
888	{
889#if API >= 11
890		D3D11_SHADER_RESOURCE_VIEW_DESC def_desc;
891#else
892		if(pDesc->ViewDimension == D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY)
893			return E_INVALIDARG;
894		D3D10_SHADER_RESOURCE_VIEW_DESC1 desc1;
895		memset(&desc1, 0, sizeof(desc1));
896		memcpy(&desc1, pDesc, sizeof(*pDesc));
897		return CreateShaderResourceView1(pResource, &desc1, (ID3D10ShaderResourceView1**)ppSRView);
898	}
899
900	virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView1(
901			ID3D11Resource *pResource,
902			const D3D10_SHADER_RESOURCE_VIEW_DESC1 *pDesc,
903			ID3D10ShaderResourceView1 **ppSRView)
904	{
905		D3D10_SHADER_RESOURCE_VIEW_DESC1 def_desc;
906#endif
907		SYNCHRONIZED;
908
909		if(!pDesc)
910		{
911			struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource;
912			init_pipe_to_dxgi_format();
913			memset(&def_desc, 0, sizeof(def_desc));
914			def_desc.Format = pipe_to_dxgi_format[resource->format];
915			switch(resource->target)
916			{
917			case PIPE_BUFFER:
918				def_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
919				def_desc.Buffer.ElementWidth = 1;
920#if API >= 11
921				def_desc.Buffer.NumElements = resource->width0;
922#endif
923				break;
924			case PIPE_TEXTURE_1D:
925				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
926				def_desc.Texture1D.MipLevels = resource->last_level + 1;
927				break;
928			case PIPE_TEXTURE_2D:
929			case PIPE_TEXTURE_RECT:
930				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
931				def_desc.Texture2D.MipLevels = resource->last_level + 1;
932				break;
933			case PIPE_TEXTURE_3D:
934				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
935				def_desc.Texture3D.MipLevels = resource->last_level + 1;
936				break;
937			case PIPE_TEXTURE_CUBE:
938				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
939				def_desc.TextureCube.MipLevels = resource->last_level + 1;
940				break;
941			default:
942				return E_INVALIDARG;
943			}
944			pDesc = &def_desc;
945		}
946
947		struct pipe_sampler_view templat;
948		memset(&templat, 0, sizeof(templat));
949		if(invalid(Format >= DXGI_FORMAT_COUNT))
950			return E_INVALIDARG;
951		templat.format = dxgi_to_pipe_format[pDesc->Format];
952		if(!templat.format)
953			return E_NOTIMPL;
954		templat.swizzle_r = PIPE_SWIZZLE_RED;
955		templat.swizzle_g = PIPE_SWIZZLE_GREEN;
956		templat.swizzle_b = PIPE_SWIZZLE_BLUE;
957		templat.swizzle_a = PIPE_SWIZZLE_ALPHA;
958
959		templat.texture = ((GalliumD3D11Resource<>*)pResource)->resource;
960		switch(pDesc->ViewDimension)
961		{
962		case D3D11_SRV_DIMENSION_TEXTURE1D:
963		case D3D11_SRV_DIMENSION_TEXTURE2D:
964		case D3D11_SRV_DIMENSION_TEXTURE3D:
965		case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
966		case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
967			/* yes, this works for all of these types (but TODO: texture arrays) */
968			templat.first_level = pDesc->Texture1D.MostDetailedMip;
969			templat.last_level = templat.first_level + pDesc->Texture1D.MipLevels - 1;
970			break;
971		case D3D11_SRV_DIMENSION_BUFFER:
972		case D3D11_SRV_DIMENSION_TEXTURE2DMS:
973		case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
974			return E_NOTIMPL;
975		default:
976			return E_INVALIDARG;
977		}
978
979		if(!ppSRView)
980			return S_FALSE;
981
982		struct pipe_sampler_view* view = immediate_pipe->create_sampler_view(immediate_pipe, templat.texture, &templat);
983		if(!view)
984			return E_FAIL;
985		*ppSRView = new GalliumD3D11ShaderResourceView(this, (GalliumD3D11Resource<>*)pResource, view, *pDesc);
986		return S_OK;
987	}
988
989#if API >= 11
990	virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView(
991		ID3D11Resource *pResource,
992		const D3D11_UNORDERED_ACCESS_VIEW_DESC *pDesc,
993		ID3D11UnorderedAccessView **ppUAView)
994	{
995		SYNCHRONIZED;
996
997		return E_NOTIMPL;
998
999		// remember to return S_FALSE and not crash if ppUAView == 0 and parameters are valid
1000	}
1001#endif
1002
1003	virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
1004		ID3D11Resource *pResource,
1005		const D3D11_RENDER_TARGET_VIEW_DESC *pDesc,
1006		ID3D11RenderTargetView **ppRTView)
1007	{
1008		SYNCHRONIZED;
1009
1010		D3D11_RENDER_TARGET_VIEW_DESC def_desc;
1011		if(!pDesc)
1012		{
1013			struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource;
1014			init_pipe_to_dxgi_format();
1015			memset(&def_desc, 0, sizeof(def_desc));
1016			def_desc.Format = pipe_to_dxgi_format[resource->format];
1017			switch(resource->target)
1018			{
1019			case PIPE_BUFFER:
1020				def_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER;
1021				def_desc.Buffer.ElementWidth = 1;
1022#if API >= 11
1023				def_desc.Buffer.NumElements = resource->width0;
1024#endif
1025				break;
1026			case PIPE_TEXTURE_1D:
1027				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
1028				break;
1029			case PIPE_TEXTURE_2D:
1030			case PIPE_TEXTURE_RECT:
1031				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1032				break;
1033			case PIPE_TEXTURE_3D:
1034				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
1035				def_desc.Texture3D.WSize = resource->depth0;
1036				break;
1037			case PIPE_TEXTURE_CUBE:
1038				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1039				def_desc.Texture2DArray.ArraySize = 6;
1040				break;
1041			default:
1042				return E_INVALIDARG;
1043			}
1044			pDesc = &def_desc;
1045		}
1046
1047		unsigned zslice = 0;
1048		unsigned face = 0;
1049		unsigned level;
1050		enum pipe_format format;
1051		if(invalid(pDesc->Format >= DXGI_FORMAT_COUNT))
1052			return E_INVALIDARG;
1053		format = dxgi_to_pipe_format[pDesc->Format];
1054		if(!format)
1055			return E_NOTIMPL;
1056
1057		switch(pDesc->ViewDimension)
1058		{
1059		case D3D11_RTV_DIMENSION_TEXTURE1D:
1060		case D3D11_RTV_DIMENSION_TEXTURE2D:
1061			level = pDesc->Texture1D.MipSlice;
1062			break;
1063		case D3D11_RTV_DIMENSION_TEXTURE3D:
1064			level = pDesc->Texture3D.MipSlice;
1065			zslice = pDesc->Texture3D.FirstWSlice;
1066			break;
1067		case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
1068		case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
1069			level = pDesc->Texture1DArray.MipSlice;
1070			face = pDesc->Texture1DArray.FirstArraySlice;
1071			break;
1072		case D3D11_RTV_DIMENSION_BUFFER:
1073		case D3D11_RTV_DIMENSION_TEXTURE2DMS:
1074		case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
1075			return E_NOTIMPL;
1076		default:
1077			return E_INVALIDARG;
1078		}
1079
1080		if(!ppRTView)
1081			return S_FALSE;
1082
1083		struct pipe_surface* surface = screen->get_tex_surface(screen,
1084				((GalliumD3D11Resource<>*)pResource)->resource,
1085				face, level, zslice, PIPE_BIND_RENDER_TARGET);
1086		if(!surface)
1087			return E_FAIL;
1088		/* muhahahahaha, let's hope this actually works */
1089		surface->format = format;
1090		*ppRTView = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)pResource, surface, *pDesc);
1091		return S_OK;
1092	}
1093
1094	virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView(
1095		ID3D11Resource *pResource,
1096		const D3D11_DEPTH_STENCIL_VIEW_DESC *pDesc,
1097		ID3D11DepthStencilView **ppDepthStencilView)
1098	{
1099		SYNCHRONIZED;
1100
1101		D3D11_DEPTH_STENCIL_VIEW_DESC def_desc;
1102		if(!pDesc)
1103		{
1104			struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource;
1105			init_pipe_to_dxgi_format();
1106			memset(&def_desc, 0, sizeof(def_desc));
1107			def_desc.Format = pipe_to_dxgi_format[resource->format];
1108			switch(resource->target)
1109			{
1110			case PIPE_TEXTURE_1D:
1111				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
1112				break;
1113			case PIPE_TEXTURE_2D:
1114			case PIPE_TEXTURE_RECT:
1115				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
1116				break;
1117			case PIPE_TEXTURE_CUBE:
1118				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
1119				def_desc.Texture2DArray.ArraySize = 6;
1120				break;
1121			default:
1122				return E_INVALIDARG;
1123			}
1124			pDesc = &def_desc;
1125		}
1126
1127		unsigned zslice = 0;
1128		unsigned face = 0;
1129		unsigned level;
1130		enum pipe_format format;
1131		if(invalid(pDesc->Format >= DXGI_FORMAT_COUNT))
1132			return E_INVALIDARG;
1133		format = dxgi_to_pipe_format[pDesc->Format];
1134		if(!format)
1135			return E_NOTIMPL;
1136
1137		switch(pDesc->ViewDimension)
1138		{
1139		case D3D11_DSV_DIMENSION_TEXTURE1D:
1140		case D3D11_DSV_DIMENSION_TEXTURE2D:
1141			level = pDesc->Texture1D.MipSlice;
1142			break;
1143		case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
1144		case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
1145			level = pDesc->Texture1DArray.MipSlice;
1146			face = pDesc->Texture1DArray.FirstArraySlice;
1147			break;
1148		case D3D11_DSV_DIMENSION_TEXTURE2DMS:
1149		case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
1150			return E_NOTIMPL;
1151		default:
1152			return E_INVALIDARG;
1153		}
1154
1155		if(!ppDepthStencilView)
1156			return S_FALSE;
1157
1158		struct pipe_surface* surface = screen->get_tex_surface(screen,
1159				((GalliumD3D11Resource<>*)pResource)->resource,
1160				face, level, zslice, PIPE_BIND_DEPTH_STENCIL);
1161		if(!surface)
1162			return E_FAIL;
1163		/* muhahahahaha, let's hope this actually works */
1164		surface->format = format;
1165		*ppDepthStencilView = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)pResource, surface, *pDesc);
1166		return S_OK;
1167	}
1168
1169	GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void *pShaderBytecode, SIZE_T BytecodeLength
1170#if API >= 11
1171			, ID3D11ClassLinkage *pClassLinkage
1172#endif
1173			)
1174	{
1175		dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(pShaderBytecode, BytecodeLength);
1176		if(!sm4_chunk)
1177			return 0;
1178
1179		std::auto_ptr<sm4_program> sm4(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size)));
1180		if(!sm4.get())
1181			return 0;
1182
1183		struct pipe_shader_state tgsi_shader;
1184		memset(&tgsi_shader, 0, sizeof(tgsi_shader));
1185		tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4);
1186		if(!tgsi_shader.tokens)
1187			return 0;
1188
1189		void* shader_cso;
1190		GalliumD3D11Shader<>* shader;
1191
1192		switch(type)
1193		{
1194		case PIPE_SHADER_VERTEX:
1195			shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader);
1196			shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso);
1197			break;
1198		case PIPE_SHADER_FRAGMENT:
1199			shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader);
1200			shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso);
1201			break;
1202		case PIPE_SHADER_GEOMETRY:
1203			shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader);
1204			shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso);
1205			break;
1206		default:
1207			shader_cso = 0;
1208			shader = 0;
1209			break;
1210		}
1211
1212		if(shader)
1213		{
1214			shader->slot_to_resource = sm4->slot_to_resource;
1215			shader->slot_to_sampler = sm4->slot_to_sampler;
1216		}
1217
1218		free((void*)tgsi_shader.tokens);
1219		return shader;
1220	}
1221
1222#if API >= 11
1223#define CREATE_SHADER_ARGS \
1224	const void *pShaderBytecode, \
1225	SIZE_T BytecodeLength, \
1226	ID3D11ClassLinkage *pClassLinkage
1227#define PASS_SHADER_ARGS pShaderBytecode, BytecodeLength, pClassLinkage
1228#else
1229#define CREATE_SHADER_ARGS \
1230	const void *pShaderBytecode, \
1231	SIZE_T BytecodeLength
1232#define PASS_SHADER_ARGS pShaderBytecode, BytecodeLength
1233#endif
1234
1235#define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \
1236	virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
1237		CREATE_SHADER_ARGS, \
1238		ID3D11##Stage##Shader **pp##Stage##Shader) \
1239	{ \
1240		SYNCHRONIZED; \
1241		GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS); \
1242		if(!shader) \
1243			return E_FAIL; \
1244		if(pp##Stage##Shader) \
1245		{ \
1246			*pp##Stage##Shader = shader; \
1247			return S_OK; \
1248		} \
1249		else \
1250		{ \
1251			shader->Release(); \
1252			return S_FALSE; \
1253		} \
1254	}
1255
1256#define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \
1257	virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
1258		CREATE_SHADER_ARGS, \
1259		ID3D11##Stage##Shader **pp##Stage##Shader) \
1260	{ \
1261		return E_NOTIMPL; \
1262	}
1263
1264	IMPLEMENT_CREATE_SHADER(Vertex, VERTEX)
1265	IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT)
1266	IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY)
1267#if API >= 11
1268	IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull)
1269	IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain)
1270	IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute)
1271#endif
1272
1273	virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput(
1274		const void *pShaderBytecode,
1275		SIZE_T BytecodeLength,
1276		const D3D11_SO_DECLARATION_ENTRY *pSODeclaration,
1277		unsigned NumEntries,
1278#if API >= 11
1279		const unsigned *pBufferStrides,
1280		unsigned NumStrides,
1281		unsigned RasterizedStream,
1282		ID3D11ClassLinkage *pClassLinkage,
1283#else
1284		UINT OutputStreamStride,
1285#endif
1286		ID3D11GeometryShader **ppGeometryShader)
1287	{
1288		SYNCHRONIZED;
1289
1290		if(!ppGeometryShader)
1291			return S_FALSE;
1292
1293		return E_NOTIMPL;
1294
1295		// remember to return S_FALSE if ppGeometyShader == NULL and the shader is OK
1296	}
1297
1298#if API >= 11
1299	virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage(
1300			ID3D11ClassLinkage **ppLinkage)
1301	{
1302		SYNCHRONIZED;
1303
1304		if(!ppLinkage)
1305			return S_FALSE;
1306
1307		return E_NOTIMPL;
1308	}
1309#endif
1310
1311	virtual HRESULT STDMETHODCALLTYPE CreateQuery(
1312		const D3D11_QUERY_DESC *pQueryDesc,
1313		ID3D11Query **ppQuery)
1314	{
1315		SYNCHRONIZED;
1316
1317		if(invalid(pQueryDesc->Query >= D3D11_QUERY_COUNT))
1318			return E_INVALIDARG;
1319		unsigned query_type = d3d11_to_pipe_query[pQueryDesc->Query];
1320		if(!query_type)
1321			return E_NOTIMPL;
1322
1323		if(ppQuery)
1324			return S_FALSE;
1325
1326		struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
1327		if(!query)
1328			return E_FAIL;
1329
1330		*ppQuery = new GalliumD3D11Query(this, query, d3d11_query_size[pQueryDesc->Query], *pQueryDesc);
1331		return S_OK;
1332	}
1333
1334	virtual HRESULT STDMETHODCALLTYPE CreatePredicate(
1335		const D3D11_QUERY_DESC *pPredicateDesc,
1336		ID3D11Predicate **ppPredicate)
1337	{
1338		SYNCHRONIZED;
1339
1340		unsigned query_type;
1341		switch(pPredicateDesc->Query)
1342		{
1343		case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
1344			return E_NOTIMPL;
1345		case D3D11_QUERY_OCCLUSION_PREDICATE:
1346			query_type = PIPE_QUERY_OCCLUSION_COUNTER;
1347			break;
1348		default:
1349			return E_INVALIDARG;
1350		}
1351
1352		if(ppPredicate)
1353			return S_FALSE;
1354
1355		struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
1356		if(!query)
1357			return E_FAIL;
1358
1359		*ppPredicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *pPredicateDesc);
1360		return S_OK;
1361	}
1362
1363
1364	virtual HRESULT STDMETHODCALLTYPE CreateCounter(
1365		const D3D11_COUNTER_DESC *pCounterDesc,
1366		ID3D11Counter **ppCounter)
1367	{
1368		SYNCHRONIZED;
1369
1370		return E_NOTIMPL;
1371
1372		// remember to return S_FALSE if ppCounter == NULL and everything is OK
1373	}
1374
1375#if API >= 11
1376	virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext(
1377		unsigned ContextFlags,
1378		ID3D11DeviceContext **ppDeferredContext)
1379	{
1380		SYNCHRONIZED;
1381
1382		// TODO: this will have to be implemented using a new Gallium util module
1383		return E_NOTIMPL;
1384
1385		// remember to return S_FALSE if ppCounter == NULL and everything is OK
1386	}
1387#endif
1388
1389	virtual HRESULT STDMETHODCALLTYPE OpenSharedResource(
1390			HANDLE hResource,
1391			REFIID ReturnedInterface,
1392			void **ppResource)
1393	{
1394		SYNCHRONIZED;
1395
1396		// TODO: the problem here is that we need to communicate dimensions somehow
1397		return E_NOTIMPL;
1398
1399		// remember to return S_FALSE if ppCounter == NULL and everything is OK
1400#if 0
1401		struct pipe_resou	rce templat;
1402		struct winsys_handle handle;
1403		handle.stride = 0;
1404		handle.handle = hResource;
1405		handle.type = DRM_API_HANDLE_TYPE_SHARED;
1406		screen->resource_from_handle(screen, &templat, &handle);
1407#endif
1408	}
1409
1410#if API < 11
1411	/* these are documented as "Not implemented".
1412	 * According to the UMDDI documentation, they apparently turn on a
1413	 * (Width + 1) x (Height + 1) convolution filter for 1-bit textures.
1414	 * Probably nothing uses these, assuming it has ever been implemented anywhere.
1415	 */
1416	void STDMETHODCALLTYPE SetTextFilterSize(
1417		UINT Width,
1418		UINT Height
1419	)
1420	{}
1421
1422	virtual void STDMETHODCALLTYPE GetTextFilterSize(
1423		UINT *Width,
1424		UINT *Height
1425	)
1426	{}
1427#endif
1428
1429#if API >= 11
1430	virtual void STDMETHODCALLTYPE RestoreGalliumState()
1431	{
1432		GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context);
1433	}
1434
1435	virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly()
1436	{
1437		GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context);
1438	}
1439#endif
1440
1441	virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void)
1442	{
1443		return immediate_pipe;
1444	}
1445
1446#undef SYNCHRONIZED
1447};
1448