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