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