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