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