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