d3d11_screen.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
27DEBUG_GET_ONCE_BOOL_OPTION(dump_shaders, "D3D1X_DUMP_SHADERS", FALSE);
28
29/* These cap sets are much more correct than the ones in u_caps.c */
30/* TODO: it seems cube levels should be the same as 2D levels */
31
32/* DX 9_1 */
33static unsigned caps_dx_9_1[] = {
34	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
35	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12),	/* 2048 */
36	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 8),	 /* 256 */
37	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
38	UTIL_CHECK_TERMINATE
39};
40
41/* DX 9_2 */
42static unsigned caps_dx_9_2[] = {
43	UTIL_CHECK_CAP(OCCLUSION_QUERY),
44	UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
45	UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
46	UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
47	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
48	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12),	/* 2048 */
49	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),	 /* 256 */
50	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
51	UTIL_CHECK_TERMINATE
52};
53
54/* DX 9_3 */
55static unsigned caps_dx_9_3[] = {
56	UTIL_CHECK_CAP(OCCLUSION_QUERY),
57	UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
58	UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
59	UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
60	UTIL_CHECK_CAP(SM3),
61	UTIL_CHECK_CAP(VERTEX_ELEMENT_INSTANCE_DIVISOR),
62	UTIL_CHECK_CAP(OCCLUSION_QUERY),
63	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4),
64	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13),	/* 4096 */
65	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),	 /* 256 */
66	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
67	UTIL_CHECK_TERMINATE
68};
69
70static unsigned caps_dx_10_0[] = {
71	UTIL_CHECK_CAP(INDEP_BLEND_ENABLE),
72	UTIL_CHECK_CAP(ANISOTROPIC_FILTER),
73	UTIL_CHECK_CAP(MIXED_COLORBUFFER_FORMATS),
74	UTIL_CHECK_CAP(FRAGMENT_COLOR_CLAMP_CONTROL),
75	UTIL_CHECK_CAP(CONDITIONAL_RENDER),
76	UTIL_CHECK_CAP(PRIMITIVE_RESTART),
77	UTIL_CHECK_CAP(TGSI_INSTANCEID),
78	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
79	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13),
80	UTIL_CHECK_INT(MAX_TEXTURE_ARRAY_LAYERS, 512),
81	UTIL_CHECK_INT(MAX_STREAM_OUTPUT_BUFFERS, 4),
82	UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16),
83	UTIL_CHECK_SHADER(GEOMETRY, MAX_CONST_BUFFERS, 14),
84	UTIL_CHECK_SHADER(GEOMETRY, MAX_TEXTURE_SAMPLERS, 16),
85	UTIL_CHECK_SHADER(GEOMETRY, SUBROUTINES, 1),
86	UTIL_CHECK_SHADER(FRAGMENT, INTEGERS, 1),
87	UTIL_CHECK_TERMINATE
88};
89
90
91// this is called "screen" because in the D3D10 case it's only part of the device
92template<bool threadsafe>
93struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
94{
95	D3D_FEATURE_LEVEL feature_level;
96	int format_support[PIPE_FORMAT_COUNT];
97	unsigned creation_flags;
98	unsigned exception_mode;
99	maybe_mutex_t<threadsafe> mutex;
100
101/* TODO: Direct3D 11 specifies that fine-grained locking should be used if the driver supports it.
102 * Right now, I don't trust Gallium drivers to get this right.
103 */
104#define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(mutex)
105
106	GalliumD3D11ScreenImpl(struct pipe_screen* screen, struct pipe_context* immediate_pipe, BOOL owns_immediate_pipe,unsigned creation_flags, IDXGIAdapter* adapter)
107	: GalliumD3D11Screen(screen, immediate_pipe, adapter), creation_flags(creation_flags)
108	{
109		memset(&screen_caps, 0, sizeof(screen_caps));
110		screen_caps.gs = screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
111		screen_caps.so = screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) > 0;
112		screen_caps.queries = screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY);
113		screen_caps.render_condition = screen->get_param(screen, PIPE_CAP_CONDITIONAL_RENDER);
114		for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
115			screen_caps.constant_buffers[i] = screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
116		screen_caps.stages = 0;
117		for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
118		{
119			if(!screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
120				break;
121			screen_caps.stages = i + 1;
122		}
123
124		screen_caps.stages_with_sampling = (1 << screen_caps.stages) - 1;
125		if(!screen->get_shader_param(screen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS))
126			screen_caps.stages_with_sampling &=~ (1 << PIPE_SHADER_VERTEX);
127
128		memset(format_support, 0xff, sizeof(format_support));
129
130		float default_level = 9.1f;
131		if(!util_check_caps(screen, caps_dx_9_1))
132			_debug_printf("Warning: driver does not even meet D3D_FEATURE_LEVEL_9_1 features, advertising it anyway!\n");
133		else if(!util_check_caps(screen, caps_dx_9_2))
134			default_level = 9.1f;
135		else if(!util_check_caps(screen, caps_dx_9_3))
136			default_level = 9.2f;
137		else if(!util_check_caps(screen, caps_dx_10_0))
138			default_level = 9.3f;
139		else
140			default_level = 10.0f;
141
142		char default_level_name[64];
143		sprintf(default_level_name, "%.1f", default_level);
144		float feature_level_number = atof(debug_get_option("D3D11_FEATURE_LEVEL", default_level_name));
145		if(!feature_level_number)
146			feature_level_number = default_level;
147
148#if API >= 11
149		if(feature_level_number >= 11.0f)
150			feature_level = D3D_FEATURE_LEVEL_11_0;
151		else
152#endif
153		if(feature_level_number >= 10.1f)
154			feature_level = D3D_FEATURE_LEVEL_10_1;
155		else if(feature_level_number >= 10.0f)
156			feature_level = D3D_FEATURE_LEVEL_10_0;
157		else if(feature_level_number >= 9.3f)
158			feature_level = D3D_FEATURE_LEVEL_9_3;
159		else if(feature_level_number >= 9.2f)
160			feature_level = D3D_FEATURE_LEVEL_9_2;
161		else
162			feature_level = D3D_FEATURE_LEVEL_9_1;
163
164#if API >= 11
165		immediate_context = GalliumD3D11ImmediateDeviceContext_Create(this, immediate_pipe, owns_immediate_pipe);
166		// release to the reference to ourselves that the immediate context took, to avoid a garbage cycle
167		immediate_context->Release();
168#endif
169	}
170
171	~GalliumD3D11ScreenImpl()
172	{
173#if API >= 11
174		GalliumD3D11ImmediateDeviceContext_Destroy(immediate_context);
175#endif
176	}
177
178	virtual D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(void)
179	{
180		return feature_level;
181	}
182
183	virtual unsigned STDMETHODCALLTYPE GetCreationFlags(void)
184	{
185		return creation_flags;
186	}
187
188	virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(void)
189	{
190		return S_OK;
191	}
192
193#if API >= 11
194	virtual void STDMETHODCALLTYPE GetImmediateContext(
195		ID3D11DeviceContext **out_immediate_context)
196	{
197		immediate_context->AddRef();
198		*out_immediate_context = immediate_context;
199	}
200#endif
201
202	virtual HRESULT STDMETHODCALLTYPE SetExceptionMode(unsigned RaiseFlags)
203	{
204		exception_mode = RaiseFlags;
205		return S_OK;
206	}
207
208	virtual unsigned STDMETHODCALLTYPE GetExceptionMode(void)
209	{
210		return exception_mode;
211	}
212
213	virtual HRESULT STDMETHODCALLTYPE CheckCounter(
214		const D3D11_COUNTER_DESC *desc,
215		D3D11_COUNTER_TYPE *type,
216		unsigned *active_counters,
217		LPSTR sz_name,
218		unsigned *name_length,
219		LPSTR sz_units,
220		unsigned *units_length,
221		LPSTR sz_description,
222		unsigned *description_length)
223	{
224		return E_NOTIMPL;
225	}
226
227	virtual void STDMETHODCALLTYPE CheckCounterInfo(
228		D3D11_COUNTER_INFO *counter_info)
229	{
230		/* none supported at the moment */
231		counter_info->LastDeviceDependentCounter = (D3D11_COUNTER)0;
232		counter_info->NumDetectableParallelUnits = 1;
233		counter_info->NumSimultaneousCounters = 0;
234	}
235
236#if API >= 11
237	virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport(
238		D3D11_FEATURE feature,
239		void *out_feature_support_data,
240		unsigned feature_support_data_size)
241	{
242		SYNCHRONIZED;
243
244		switch(feature)
245		{
246			case D3D11_FEATURE_THREADING:
247			{
248				D3D11_FEATURE_DATA_THREADING* data = (D3D11_FEATURE_DATA_THREADING*)out_feature_support_data;
249				if(feature_support_data_size != sizeof(*data))
250					return E_INVALIDARG;
251
252				data->DriverCommandLists = FALSE;
253				data->DriverConcurrentCreates = FALSE;
254				return S_OK;
255			}
256			case D3D11_FEATURE_DOUBLES:
257			{
258				D3D11_FEATURE_DATA_DOUBLES* data = (D3D11_FEATURE_DATA_DOUBLES*)out_feature_support_data;
259				if(feature_support_data_size != sizeof(*data))
260					return E_INVALIDARG;
261
262				data->DoublePrecisionFloatShaderOps = FALSE;
263				return S_OK;
264			}
265			case D3D11_FEATURE_FORMAT_SUPPORT:
266			{
267				D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)out_feature_support_data;
268				if(feature_support_data_size != sizeof(*data))
269					return E_INVALIDARG;
270
271				return this->CheckFormatSupport(data->InFormat, &data->OutFormatSupport);
272			}
273			case D3D11_FEATURE_FORMAT_SUPPORT2:
274			{
275				D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)out_feature_support_data;
276				if(feature_support_data_size != sizeof(*data))
277					return E_INVALIDARG;
278
279				data->OutFormatSupport = 0;
280				/* TODO: should this be S_OK? */
281				return E_INVALIDARG;
282			}
283			case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS:
284			{
285				D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS* data = (D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS*)out_feature_support_data;
286				if(feature_support_data_size != sizeof(*data))
287					return E_INVALIDARG;
288
289				data->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = FALSE;
290				return S_OK;
291			}
292			default:
293				return E_INVALIDARG;
294		}
295	}
296#endif
297
298	virtual HRESULT STDMETHODCALLTYPE CheckFormatSupport(
299		DXGI_FORMAT dxgi_format,
300		unsigned *out_format_support
301	)
302	{
303		SYNCHRONIZED;
304
305		/* TODO: MSAA, advanced features */
306
307		pipe_format format = dxgi_to_pipe_format[dxgi_format];
308		if(!format)
309			return E_INVALIDARG;
310
311		int support = format_support[format];
312		if(support < 0)
313		{
314			support = 0;
315
316			if(dxgi_format == DXGI_FORMAT_R8_UINT ||
317			   dxgi_format == DXGI_FORMAT_R16_UINT ||
318			   dxgi_format == DXGI_FORMAT_R32_UINT)
319				support |= D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER;
320
321			if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER))
322				support |= D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER;
323
324                        if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_STREAM_OUTPUT))
325				support |= D3D11_FORMAT_SUPPORT_SO_BUFFER;
326
327                        if(screen->is_format_supported(screen, format, PIPE_TEXTURE_1D, 0, PIPE_BIND_SAMPLER_VIEW))
328				support |= D3D11_FORMAT_SUPPORT_TEXTURE1D;
329                        if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW))
330				support |= D3D11_FORMAT_SUPPORT_TEXTURE2D;
331                        if(screen->is_format_supported(screen, format, PIPE_TEXTURE_CUBE, 0, PIPE_BIND_SAMPLER_VIEW))
332				support |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
333                        if(screen->is_format_supported(screen, format, PIPE_TEXTURE_3D, 0, PIPE_BIND_SAMPLER_VIEW))
334				support |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
335
336			if(support & (D3D11_FORMAT_SUPPORT_TEXTURE1D | D3D11_FORMAT_SUPPORT_TEXTURE2D |
337				      D3D11_FORMAT_SUPPORT_TEXTURE3D | D3D11_FORMAT_SUPPORT_TEXTURECUBE))
338			{
339				support |=
340					D3D11_FORMAT_SUPPORT_SHADER_LOAD |
341					D3D11_FORMAT_SUPPORT_SHADER_SAMPLE |
342					D3D11_FORMAT_SUPPORT_MIP |
343					D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
344				if(util_format_is_depth_or_stencil(format))
345					support |= D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON;
346			}
347
348			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET | PIPE_BIND_BLENDABLE))
349				support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_BLENDABLE;
350			else
351			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET))
352				support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET;
353			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL))
354				support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DEPTH_STENCIL;
355			if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DISPLAY_TARGET))
356				support |= D3D11_FORMAT_SUPPORT_DISPLAY;
357
358			unsigned ms;
359			for(ms = 2; ms <= 8; ++ms)
360			{
361				if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, ms, PIPE_BIND_RENDER_TARGET))
362				{
363					support |= D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE;
364					break;
365				}
366			}
367			if(ms <= 8 && screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, ms, PIPE_BIND_SAMPLER_VIEW))
368				support |= D3D11_FORMAT_SUPPORT_MULTISAMPLE_LOAD;
369
370			format_support[format] = support;
371		}
372		*out_format_support = support;
373		return S_OK;
374	}
375
376	virtual HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels(
377		DXGI_FORMAT format,
378		unsigned sample_count,
379		unsigned *pcount
380	)
381	{
382		SYNCHRONIZED;
383
384		if(sample_count == 1)
385			*pcount = 1;
386		else
387			*pcount = 0;
388		return S_OK;
389	}
390
391	template<typename T, typename U>
392	bool convert_blend_state(T& to, const U& from, unsigned BlendEnable, unsigned RenderTargetWriteMask)
393	{
394		if(unlikely(BlendEnable &&
395			    (from.SrcBlend >= D3D11_BLEND_COUNT ||
396			     from.SrcBlendAlpha >= D3D11_BLEND_COUNT ||
397			     from.DestBlend >= D3D11_BLEND_COUNT ||
398			     from.DestBlendAlpha >= D3D11_BLEND_COUNT ||
399			     from.BlendOp >= 6 ||
400			     from.BlendOp == 0 ||
401			     from.BlendOpAlpha >= 6 ||
402			     from.BlendOpAlpha == 0)))
403			return false;
404
405		to.blend_enable = BlendEnable;
406
407		if(BlendEnable)
408		{
409			to.rgb_func = from.BlendOp - 1;
410			to.alpha_func = from.BlendOpAlpha - 1;
411
412			to.rgb_src_factor = d3d11_to_pipe_blend[from.SrcBlend];
413			to.alpha_src_factor = d3d11_to_pipe_blend[from.SrcBlendAlpha];
414			to.rgb_dst_factor = d3d11_to_pipe_blend[from.DestBlend];
415			to.alpha_dst_factor = d3d11_to_pipe_blend[from.DestBlendAlpha];
416		}
417
418		to.colormask = RenderTargetWriteMask & 0xf;
419		return true;
420	}
421
422#if API >= 11
423	virtual HRESULT STDMETHODCALLTYPE CreateBlendState(
424		const D3D11_BLEND_DESC *blend_state_desc,
425		ID3D11BlendState **out_blend_state
426	)
427#else
428	virtual HRESULT STDMETHODCALLTYPE CreateBlendState1(
429		const D3D10_BLEND_DESC1 *blend_state_desc,
430		ID3D10BlendState1 **out_blend_state
431	)
432#endif
433	{
434		SYNCHRONIZED;
435
436		pipe_blend_state state;
437		memset(&state, 0, sizeof(state));
438		state.alpha_to_coverage = !!blend_state_desc->AlphaToCoverageEnable;
439		state.independent_blend_enable = !!blend_state_desc->IndependentBlendEnable;
440
441		assert(PIPE_MAX_COLOR_BUFS >= 8);
442		const unsigned n = blend_state_desc->IndependentBlendEnable ? 8 : 1;
443		for(unsigned i = 0; i < n; ++i)
444		{
445			 if(!convert_blend_state(
446					 state.rt[i],
447					 blend_state_desc->RenderTarget[i],
448					 blend_state_desc->RenderTarget[i].BlendEnable,
449					 blend_state_desc->RenderTarget[i].RenderTargetWriteMask))
450				 return E_INVALIDARG;
451		}
452
453		if(!out_blend_state)
454			return S_FALSE;
455
456		void* object = immediate_pipe->create_blend_state(immediate_pipe, &state);
457		if(!object)
458			return E_FAIL;
459
460		*out_blend_state = new GalliumD3D11BlendState(this, object, *blend_state_desc);
461		return S_OK;
462	}
463
464#if API < 11
465	virtual HRESULT STDMETHODCALLTYPE CreateBlendState(
466		const D3D10_BLEND_DESC *blend_state_desc,
467		ID3D10BlendState **out_blend_state
468	)
469	{
470		SYNCHRONIZED;
471
472		pipe_blend_state state;
473		memset(&state, 0, sizeof(state));
474		state.alpha_to_coverage = !!blend_state_desc->AlphaToCoverageEnable;
475		assert(PIPE_MAX_COLOR_BUFS >= 8);
476		for(unsigned i = 0; i < 8; ++i)
477		{
478			if(!convert_blend_state(
479				state.rt[i],
480				*blend_state_desc,
481				blend_state_desc->BlendEnable[i],
482				blend_state_desc->RenderTargetWriteMask[i]))
483				return E_INVALIDARG;
484		}
485
486		for(unsigned i = 1; i < 8; ++i)
487		{
488			if(memcmp(&state.rt[0], &state.rt[i], sizeof(state.rt[0])))
489			{
490				state.independent_blend_enable = TRUE;
491				break;
492			}
493		}
494
495		void* object = immediate_pipe->create_blend_state(immediate_pipe, &state);
496		if(!object)
497			return E_FAIL;
498
499		*out_blend_state = new GalliumD3D11BlendState(this, object, *blend_state_desc);
500		return S_OK;
501	}
502#endif
503
504	virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilState(
505		const D3D11_DEPTH_STENCIL_DESC *depth_stencil_state_desc,
506		ID3D11DepthStencilState **depth_stencil_state
507	)
508	{
509		SYNCHRONIZED;
510
511		pipe_depth_stencil_alpha_state state;
512		memset(&state, 0, sizeof(state));
513
514		state.depth.enabled = !!depth_stencil_state_desc->DepthEnable;
515		if(depth_stencil_state_desc->DepthEnable)
516		{
517			if(depth_stencil_state_desc->DepthFunc == 0 ||
518			   depth_stencil_state_desc->DepthFunc >= 9)
519				return E_INVALIDARG;
520			state.depth.writemask = depth_stencil_state_desc->DepthWriteMask;
521			state.depth.func = depth_stencil_state_desc->DepthFunc - 1;
522		}
523
524		state.stencil[0].enabled = !!depth_stencil_state_desc->StencilEnable;
525		if(depth_stencil_state_desc->StencilEnable)
526		{
527			if(depth_stencil_state_desc->FrontFace.StencilPassOp >= D3D11_STENCIL_OP_COUNT ||
528			   depth_stencil_state_desc->FrontFace.StencilFailOp >= D3D11_STENCIL_OP_COUNT ||
529			   depth_stencil_state_desc->FrontFace.StencilDepthFailOp >= D3D11_STENCIL_OP_COUNT ||
530			   depth_stencil_state_desc->BackFace.StencilPassOp >= D3D11_STENCIL_OP_COUNT ||
531			   depth_stencil_state_desc->BackFace.StencilFailOp >= D3D11_STENCIL_OP_COUNT ||
532			   depth_stencil_state_desc->BackFace.StencilDepthFailOp >= D3D11_STENCIL_OP_COUNT)
533				return E_INVALIDARG;
534			state.stencil[0].writemask = depth_stencil_state_desc->StencilWriteMask;
535			state.stencil[0].valuemask = depth_stencil_state_desc->StencilReadMask;
536			state.stencil[0].zpass_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->FrontFace.StencilPassOp];
537			state.stencil[0].fail_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->FrontFace.StencilFailOp];
538			state.stencil[0].zfail_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->FrontFace.StencilDepthFailOp];
539			state.stencil[0].func = depth_stencil_state_desc->FrontFace.StencilFunc - 1;
540			state.stencil[1].enabled = !!depth_stencil_state_desc->StencilEnable;
541			state.stencil[1].writemask = depth_stencil_state_desc->StencilWriteMask;
542			state.stencil[1].valuemask = depth_stencil_state_desc->StencilReadMask;
543			state.stencil[1].zpass_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->BackFace.StencilPassOp];
544			state.stencil[1].fail_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->BackFace.StencilFailOp];
545			state.stencil[1].zfail_op = d3d11_to_pipe_stencil_op[depth_stencil_state_desc->BackFace.StencilDepthFailOp];
546			state.stencil[1].func = depth_stencil_state_desc->BackFace.StencilFunc - 1;
547		}
548
549		if(!depth_stencil_state)
550			return S_FALSE;
551
552		void* object = immediate_pipe->create_depth_stencil_alpha_state(immediate_pipe, &state);
553		if(!object)
554			return E_FAIL;
555
556		*depth_stencil_state = new GalliumD3D11DepthStencilState(this, object, *depth_stencil_state_desc);
557		return S_OK;
558	}
559
560	virtual HRESULT STDMETHODCALLTYPE CreateRasterizerState(
561		const D3D11_RASTERIZER_DESC *rasterizer_desc,
562		ID3D11RasterizerState **out_rasterizer_state)
563	{
564		SYNCHRONIZED;
565
566		pipe_rasterizer_state state;
567		memset(&state, 0, sizeof(state));
568		state.gl_rasterization_rules = 1; /* D3D10/11 use GL rules */
569		state.fill_front = state.fill_back = (rasterizer_desc->FillMode == D3D11_FILL_WIREFRAME) ? PIPE_POLYGON_MODE_LINE : PIPE_POLYGON_MODE_FILL;
570		if(rasterizer_desc->CullMode == D3D11_CULL_FRONT)
571			state.cull_face = PIPE_FACE_FRONT;
572		else if(rasterizer_desc->CullMode == D3D11_CULL_BACK)
573			state.cull_face = PIPE_FACE_BACK;
574		else
575			state.cull_face = PIPE_FACE_NONE;
576		state.front_ccw = !!rasterizer_desc->FrontCounterClockwise;
577		state.offset_tri = state.offset_line = state.offset_point = rasterizer_desc->SlopeScaledDepthBias || rasterizer_desc->DepthBias;
578		state.offset_scale = rasterizer_desc->SlopeScaledDepthBias;
579		state.offset_units = rasterizer_desc->DepthBias;
580		state.offset_clamp = rasterizer_desc->DepthBiasClamp;
581		state.scissor = !!rasterizer_desc->ScissorEnable;
582		state.multisample = !!rasterizer_desc->MultisampleEnable;
583		state.line_smooth = !!rasterizer_desc->AntialiasedLineEnable;
584		state.flatshade_first = 1;
585		state.line_width = 1.0f;
586		state.point_size = 1.0f;
587
588		/* TODO: is this correct? */
589		state.point_quad_rasterization = 1;
590
591		if(!out_rasterizer_state)
592			return S_FALSE;
593
594		void* object = immediate_pipe->create_rasterizer_state(immediate_pipe, &state);
595		if(!object)
596			return E_FAIL;
597
598		*out_rasterizer_state = new GalliumD3D11RasterizerState(this, object, *rasterizer_desc, !rasterizer_desc->DepthClipEnable);
599		return S_OK;
600	}
601
602	virtual HRESULT STDMETHODCALLTYPE CreateSamplerState(
603		const D3D11_SAMPLER_DESC *sampler_desc,
604		ID3D11SamplerState **out_sampler_state)
605	{
606		SYNCHRONIZED;
607
608		pipe_sampler_state state;
609		memset(&state, 0, sizeof(state));
610		state.normalized_coords = 1;
611		state.min_mip_filter = (sampler_desc->Filter & 1);
612		state.mag_img_filter = ((sampler_desc->Filter >> 2) & 1);
613		state.min_img_filter = ((sampler_desc->Filter >> 4) & 1);
614		if(sampler_desc->Filter & 0x40)
615			state.max_anisotropy = sampler_desc->MaxAnisotropy;
616		if(sampler_desc->Filter & 0x80)
617		{
618			state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
619			state.compare_func = sampler_desc->ComparisonFunc - 1;
620		}
621		state.wrap_s = d3d11_to_pipe_wrap[sampler_desc->AddressU];
622		state.wrap_t = d3d11_to_pipe_wrap[sampler_desc->AddressV];
623		state.wrap_r = d3d11_to_pipe_wrap[sampler_desc->AddressW];
624		state.lod_bias = sampler_desc->MipLODBias;
625		memcpy(state.border_color.f, sampler_desc->BorderColor, sizeof(state.border_color));
626		state.min_lod = sampler_desc->MinLOD;
627		state.max_lod = sampler_desc->MaxLOD;
628
629		if(!out_sampler_state)
630			return S_FALSE;
631
632		void* object = immediate_pipe->create_sampler_state(immediate_pipe, &state);
633		if(!object)
634			return E_FAIL;
635
636		*out_sampler_state = new GalliumD3D11SamplerState(this, object, *sampler_desc);
637		return S_OK;
638	}
639
640	virtual HRESULT STDMETHODCALLTYPE CreateInputLayout(
641		const D3D11_INPUT_ELEMENT_DESC *input_element_descs,
642		unsigned count,
643		const void *shader_bytecode_with_input_signature,
644		SIZE_T bytecode_length,
645		ID3D11InputLayout **out_input_layout)
646	{
647		SYNCHRONIZED;
648
649		if(count > D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT)
650			return E_INVALIDARG;
651		assert(D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT <= PIPE_MAX_ATTRIBS);
652
653		// putting semantics matching in the core API seems to be a (minor) design mistake
654
655		struct dxbc_chunk_signature* sig = dxbc_find_signature(shader_bytecode_with_input_signature, bytecode_length, DXBC_FIND_INPUT_SIGNATURE);
656		D3D11_SIGNATURE_PARAMETER_DESC* params;
657		unsigned num_params = dxbc_parse_signature(sig, &params);
658
659		typedef std::unordered_map<std::pair<c_string, unsigned>, unsigned> semantic_to_idx_map_t;
660		semantic_to_idx_map_t semantic_to_idx_map;
661		for(unsigned i = 0; i < count; ++i)
662			semantic_to_idx_map[std::make_pair(c_string(input_element_descs[i].SemanticName), input_element_descs[i].SemanticIndex)] = i;
663
664		struct pipe_vertex_element elements[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
665
666		enum pipe_format formats[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
667		unsigned offsets[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
668
669		offsets[0] = 0;
670		for(unsigned i = 0; i < count; ++i)
671		{
672			formats[i] = dxgi_to_pipe_format[input_element_descs[i].Format];
673
674			if(likely(input_element_descs[i].AlignedByteOffset != D3D11_APPEND_ALIGNED_ELEMENT))
675			{
676				offsets[i] = input_element_descs[i].AlignedByteOffset;
677			}
678			else if(i > 0)
679			{
680				unsigned align_mask = util_format_description(formats[i])->channel[0].size;
681				if(align_mask & 7) // e.g. R10G10B10A2
682					align_mask = 32;
683				align_mask = (align_mask / 8) - 1;
684
685				offsets[i] = (offsets[i - 1] + util_format_get_blocksize(formats[i - 1]) + align_mask) & ~align_mask;
686			}
687		}
688
689		// TODO: check for & report errors (e.g. ambiguous layouts, unmatched semantics)
690
691		unsigned num_params_to_use = 0;
692		for(unsigned i = 0; i < num_params && num_params_to_use < D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT; ++i)
693		{
694			if(!strcasecmp(params[i].SemanticName, "SV_INSTANCEID") ||
695			   !strcasecmp(params[i].SemanticName, "SV_VERTEXID"))
696				continue;
697			const unsigned n = num_params_to_use++;
698
699			semantic_to_idx_map_t::iterator iter = semantic_to_idx_map.find(std::make_pair(c_string(params[i].SemanticName), params[i].SemanticIndex));
700
701			if(iter != semantic_to_idx_map.end())
702			{
703				unsigned idx = iter->second;
704
705				elements[n].src_format = formats[idx];
706				elements[n].src_offset = offsets[idx];
707				elements[n].vertex_buffer_index = input_element_descs[idx].InputSlot;
708				elements[n].instance_divisor = input_element_descs[idx].InstanceDataStepRate;
709				if (input_element_descs[idx].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA)
710					if (elements[n].instance_divisor == 0)
711						elements[n].instance_divisor = ~0; // XXX: can't specify 'never' to gallium
712			}
713			else
714			{
715				// XXX: undefined input, is this valid or should we return an error ?
716				elements[n].src_format = PIPE_FORMAT_NONE;
717				elements[n].src_offset = 0;
718				elements[n].vertex_buffer_index = 0;
719				elements[n].instance_divisor = 0;
720			}
721		}
722
723		free(params);
724
725		if(!out_input_layout)
726			return S_FALSE;
727
728		void* object = immediate_pipe->create_vertex_elements_state(immediate_pipe, num_params_to_use, elements);
729		if(!object)
730			return E_FAIL;
731
732		*out_input_layout = new GalliumD3D11InputLayout(this, object);
733		return S_OK;
734	}
735
736	static unsigned d3d11_to_pipe_bind_flags(unsigned bind_flags)
737	{
738		unsigned bind = 0;
739		if(bind_flags & D3D11_BIND_VERTEX_BUFFER)
740			bind |= PIPE_BIND_VERTEX_BUFFER;
741		if(bind_flags & D3D11_BIND_INDEX_BUFFER)
742			bind |= PIPE_BIND_INDEX_BUFFER;
743		if(bind_flags & D3D11_BIND_CONSTANT_BUFFER)
744			bind |= PIPE_BIND_CONSTANT_BUFFER;
745		if(bind_flags & D3D11_BIND_SHADER_RESOURCE)
746			bind |= PIPE_BIND_SAMPLER_VIEW;
747		if(bind_flags & D3D11_BIND_STREAM_OUTPUT)
748			bind |= PIPE_BIND_STREAM_OUTPUT;
749		if(bind_flags & D3D11_BIND_RENDER_TARGET)
750			bind |= PIPE_BIND_RENDER_TARGET;
751		if(bind_flags & D3D11_BIND_DEPTH_STENCIL)
752			bind |= PIPE_BIND_DEPTH_STENCIL;
753		return bind;
754	}
755
756	inline HRESULT create_resource(
757		pipe_texture_target target,
758		unsigned width,
759		unsigned height,
760		unsigned depth,
761		unsigned mip_levels,
762		unsigned array_size,
763		DXGI_FORMAT format,
764		const DXGI_SAMPLE_DESC* SampleDesc,
765		D3D11_USAGE usage,
766		unsigned bind_flags,
767		unsigned c_p_u_access_flags,
768		unsigned misc_flags,
769		const D3D11_SUBRESOURCE_DATA *initial_data,
770		DXGI_USAGE dxgi_usage,
771		struct pipe_resource** ppresource
772	)
773	{
774		if(invalid(format >= DXGI_FORMAT_COUNT))
775			return E_INVALIDARG;
776		if(misc_flags & D3D11_RESOURCE_MISC_TEXTURECUBE)
777		{
778			if(target != PIPE_TEXTURE_2D)
779				return E_INVALIDARG;
780			target = PIPE_TEXTURE_CUBE;
781			if(array_size % 6)
782				return E_INVALIDARG;
783		}
784		else if(array_size > 1)
785		{
786			switch (target) {
787			case PIPE_TEXTURE_1D: target = PIPE_TEXTURE_1D_ARRAY; break;
788			case PIPE_TEXTURE_2D: target = PIPE_TEXTURE_2D_ARRAY; break;
789			default:
790				return E_INVALIDARG;
791			}
792		}
793		/* TODO: msaa */
794		struct pipe_resource templat;
795		memset(&templat, 0, sizeof(templat));
796		templat.target = target;
797		templat.width0 = width;
798		templat.height0 = height;
799		templat.depth0 = depth;
800		templat.array_size = array_size;
801		if(mip_levels)
802			templat.last_level = mip_levels - 1;
803		else
804			templat.last_level = MAX2(MAX2(util_logbase2(templat.width0), util_logbase2(templat.height0)), util_logbase2(templat.depth0));
805		templat.format = dxgi_to_pipe_format[format];
806		if(bind_flags & D3D11_BIND_DEPTH_STENCIL) {
807			// colour formats are not depth-renderable, but depth/stencil-formats may be colour-renderable
808			switch(format)
809			{
810			case DXGI_FORMAT_R32_TYPELESS: templat.format = PIPE_FORMAT_Z32_FLOAT; break;
811			case DXGI_FORMAT_R16_TYPELESS: templat.format = PIPE_FORMAT_Z16_UNORM; break;
812			default:
813				break;
814			}
815		}
816		templat.bind = d3d11_to_pipe_bind_flags(bind_flags);
817		if(c_p_u_access_flags & D3D11_CPU_ACCESS_READ)
818			templat.bind |= PIPE_BIND_TRANSFER_READ;
819		if(c_p_u_access_flags & D3D11_CPU_ACCESS_WRITE)
820			templat.bind |= PIPE_BIND_TRANSFER_WRITE;
821		if(misc_flags & D3D11_RESOURCE_MISC_SHARED)
822			templat.bind |= PIPE_BIND_SHARED;
823		if(misc_flags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE)
824			templat.bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE;
825		if(dxgi_usage & DXGI_USAGE_BACK_BUFFER)
826			templat.bind |= PIPE_BIND_DISPLAY_TARGET;
827		templat.usage = d3d11_to_pipe_usage[usage];
828		if(invalid(!templat.format))
829			return E_NOTIMPL;
830
831		if(!ppresource)
832			return S_FALSE;
833
834		struct pipe_resource* resource = screen->resource_create(screen, &templat);
835		if(!resource)
836			return E_FAIL;
837		if(initial_data)
838		{
839			for(unsigned slice = 0; slice < array_size; ++slice)
840			{
841				for(unsigned level = 0; level <= templat.last_level; ++level)
842				{
843					struct pipe_box box;
844					box.x = box.y = 0;
845					box.z = slice;
846					box.width = u_minify(width, level);
847					box.height = u_minify(height, level);
848					box.depth = u_minify(depth, level);
849					immediate_pipe->transfer_inline_write(immediate_pipe, resource, level, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_UNSYNCHRONIZED, &box, initial_data->pSysMem, initial_data->SysMemPitch, initial_data->SysMemSlicePitch);
850					++initial_data;
851				}
852			}
853		}
854		*ppresource = resource;
855		return S_OK;
856	}
857
858	static unsigned d3d_to_dxgi_usage(unsigned bind, unsigned misc)
859	{
860		unsigned dxgi_usage = 0;
861		if(bind |= D3D11_BIND_RENDER_TARGET)
862			dxgi_usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
863		if(bind & D3D11_BIND_SHADER_RESOURCE)
864			dxgi_usage |= DXGI_USAGE_SHADER_INPUT;
865#if API >= 11
866		if(bind & D3D11_BIND_UNORDERED_ACCESS)
867			dxgi_usage |= DXGI_USAGE_UNORDERED_ACCESS;
868#endif
869		if(misc & D3D11_RESOURCE_MISC_SHARED)
870			dxgi_usage |= DXGI_USAGE_SHARED;
871		return dxgi_usage;
872	}
873
874	virtual HRESULT STDMETHODCALLTYPE CreateTexture1D(
875		const D3D11_TEXTURE1D_DESC *desc,
876		const D3D11_SUBRESOURCE_DATA *initial_data,
877		ID3D11Texture1D **out_texture1d)
878	{
879		SYNCHRONIZED;
880
881		struct pipe_resource* resource;
882		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
883		HRESULT hr = create_resource(PIPE_TEXTURE_1D, desc->Width, 1, 1, desc->MipLevels, desc->ArraySize, desc->Format, 0, desc->Usage, desc->BindFlags, desc->CPUAccessFlags, desc->MiscFlags, initial_data, dxgi_usage, out_texture1d ? &resource : 0);
884		if(hr != S_OK)
885			return hr;
886		D3D11_TEXTURE1D_DESC cdesc = *desc;
887		cdesc.MipLevels = resource->last_level + 1;
888		*out_texture1d = new GalliumD3D11Texture1D(this, resource, cdesc, dxgi_usage);
889		return S_OK;
890	}
891
892	virtual HRESULT STDMETHODCALLTYPE CreateTexture2D(
893		const D3D11_TEXTURE2D_DESC *desc,
894		const D3D11_SUBRESOURCE_DATA *initial_data,
895		ID3D11Texture2D **out_texture2d)
896	{
897		SYNCHRONIZED;
898
899		struct pipe_resource* resource;
900		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
901		HRESULT hr = create_resource(PIPE_TEXTURE_2D, desc->Width, desc->Height, 1, desc->MipLevels, desc->ArraySize, desc->Format, &desc->SampleDesc, desc->Usage, desc->BindFlags, desc->CPUAccessFlags, desc->MiscFlags, initial_data, dxgi_usage, out_texture2d ? &resource : 0);
902		if(hr != S_OK)
903			return hr;
904		D3D11_TEXTURE2D_DESC cdesc = *desc;
905		cdesc.MipLevels = resource->last_level + 1;
906		if(cdesc.MipLevels == 1 && cdesc.ArraySize == 1)
907			*out_texture2d = new GalliumD3D11Surface(this, resource, cdesc, dxgi_usage);
908		else
909			*out_texture2d = new GalliumD3D11Texture2D(this, resource, cdesc, dxgi_usage);
910		return S_OK;
911	}
912
913	virtual HRESULT STDMETHODCALLTYPE CreateTexture3D(
914		const D3D11_TEXTURE3D_DESC *desc,
915		const D3D11_SUBRESOURCE_DATA *initial_data,
916		ID3D11Texture3D **out_texture3d)
917	{
918		SYNCHRONIZED;
919
920		struct pipe_resource* resource;
921		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
922		HRESULT hr = create_resource(PIPE_TEXTURE_3D, desc->Width, desc->Height, desc->Depth, desc->MipLevels, 1, desc->Format, 0, desc->Usage, desc->BindFlags, desc->CPUAccessFlags, desc->MiscFlags, initial_data, dxgi_usage, out_texture3d ? &resource : 0);
923		if(hr != S_OK)
924			return hr;
925		D3D11_TEXTURE3D_DESC cdesc = *desc;
926		cdesc.MipLevels = resource->last_level + 1;
927		*out_texture3d = new GalliumD3D11Texture3D(this, resource, cdesc, dxgi_usage);
928		return S_OK;
929	}
930
931	virtual HRESULT STDMETHODCALLTYPE CreateBuffer(
932		const D3D11_BUFFER_DESC *desc,
933		const D3D11_SUBRESOURCE_DATA *initial_data,
934		ID3D11Buffer **out_buffer)
935	{
936		SYNCHRONIZED;
937
938		struct pipe_resource* resource;
939		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
940		HRESULT hr = create_resource(PIPE_BUFFER, desc->ByteWidth, 1, 1, 1, 1, DXGI_FORMAT_R8_UNORM, 0, desc->Usage, desc->BindFlags, desc->CPUAccessFlags, desc->MiscFlags, initial_data, dxgi_usage, out_buffer ? &resource : 0);
941		if(hr != S_OK)
942			return hr;
943		*out_buffer = new GalliumD3D11Buffer(this, resource, *desc, dxgi_usage);
944		return S_OK;
945	}
946
947	virtual HRESULT STDMETHODCALLTYPE OpenGalliumResource(
948		struct pipe_resource* resource,
949		IUnknown** dxgi_resource)
950	{
951		SYNCHRONIZED;
952
953		/* TODO: maybe support others */
954		assert(resource->target == PIPE_TEXTURE_2D);
955		*dxgi_resource = 0;
956		D3D11_TEXTURE2D_DESC desc;
957		memset(&desc, 0, sizeof(desc));
958		desc.Width = resource->width0;
959		desc.Height = resource->height0;
960		init_pipe_to_dxgi_format();
961		desc.Format = pipe_to_dxgi_format[resource->format];
962		desc.SampleDesc.Count = resource->nr_samples;
963		desc.SampleDesc.Quality = 0;
964		desc.ArraySize = 1;
965		desc.MipLevels = resource->last_level + 1;
966		desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
967		if(resource->bind & PIPE_BIND_RENDER_TARGET)
968			desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
969		if(resource->bind & PIPE_BIND_DEPTH_STENCIL)
970			desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
971		if(resource->bind & PIPE_BIND_SAMPLER_VIEW)
972			desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
973		if(resource->bind & PIPE_BIND_SHARED)
974			desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
975		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc.BindFlags, desc.MiscFlags);
976		if(desc.MipLevels == 1 && desc.ArraySize == 1)
977			*dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Surface(this, resource, desc, dxgi_usage);
978		else
979			*dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Texture2D(this, resource, desc, dxgi_usage);
980		return S_OK;
981	}
982
983	virtual HRESULT STDMETHODCALLTYPE CreateSurface(
984		const DXGI_SURFACE_DESC *dxgi_desc,
985		unsigned count,
986		DXGI_USAGE usage,
987		const DXGI_SHARED_RESOURCE *shared_resource,
988		IDXGISurface **out_surface)
989	{
990		SYNCHRONIZED;
991
992		D3D11_TEXTURE2D_DESC desc;
993		memset(&desc, 0, sizeof(desc));
994
995		struct pipe_resource* resource;
996		desc.Width = dxgi_desc->Width;
997		desc.Height = dxgi_desc->Height;
998		desc.Format = dxgi_desc->Format;
999		desc.SampleDesc = dxgi_desc->SampleDesc;
1000		desc.ArraySize = count;
1001		desc.MipLevels = 1;
1002		desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
1003		if(usage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
1004			desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
1005		if(usage & DXGI_USAGE_SHADER_INPUT)
1006			desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
1007#if API >= 11
1008		if(usage & DXGI_USAGE_UNORDERED_ACCESS)
1009			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
1010#endif
1011		if(usage & DXGI_USAGE_SHARED)
1012			desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
1013		HRESULT hr = create_resource(PIPE_TEXTURE_2D, dxgi_desc->Width, dxgi_desc->Height, 1, 1, count, dxgi_desc->Format, &dxgi_desc->SampleDesc, D3D11_USAGE_DEFAULT, desc.BindFlags, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE, desc.MiscFlags, 0, usage, &resource);
1014		if(hr != S_OK)
1015			return hr;
1016		*out_surface = new GalliumD3D11Surface(this, resource, desc, usage);
1017		return S_OK;
1018	}
1019
1020	virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView(
1021		ID3D11Resource *iresource,
1022		const D3D11_SHADER_RESOURCE_VIEW_DESC *desc,
1023		ID3D11ShaderResourceView **out_srv)
1024	{
1025#if API >= 11
1026		D3D11_SHADER_RESOURCE_VIEW_DESC def_desc;
1027#else
1028		if(desc->ViewDimension == D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY)
1029			return E_INVALIDARG;
1030		D3D10_SHADER_RESOURCE_VIEW_DESC1 desc1;
1031		memset(&desc1, 0, sizeof(desc1));
1032		memcpy(&desc1, desc, sizeof(*desc));
1033		return CreateShaderResourceView1(iresource, &desc1, (ID3D10ShaderResourceView1**)out_srv);
1034	}
1035
1036	virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView1(
1037			ID3D11Resource *iresource,
1038			const D3D10_SHADER_RESOURCE_VIEW_DESC1 *desc,
1039			ID3D10ShaderResourceView1 **out_srv)
1040	{
1041		D3D10_SHADER_RESOURCE_VIEW_DESC1 def_desc;
1042#endif
1043		SYNCHRONIZED;
1044
1045		const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
1046
1047		if(!desc)
1048		{
1049			init_pipe_to_dxgi_format();
1050			memset(&def_desc, 0, sizeof(def_desc));
1051			def_desc.Format = pipe_to_dxgi_format[resource->format];
1052			switch(resource->target)
1053			{
1054			case PIPE_BUFFER:
1055				def_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
1056				def_desc.Buffer.ElementWidth = resource->width0;
1057				break;
1058			case PIPE_TEXTURE_1D:
1059				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
1060				def_desc.Texture1D.MipLevels = resource->last_level + 1;
1061				break;
1062			case PIPE_TEXTURE_1D_ARRAY:
1063				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
1064				def_desc.Texture1DArray.MipLevels = resource->last_level + 1;
1065				def_desc.Texture1DArray.ArraySize = resource->array_size;
1066				break;
1067			case PIPE_TEXTURE_2D:
1068			case PIPE_TEXTURE_RECT:
1069				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
1070				def_desc.Texture2D.MipLevels = resource->last_level + 1;
1071				break;
1072			case PIPE_TEXTURE_2D_ARRAY:
1073				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1074				def_desc.Texture2DArray.MipLevels = resource->last_level + 1;
1075				def_desc.Texture2DArray.ArraySize = resource->array_size;
1076				break;
1077			case PIPE_TEXTURE_3D:
1078				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
1079				def_desc.Texture3D.MipLevels = resource->last_level + 1;
1080				break;
1081			case PIPE_TEXTURE_CUBE:
1082				if(resource->array_size > 6)
1083				{
1084					def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
1085					def_desc.TextureCubeArray.NumCubes = resource->array_size / 6;
1086				}
1087				else
1088				{
1089					def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
1090				}
1091				def_desc.TextureCube.MipLevels = resource->last_level + 1;
1092				break;
1093			default:
1094				return E_INVALIDARG;
1095			}
1096			desc = &def_desc;
1097		}
1098
1099		struct pipe_sampler_view templat;
1100		memset(&templat, 0, sizeof(templat));
1101		if(invalid(format >= DXGI_FORMAT_COUNT))
1102			return E_INVALIDARG;
1103		templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format];
1104		if(!templat.format)
1105			return E_NOTIMPL;
1106		templat.swizzle_r = PIPE_SWIZZLE_RED;
1107		templat.swizzle_g = PIPE_SWIZZLE_GREEN;
1108		templat.swizzle_b = PIPE_SWIZZLE_BLUE;
1109		templat.swizzle_a = PIPE_SWIZZLE_ALPHA;
1110
1111		templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
1112		switch(desc->ViewDimension)
1113		{
1114		case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
1115		case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
1116		case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY:
1117			templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
1118			templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1;
1119			if (desc->ViewDimension == D3D11_SRV_DIMENSION_TEXTURECUBEARRAY) {
1120				templat.u.tex.first_layer *= 6;
1121				templat.u.tex.last_layer *= 6;
1122			}
1123			// fall through
1124		case D3D11_SRV_DIMENSION_TEXTURE1D:
1125		case D3D11_SRV_DIMENSION_TEXTURE2D:
1126		case D3D11_SRV_DIMENSION_TEXTURE3D:
1127		case D3D11_SRV_DIMENSION_TEXTURECUBE:
1128			// yes, this works for all of these types
1129			templat.u.tex.first_level = desc->Texture1D.MostDetailedMip;
1130			if(desc->Texture1D.MipLevels == (unsigned)-1)
1131				templat.u.tex.last_level = templat.texture->last_level;
1132			else
1133				templat.u.tex.last_level = templat.u.tex.first_level + desc->Texture1D.MipLevels - 1;
1134			assert(templat.u.tex.last_level >= templat.u.tex.first_level);
1135			break;
1136		case D3D11_SRV_DIMENSION_BUFFER:
1137			templat.u.buf.first_element = desc->Buffer.ElementOffset;
1138			templat.u.buf.last_element = desc->Buffer.ElementOffset + desc->Buffer.ElementWidth - 1;
1139			break;
1140		case D3D11_SRV_DIMENSION_TEXTURE2DMS:
1141		case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
1142			return E_NOTIMPL;
1143		default:
1144			return E_INVALIDARG;
1145		}
1146
1147		if(!out_srv)
1148			return S_FALSE;
1149
1150		struct pipe_sampler_view* view = immediate_pipe->create_sampler_view(immediate_pipe, templat.texture, &templat);
1151		if(!view)
1152			return E_FAIL;
1153		*out_srv = new GalliumD3D11ShaderResourceView(this, (GalliumD3D11Resource<>*)iresource, view, *desc);
1154		return S_OK;
1155	}
1156
1157#if API >= 11
1158	virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView(
1159		ID3D11Resource *resource,
1160		const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc,
1161		ID3D11UnorderedAccessView **out_uav)
1162	{
1163		SYNCHRONIZED;
1164
1165		return E_NOTIMPL;
1166
1167		// remember to return S_FALSE and not crash if out_u_a_view == 0 and parameters are valid
1168	}
1169#endif
1170
1171	virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
1172		ID3D11Resource *iresource,
1173		const D3D11_RENDER_TARGET_VIEW_DESC *desc,
1174		ID3D11RenderTargetView **out_rtv)
1175	{
1176		SYNCHRONIZED;
1177
1178		const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
1179
1180		D3D11_RENDER_TARGET_VIEW_DESC def_desc;
1181		if(!desc)
1182		{
1183			init_pipe_to_dxgi_format();
1184			memset(&def_desc, 0, sizeof(def_desc));
1185			def_desc.Format = pipe_to_dxgi_format[resource->format];
1186			switch(resource->target)
1187			{
1188			case PIPE_BUFFER:
1189				def_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER;
1190				def_desc.Buffer.ElementWidth = resource->width0;
1191				break;
1192			case PIPE_TEXTURE_1D:
1193				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
1194				break;
1195			case PIPE_TEXTURE_1D_ARRAY:
1196				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
1197				def_desc.Texture1DArray.ArraySize = resource->array_size;
1198				break;
1199			case PIPE_TEXTURE_2D:
1200			case PIPE_TEXTURE_RECT:
1201				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1202				break;
1203			case PIPE_TEXTURE_2D_ARRAY:
1204				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1205				def_desc.Texture2DArray.ArraySize = resource->array_size;
1206				break;
1207			case PIPE_TEXTURE_3D:
1208				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
1209				def_desc.Texture3D.WSize = resource->depth0;
1210				break;
1211			case PIPE_TEXTURE_CUBE:
1212				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1213				def_desc.Texture2DArray.ArraySize = 6;
1214				break;
1215			default:
1216				return E_INVALIDARG;
1217			}
1218			desc = &def_desc;
1219		}
1220
1221		struct pipe_surface templat;
1222		memset(&templat, 0, sizeof(templat));
1223		if(invalid(desc->format >= DXGI_FORMAT_COUNT))
1224			return E_INVALIDARG;
1225		templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format];
1226		if(!templat.format)
1227			return E_NOTIMPL;
1228		templat.usage = PIPE_BIND_RENDER_TARGET;
1229		templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
1230
1231		switch(desc->ViewDimension)
1232		{
1233		case D3D11_RTV_DIMENSION_TEXTURE1D:
1234		case D3D11_RTV_DIMENSION_TEXTURE2D:
1235			templat.u.tex.level = desc->Texture1D.MipSlice;
1236			break;
1237		case D3D11_RTV_DIMENSION_TEXTURE3D:
1238			templat.u.tex.level = desc->Texture3D.MipSlice;
1239			templat.u.tex.first_layer = desc->Texture3D.FirstWSlice;
1240			templat.u.tex.last_layer = desc->Texture3D.FirstWSlice + desc->Texture3D.WSize - 1;
1241			break;
1242		case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
1243		case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
1244			templat.u.tex.level = desc->Texture1DArray.MipSlice;
1245			templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
1246			templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1;
1247			break;
1248		case D3D11_RTV_DIMENSION_BUFFER:
1249			templat.u.buf.first_element = desc->Buffer.ElementOffset;
1250			templat.u.buf.last_element = desc->Buffer.ElementOffset + desc->Buffer.ElementWidth - 1;
1251			break;
1252		case D3D11_RTV_DIMENSION_TEXTURE2DMS:
1253		case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
1254			return E_NOTIMPL;
1255		default:
1256			return E_INVALIDARG;
1257		}
1258
1259		if(!out_rtv)
1260			return S_FALSE;
1261
1262		struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat);
1263		if(!surface)
1264			return E_FAIL;
1265		*out_rtv = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc);
1266		return S_OK;
1267	}
1268
1269	virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView(
1270		ID3D11Resource *iresource,
1271		const D3D11_DEPTH_STENCIL_VIEW_DESC *desc,
1272		ID3D11DepthStencilView **out_depth_stencil_view)
1273	{
1274		SYNCHRONIZED;
1275
1276		const struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
1277
1278		D3D11_DEPTH_STENCIL_VIEW_DESC def_desc;
1279		if(!desc)
1280		{
1281			init_pipe_to_dxgi_format();
1282			memset(&def_desc, 0, sizeof(def_desc));
1283			def_desc.Format = pipe_to_dxgi_format[resource->format];
1284			switch(resource->target)
1285			{
1286			case PIPE_TEXTURE_1D:
1287				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
1288				break;
1289			case PIPE_TEXTURE_1D_ARRAY:
1290				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY;
1291				def_desc.Texture1DArray.ArraySize = resource->array_size;
1292				break;
1293			case PIPE_TEXTURE_2D:
1294			case PIPE_TEXTURE_RECT:
1295				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
1296				break;
1297			case PIPE_TEXTURE_2D_ARRAY:
1298				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
1299				def_desc.Texture2DArray.ArraySize = resource->array_size;
1300				break;
1301			case PIPE_TEXTURE_CUBE:
1302				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
1303				def_desc.Texture2DArray.ArraySize = 6;
1304				break;
1305			default:
1306				return E_INVALIDARG;
1307			}
1308			desc = &def_desc;
1309		}
1310
1311		struct pipe_surface templat;
1312		memset(&templat, 0, sizeof(templat));
1313		if(invalid(desc->format >= DXGI_FORMAT_COUNT))
1314			return E_INVALIDARG;
1315		templat.format = (desc->Format == DXGI_FORMAT_UNKNOWN) ? resource->format : dxgi_to_pipe_format[desc->Format];
1316		if(!templat.format)
1317			return E_NOTIMPL;
1318		templat.usage = PIPE_BIND_DEPTH_STENCIL;
1319		templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
1320
1321		switch(desc->ViewDimension)
1322		{
1323		case D3D11_DSV_DIMENSION_TEXTURE1D:
1324		case D3D11_DSV_DIMENSION_TEXTURE2D:
1325			templat.u.tex.level = desc->Texture1D.MipSlice;
1326			break;
1327		case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
1328		case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
1329			templat.u.tex.level = desc->Texture1DArray.MipSlice;
1330			templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
1331			templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice + desc->Texture1DArray.ArraySize - 1;
1332			break;
1333		case D3D11_DSV_DIMENSION_TEXTURE2DMS:
1334		case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
1335			return E_NOTIMPL;
1336		default:
1337			return E_INVALIDARG;
1338		}
1339
1340		if(!out_depth_stencil_view)
1341			return S_FALSE;
1342
1343		struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat);
1344		if(!surface)
1345			return E_FAIL;
1346		*out_depth_stencil_view = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc);
1347		return S_OK;
1348	}
1349
1350#define D3D1X_SHVER_GEOMETRY_SHADER 2 /* D3D11_SHVER_GEOMETRY_SHADER */
1351
1352	GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void* shader_bytecode, SIZE_T bytecode_length
1353#if API >= 11
1354			, ID3D11ClassLinkage *class_linkage
1355#endif
1356			, struct pipe_stream_output_info* so_info)
1357	{
1358		bool dump = debug_get_option_dump_shaders();
1359
1360		std::auto_ptr<sm4_program> sm4(0);
1361
1362		dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(shader_bytecode, bytecode_length);
1363		if(!sm4_chunk)
1364		{
1365			if(so_info)
1366				sm4.reset(new sm4_program());
1367		}
1368		else
1369		{
1370			sm4.reset(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size)));
1371			// check if this is a dummy GS, in which case we only need a place to store the signature
1372			if(sm4.get() && so_info && sm4->version.type != D3D1X_SHVER_GEOMETRY_SHADER)
1373				sm4.reset(new sm4_program());
1374		}
1375		if(!sm4.get())
1376			return 0;
1377
1378		if(dump)
1379			sm4->dump();
1380
1381		struct dxbc_chunk_signature* sig;
1382
1383		sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_INPUT_SIGNATURE);
1384		if(sig)
1385			sm4->num_params_in = dxbc_parse_signature(sig, &sm4->params_in);
1386
1387		sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE);
1388		if(sig)
1389			sm4->num_params_out = dxbc_parse_signature(sig, &sm4->params_out);
1390
1391		sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_PATCH_SIGNATURE);
1392		if(sig)
1393			sm4->num_params_patch = dxbc_parse_signature(sig, &sm4->params_patch);
1394
1395		struct pipe_shader_state tgsi_shader;
1396		memset(&tgsi_shader, 0, sizeof(tgsi_shader));
1397		if(so_info)
1398			memcpy(&tgsi_shader.stream_output, so_info, sizeof(tgsi_shader.stream_output));
1399
1400		if(so_info && sm4->version.type != D3D1X_SHVER_GEOMETRY_SHADER)
1401			tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi_linkage_only(*sm4);
1402		else
1403			tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4);
1404		if(!tgsi_shader.tokens)
1405			return 0;
1406
1407		if(dump)
1408			tgsi_dump(tgsi_shader.tokens, 0);
1409
1410		void* shader_cso;
1411		GalliumD3D11Shader<>* shader;
1412
1413		switch(type)
1414		{
1415		case PIPE_SHADER_VERTEX:
1416			shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader);
1417			shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso);
1418			break;
1419		case PIPE_SHADER_FRAGMENT:
1420			shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader);
1421			shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso);
1422			break;
1423		case PIPE_SHADER_GEOMETRY:
1424			shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader);
1425			shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso);
1426			break;
1427		default:
1428			shader_cso = 0;
1429			shader = 0;
1430			break;
1431		}
1432
1433		free((void*)tgsi_shader.tokens);
1434		return shader;
1435	}
1436
1437#if API >= 11
1438#define CREATE_SHADER_ARGS \
1439	const void *shader_bytecode, \
1440	SIZE_T bytecode_length, \
1441	ID3D11ClassLinkage *class_linkage
1442#define PASS_SHADER_ARGS shader_bytecode, bytecode_length, class_linkage
1443#else
1444#define CREATE_SHADER_ARGS \
1445	const void *shader_bytecode, \
1446	SIZE_T bytecode_length
1447#define PASS_SHADER_ARGS shader_bytecode, bytecode_length
1448#endif
1449
1450#define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \
1451	virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
1452		CREATE_SHADER_ARGS, \
1453		ID3D11##Stage##Shader **out_shader) \
1454	{ \
1455		SYNCHRONIZED; \
1456		GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS, NULL); \
1457		if(!shader) \
1458			return E_FAIL; \
1459		if(out_shader) \
1460		{ \
1461			*out_shader = shader; \
1462			return S_OK; \
1463		} \
1464		else \
1465		{ \
1466			shader->Release(); \
1467			return S_FALSE; \
1468		} \
1469	}
1470
1471#define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \
1472	virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
1473		CREATE_SHADER_ARGS, \
1474		ID3D11##Stage##Shader **out_shader) \
1475	{ \
1476		return E_NOTIMPL; \
1477	}
1478
1479	IMPLEMENT_CREATE_SHADER(Vertex, VERTEX)
1480	IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT)
1481	IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY)
1482#if API >= 11
1483	IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull)
1484	IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain)
1485	IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute)
1486#endif
1487
1488	virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput(
1489		const void *shader_bytecode,
1490		SIZE_T bytecode_length,
1491		const D3D11_SO_DECLARATION_ENTRY *so_declaration,
1492		unsigned num_entries,
1493#if API >= 11
1494		const unsigned *buffer_strides,
1495		unsigned num_strides,
1496		unsigned rasterized_stream,
1497		ID3D11ClassLinkage *class_linkage,
1498#else
1499		UINT output_stream_stride,
1500#endif
1501		ID3D11GeometryShader **out_geometry_shader)
1502	{
1503		SYNCHRONIZED;
1504		GalliumD3D11GeometryShader* gs;
1505
1506#if API >= 11
1507		if(rasterized_stream != 0)
1508			return E_NOTIMPL; // not yet supported by gallium
1509#endif
1510		struct dxbc_chunk_signature* sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE);
1511		if(!sig)
1512			return E_INVALIDARG;
1513		D3D11_SIGNATURE_PARAMETER_DESC* out;
1514		unsigned num_outputs = dxbc_parse_signature(sig, &out);
1515
1516		struct pipe_stream_output_info so;
1517		memset(&so, 0, sizeof(so));
1518
1519#if API >= 11
1520		if(num_strides)
1521			so.stride = buffer_strides[0];
1522		if(num_strides > 1)
1523			debug_printf("Warning: multiple user-specified strides not implemented !\n");
1524#else
1525		so.stride = output_stream_stride;
1526#endif
1527
1528		for(unsigned i = 0; i < num_entries; ++i)
1529		{
1530			unsigned j;
1531			for(j = 0; j < num_outputs; ++j)
1532				if(out[j].SemanticIndex == so_declaration[i].SemanticIndex && !strcasecmp(out[j].SemanticName, so_declaration[i].SemanticName))
1533					break;
1534			if(j >= num_outputs)
1535				continue;
1536			const int first_comp = ffs(out[j].Mask) - 1 + so_declaration[i].StartComponent;
1537			so.output[i].output_buffer = so_declaration[i].OutputSlot;
1538			so.output[i].register_index = out[j].Register;
1539			so.output[i].register_mask = ((1 << so_declaration[i].ComponentCount) - 1) << first_comp;
1540			++so.num_outputs;
1541		}
1542		if(out)
1543			free(out);
1544
1545		gs = reinterpret_cast<GalliumD3D11GeometryShader*>(create_stage_shader(PIPE_SHADER_GEOMETRY, PASS_SHADER_ARGS, &so));
1546		if(!gs)
1547			return E_FAIL;
1548
1549		if(!out_geometry_shader) {
1550			gs->Release();
1551			return S_FALSE;
1552		}
1553		*out_geometry_shader = gs;
1554
1555		return S_OK;
1556	}
1557
1558#if API >= 11
1559	virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage(
1560		ID3D11ClassLinkage **out_linkage)
1561	{
1562		SYNCHRONIZED;
1563
1564		return E_NOTIMPL;
1565	}
1566#endif
1567
1568	virtual HRESULT STDMETHODCALLTYPE CreateQuery(
1569		const D3D11_QUERY_DESC *query_desc,
1570		ID3D11Query **out_query)
1571	{
1572		SYNCHRONIZED;
1573
1574		if(invalid(query_desc->Query >= D3D11_QUERY_COUNT))
1575			return E_INVALIDARG;
1576		unsigned query_type = d3d11_to_pipe_query[query_desc->Query];
1577		if(query_type >= PIPE_QUERY_TYPES)
1578			return E_NOTIMPL;
1579
1580		if(!out_query)
1581			return S_FALSE;
1582
1583		struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
1584		if(!query)
1585			return E_FAIL;
1586
1587		*out_query = new GalliumD3D11Query(this, query, d3d11_query_size[query_desc->Query], *query_desc);
1588		return S_OK;
1589	}
1590
1591	virtual HRESULT STDMETHODCALLTYPE CreatePredicate(
1592		const D3D11_QUERY_DESC *predicate_desc,
1593		ID3D11Predicate **out_predicate)
1594	{
1595		SYNCHRONIZED;
1596
1597		unsigned query_type;
1598		switch(predicate_desc->Query)
1599		{
1600		case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
1601			query_type = PIPE_QUERY_SO_OVERFLOW_PREDICATE;
1602			break;
1603		case D3D11_QUERY_OCCLUSION_PREDICATE:
1604			query_type = PIPE_QUERY_OCCLUSION_PREDICATE;
1605			break;
1606		default:
1607			return E_INVALIDARG;
1608		}
1609
1610		if(out_predicate)
1611			return S_FALSE;
1612
1613		struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
1614		if(!query)
1615			return E_FAIL;
1616
1617		*out_predicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *predicate_desc);
1618		return S_OK;
1619	}
1620
1621
1622	virtual HRESULT STDMETHODCALLTYPE CreateCounter(
1623		const D3D11_COUNTER_DESC *counter_desc,
1624		ID3D11Counter **out_counter)
1625	{
1626		SYNCHRONIZED;
1627
1628		return E_NOTIMPL;
1629
1630		// remember to return S_FALSE if out_counter == NULL and everything is OK
1631	}
1632
1633#if API >= 11
1634	virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext(
1635		unsigned context_flags,
1636		ID3D11DeviceContext **out_deferred_context)
1637	{
1638		SYNCHRONIZED;
1639
1640		// TODO: this will have to be implemented using a new Gallium util module
1641		return E_NOTIMPL;
1642
1643		// remember to return S_FALSE if out_counter == NULL and everything is OK
1644	}
1645#endif
1646
1647	virtual HRESULT STDMETHODCALLTYPE OpenSharedResource(
1648			HANDLE resource,
1649			REFIID iid,
1650			void **out_resource)
1651	{
1652		SYNCHRONIZED;
1653
1654		// TODO: the problem here is that we need to communicate dimensions somehow
1655		return E_NOTIMPL;
1656
1657		// remember to return S_FALSE if out_counter == NULL and everything is OK
1658#if 0
1659		struct pipe_resou	rce templat;
1660		struct winsys_handle handle;
1661		handle.stride = 0;
1662		handle.handle = resource;
1663		handle.type = DRM_API_HANDLE_TYPE_SHARED;
1664		screen->resource_from_handle(screen, &templat, &handle);
1665#endif
1666	}
1667
1668#if API < 11
1669	/* these are documented as "Not implemented".
1670	 * According to the UMDDI documentation, they apparently turn on a
1671	 * (width + 1) x (height + 1) convolution filter for 1-bit textures.
1672	 * Probably nothing uses these, assuming it has ever been implemented anywhere.
1673	 */
1674	void STDMETHODCALLTYPE SetTextFilterSize(
1675		UINT width,
1676		UINT height
1677	)
1678	{}
1679
1680	virtual void STDMETHODCALLTYPE GetTextFilterSize(
1681		UINT *width,
1682		UINT *height
1683	)
1684	{}
1685#endif
1686
1687#if API >= 11
1688	virtual void STDMETHODCALLTYPE RestoreGalliumState()
1689	{
1690		GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context);
1691	}
1692
1693	virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly()
1694	{
1695		GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context);
1696	}
1697#endif
1698
1699	virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void)
1700	{
1701		return immediate_pipe;
1702	}
1703
1704#undef SYNCHRONIZED
1705};
1706