d3d11_screen.h revision d2cc8aedb5d544608842b58b6ae4754313ded939
168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer/**************************************************************************
268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer *
368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * Copyright 2010 Luca Barbieri
468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer *
568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * Permission is hereby granted, free of charge, to any person obtaining
668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * a copy of this software and associated documentation files (the
768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * "Software"), to deal in the Software without restriction, including
868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * without limitation the rights to use, copy, modify, merge, publish,
968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * distribute, sublicense, and/or sell copies of the Software, and to
1068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * permit persons to whom the Software is furnished to do so, subject to
1168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * the following conditions:
1268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer *
1368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * The above copyright notice and this permission notice (including the
1468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * next paragraph) shall be included in all copies or substantial
1568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * portions of the Software.
1668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer *
17001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1888af6b9217f9ff8b4592f38ac5175de697275f49Michael J. Spencer * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
191f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
227acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer *
2568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer **************************************************************************/
2668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
2768b3f0c40e29e461dbbc85370078692df4336b42Michael J. SpencerDEBUG_GET_ONCE_BOOL_OPTION(dump_shaders, "D3D1X_DUMP_SHADERS", FALSE);
287acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer
297acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer/* These cap sets are much more correct than the ones in u_caps.c */
307acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer/* TODO: it seems cube levels should be the same as 2D levels */
317acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer
327acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer/* DX 9_1 */
3325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerstatic unsigned caps_dx_9_1[] = {
347acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
357acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12),	/* 2048 */
367acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 8),	 /* 256 */
377acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
387acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer	UTIL_CHECK_TERMINATE
397acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer};
407acdb4d237181976b04e72f6a6c329c3b2604440Michael J. Spencer
4168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer/* DX 9_2 */
4225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerstatic unsigned caps_dx_9_2[] = {
4325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(OCCLUSION_QUERY),
4425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
4525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
4625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
47dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
48dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12),	/* 2048 */
49dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),	 /* 256 */
50dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
5125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_TERMINATE
5225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer};
5325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
5425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer/* DX 9_3 */
5525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencerstatic unsigned caps_dx_9_3[] = {
5625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(OCCLUSION_QUERY),
5725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
5868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
5968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
6068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_CAP(SM3),
6107ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer	UTIL_CHECK_CAP(VERTEX_ELEMENT_INSTANCE_DIVISOR),
6268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_CAP(OCCLUSION_QUERY),
6368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4),
6468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13),	/* 4096 */
6568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9),	 /* 256 */
66dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
67dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	UTIL_CHECK_TERMINATE
68dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer};
69dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer
7068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencerstatic unsigned caps_dx_10_0[] = {
7168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_CAP(INDEP_BLEND_ENABLE),
7268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_CAP(ANISOTROPIC_FILTER),
7368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_CAP(MIXED_COLORBUFFER_FORMATS),
7425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(FRAGMENT_COLOR_CLAMP_CONTROL),
7568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_CAP(STREAM_OUTPUT),
7625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(CONDITIONAL_RENDER),
7725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(PRIMITIVE_RESTART),
7825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_CAP(TGSI_INSTANCEID),
7968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
8068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13),
8168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_INT(MAX_TEXTURE_ARRAY_LAYERS, 512),
8225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16),
8368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_SHADER(GEOMETRY, MAX_CONST_BUFFERS, 14),
8468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_SHADER(GEOMETRY, MAX_TEXTURE_SAMPLERS, 16),
8568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_SHADER(GEOMETRY, SUBROUTINES, 1),
8625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	UTIL_CHECK_SHADER(FRAGMENT, INTEGERS, 1),
8768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	UTIL_CHECK_TERMINATE
8868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer};
8968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
9068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
9168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer// this is called "screen" because in the D3D10 case it's only part of the device
9207ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramertemplate<bool threadsafe>
9368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencerstruct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
9468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer{
9568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	D3D_FEATURE_LEVEL feature_level;
9668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	int format_support[PIPE_FORMAT_COUNT];
97dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	unsigned creation_flags;
98dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	unsigned exception_mode;
99dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer	maybe_mutex_t<threadsafe> mutex;
100dedd6ee135f886e219035b2cf5957ce492f90ed1Michael J. Spencer
10168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer/* TODO: Direct3D 11 specifies that fine-grained locking should be used if the driver supports it.
10268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer * Right now, I don't trust Gallium drivers to get this right.
10368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer */
10468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(mutex)
10525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
10668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	GalliumD3D11ScreenImpl(struct pipe_screen* screen, struct pipe_context* immediate_pipe, BOOL owns_immediate_pipe,unsigned creation_flags, IDXGIAdapter* adapter)
10725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	: GalliumD3D11Screen(screen, immediate_pipe, adapter), creation_flags(creation_flags)
10825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	{
10925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		memset(&screen_caps, 0, sizeof(screen_caps));
11025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		screen_caps.gs = screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
11168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		screen_caps.so = !!screen->get_param(screen, PIPE_CAP_STREAM_OUTPUT);
11268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		screen_caps.queries = screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY);
11325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		screen_caps.render_condition = screen->get_param(screen, PIPE_CAP_CONDITIONAL_RENDER);
11407ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer		for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
11507ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer			screen_caps.constant_buffers[i] = screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
11668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		screen_caps.stages = 0;
11768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
11868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		{
11968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			if(!screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
12068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				break;
12168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			screen_caps.stages = i + 1;
12268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		}
123001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer
12468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		screen_caps.stages_with_sampling = (1 << screen_caps.stages) - 1;
12568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		if(!screen->get_shader_param(screen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS))
12668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			screen_caps.stages_with_sampling &=~ (1 << PIPE_SHADER_VERTEX);
12768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
12868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		memset(format_support, 0xff, sizeof(format_support));
129001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer
13068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		float default_level = 9.1f;
131001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		if(!util_check_caps(screen, caps_dx_9_1))
132001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer			_debug_printf("Warning: driver does not even meet D3D_FEATURE_LEVEL_9_1 features, advertising it anyway!\n");
133001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		else if(!util_check_caps(screen, caps_dx_9_2))
13468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			default_level = 9.1f;
13568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		else if(!util_check_caps(screen, caps_dx_9_3))
13668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			default_level = 9.2f;
13768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		else if(!util_check_caps(screen, caps_dx_10_0))
13868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			default_level = 9.3f;
13968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		else
14025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			default_level = 10.0f;
14125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
14225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		char default_level_name[64];
14368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		sprintf(default_level_name, "%.1f", default_level);
14425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		float feature_level_number = atof(debug_get_option("D3D11_FEATURE_LEVEL", default_level_name));
14525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		if(!feature_level_number)
14625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			feature_level_number = default_level;
14725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
14825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer#if API >= 11
14925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		if(feature_level_number >= 11.0f)
15068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			feature_level = D3D_FEATURE_LEVEL_11_0;
15168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		else
15268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#endif
15325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		if(feature_level_number >= 10.1f)
15425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			feature_level = D3D_FEATURE_LEVEL_10_1;
15525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		else if(feature_level_number >= 10.0f)
15625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			feature_level = D3D_FEATURE_LEVEL_10_0;
15725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		else if(feature_level_number >= 9.3f)
15825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			feature_level = D3D_FEATURE_LEVEL_9_3;
15907ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer		else if(feature_level_number >= 9.2f)
16007ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer			feature_level = D3D_FEATURE_LEVEL_9_2;
16168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		else
16268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			feature_level = D3D_FEATURE_LEVEL_9_1;
16368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
16468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#if API >= 11
16568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		immediate_context = GalliumD3D11ImmediateDeviceContext_Create(this, immediate_pipe, owns_immediate_pipe);
16668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		// release to the reference to ourselves that the immediate context took, to avoid a garbage cycle
16768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		immediate_context->Release();
16868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#endif
16968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
17068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
17168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	~GalliumD3D11ScreenImpl()
17268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
17368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#if API >= 11
17468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		GalliumD3D11ImmediateDeviceContext_Destroy(immediate_context);
17568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#endif
17668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
17768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
17868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	virtual D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(void)
17968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
18068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		return feature_level;
18168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
18268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
18325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	virtual unsigned STDMETHODCALLTYPE GetCreationFlags(void)
18425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	{
18525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		return creation_flags;
18625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	}
18725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
18825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(void)
18968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
19068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		return S_OK;
19168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
19268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
19368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#if API >= 11
19468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	virtual void STDMETHODCALLTYPE GetImmediateContext(
19568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		ID3D11DeviceContext **out_immediate_context)
19668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
19768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		immediate_context->AddRef();
19868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		*out_immediate_context = immediate_context;
19968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
20068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#endif
20168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
20268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	virtual HRESULT STDMETHODCALLTYPE SetExceptionMode(unsigned RaiseFlags)
20368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
20468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		exception_mode = RaiseFlags;
20568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		return S_OK;
20668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
20788af6b9217f9ff8b4592f38ac5175de697275f49Michael J. Spencer
20868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	virtual unsigned STDMETHODCALLTYPE GetExceptionMode(void)
20968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
21068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		return exception_mode;
21168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
21268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
21388af6b9217f9ff8b4592f38ac5175de697275f49Michael J. Spencer	virtual HRESULT STDMETHODCALLTYPE CheckCounter(
21468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		const D3D11_COUNTER_DESC *desc,
21568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		D3D11_COUNTER_TYPE *type,
216001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		unsigned *active_counters,
217001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		LPSTR sz_name,
218001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		unsigned *name_length,
219001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		LPSTR sz_units,
220001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		unsigned *units_length,
221001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		LPSTR sz_description,
222001c9205fca2220480589ec355cb6ec701a37e08Michael J. Spencer		unsigned *description_length)
22368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
22468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		return E_NOTIMPL;
22568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
22668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
22768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	virtual void STDMETHODCALLTYPE CheckCounterInfo(
22868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		D3D11_COUNTER_INFO *counter_info)
22968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
23068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		/* none supported at the moment */
23168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		counter_info->LastDeviceDependentCounter = (D3D11_COUNTER)0;
23268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		counter_info->NumDetectableParallelUnits = 1;
23368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		counter_info->NumSimultaneousCounters = 0;
23468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
23568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
23668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer#if API >= 11
23725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport(
23825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		D3D11_FEATURE feature,
23968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		void *out_feature_support_data,
24068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		unsigned feature_support_data_size)
24125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer	{
24225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		SYNCHRONIZED;
24368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
24468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		switch(feature)
24525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer		{
24625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			case D3D11_FEATURE_THREADING:
24768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			{
24868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				D3D11_FEATURE_DATA_THREADING* data = (D3D11_FEATURE_DATA_THREADING*)out_feature_support_data;
24925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				if(feature_support_data_size != sizeof(*data))
25025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer					return E_INVALIDARG;
25168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
25268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				data->DriverCommandLists = FALSE;
25325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				data->DriverConcurrentCreates = FALSE;
25425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				return S_OK;
25568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			}
25668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			case D3D11_FEATURE_DOUBLES:
25725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			{
25825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				D3D11_FEATURE_DATA_DOUBLES* data = (D3D11_FEATURE_DATA_DOUBLES*)out_feature_support_data;
25968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				if(feature_support_data_size != sizeof(*data))
26068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer					return E_INVALIDARG;
26168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
26268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				data->DoublePrecisionFloatShaderOps = FALSE;
26368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				return S_OK;
26468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			}
26568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			case D3D11_FEATURE_FORMAT_SUPPORT:
26668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			{
26768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)out_feature_support_data;
26868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				if(feature_support_data_size != sizeof(*data))
26968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer					return E_INVALIDARG;
27068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
27168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				return this->CheckFormatSupport(data->InFormat, &data->OutFormatSupport);
27225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			}
27325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			case D3D11_FEATURE_FORMAT_SUPPORT2:
27468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			{
27568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)out_feature_support_data;
27625b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				if(feature_support_data_size != sizeof(*data))
27725b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer					return E_INVALIDARG;
27868b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
27968b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				data->OutFormatSupport = 0;
28025b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				/* TODO: should this be S_OK? */
28125b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				return E_INVALIDARG;
28268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			}
28368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS:
28425b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			{
28525b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS* data = (D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS*)out_feature_support_data;
28668b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				if(feature_support_data_size != sizeof(*data))
28768b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer					return E_INVALIDARG;
28825b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer
28925b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				data->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = FALSE;
29068b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer				return S_OK;
29168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer			}
29225b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer			default:
29325b15777df42d5d608810f6881b6c98107481d69Michael J. Spencer				return E_INVALIDARG;
29468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		}
29568b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	}
29607ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer#endif
29707ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer
29807ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer	virtual HRESULT STDMETHODCALLTYPE CheckFormatSupport(
29907ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer		DXGI_FORMAT dxgi_format,
30007ea23aa2d17f701fa125442c20c1eba75b55fdbBenjamin Kramer		unsigned *out_format_support
30168b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	)
30268b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer	{
30368b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer		SYNCHRONIZED;
30468b3f0c40e29e461dbbc85370078692df4336b42Michael J. Spencer
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
693			if(array_size != 6)
694				return E_NOTIMPL;
695		}
696		else
697		{
698			if(array_size > 1)
699				return E_NOTIMPL;
700			array_size = 1;
701		}
702		/* TODO: msaa */
703		struct pipe_resource templat;
704		memset(&templat, 0, sizeof(templat));
705		templat.target = target;
706		templat.width0 = width;
707		templat.height0 = height;
708		templat.depth0 = depth;
709		if(mip_levels)
710			templat.last_level = mip_levels - 1;
711		else
712			templat.last_level = MAX2(MAX2(util_logbase2(templat.width0), util_logbase2(templat.height0)), util_logbase2(templat.depth0));
713		templat.format = dxgi_to_pipe_format[format];
714		templat.bind = d3d11_to_pipe_bind_flags(bind_flags);
715		if(c_p_u_access_flags & D3D11_CPU_ACCESS_READ)
716			templat.bind |= PIPE_BIND_TRANSFER_READ;
717		if(c_p_u_access_flags & D3D11_CPU_ACCESS_WRITE)
718			templat.bind |= PIPE_BIND_TRANSFER_WRITE;
719		if(misc_flags & D3D11_RESOURCE_MISC_SHARED)
720			templat.bind |= PIPE_BIND_SHARED;
721		if(misc_flags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE)
722			templat.bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE;
723		if(dxgi_usage & DXGI_USAGE_BACK_BUFFER)
724			templat.bind |= PIPE_BIND_DISPLAY_TARGET;
725		templat.usage = d3d11_to_pipe_usage[usage];
726		if(invalid(!templat.format))
727			return E_NOTIMPL;
728
729		if(!ppresource)
730			return S_FALSE;
731
732		struct pipe_resource* resource = screen->resource_create(screen, &templat);
733		if(!resource)
734			return E_FAIL;
735		if(initial_data)
736		{
737			for(unsigned slice = 0; slice < array_size; ++slice)
738			{
739				for(unsigned level = 0; level <= templat.last_level; ++level)
740				{
741					struct pipe_box box;
742					box.x = box.y = 0;
743					box.z = slice;
744					box.width = u_minify(width, level);
745					box.height = u_minify(height, level);
746					box.depth = 1;
747					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);
748					++initial_data;
749				}
750			}
751		}
752		*ppresource = resource;
753		return S_OK;
754	}
755
756	static unsigned d3d_to_dxgi_usage(unsigned bind, unsigned misc)
757	{
758		unsigned dxgi_usage = 0;
759		if(bind |= D3D11_BIND_RENDER_TARGET)
760			dxgi_usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
761		if(bind & D3D11_BIND_SHADER_RESOURCE)
762			dxgi_usage |= DXGI_USAGE_SHADER_INPUT;
763#if API >= 11
764		if(bind & D3D11_BIND_UNORDERED_ACCESS)
765			dxgi_usage |= DXGI_USAGE_UNORDERED_ACCESS;
766#endif
767		if(misc & D3D11_RESOURCE_MISC_SHARED)
768			dxgi_usage |= DXGI_USAGE_SHARED;
769		return dxgi_usage;
770	}
771
772	virtual HRESULT STDMETHODCALLTYPE CreateTexture1D(
773		const D3D11_TEXTURE1D_DESC *desc,
774		const D3D11_SUBRESOURCE_DATA *initial_data,
775		ID3D11Texture1D **out_texture1d)
776	{
777		SYNCHRONIZED;
778
779		struct pipe_resource* resource;
780		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
781		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);
782		if(hr != S_OK)
783			return hr;
784		D3D11_TEXTURE1D_DESC cdesc = *desc;
785		cdesc.MipLevels = resource->last_level + 1;
786		*out_texture1d = new GalliumD3D11Texture1D(this, resource, cdesc, dxgi_usage);
787		return S_OK;
788	}
789
790	virtual HRESULT STDMETHODCALLTYPE CreateTexture2D(
791		const D3D11_TEXTURE2D_DESC *desc,
792		const D3D11_SUBRESOURCE_DATA *initial_data,
793		ID3D11Texture2D **out_texture2d)
794	{
795		SYNCHRONIZED;
796
797		struct pipe_resource* resource;
798		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
799		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);
800		if(hr != S_OK)
801			return hr;
802		D3D11_TEXTURE2D_DESC cdesc = *desc;
803		cdesc.MipLevels = resource->last_level + 1;
804		if(cdesc.MipLevels == 1 && cdesc.ArraySize == 1)
805			*out_texture2d = new GalliumD3D11Surface(this, resource, cdesc, dxgi_usage);
806		else
807			*out_texture2d = new GalliumD3D11Texture2D(this, resource, cdesc, dxgi_usage);
808		return S_OK;
809	}
810
811	virtual HRESULT STDMETHODCALLTYPE CreateTexture3D(
812		const D3D11_TEXTURE3D_DESC *desc,
813		const D3D11_SUBRESOURCE_DATA *initial_data,
814		ID3D11Texture3D **out_texture3d)
815	{
816		SYNCHRONIZED;
817
818		struct pipe_resource* resource;
819		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
820		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);
821		if(hr != S_OK)
822			return hr;
823		D3D11_TEXTURE3D_DESC cdesc = *desc;
824		cdesc.MipLevels = resource->last_level + 1;
825		*out_texture3d = new GalliumD3D11Texture3D(this, resource, cdesc, dxgi_usage);
826		return S_OK;
827	}
828
829	virtual HRESULT STDMETHODCALLTYPE CreateBuffer(
830		const D3D11_BUFFER_DESC *desc,
831		const D3D11_SUBRESOURCE_DATA *initial_data,
832		ID3D11Buffer **out_buffer)
833	{
834		SYNCHRONIZED;
835
836		struct pipe_resource* resource;
837		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc->BindFlags, desc->MiscFlags);
838		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);
839		if(hr != S_OK)
840			return hr;
841		*out_buffer = new GalliumD3D11Buffer(this, resource, *desc, dxgi_usage);
842		return S_OK;
843	}
844
845	virtual HRESULT STDMETHODCALLTYPE OpenGalliumResource(
846		struct pipe_resource* resource,
847		IUnknown** dxgi_resource)
848	{
849		SYNCHRONIZED;
850
851		/* TODO: maybe support others */
852		assert(resource->target == PIPE_TEXTURE_2D);
853		*dxgi_resource = 0;
854		D3D11_TEXTURE2D_DESC desc;
855		memset(&desc, 0, sizeof(desc));
856		desc.Width = resource->width0;
857		desc.Height = resource->height0;
858		init_pipe_to_dxgi_format();
859		desc.Format = pipe_to_dxgi_format[resource->format];
860		desc.SampleDesc.Count = resource->nr_samples;
861		desc.SampleDesc.Quality = 0;
862		desc.ArraySize = 1;
863		desc.MipLevels = resource->last_level + 1;
864		desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
865		if(resource->bind & PIPE_BIND_RENDER_TARGET)
866			desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
867		if(resource->bind & PIPE_BIND_DEPTH_STENCIL)
868			desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
869		if(resource->bind & PIPE_BIND_SAMPLER_VIEW)
870			desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
871		if(resource->bind & PIPE_BIND_SHARED)
872			desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
873		DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc.BindFlags, desc.MiscFlags);
874		if(desc.MipLevels == 1 && desc.ArraySize == 1)
875			*dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Surface(this, resource, desc, dxgi_usage);
876		else
877			*dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Texture2D(this, resource, desc, dxgi_usage);
878		return S_OK;
879	}
880
881	virtual HRESULT STDMETHODCALLTYPE CreateSurface(
882		const DXGI_SURFACE_DESC *dxgi_desc,
883		unsigned count,
884		DXGI_USAGE usage,
885		const DXGI_SHARED_RESOURCE *shared_resource,
886		IDXGISurface **out_surface)
887	{
888		SYNCHRONIZED;
889
890		D3D11_TEXTURE2D_DESC desc;
891		memset(&desc, 0, sizeof(desc));
892
893		struct pipe_resource* resource;
894		desc.Width = dxgi_desc->Width;
895		desc.Height = dxgi_desc->Height;
896		desc.Format = dxgi_desc->Format;
897		desc.SampleDesc = dxgi_desc->SampleDesc;
898		desc.ArraySize = count;
899		desc.MipLevels = 1;
900		desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
901		if(usage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
902			desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
903		if(usage & DXGI_USAGE_SHADER_INPUT)
904			desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
905#if API >= 11
906		if(usage & DXGI_USAGE_UNORDERED_ACCESS)
907			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
908#endif
909		if(usage & DXGI_USAGE_SHARED)
910			desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
911		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);
912		if(hr != S_OK)
913			return hr;
914		*out_surface = new GalliumD3D11Surface(this, resource, desc, usage);
915		return S_OK;
916	}
917
918	virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView(
919		ID3D11Resource *iresource,
920		const D3D11_SHADER_RESOURCE_VIEW_DESC *desc,
921		ID3D11ShaderResourceView **out_srv)
922	{
923#if API >= 11
924		D3D11_SHADER_RESOURCE_VIEW_DESC def_desc;
925#else
926		if(desc->ViewDimension == D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY)
927			return E_INVALIDARG;
928		D3D10_SHADER_RESOURCE_VIEW_DESC1 desc1;
929		memset(&desc1, 0, sizeof(desc1));
930		memcpy(&desc1, desc, sizeof(*desc));
931		return CreateShaderResourceView1(iresource, &desc1, (ID3D10ShaderResourceView1**)out_srv);
932	}
933
934	virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView1(
935			ID3D11Resource *iresource,
936			const D3D10_SHADER_RESOURCE_VIEW_DESC1 *desc,
937			ID3D10ShaderResourceView1 **out_srv)
938	{
939		D3D10_SHADER_RESOURCE_VIEW_DESC1 def_desc;
940#endif
941		SYNCHRONIZED;
942
943		if(!desc)
944		{
945			struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
946			init_pipe_to_dxgi_format();
947			memset(&def_desc, 0, sizeof(def_desc));
948			def_desc.Format = pipe_to_dxgi_format[resource->format];
949			switch(resource->target)
950			{
951			case PIPE_BUFFER:
952				def_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
953				def_desc.Buffer.ElementWidth = resource->width0;
954				break;
955			case PIPE_TEXTURE_1D:
956				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
957				def_desc.Texture1D.MipLevels = resource->last_level + 1;
958				break;
959			case PIPE_TEXTURE_2D:
960			case PIPE_TEXTURE_RECT:
961				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
962				def_desc.Texture2D.MipLevels = resource->last_level + 1;
963				break;
964			case PIPE_TEXTURE_3D:
965				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
966				def_desc.Texture3D.MipLevels = resource->last_level + 1;
967				break;
968			case PIPE_TEXTURE_CUBE:
969				def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
970				def_desc.TextureCube.MipLevels = resource->last_level + 1;
971				break;
972			default:
973				return E_INVALIDARG;
974			}
975			desc = &def_desc;
976		}
977
978		struct pipe_sampler_view templat;
979		memset(&templat, 0, sizeof(templat));
980		if(invalid(format >= DXGI_FORMAT_COUNT))
981			return E_INVALIDARG;
982		templat.format = dxgi_to_pipe_format[desc->Format];
983		if(!templat.format)
984			return E_NOTIMPL;
985		templat.swizzle_r = PIPE_SWIZZLE_RED;
986		templat.swizzle_g = PIPE_SWIZZLE_GREEN;
987		templat.swizzle_b = PIPE_SWIZZLE_BLUE;
988		templat.swizzle_a = PIPE_SWIZZLE_ALPHA;
989
990		templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
991		switch(desc->ViewDimension)
992		{
993		case D3D11_SRV_DIMENSION_TEXTURE1D:
994		case D3D11_SRV_DIMENSION_TEXTURE2D:
995		case D3D11_SRV_DIMENSION_TEXTURE3D:
996		case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
997		case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
998			/* yes, this works for all of these types (but TODO: texture arrays) */
999			templat.u.tex.first_level = desc->Texture1D.MostDetailedMip;
1000			templat.u.tex.last_level = templat.u.tex.first_level + desc->Texture1D.MipLevels - 1;
1001			break;
1002		case D3D11_SRV_DIMENSION_BUFFER:
1003		case D3D11_SRV_DIMENSION_TEXTURE2DMS:
1004		case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
1005			return E_NOTIMPL;
1006		default:
1007			return E_INVALIDARG;
1008		}
1009
1010		if(!out_srv)
1011			return S_FALSE;
1012
1013		struct pipe_sampler_view* view = immediate_pipe->create_sampler_view(immediate_pipe, templat.texture, &templat);
1014		if(!view)
1015			return E_FAIL;
1016		*out_srv = new GalliumD3D11ShaderResourceView(this, (GalliumD3D11Resource<>*)iresource, view, *desc);
1017		return S_OK;
1018	}
1019
1020#if API >= 11
1021	virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView(
1022		ID3D11Resource *resource,
1023		const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc,
1024		ID3D11UnorderedAccessView **out_uav)
1025	{
1026		SYNCHRONIZED;
1027
1028		return E_NOTIMPL;
1029
1030		// remember to return S_FALSE and not crash if out_u_a_view == 0 and parameters are valid
1031	}
1032#endif
1033
1034	virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
1035		ID3D11Resource *iresource,
1036		const D3D11_RENDER_TARGET_VIEW_DESC *desc,
1037		ID3D11RenderTargetView **out_rtv)
1038	{
1039		SYNCHRONIZED;
1040
1041		D3D11_RENDER_TARGET_VIEW_DESC def_desc;
1042		if(!desc)
1043		{
1044			struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
1045			init_pipe_to_dxgi_format();
1046			memset(&def_desc, 0, sizeof(def_desc));
1047			def_desc.Format = pipe_to_dxgi_format[resource->format];
1048			switch(resource->target)
1049			{
1050			case PIPE_BUFFER:
1051				def_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER;
1052				def_desc.Buffer.ElementWidth = resource->width0;
1053				break;
1054			case PIPE_TEXTURE_1D:
1055				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
1056				break;
1057			case PIPE_TEXTURE_2D:
1058			case PIPE_TEXTURE_RECT:
1059				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1060				break;
1061			case PIPE_TEXTURE_3D:
1062				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
1063				def_desc.Texture3D.WSize = resource->depth0;
1064				break;
1065			case PIPE_TEXTURE_CUBE:
1066				def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1067				def_desc.Texture2DArray.ArraySize = 6;
1068				break;
1069			default:
1070				return E_INVALIDARG;
1071			}
1072			desc = &def_desc;
1073		}
1074
1075		struct pipe_surface templat;
1076		memset(&templat, 0, sizeof(templat));
1077		if(invalid(desc->format >= DXGI_FORMAT_COUNT))
1078			return E_INVALIDARG;
1079		templat.format = dxgi_to_pipe_format[desc->Format];
1080		if(!templat.format)
1081			return E_NOTIMPL;
1082		templat.usage = PIPE_BIND_RENDER_TARGET;
1083		templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
1084
1085		switch(desc->ViewDimension)
1086		{
1087		case D3D11_RTV_DIMENSION_TEXTURE1D:
1088		case D3D11_RTV_DIMENSION_TEXTURE2D:
1089			templat.u.tex.level = desc->Texture1D.MipSlice;
1090			break;
1091		case D3D11_RTV_DIMENSION_TEXTURE3D:
1092			templat.u.tex.level = desc->Texture3D.MipSlice;
1093			templat.u.tex.first_layer = desc->Texture3D.FirstWSlice;
1094			/* XXX FIXME */
1095			templat.u.tex.last_layer = desc->Texture3D.FirstWSlice;
1096			break;
1097		case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
1098		case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
1099			templat.u.tex.level = desc->Texture1DArray.MipSlice;
1100			templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
1101			/* XXX FIXME */
1102			templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice;
1103			break;
1104		case D3D11_RTV_DIMENSION_BUFFER:
1105		case D3D11_RTV_DIMENSION_TEXTURE2DMS:
1106		case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
1107			return E_NOTIMPL;
1108		default:
1109			return E_INVALIDARG;
1110		}
1111
1112		if(!out_rtv)
1113			return S_FALSE;
1114
1115		struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat);
1116		if(!surface)
1117			return E_FAIL;
1118		*out_rtv = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc);
1119		return S_OK;
1120	}
1121
1122	virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView(
1123		ID3D11Resource *iresource,
1124		const D3D11_DEPTH_STENCIL_VIEW_DESC *desc,
1125		ID3D11DepthStencilView **out_depth_stencil_view)
1126	{
1127		SYNCHRONIZED;
1128
1129		D3D11_DEPTH_STENCIL_VIEW_DESC def_desc;
1130		if(!desc)
1131		{
1132			struct pipe_resource* resource = ((GalliumD3D11Resource<>*)iresource)->resource;
1133			init_pipe_to_dxgi_format();
1134			memset(&def_desc, 0, sizeof(def_desc));
1135			def_desc.Format = pipe_to_dxgi_format[resource->format];
1136			switch(resource->target)
1137			{
1138			case PIPE_TEXTURE_1D:
1139				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
1140				break;
1141			case PIPE_TEXTURE_2D:
1142			case PIPE_TEXTURE_RECT:
1143				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
1144				break;
1145			case PIPE_TEXTURE_CUBE:
1146				def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
1147				def_desc.Texture2DArray.ArraySize = 6;
1148				break;
1149			default:
1150				return E_INVALIDARG;
1151			}
1152			desc = &def_desc;
1153		}
1154
1155		struct pipe_surface templat;
1156		memset(&templat, 0, sizeof(templat));
1157		if(invalid(desc->format >= DXGI_FORMAT_COUNT))
1158			return E_INVALIDARG;
1159		templat.format = dxgi_to_pipe_format[desc->Format];
1160		if(!templat.format)
1161			return E_NOTIMPL;
1162		templat.usage = PIPE_BIND_DEPTH_STENCIL;
1163		templat.texture = ((GalliumD3D11Resource<>*)iresource)->resource;
1164
1165		switch(desc->ViewDimension)
1166		{
1167		case D3D11_DSV_DIMENSION_TEXTURE1D:
1168		case D3D11_DSV_DIMENSION_TEXTURE2D:
1169			templat.u.tex.level = desc->Texture1D.MipSlice;
1170			break;
1171		case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
1172		case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
1173			templat.u.tex.level = desc->Texture1DArray.MipSlice;
1174			templat.u.tex.first_layer = desc->Texture1DArray.FirstArraySlice;
1175			/* XXX FIXME */
1176			templat.u.tex.last_layer = desc->Texture1DArray.FirstArraySlice;
1177			break;
1178		case D3D11_DSV_DIMENSION_TEXTURE2DMS:
1179		case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
1180			return E_NOTIMPL;
1181		default:
1182			return E_INVALIDARG;
1183		}
1184
1185		if(!out_depth_stencil_view)
1186			return S_FALSE;
1187
1188		struct pipe_surface* surface = immediate_pipe->create_surface(immediate_pipe, templat.texture, &templat);
1189		if(!surface)
1190			return E_FAIL;
1191		*out_depth_stencil_view = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)iresource, surface, *desc);
1192		return S_OK;
1193	}
1194
1195	GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void* shader_bytecode, SIZE_T bytecode_length
1196#if API >= 11
1197			, ID3D11ClassLinkage *class_linkage
1198#endif
1199			)
1200	{
1201		bool dump = debug_get_option_dump_shaders();
1202
1203		dxbc_chunk_header* sm4_chunk = dxbc_find_shader_bytecode(shader_bytecode, bytecode_length);
1204		if(!sm4_chunk)
1205			return 0;
1206
1207		std::auto_ptr<sm4_program> sm4(sm4_parse(sm4_chunk + 1, bswap_le32(sm4_chunk->size)));
1208		if(!sm4.get())
1209			return 0;
1210
1211		if(dump)
1212			sm4->dump();
1213
1214		struct dxbc_chunk_signature* sig;
1215
1216		sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_INPUT_SIGNATURE);
1217		if(sig)
1218			sm4->num_params_in = dxbc_parse_signature(sig, &sm4->params_in);
1219
1220		sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_OUTPUT_SIGNATURE);
1221		if(sig)
1222			sm4->num_params_out = dxbc_parse_signature(sig, &sm4->params_out);
1223
1224		sig = dxbc_find_signature(shader_bytecode, bytecode_length, DXBC_FIND_PATCH_SIGNATURE);
1225		if(sig)
1226			sm4->num_params_patch = dxbc_parse_signature(sig, &sm4->params_patch);
1227
1228		struct pipe_shader_state tgsi_shader;
1229		memset(&tgsi_shader, 0, sizeof(tgsi_shader));
1230		tgsi_shader.tokens = (const tgsi_token*)sm4_to_tgsi(*sm4);
1231		if(!tgsi_shader.tokens)
1232			return 0;
1233
1234		if(dump)
1235			tgsi_dump(tgsi_shader.tokens, 0);
1236
1237		void* shader_cso;
1238		GalliumD3D11Shader<>* shader;
1239
1240		switch(type)
1241		{
1242		case PIPE_SHADER_VERTEX:
1243			shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader);
1244			shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso);
1245			break;
1246		case PIPE_SHADER_FRAGMENT:
1247			shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader);
1248			shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso);
1249			break;
1250		case PIPE_SHADER_GEOMETRY:
1251			shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader);
1252			shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso);
1253			break;
1254		default:
1255			shader_cso = 0;
1256			shader = 0;
1257			break;
1258		}
1259
1260		free((void*)tgsi_shader.tokens);
1261		return shader;
1262	}
1263
1264#if API >= 11
1265#define CREATE_SHADER_ARGS \
1266	const void *shader_bytecode, \
1267	SIZE_T bytecode_length, \
1268	ID3D11ClassLinkage *class_linkage
1269#define PASS_SHADER_ARGS shader_bytecode, bytecode_length, class_linkage
1270#else
1271#define CREATE_SHADER_ARGS \
1272	const void *shader_bytecode, \
1273	SIZE_T bytecode_length
1274#define PASS_SHADER_ARGS shader_bytecode, bytecode_length
1275#endif
1276
1277#define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \
1278	virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
1279		CREATE_SHADER_ARGS, \
1280		ID3D11##Stage##Shader **out_shader) \
1281	{ \
1282		SYNCHRONIZED; \
1283		GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS); \
1284		if(!shader) \
1285			return E_FAIL; \
1286		if(out_shader) \
1287		{ \
1288			*out_shader = shader; \
1289			return S_OK; \
1290		} \
1291		else \
1292		{ \
1293			shader->Release(); \
1294			return S_FALSE; \
1295		} \
1296	}
1297
1298#define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \
1299	virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
1300		CREATE_SHADER_ARGS, \
1301		ID3D11##Stage##Shader **out_shader) \
1302	{ \
1303		return E_NOTIMPL; \
1304	}
1305
1306	IMPLEMENT_CREATE_SHADER(Vertex, VERTEX)
1307	IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT)
1308	IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY)
1309#if API >= 11
1310	IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull)
1311	IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain)
1312	IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute)
1313#endif
1314
1315	virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput(
1316		const void *shader_bytecode,
1317		SIZE_T bytecode_length,
1318		const D3D11_SO_DECLARATION_ENTRY *so_declaration,
1319		unsigned num_entries,
1320#if API >= 11
1321		const unsigned *buffer_strides,
1322		unsigned num_strides,
1323		unsigned rasterized_stream,
1324		ID3D11ClassLinkage *class_linkage,
1325#else
1326		UINT output_stream_stride,
1327#endif
1328		ID3D11GeometryShader **out_geometry_shader)
1329	{
1330		SYNCHRONIZED;
1331
1332		return E_NOTIMPL;
1333
1334		// remember to return S_FALSE if ppGeometyShader == NULL and the shader is OK
1335	}
1336
1337#if API >= 11
1338	virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage(
1339		ID3D11ClassLinkage **out_linkage)
1340	{
1341		SYNCHRONIZED;
1342
1343		return E_NOTIMPL;
1344	}
1345#endif
1346
1347	virtual HRESULT STDMETHODCALLTYPE CreateQuery(
1348		const D3D11_QUERY_DESC *query_desc,
1349		ID3D11Query **out_query)
1350	{
1351		SYNCHRONIZED;
1352
1353		if(invalid(query_desc->Query >= D3D11_QUERY_COUNT))
1354			return E_INVALIDARG;
1355		unsigned query_type = d3d11_to_pipe_query[query_desc->Query];
1356		if(query_type >= PIPE_QUERY_TYPES)
1357			return E_NOTIMPL;
1358
1359		if(!out_query)
1360			return S_FALSE;
1361
1362		struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
1363		if(!query)
1364			return E_FAIL;
1365
1366		*out_query = new GalliumD3D11Query(this, query, d3d11_query_size[query_desc->Query], *query_desc);
1367		return S_OK;
1368	}
1369
1370	virtual HRESULT STDMETHODCALLTYPE CreatePredicate(
1371		const D3D11_QUERY_DESC *predicate_desc,
1372		ID3D11Predicate **out_predicate)
1373	{
1374		SYNCHRONIZED;
1375
1376		unsigned query_type;
1377		switch(predicate_desc->Query)
1378		{
1379		case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
1380			query_type = PIPE_QUERY_SO_OVERFLOW_PREDICATE;
1381			break;
1382		case D3D11_QUERY_OCCLUSION_PREDICATE:
1383			query_type = PIPE_QUERY_OCCLUSION_PREDICATE;
1384			break;
1385		default:
1386			return E_INVALIDARG;
1387		}
1388
1389		if(out_predicate)
1390			return S_FALSE;
1391
1392		struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
1393		if(!query)
1394			return E_FAIL;
1395
1396		*out_predicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *predicate_desc);
1397		return S_OK;
1398	}
1399
1400
1401	virtual HRESULT STDMETHODCALLTYPE CreateCounter(
1402		const D3D11_COUNTER_DESC *counter_desc,
1403		ID3D11Counter **out_counter)
1404	{
1405		SYNCHRONIZED;
1406
1407		return E_NOTIMPL;
1408
1409		// remember to return S_FALSE if out_counter == NULL and everything is OK
1410	}
1411
1412#if API >= 11
1413	virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext(
1414		unsigned context_flags,
1415		ID3D11DeviceContext **out_deferred_context)
1416	{
1417		SYNCHRONIZED;
1418
1419		// TODO: this will have to be implemented using a new Gallium util module
1420		return E_NOTIMPL;
1421
1422		// remember to return S_FALSE if out_counter == NULL and everything is OK
1423	}
1424#endif
1425
1426	virtual HRESULT STDMETHODCALLTYPE OpenSharedResource(
1427			HANDLE resource,
1428			REFIID iid,
1429			void **out_resource)
1430	{
1431		SYNCHRONIZED;
1432
1433		// TODO: the problem here is that we need to communicate dimensions somehow
1434		return E_NOTIMPL;
1435
1436		// remember to return S_FALSE if out_counter == NULL and everything is OK
1437#if 0
1438		struct pipe_resou	rce templat;
1439		struct winsys_handle handle;
1440		handle.stride = 0;
1441		handle.handle = resource;
1442		handle.type = DRM_API_HANDLE_TYPE_SHARED;
1443		screen->resource_from_handle(screen, &templat, &handle);
1444#endif
1445	}
1446
1447#if API < 11
1448	/* these are documented as "Not implemented".
1449	 * According to the UMDDI documentation, they apparently turn on a
1450	 * (width + 1) x (height + 1) convolution filter for 1-bit textures.
1451	 * Probably nothing uses these, assuming it has ever been implemented anywhere.
1452	 */
1453	void STDMETHODCALLTYPE SetTextFilterSize(
1454		UINT width,
1455		UINT height
1456	)
1457	{}
1458
1459	virtual void STDMETHODCALLTYPE GetTextFilterSize(
1460		UINT *width,
1461		UINT *height
1462	)
1463	{}
1464#endif
1465
1466#if API >= 11
1467	virtual void STDMETHODCALLTYPE RestoreGalliumState()
1468	{
1469		GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context);
1470	}
1471
1472	virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly()
1473	{
1474		GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context);
1475	}
1476#endif
1477
1478	virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void)
1479	{
1480		return immediate_pipe;
1481	}
1482
1483#undef SYNCHRONIZED
1484};
1485