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 /* used to unbind things, we need 128 due to resources */
28 static const void* zero_data[128];
29
30 #define UPDATE_VIEWS_SHIFT (D3D11_STAGES * 0)
31 #define UPDATE_SAMPLERS_SHIFT (D3D11_STAGES * 1)
32 #define UPDATE_VERTEX_BUFFERS (1 << (D3D11_STAGES * 2))
33
34 #if API >= 11
35 template<typename PtrTraits>
36 struct GalliumD3D11DeviceContext :
37 public GalliumD3D11DeviceChild<ID3D11DeviceContext>
38 {
39 #else
40 template<bool threadsafe>
41 struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
42 {
43 typedef simple_ptr_traits PtrTraits;
44 typedef GalliumD3D10Device GalliumD3D10DeviceContext;
45 #endif
46
47 refcnt_ptr<GalliumD3D11Shader<>, PtrTraits> shaders[D3D11_STAGES];
48 refcnt_ptr<GalliumD3D11InputLayout, PtrTraits> input_layout;
49 refcnt_ptr<GalliumD3D11Buffer, PtrTraits> index_buffer;
50 refcnt_ptr<GalliumD3D11RasterizerState, PtrTraits> rasterizer_state;
51 refcnt_ptr<GalliumD3D11DepthStencilState, PtrTraits> depth_stencil_state;
52 refcnt_ptr<GalliumD3D11BlendState, PtrTraits> blend_state;
53 refcnt_ptr<GalliumD3D11DepthStencilView, PtrTraits> depth_stencil_view;
54 refcnt_ptr<GalliumD3D11Predicate, PtrTraits> render_predicate;
55
56 refcnt_ptr<GalliumD3D11Buffer, PtrTraits> constant_buffers[D3D11_STAGES][D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
57 refcnt_ptr<GalliumD3D11ShaderResourceView, PtrTraits> shader_resource_views[D3D11_STAGES][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
58 refcnt_ptr<GalliumD3D11SamplerState, PtrTraits> samplers[D3D11_STAGES][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
59 refcnt_ptr<GalliumD3D11Buffer, PtrTraits> input_buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
60 refcnt_ptr<GalliumD3D11RenderTargetView, PtrTraits> render_target_views[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
61 refcnt_ptr<GalliumD3D11Buffer, PtrTraits> so_buffers[D3D11_SO_BUFFER_SLOT_COUNT];
62
63 #if API >= 11
64 refcnt_ptr<ID3D11UnorderedAccessView, PtrTraits> cs_unordered_access_views[D3D11_PS_CS_UAV_REGISTER_COUNT];
65 refcnt_ptr<ID3D11UnorderedAccessView, PtrTraits> om_unordered_access_views[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
66 #endif
67
68 D3D11_VIEWPORT viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
69 D3D11_RECT scissor_rects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
70 D3D11_PRIMITIVE_TOPOLOGY primitive_topology;
71 DXGI_FORMAT index_format;
72 unsigned index_offset;
73 uint32_t strip_cut_index;
74 BOOL render_predicate_value;
75 float blend_color[4];
76 unsigned sample_mask;
77 unsigned stencil_ref;
78
79 void* default_input_layout;
80 void* default_rasterizer;
81 void* default_depth_stencil;
82 void* default_blend;
83 void* default_sampler;
84 void* default_shaders[D3D11_STAGES];
85
86 // derived state
87 int primitive_mode;
88 struct pipe_vertex_buffer vertex_buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
89 struct pipe_stream_output_target* so_targets[D3D11_SO_BUFFER_SLOT_COUNT];
90 struct pipe_sampler_view* sampler_views[D3D11_STAGES][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
91 void* sampler_csos[D3D11_STAGES][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
92 unsigned num_shader_resource_views[D3D11_STAGES];
93 unsigned num_samplers[D3D11_STAGES];
94 unsigned num_vertex_buffers;
95 unsigned num_render_target_views;
96 unsigned num_viewports;
97 unsigned num_scissor_rects;
98 unsigned num_so_targets;
99
100 struct pipe_context* pipe;
101 unsigned update_flags;
102
103 bool owns_pipe;
104 unsigned context_flags;
105
106 GalliumD3D11Caps caps;
107
108 cso_context* cso_ctx;
109 gen_mipmap_state* gen_mipmap;
110
111 #if API >= 11
112 #define SYNCHRONIZED do {} while(0)
113
114 GalliumD3D11DeviceContext(GalliumD3D11Screen* device, pipe_context* pipe, bool owns_pipe, unsigned context_flags = 0)
115 : GalliumD3D11DeviceChild<ID3D11DeviceContext>(device), pipe(pipe), owns_pipe(owns_pipe), context_flags(context_flags)
116 {
117 caps = device->screen_caps;
118 init_context();
119 }
120
~GalliumD3D11DeviceContextGalliumD3D11DeviceContext121 ~GalliumD3D11DeviceContext()
122 {
123 destroy_context();
124 }
125 #else
126 #define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(this->mutex)
127
GalliumD3D10DeviceGalliumD3D11DeviceContext128 GalliumD3D10Device(pipe_screen* screen, pipe_context* pipe, bool owns_pipe, unsigned creation_flags, IDXGIAdapter* adapter)
129 : GalliumD3D10ScreenImpl<threadsafe>(screen, pipe, owns_pipe, creation_flags, adapter), pipe(pipe), owns_pipe(owns_pipe), context_flags(0)
130 {
131 caps = this->screen_caps;
132 init_context();
133 }
134
~GalliumD3D10DeviceGalliumD3D11DeviceContext135 ~GalliumD3D10Device()
136 {
137 destroy_context();
138 }
139 #endif
140
init_contextGalliumD3D11DeviceContext141 void init_context()
142 {
143 if(!pipe->begin_query)
144 caps.queries = false;
145 if(!pipe->bind_gs_state)
146 {
147 caps.gs = false;
148 caps.stages = 2;
149 }
150 assert(!caps.so || pipe->set_stream_output_targets);
151 if(!pipe->set_geometry_sampler_views)
152 caps.stages_with_sampling &=~ (1 << PIPE_SHADER_GEOMETRY);
153 if(!pipe->set_fragment_sampler_views)
154 caps.stages_with_sampling &=~ (1 << PIPE_SHADER_FRAGMENT);
155 if(!pipe->set_vertex_sampler_views)
156 caps.stages_with_sampling &=~ (1 << PIPE_SHADER_VERTEX);
157
158 update_flags = 0;
159
160 // pipeline state
161 memset(viewports, 0, sizeof(viewports));
162 memset(scissor_rects, 0, sizeof(scissor_rects));
163 primitive_topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
164 index_format = DXGI_FORMAT_UNKNOWN;
165 index_offset = 0;
166 strip_cut_index = 0xffffffff;
167 render_predicate_value = 0;
168 memset(blend_color, 0, sizeof(blend_color));
169 sample_mask = ~0;
170 stencil_ref = 0;
171
172 // derived state
173 primitive_mode = 0;
174 memset(vertex_buffers, 0, sizeof(vertex_buffers));
175 memset(so_targets, 0, sizeof(so_buffers));
176 memset(sampler_views, 0, sizeof(sampler_views));
177 memset(sampler_csos, 0, sizeof(sampler_csos));
178 memset(num_shader_resource_views, 0, sizeof(num_shader_resource_views));
179 memset(num_samplers, 0, sizeof(num_samplers));
180 num_vertex_buffers = 0;
181 num_render_target_views = 0;
182 num_viewports = 0;
183 num_scissor_rects = 0;
184 num_so_targets = 0;
185
186 default_input_layout = pipe->create_vertex_elements_state(pipe, 0, 0);
187
188 struct pipe_rasterizer_state rasterizerd;
189 memset(&rasterizerd, 0, sizeof(rasterizerd));
190 rasterizerd.gl_rasterization_rules = 1;
191 rasterizerd.cull_face = PIPE_FACE_BACK;
192 rasterizerd.flatshade_first = 1;
193 rasterizerd.line_width = 1.0f;
194 rasterizerd.point_size = 1.0f;
195 rasterizerd.depth_clip = TRUE;
196 default_rasterizer = pipe->create_rasterizer_state(pipe, &rasterizerd);
197
198 struct pipe_depth_stencil_alpha_state depth_stencild;
199 memset(&depth_stencild, 0, sizeof(depth_stencild));
200 depth_stencild.depth.enabled = TRUE;
201 depth_stencild.depth.writemask = 1;
202 depth_stencild.depth.func = PIPE_FUNC_LESS;
203 default_depth_stencil = pipe->create_depth_stencil_alpha_state(pipe, &depth_stencild);
204
205 struct pipe_blend_state blendd;
206 memset(&blendd, 0, sizeof(blendd));
207 blendd.rt[0].colormask = 0xf;
208 default_blend = pipe->create_blend_state(pipe, &blendd);
209
210 struct pipe_sampler_state samplerd;
211 memset(&samplerd, 0, sizeof(samplerd));
212 samplerd.normalized_coords = 1;
213 samplerd.min_img_filter = PIPE_TEX_FILTER_LINEAR;
214 samplerd.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
215 samplerd.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
216 samplerd.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
217 samplerd.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
218 samplerd.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
219 samplerd.border_color.f[0] = 1.0f;
220 samplerd.border_color.f[1] = 1.0f;
221 samplerd.border_color.f[2] = 1.0f;
222 samplerd.border_color.f[3] = 1.0f;
223 samplerd.min_lod = -FLT_MAX;
224 samplerd.max_lod = FLT_MAX;
225 samplerd.max_anisotropy = 1;
226 default_sampler = pipe->create_sampler_state(pipe, &samplerd);
227
228 memset(&samplerd, 0, sizeof(samplerd));
229 samplerd.normalized_coords = 0;
230 samplerd.min_img_filter = PIPE_TEX_FILTER_NEAREST;
231 samplerd.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
232 samplerd.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
233 samplerd.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
234 samplerd.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
235 samplerd.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
236 samplerd.min_lod = -FLT_MAX;
237 samplerd.max_lod = FLT_MAX;
238 samplerd.max_anisotropy = 1;
239
240 for(unsigned s = 0; s < D3D11_STAGES; ++s)
241 for(unsigned i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i)
242 sampler_csos[s][i] = default_sampler;
243
244 // TODO: should this really be empty shaders, or should they be all-passthrough?
245 memset(default_shaders, 0, sizeof(default_shaders));
246 struct ureg_program *ureg;
247 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
248 ureg_END(ureg);
249 default_shaders[PIPE_SHADER_FRAGMENT] = ureg_create_shader_and_destroy(ureg, pipe);
250
251 ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
252 ureg_END(ureg);
253 default_shaders[PIPE_SHADER_VERTEX] = ureg_create_shader_and_destroy(ureg, pipe);
254
255 cso_ctx = cso_create_context(pipe);
256 gen_mipmap = util_create_gen_mipmap(pipe, cso_ctx);
257
258 RestoreGalliumState();
259 }
260
destroy_contextGalliumD3D11DeviceContext261 void destroy_context()
262 {
263 util_destroy_gen_mipmap(gen_mipmap);
264 cso_destroy_context(cso_ctx);
265
266 pipe->bind_vertex_elements_state(pipe, 0);
267 pipe->delete_vertex_elements_state(pipe, default_input_layout);
268
269 pipe->bind_rasterizer_state(pipe, 0);
270 pipe->delete_rasterizer_state(pipe, default_rasterizer);
271
272 pipe->bind_depth_stencil_alpha_state(pipe, 0);
273 pipe->delete_depth_stencil_alpha_state(pipe, default_depth_stencil);
274
275 pipe->bind_blend_state(pipe, 0);
276 pipe->delete_blend_state(pipe, default_blend);
277
278 pipe->bind_fragment_sampler_states(pipe, 0, 0);
279 pipe->bind_vertex_sampler_states(pipe, 0, 0);
280 if(pipe->bind_geometry_sampler_states)
281 pipe->bind_geometry_sampler_states(pipe, 0, 0);
282 pipe->delete_sampler_state(pipe, default_sampler);
283
284 pipe->bind_fs_state(pipe, 0);
285 pipe->delete_fs_state(pipe, default_shaders[PIPE_SHADER_FRAGMENT]);
286
287 pipe->bind_vs_state(pipe, 0);
288 pipe->delete_vs_state(pipe, default_shaders[PIPE_SHADER_VERTEX]);
289
290 if(owns_pipe)
291 pipe->destroy(pipe);
292 }
293
GetContextFlagsGalliumD3D11DeviceContext294 virtual unsigned STDMETHODCALLTYPE GetContextFlags(void)
295 {
296 return context_flags;
297 }
298 #if API >= 11
299 #define SET_SHADER_EXTRA_ARGS , \
300 ID3D11ClassInstance *const *ppClassInstances, \
301 unsigned count
302 #define GET_SHADER_EXTRA_ARGS , \
303 ID3D11ClassInstance **ppClassInstances, \
304 unsigned *out_count
305 #else
306 #define SET_SHADER_EXTRA_ARGS
307 #define GET_SHADER_EXTRA_ARGS
308 #endif
309
310 /* On Windows D3D11, SetConstantBuffers and SetShaderResources crash if passed a null pointer.
311 * Instead, you have to pass a pointer to nulls to unbind things.
312 * We do the same.
313 * TODO: is D3D10 the same?
314 */
315 template<unsigned s>
xs_set_shaderGalliumD3D11DeviceContext316 void xs_set_shader(GalliumD3D11Shader<>* shader)
317 {
318 if(shader != shaders[s].p)
319 {
320 shaders[s] = shader;
321 void* shader_cso = shader ? shader->object : default_shaders[s];
322 switch(s)
323 {
324 case PIPE_SHADER_VERTEX:
325 pipe->bind_vs_state(pipe, shader_cso);
326 break;
327 case PIPE_SHADER_FRAGMENT:
328 pipe->bind_fs_state(pipe, shader_cso);
329 break;
330 case PIPE_SHADER_GEOMETRY:
331 pipe->bind_gs_state(pipe, shader_cso);
332 break;
333 }
334 update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + s)) | (1 << (UPDATE_VIEWS_SHIFT + s));
335 }
336 }
337
338 template<unsigned s>
xs_set_constant_buffersGalliumD3D11DeviceContext339 void xs_set_constant_buffers(unsigned start, unsigned count, GalliumD3D11Buffer *const *constbufs)
340 {
341 for(unsigned i = 0; i < count; ++i)
342 {
343 if(constbufs[i] != constant_buffers[s][start + i].p)
344 {
345 constant_buffers[s][start + i] = constbufs[i];
346 if(s < caps.stages && start + i < caps.constant_buffers[s])
347 pipe_set_constant_buffer(pipe, s, start + i, constbufs[i] ? constbufs[i]->resource : NULL);
348 }
349 }
350 }
351
352 template<unsigned s>
xs_set_shader_resourcesGalliumD3D11DeviceContext353 void xs_set_shader_resources(unsigned start, unsigned count, GalliumD3D11ShaderResourceView *const *srvs)
354 {
355 int last_different = -1;
356 for(unsigned i = 0; i < count; ++i)
357 {
358 if(shader_resource_views[s][start + i].p != srvs[i])
359 {
360 shader_resource_views[s][start + i] = srvs[i];
361 sampler_views[s][start + i] = srvs[i] ? srvs[i]->object : 0;
362 last_different = i;
363 }
364 }
365 if(last_different >= 0)
366 {
367 num_shader_resource_views[s] = std::max(num_shader_resource_views[s], start + last_different + 1);
368 update_flags |= 1 << (UPDATE_VIEWS_SHIFT + s);
369 }
370 }
371
372 template<unsigned s>
xs_set_samplersGalliumD3D11DeviceContext373 void xs_set_samplers(unsigned start, unsigned count, GalliumD3D11SamplerState *const *samps)
374 {
375 int last_different = -1;
376 for(unsigned i = 0; i < count; ++i)
377 {
378 if(samplers[s][start + i].p != samps[i])
379 {
380 samplers[s][start + i] = samps[i];
381 sampler_csos[s][start + i] = samps[i] ? samps[i]->object : default_sampler;
382 last_different = i;
383 }
384 }
385 if(last_different >= 0)
386 {
387 num_samplers[s] = std::max(num_samplers[s], start + last_different + 1);
388 update_flags |= 1 << (UPDATE_SAMPLERS_SHIFT + s);
389 }
390 }
391
392 #define IMPLEMENT_SHADER_STAGE(XS, Stage) \
393 virtual void STDMETHODCALLTYPE XS##SetShader( \
394 ID3D11##Stage##Shader *pShader \
395 SET_SHADER_EXTRA_ARGS) \
396 { \
397 SYNCHRONIZED; \
398 xs_set_shader<D3D11_STAGE_##XS>((GalliumD3D11Shader<>*)pShader); \
399 } \
400 virtual void STDMETHODCALLTYPE XS##GetShader(\
401 ID3D11##Stage##Shader **ppShader \
402 GET_SHADER_EXTRA_ARGS) \
403 { \
404 SYNCHRONIZED; \
405 *ppShader = (ID3D11##Stage##Shader*)shaders[D3D11_STAGE_##XS].ref(); \
406 } \
407 virtual void STDMETHODCALLTYPE XS##SetConstantBuffers(\
408 unsigned start, \
409 unsigned count, \
410 ID3D11Buffer *const* constant_buffers) \
411 { \
412 SYNCHRONIZED; \
413 xs_set_constant_buffers<D3D11_STAGE_##XS>(start, count, (GalliumD3D11Buffer *const *)constant_buffers); \
414 } \
415 virtual void STDMETHODCALLTYPE XS##GetConstantBuffers(\
416 unsigned start, \
417 unsigned count, \
418 ID3D11Buffer **out_constant_buffers) \
419 { \
420 SYNCHRONIZED; \
421 for(unsigned i = 0; i < count; ++i) \
422 out_constant_buffers[i] = constant_buffers[D3D11_STAGE_##XS][start + i].ref(); \
423 } \
424 virtual void STDMETHODCALLTYPE XS##SetShaderResources(\
425 unsigned start, \
426 unsigned count, \
427 ID3D11ShaderResourceView *const *new_shader_resource_views) \
428 { \
429 SYNCHRONIZED; \
430 xs_set_shader_resources<D3D11_STAGE_##XS>(start, count, (GalliumD3D11ShaderResourceView *const *)new_shader_resource_views); \
431 } \
432 virtual void STDMETHODCALLTYPE XS##GetShaderResources(\
433 unsigned start, \
434 unsigned count, \
435 ID3D11ShaderResourceView **out_shader_resource_views) \
436 { \
437 SYNCHRONIZED; \
438 for(unsigned i = 0; i < count; ++i) \
439 out_shader_resource_views[i] = shader_resource_views[D3D11_STAGE_##XS][start + i].ref(); \
440 } \
441 virtual void STDMETHODCALLTYPE XS##SetSamplers(\
442 unsigned start, \
443 unsigned count, \
444 ID3D11SamplerState *const *new_samplers) \
445 { \
446 SYNCHRONIZED; \
447 xs_set_samplers<D3D11_STAGE_##XS>(start, count, (GalliumD3D11SamplerState *const *)new_samplers); \
448 } \
449 virtual void STDMETHODCALLTYPE XS##GetSamplers( \
450 unsigned start, \
451 unsigned count, \
452 ID3D11SamplerState **out_samplers) \
453 { \
454 SYNCHRONIZED; \
455 for(unsigned i = 0; i < count; ++i) \
456 out_samplers[i] = samplers[D3D11_STAGE_##XS][start + i].ref(); \
457 }
458
459 #define DO_VS(x) x
460 #define DO_GS(x) do {if(caps.gs) {x;}} while(0)
461 #define DO_PS(x) x
462 #define DO_HS(x)
463 #define DO_DS(x)
464 #define DO_CS(x)
IMPLEMENT_SHADER_STAGEGalliumD3D11DeviceContext465 IMPLEMENT_SHADER_STAGE(VS, Vertex)
466 IMPLEMENT_SHADER_STAGE(GS, Geometry)
467 IMPLEMENT_SHADER_STAGE(PS, Pixel)
468
469 #if API >= 11
470 IMPLEMENT_SHADER_STAGE(HS, Hull)
471 IMPLEMENT_SHADER_STAGE(DS, Domain)
472 IMPLEMENT_SHADER_STAGE(CS, Compute)
473
474 virtual void STDMETHODCALLTYPE CSSetUnorderedAccessViews(
475 unsigned start,
476 unsigned count,
477 ID3D11UnorderedAccessView *const *new_unordered_access_views,
478 const unsigned *new_uav_initial_counts)
479 {
480 SYNCHRONIZED;
481 for(unsigned i = 0; i < count; ++i)
482 cs_unordered_access_views[start + i] = new_unordered_access_views[i];
483 }
484
CSGetUnorderedAccessViewsGalliumD3D11DeviceContext485 virtual void STDMETHODCALLTYPE CSGetUnorderedAccessViews(
486 unsigned start,
487 unsigned count,
488 ID3D11UnorderedAccessView **out_unordered_access_views)
489 {
490 SYNCHRONIZED;
491 for(unsigned i = 0; i < count; ++i)
492 out_unordered_access_views[i] = cs_unordered_access_views[start + i].ref();
493 }
494 #endif
495
496 template<unsigned s>
update_stageGalliumD3D11DeviceContext497 void update_stage()
498 {
499 if(update_flags & (1 << (UPDATE_VIEWS_SHIFT + s)))
500 {
501 while(num_shader_resource_views[s] && !sampler_views[s][num_shader_resource_views[s] - 1]) \
502 --num_shader_resource_views[s];
503 if((1 << s) & caps.stages_with_sampling)
504 {
505 const unsigned num_views_to_bind = num_shader_resource_views[s];
506 switch(s)
507 {
508 case PIPE_SHADER_VERTEX:
509 pipe->set_vertex_sampler_views(pipe, num_views_to_bind, sampler_views[s]);
510 break;
511 case PIPE_SHADER_FRAGMENT:
512 pipe->set_fragment_sampler_views(pipe, num_views_to_bind, sampler_views[s]);
513 break;
514 case PIPE_SHADER_GEOMETRY:
515 pipe->set_geometry_sampler_views(pipe, num_views_to_bind, sampler_views[s]);
516 break;
517 }
518 }
519 }
520
521 if(update_flags & (1 << (UPDATE_SAMPLERS_SHIFT + s)))
522 {
523 while(num_samplers[s] && !sampler_csos[s][num_samplers[s] - 1])
524 --num_samplers[s];
525 if((1 << s) & caps.stages_with_sampling)
526 {
527 const unsigned num_samplers_to_bind = num_samplers[s];
528 switch(s)
529 {
530 case PIPE_SHADER_VERTEX:
531 pipe->bind_vertex_sampler_states(pipe, num_samplers_to_bind, sampler_csos[s]);
532 break;
533 case PIPE_SHADER_FRAGMENT:
534 pipe->bind_fragment_sampler_states(pipe, num_samplers_to_bind, sampler_csos[s]);
535 break;
536 case PIPE_SHADER_GEOMETRY:
537 pipe->bind_geometry_sampler_states(pipe, num_samplers_to_bind, sampler_csos[s]);
538 break;
539 }
540 }
541 }
542 }
543
update_stateGalliumD3D11DeviceContext544 void update_state()
545 {
546 update_stage<D3D11_STAGE_PS>();
547 update_stage<D3D11_STAGE_VS>();
548 update_stage<D3D11_STAGE_GS>();
549 #if API >= 11
550 update_stage<D3D11_STAGE_HS>();
551 update_stage<D3D11_STAGE_DS>();
552 update_stage<D3D11_STAGE_CS>();
553 #endif
554
555 if(update_flags & UPDATE_VERTEX_BUFFERS)
556 {
557 while(num_vertex_buffers && !vertex_buffers[num_vertex_buffers - 1].buffer)
558 --num_vertex_buffers;
559 pipe->set_vertex_buffers(pipe, num_vertex_buffers, vertex_buffers);
560 }
561
562 update_flags = 0;
563 }
564
IASetInputLayoutGalliumD3D11DeviceContext565 virtual void STDMETHODCALLTYPE IASetInputLayout(
566 ID3D11InputLayout *new_input_layout)
567 {
568 SYNCHRONIZED;
569 if(new_input_layout != input_layout.p)
570 {
571 input_layout = new_input_layout;
572 pipe->bind_vertex_elements_state(pipe, new_input_layout ? ((GalliumD3D11InputLayout*)new_input_layout)->object : default_input_layout);
573 }
574 }
575
IAGetInputLayoutGalliumD3D11DeviceContext576 virtual void STDMETHODCALLTYPE IAGetInputLayout(
577 ID3D11InputLayout **out_input_layout)
578 {
579 SYNCHRONIZED;
580 *out_input_layout = input_layout.ref();
581 }
582
IASetVertexBuffersGalliumD3D11DeviceContext583 virtual void STDMETHODCALLTYPE IASetVertexBuffers(
584 unsigned start,
585 unsigned count,
586 ID3D11Buffer *const *new_vertex_buffers,
587 const unsigned *new_strides,
588 const unsigned *new_offsets)
589 {
590 SYNCHRONIZED;
591 int last_different = -1;
592 for(unsigned i = 0; i < count; ++i)
593 {
594 ID3D11Buffer* buffer = new_vertex_buffers[i];
595 if(buffer != input_buffers[start + i].p
596 || vertex_buffers[start + i].buffer_offset != new_offsets[i]
597 || vertex_buffers[start + i].stride != new_strides[i]
598 )
599 {
600 input_buffers[start + i] = buffer;
601 vertex_buffers[start + i].buffer = buffer ? ((GalliumD3D11Buffer*)buffer)->resource : 0;
602 vertex_buffers[start + i].buffer_offset = new_offsets[i];
603 vertex_buffers[start + i].stride = new_strides[i];
604 last_different = i;
605 }
606 }
607 if(last_different >= 0)
608 {
609 num_vertex_buffers = std::max(num_vertex_buffers, start + count);
610 update_flags |= UPDATE_VERTEX_BUFFERS;
611 }
612 }
613
IAGetVertexBuffersGalliumD3D11DeviceContext614 virtual void STDMETHODCALLTYPE IAGetVertexBuffers(
615 unsigned start,
616 unsigned count,
617 ID3D11Buffer **out_vertex_buffers,
618 unsigned *out_strides,
619 unsigned *out_offsets)
620 {
621 SYNCHRONIZED;
622 if(out_vertex_buffers)
623 {
624 for(unsigned i = 0; i < count; ++i)
625 out_vertex_buffers[i] = input_buffers[start + i].ref();
626 }
627
628 if(out_offsets)
629 {
630 for(unsigned i = 0; i < count; ++i)
631 out_offsets[i] = vertex_buffers[start + i].buffer_offset;
632 }
633
634 if(out_strides)
635 {
636 for(unsigned i = 0; i < count; ++i)
637 out_strides[i] = vertex_buffers[start + i].stride;
638 }
639 }
640
set_index_bufferGalliumD3D11DeviceContext641 void set_index_buffer()
642 {
643 pipe_index_buffer ib;
644 if(!index_buffer)
645 {
646 memset(&ib, 0, sizeof(ib));
647 }
648 else
649 {
650 switch(index_format) {
651 case DXGI_FORMAT_R32_UINT:
652 ib.index_size = 4;
653 strip_cut_index = 0xffffffff;
654 break;
655 case DXGI_FORMAT_R16_UINT:
656 ib.index_size = 2;
657 strip_cut_index = 0xffff;
658 break;
659 default:
660 ib.index_size = 1;
661 strip_cut_index = 0xff;
662 break;
663 }
664 ib.offset = index_offset;
665 ib.buffer = index_buffer ? ((GalliumD3D11Buffer*)index_buffer.p)->resource : 0;
666 }
667 pipe->set_index_buffer(pipe, &ib);
668 }
669
IASetIndexBufferGalliumD3D11DeviceContext670 virtual void STDMETHODCALLTYPE IASetIndexBuffer(
671 ID3D11Buffer *new_index_buffer,
672 DXGI_FORMAT new_index_format,
673 unsigned new_index_offset)
674 {
675 SYNCHRONIZED;
676 if(index_buffer.p != new_index_buffer || index_format != new_index_format || index_offset != new_index_offset)
677 {
678 index_buffer = new_index_buffer;
679 index_format = new_index_format;
680 index_offset = new_index_offset;
681
682 set_index_buffer();
683 }
684 }
685
IAGetIndexBufferGalliumD3D11DeviceContext686 virtual void STDMETHODCALLTYPE IAGetIndexBuffer(
687 ID3D11Buffer **out_index_buffer,
688 DXGI_FORMAT *out_index_format,
689 unsigned *out_index_offset)
690 {
691 SYNCHRONIZED;
692 if(out_index_buffer)
693 *out_index_buffer = index_buffer.ref();
694 if(out_index_format)
695 *out_index_format = index_format;
696 if(out_index_offset)
697 *out_index_offset = index_offset;
698 }
699
IASetPrimitiveTopologyGalliumD3D11DeviceContext700 virtual void STDMETHODCALLTYPE IASetPrimitiveTopology(
701 D3D11_PRIMITIVE_TOPOLOGY new_primitive_topology)
702 {
703 SYNCHRONIZED;
704 if(primitive_topology != new_primitive_topology)
705 {
706 if(new_primitive_topology < D3D_PRIMITIVE_TOPOLOGY_COUNT)
707 primitive_mode = d3d_to_pipe_prim[new_primitive_topology];
708 else
709 primitive_mode = 0;
710 primitive_topology = new_primitive_topology;
711 }
712 }
713
IAGetPrimitiveTopologyGalliumD3D11DeviceContext714 virtual void STDMETHODCALLTYPE IAGetPrimitiveTopology(
715 D3D11_PRIMITIVE_TOPOLOGY *out_primitive_topology)
716 {
717 SYNCHRONIZED;
718 *out_primitive_topology = primitive_topology;
719 }
720
DrawIndexedGalliumD3D11DeviceContext721 virtual void STDMETHODCALLTYPE DrawIndexed(
722 unsigned index_count,
723 unsigned start_index_location,
724 int base_vertex_location)
725 {
726 SYNCHRONIZED;
727 if(update_flags)
728 update_state();
729
730 pipe_draw_info info;
731 info.mode = primitive_mode;
732 info.indexed = TRUE;
733 info.count = index_count;
734 info.start = start_index_location;
735 info.index_bias = base_vertex_location;
736 info.min_index = 0;
737 info.max_index = ~0;
738 info.start_instance = 0;
739 info.instance_count = 1;
740 info.primitive_restart = TRUE;
741 info.restart_index = strip_cut_index;
742 info.count_from_stream_output = NULL;
743
744 pipe->draw_vbo(pipe, &info);
745 }
746
DrawGalliumD3D11DeviceContext747 virtual void STDMETHODCALLTYPE Draw(
748 unsigned vertex_count,
749 unsigned start_vertex_location)
750 {
751 SYNCHRONIZED;
752 if(update_flags)
753 update_state();
754
755 pipe_draw_info info;
756 info.mode = primitive_mode;
757 info.indexed = FALSE;
758 info.count = vertex_count;
759 info.start = start_vertex_location;
760 info.index_bias = 0;
761 info.min_index = 0;
762 info.max_index = ~0;
763 info.start_instance = 0;
764 info.instance_count = 1;
765 info.primitive_restart = FALSE;
766 info.count_from_stream_output = NULL;
767
768 pipe->draw_vbo(pipe, &info);
769 }
770
DrawIndexedInstancedGalliumD3D11DeviceContext771 virtual void STDMETHODCALLTYPE DrawIndexedInstanced(
772 unsigned index_countPerInstance,
773 unsigned instance_count,
774 unsigned start_index_location,
775 int base_vertex_location,
776 unsigned start_instance_location)
777 {
778 SYNCHRONIZED;
779 if(update_flags)
780 update_state();
781
782 pipe_draw_info info;
783 info.mode = primitive_mode;
784 info.indexed = TRUE;
785 info.count = index_countPerInstance;
786 info.start = start_index_location;
787 info.index_bias = base_vertex_location;
788 info.min_index = 0;
789 info.max_index = ~0;
790 info.start_instance = start_instance_location;
791 info.instance_count = instance_count;
792 info.primitive_restart = TRUE;
793 info.restart_index = strip_cut_index;
794 info.count_from_stream_output = NULL;
795
796 pipe->draw_vbo(pipe, &info);
797 }
798
DrawInstancedGalliumD3D11DeviceContext799 virtual void STDMETHODCALLTYPE DrawInstanced(
800 unsigned vertex_countPerInstance,
801 unsigned instance_count,
802 unsigned start_vertex_location,
803 unsigned start_instance_location)
804 {
805 SYNCHRONIZED;
806 if(update_flags)
807 update_state();
808
809 pipe_draw_info info;
810 info.mode = primitive_mode;
811 info.indexed = FALSE;
812 info.count = vertex_countPerInstance;
813 info.start = start_vertex_location;
814 info.index_bias = 0;
815 info.min_index = 0;
816 info.max_index = ~0;
817 info.start_instance = start_instance_location;
818 info.instance_count = instance_count;
819 info.primitive_restart = FALSE;
820 info.count_from_stream_output = NULL;
821
822 pipe->draw_vbo(pipe, &info);
823 }
824
DrawAutoGalliumD3D11DeviceContext825 virtual void STDMETHODCALLTYPE DrawAuto(void)
826 {
827 if(!caps.so)
828 return;
829
830 SYNCHRONIZED;
831 if(update_flags)
832 update_state();
833
834 pipe_draw_info info;
835 info.mode = primitive_mode;
836 info.indexed = FALSE;
837 info.count = 0;
838 info.start = 0;
839 info.index_bias = 0;
840 info.min_index = 0;
841 info.max_index = ~0;
842 info.start_instance = 0;
843 info.instance_count = 1;
844 info.primitive_restart = FALSE;
845 info.restart_index = 0;
846 info.count_from_stream_output = input_buffers[0].p->so_target;
847
848 pipe->draw_vbo(pipe, &info);
849 }
850
DrawIndexedInstancedIndirectGalliumD3D11DeviceContext851 virtual void STDMETHODCALLTYPE DrawIndexedInstancedIndirect(
852 ID3D11Buffer *buffer,
853 unsigned aligned_byte_offset)
854 {
855 SYNCHRONIZED;
856 if(update_flags)
857 update_state();
858
859 struct {
860 unsigned count;
861 unsigned instance_count;
862 unsigned start;
863 unsigned index_bias;
864 } data;
865
866 pipe_buffer_read(pipe, ((GalliumD3D11Buffer*)buffer)->resource, aligned_byte_offset, sizeof(data), &data);
867
868 pipe_draw_info info;
869 info.mode = primitive_mode;
870 info.indexed = TRUE;
871 info.start = data.start;
872 info.count = data.count;
873 info.index_bias = data.index_bias;
874 info.min_index = 0;
875 info.max_index = ~0;
876 info.start_instance = 0;
877 info.instance_count = data.instance_count;
878 info.primitive_restart = TRUE;
879 info.restart_index = strip_cut_index;
880 info.count_from_stream_output = NULL;
881
882 pipe->draw_vbo(pipe, &info);
883 }
884
DrawInstancedIndirectGalliumD3D11DeviceContext885 virtual void STDMETHODCALLTYPE DrawInstancedIndirect(
886 ID3D11Buffer *buffer,
887 unsigned aligned_byte_offset)
888 {
889 SYNCHRONIZED;
890 if(update_flags)
891 update_state();
892
893 struct {
894 unsigned count;
895 unsigned instance_count;
896 unsigned start;
897 } data;
898
899 pipe_buffer_read(pipe, ((GalliumD3D11Buffer*)buffer)->resource, aligned_byte_offset, sizeof(data), &data);
900
901 pipe_draw_info info;
902 info.mode = primitive_mode;
903 info.indexed = FALSE;
904 info.start = data.start;
905 info.count = data.count;
906 info.index_bias = 0;
907 info.min_index = 0;
908 info.max_index = ~0;
909 info.start_instance = 0;
910 info.instance_count = data.instance_count;
911 info.primitive_restart = FALSE;
912 info.count_from_stream_output = NULL;
913
914 pipe->draw_vbo(pipe, &info);
915 }
916
917 #if API >= 11
DispatchGalliumD3D11DeviceContext918 virtual void STDMETHODCALLTYPE Dispatch(
919 unsigned thread_group_count_x,
920 unsigned thread_group_count_y,
921 unsigned thread_group_count_z)
922 {
923 // uncomment this when this is implemented
924 // SYNCHRONIZED;
925 // if(update_flags)
926 // update_state();
927 }
928
DispatchIndirectGalliumD3D11DeviceContext929 virtual void STDMETHODCALLTYPE DispatchIndirect(
930 ID3D11Buffer *buffer,
931 unsigned aligned_byte_offset)
932 {
933 // uncomment this when this is implemented
934 // SYNCHRONIZED;
935 // if(update_flags)
936 // update_state();
937 }
938 #endif
939
RSSetStateGalliumD3D11DeviceContext940 virtual void STDMETHODCALLTYPE RSSetState(
941 ID3D11RasterizerState *new_rasterizer_state)
942 {
943 SYNCHRONIZED;
944 if(new_rasterizer_state != rasterizer_state.p)
945 {
946 rasterizer_state = new_rasterizer_state;
947 pipe->bind_rasterizer_state(pipe, new_rasterizer_state ? ((GalliumD3D11RasterizerState*)new_rasterizer_state)->object : default_rasterizer);
948 }
949 }
950
RSGetStateGalliumD3D11DeviceContext951 virtual void STDMETHODCALLTYPE RSGetState(
952 ID3D11RasterizerState **out_rasterizer_state)
953 {
954 SYNCHRONIZED;
955 *out_rasterizer_state = rasterizer_state.ref();
956 }
957
set_viewportGalliumD3D11DeviceContext958 void set_viewport()
959 {
960 // TODO: is depth correct? it seems D3D10/11 uses a [-1,1]x[-1,1]x[0,1] cube
961 pipe_viewport_state viewport;
962 float half_width = viewports[0].Width * 0.5f;
963 float half_height = viewports[0].Height * 0.5f;
964
965 viewport.scale[0] = half_width;
966 viewport.scale[1] = -half_height;
967 viewport.scale[2] = (viewports[0].MaxDepth - viewports[0].MinDepth);
968 viewport.scale[3] = 1.0f;
969 viewport.translate[0] = half_width + viewports[0].TopLeftX;
970 viewport.translate[1] = half_height + viewports[0].TopLeftY;
971 viewport.translate[2] = viewports[0].MinDepth;
972 viewport.translate[3] = 1.0f;
973 pipe->set_viewport_state(pipe, &viewport);
974 }
975
RSSetViewportsGalliumD3D11DeviceContext976 virtual void STDMETHODCALLTYPE RSSetViewports(
977 unsigned count,
978 const D3D11_VIEWPORT *new_viewports)
979 {
980 SYNCHRONIZED;
981 if(count)
982 {
983 if(memcmp(&viewports[0], &new_viewports[0], sizeof(viewports[0])))
984 {
985 viewports[0] = new_viewports[0];
986 set_viewport();
987 }
988 for(unsigned i = 1; i < count; ++i)
989 viewports[i] = new_viewports[i];
990 }
991 else if(num_viewports)
992 {
993 // TODO: what should we do here?
994 memset(&viewports[0], 0, sizeof(viewports[0]));
995 set_viewport();
996 }
997 num_viewports = count;
998 }
999
RSGetViewportsGalliumD3D11DeviceContext1000 virtual void STDMETHODCALLTYPE RSGetViewports(
1001 unsigned *out_count,
1002 D3D11_VIEWPORT *out_viewports)
1003 {
1004 SYNCHRONIZED;
1005 if(out_viewports)
1006 {
1007 unsigned i;
1008 for(i = 0; i < std::min(*out_count, num_viewports); ++i)
1009 out_viewports[i] = viewports[i];
1010
1011 memset(out_viewports + i, 0, (*out_count - i) * sizeof(D3D11_VIEWPORT));
1012 }
1013
1014 *out_count = num_viewports;
1015 }
1016
set_scissorGalliumD3D11DeviceContext1017 void set_scissor()
1018 {
1019 pipe_scissor_state scissor;
1020 scissor.minx = scissor_rects[0].left;
1021 scissor.miny = scissor_rects[0].top;
1022 scissor.maxx = scissor_rects[0].right;
1023 scissor.maxy = scissor_rects[0].bottom;
1024 pipe->set_scissor_state(pipe, &scissor);
1025 }
1026
RSSetScissorRectsGalliumD3D11DeviceContext1027 virtual void STDMETHODCALLTYPE RSSetScissorRects(
1028 unsigned count,
1029 const D3D11_RECT *new_rects)
1030 {
1031 SYNCHRONIZED;
1032 if(count)
1033 {
1034 if(memcmp(&scissor_rects[0], &new_rects[0], sizeof(scissor_rects[0])))
1035 {
1036 scissor_rects[0] = new_rects[0];
1037 set_scissor();
1038 }
1039 for(unsigned i = 1; i < count; ++i)
1040 scissor_rects[i] = new_rects[i];
1041 }
1042 else if(num_scissor_rects)
1043 {
1044 // TODO: what should we do here?
1045 memset(&scissor_rects[0], 0, sizeof(scissor_rects[0]));
1046 set_scissor();
1047 }
1048
1049 num_scissor_rects = count;
1050 }
1051
RSGetScissorRectsGalliumD3D11DeviceContext1052 virtual void STDMETHODCALLTYPE RSGetScissorRects(
1053 unsigned *out_count,
1054 D3D11_RECT *out_rects)
1055 {
1056 SYNCHRONIZED;
1057 if(out_rects)
1058 {
1059 unsigned i;
1060 for(i = 0; i < std::min(*out_count, num_scissor_rects); ++i)
1061 out_rects[i] = scissor_rects[i];
1062
1063 memset(out_rects + i, 0, (*out_count - i) * sizeof(D3D11_RECT));
1064 }
1065
1066 *out_count = num_scissor_rects;
1067 }
1068
OMSetBlendStateGalliumD3D11DeviceContext1069 virtual void STDMETHODCALLTYPE OMSetBlendState(
1070 ID3D11BlendState *new_blend_state,
1071 const float new_blend_factor[4],
1072 unsigned new_sample_mask)
1073 {
1074 SYNCHRONIZED;
1075 float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1076
1077 if(blend_state.p != new_blend_state)
1078 {
1079 pipe->bind_blend_state(pipe, new_blend_state ? ((GalliumD3D11BlendState*)new_blend_state)->object : default_blend);
1080 blend_state = new_blend_state;
1081 }
1082
1083 // Windows D3D11 does this, even though it's apparently undocumented
1084 if(!new_blend_factor)
1085 new_blend_factor = white;
1086
1087 if(memcmp(blend_color, new_blend_factor, sizeof(blend_color)))
1088 {
1089 pipe->set_blend_color(pipe, (struct pipe_blend_color*)new_blend_factor);
1090 memcpy(blend_color, new_blend_factor, sizeof(blend_color));
1091 }
1092
1093 if(sample_mask != new_sample_mask)
1094 {
1095 pipe->set_sample_mask(pipe, new_sample_mask);
1096 sample_mask = new_sample_mask;
1097 }
1098 }
1099
OMGetBlendStateGalliumD3D11DeviceContext1100 virtual void STDMETHODCALLTYPE OMGetBlendState(
1101 ID3D11BlendState **out_blend_state,
1102 float out_blend_factor[4],
1103 unsigned *out_sample_mask)
1104 {
1105 SYNCHRONIZED;
1106 if(out_blend_state)
1107 *out_blend_state = blend_state.ref();
1108 if(out_blend_factor)
1109 memcpy(out_blend_factor, blend_color, sizeof(blend_color));
1110 if(out_sample_mask)
1111 *out_sample_mask = sample_mask;
1112 }
1113
set_stencil_refGalliumD3D11DeviceContext1114 void set_stencil_ref()
1115 {
1116 struct pipe_stencil_ref sref;
1117 sref.ref_value[0] = stencil_ref;
1118 sref.ref_value[1] = stencil_ref;
1119 pipe->set_stencil_ref(pipe, &sref);
1120 }
1121
OMSetDepthStencilStateGalliumD3D11DeviceContext1122 virtual void STDMETHODCALLTYPE OMSetDepthStencilState(
1123 ID3D11DepthStencilState *new_depth_stencil_state,
1124 unsigned new_stencil_ref)
1125 {
1126 SYNCHRONIZED;
1127 if(new_depth_stencil_state != depth_stencil_state.p)
1128 {
1129 pipe->bind_depth_stencil_alpha_state(pipe, new_depth_stencil_state ? ((GalliumD3D11DepthStencilState*)new_depth_stencil_state)->object : default_depth_stencil);
1130 depth_stencil_state = new_depth_stencil_state;
1131 }
1132
1133 if(new_stencil_ref != stencil_ref)
1134 {
1135 stencil_ref = new_stencil_ref;
1136 set_stencil_ref();
1137 }
1138 }
1139
OMGetDepthStencilStateGalliumD3D11DeviceContext1140 virtual void STDMETHODCALLTYPE OMGetDepthStencilState(
1141 ID3D11DepthStencilState **out_depth_stencil_state,
1142 unsigned *out_stencil_ref)
1143 {
1144 SYNCHRONIZED;
1145 if(*out_depth_stencil_state)
1146 *out_depth_stencil_state = depth_stencil_state.ref();
1147 if(out_stencil_ref)
1148 *out_stencil_ref = stencil_ref;
1149 }
1150
set_framebufferGalliumD3D11DeviceContext1151 void set_framebuffer()
1152 {
1153 struct pipe_framebuffer_state fb;
1154 memset(&fb, 0, sizeof(fb));
1155 if(depth_stencil_view)
1156 {
1157 struct pipe_surface* surf = ((GalliumD3D11DepthStencilView*)depth_stencil_view.p)->object;
1158 fb.zsbuf = surf;
1159 if(surf->width > fb.width)
1160 fb.width = surf->width;
1161 if(surf->height > fb.height)
1162 fb.height = surf->height;
1163 }
1164 fb.nr_cbufs = num_render_target_views;
1165 unsigned i;
1166 for(i = 0; i < num_render_target_views; ++i)
1167 {
1168 if(render_target_views[i])
1169 {
1170 struct pipe_surface* surf = ((GalliumD3D11RenderTargetView*)render_target_views[i].p)->object;
1171 fb.cbufs[i] = surf;
1172 if(surf->width > fb.width)
1173 fb.width = surf->width;
1174 if(surf->height > fb.height)
1175 fb.height = surf->height;
1176 }
1177 }
1178
1179 pipe->set_framebuffer_state(pipe, &fb);
1180 }
1181
1182 /* TODO: the docs say that we should unbind conflicting resources (e.g. those bound for read while we are binding them for write too), but we aren't.
1183 * Hopefully nobody relies on this happening
1184 */
1185
OMSetRenderTargetsGalliumD3D11DeviceContext1186 virtual void STDMETHODCALLTYPE OMSetRenderTargets(
1187 unsigned count,
1188 ID3D11RenderTargetView *const *new_render_target_views,
1189 ID3D11DepthStencilView *new_depth_stencil_view)
1190 {
1191 SYNCHRONIZED;
1192
1193 bool update = false;
1194 unsigned i, num;
1195
1196 if(depth_stencil_view.p != new_depth_stencil_view) {
1197 update = true;
1198 depth_stencil_view = new_depth_stencil_view;
1199 }
1200
1201 if(!new_render_target_views)
1202 count = 0;
1203
1204 for(num = 0, i = 0; i < count; ++i) {
1205 #if API >= 11
1206 // XXX: is unbinding the UAVs here correct ?
1207 om_unordered_access_views[i] = (ID3D11UnorderedAccessView*)NULL;
1208 #endif
1209 if(new_render_target_views[i] != render_target_views[i].p) {
1210 update = true;
1211 render_target_views[i] = new_render_target_views[i];
1212 }
1213 if(new_render_target_views[i])
1214 num = i + 1;
1215 }
1216 if(num != num_render_target_views) {
1217 update = true;
1218 for(; i < num_render_target_views; ++i)
1219 render_target_views[i] = (ID3D11RenderTargetView*)NULL;
1220 }
1221 num_render_target_views = num;
1222 if(update)
1223 set_framebuffer();
1224 }
1225
OMGetRenderTargetsGalliumD3D11DeviceContext1226 virtual void STDMETHODCALLTYPE OMGetRenderTargets(
1227 unsigned count,
1228 ID3D11RenderTargetView **out_render_target_views,
1229 ID3D11DepthStencilView **out_depth_stencil_view)
1230 {
1231 SYNCHRONIZED;
1232 if(out_render_target_views)
1233 {
1234 unsigned i;
1235 for(i = 0; i < std::min(num_render_target_views, count); ++i)
1236 out_render_target_views[i] = render_target_views[i].ref();
1237
1238 for(; i < count; ++i)
1239 out_render_target_views[i] = 0;
1240 }
1241
1242 if(out_depth_stencil_view)
1243 *out_depth_stencil_view = depth_stencil_view.ref();
1244 }
1245
1246 #if API >= 11
1247 /* TODO: what is this supposed to do _exactly_? are we doing the right thing? */
OMSetRenderTargetsAndUnorderedAccessViewsGalliumD3D11DeviceContext1248 virtual void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews(
1249 unsigned rtv_count,
1250 ID3D11RenderTargetView *const *new_render_target_views,
1251 ID3D11DepthStencilView *new_depth_stencil_view,
1252 unsigned uav_start,
1253 unsigned uav_count,
1254 ID3D11UnorderedAccessView *const *new_unordered_access_views,
1255 const unsigned *new_uav_initial_counts)
1256 {
1257 SYNCHRONIZED;
1258 if(rtv_count != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
1259 OMSetRenderTargets(rtv_count, new_render_target_views, new_depth_stencil_view);
1260
1261 if(uav_count != D3D11_KEEP_UNORDERED_ACCESS_VIEWS)
1262 {
1263 for(unsigned i = 0; i < uav_count; ++i)
1264 {
1265 om_unordered_access_views[uav_start + i] = new_unordered_access_views[i];
1266 render_target_views[uav_start + i] = (ID3D11RenderTargetView*)0;
1267 }
1268 }
1269 }
1270
OMGetRenderTargetsAndUnorderedAccessViewsGalliumD3D11DeviceContext1271 virtual void STDMETHODCALLTYPE OMGetRenderTargetsAndUnorderedAccessViews(
1272 unsigned rtv_count,
1273 ID3D11RenderTargetView **out_render_target_views,
1274 ID3D11DepthStencilView **out_depth_stencil_view,
1275 unsigned uav_start,
1276 unsigned uav_count,
1277 ID3D11UnorderedAccessView **out_unordered_access_views)
1278 {
1279 SYNCHRONIZED;
1280 if(out_render_target_views)
1281 OMGetRenderTargets(rtv_count, out_render_target_views, out_depth_stencil_view);
1282
1283 if(out_unordered_access_views)
1284 {
1285 for(unsigned i = 0; i < uav_count; ++i)
1286 out_unordered_access_views[i] = om_unordered_access_views[uav_start + i].ref();
1287 }
1288 }
1289 #endif
1290
SOSetTargetsGalliumD3D11DeviceContext1291 virtual void STDMETHODCALLTYPE SOSetTargets(
1292 unsigned count,
1293 ID3D11Buffer *const *new_so_targets,
1294 const unsigned *new_offsets)
1295 {
1296 SYNCHRONIZED;
1297
1298 unsigned new_count, i;
1299 bool changed = false;
1300
1301 uint32_t append_mask = 0xffffffff;
1302
1303 if(!new_so_targets)
1304 count = 0;
1305 for(new_count = 0, i = 0; i < count; ++i)
1306 {
1307 GalliumD3D11Buffer* buffer = static_cast<GalliumD3D11Buffer*>(new_so_targets[i]);
1308
1309 if(buffer != so_buffers[i].p)
1310 {
1311 changed = true;
1312 so_buffers[i] = buffer;
1313 so_targets[i] = buffer ? buffer->so_target : 0;
1314 }
1315 if(!buffer)
1316 continue;
1317 new_count = i + 1;
1318
1319 if(new_offsets[i] == (unsigned)-1)
1320 {
1321 assert(so_targets[i]);
1322 continue;
1323 }
1324 append_mask &= ~(1 << i);
1325
1326 if(!so_targets[i] || new_offsets[i] != so_targets[i]->buffer_offset)
1327 {
1328 pipe_so_target_reference(&buffer->so_target, NULL);
1329 buffer->so_target = pipe->create_stream_output_target(
1330 pipe, buffer->resource, new_offsets[i], buffer->resource->width0 - new_offsets[i]);
1331 so_targets[i] = buffer->so_target;
1332 changed = true;
1333 }
1334 }
1335 if(i < num_so_targets) {
1336 changed = true;
1337 for(; i < num_so_targets; ++i)
1338 so_buffers[i] = (GalliumD3D11Buffer*)0;
1339 }
1340 num_so_targets = new_count;
1341
1342 if(likely(caps.so) && (changed || append_mask != 0xffffffff))
1343 pipe->set_stream_output_targets(pipe, num_so_targets, so_targets, append_mask);
1344 }
1345
SOGetTargetsGalliumD3D11DeviceContext1346 virtual void STDMETHODCALLTYPE SOGetTargets(
1347 unsigned count,
1348 ID3D11Buffer **out_so_targets
1349 #if API < 11
1350 , UINT *out_offsets
1351 #endif
1352 )
1353 {
1354 SYNCHRONIZED;
1355 for(unsigned i = 0; i < count; ++i)
1356 {
1357 out_so_targets[i] = so_buffers[i].ref();
1358 #if API < 11
1359 out_offsets[i] = so_targets[i]->buffer_offset;
1360 #endif
1361 }
1362 }
1363
BeginGalliumD3D11DeviceContext1364 virtual void STDMETHODCALLTYPE Begin(
1365 ID3D11Asynchronous *async)
1366 {
1367 SYNCHRONIZED;
1368 if(caps.queries)
1369 pipe->begin_query(pipe, ((GalliumD3D11Asynchronous<>*)async)->query);
1370 }
1371
EndGalliumD3D11DeviceContext1372 virtual void STDMETHODCALLTYPE End(
1373 ID3D11Asynchronous *async)
1374 {
1375 SYNCHRONIZED;
1376 if(caps.queries)
1377 pipe->end_query(pipe, ((GalliumD3D11Asynchronous<>*)async)->query);
1378 }
1379
GetDataGalliumD3D11DeviceContext1380 virtual HRESULT STDMETHODCALLTYPE GetData(
1381 ID3D11Asynchronous *iasync,
1382 void *out_data,
1383 unsigned data_size,
1384 unsigned get_data_flags)
1385 {
1386 SYNCHRONIZED;
1387 if(!caps.queries)
1388 return E_NOTIMPL;
1389
1390 GalliumD3D11Asynchronous<>* async = (GalliumD3D11Asynchronous<>*)iasync;
1391 void* tmp_data = alloca(async->data_size);
1392 memset(tmp_data, 0, async->data_size); // sizeof(BOOL) is 4, sizeof(boolean) is 1
1393 boolean ret = pipe->get_query_result(pipe, async->query, !(get_data_flags & D3D11_ASYNC_GETDATA_DONOTFLUSH), tmp_data);
1394 if(out_data)
1395 {
1396 memcpy(out_data, tmp_data, std::min(async->data_size, data_size));
1397 }
1398 return ret ? S_OK : S_FALSE;
1399 }
1400
set_render_conditionGalliumD3D11DeviceContext1401 void set_render_condition()
1402 {
1403 if(caps.render_condition)
1404 {
1405 if(!render_predicate)
1406 pipe->render_condition(pipe, 0, 0);
1407 else
1408 {
1409 GalliumD3D11Predicate* predicate = (GalliumD3D11Predicate*)render_predicate.p;
1410 if(!render_predicate_value && predicate->desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE)
1411 {
1412 unsigned mode = (predicate->desc.MiscFlags & D3D11_QUERY_MISC_PREDICATEHINT) ? PIPE_RENDER_COND_NO_WAIT : PIPE_RENDER_COND_WAIT;
1413 pipe->render_condition(pipe, predicate->query, mode);
1414 }
1415 else
1416 {
1417 /* TODO: add inverted predication to Gallium*/
1418 pipe->render_condition(pipe, 0, 0);
1419 }
1420 }
1421 }
1422 }
1423
SetPredicationGalliumD3D11DeviceContext1424 virtual void STDMETHODCALLTYPE SetPredication(
1425 ID3D11Predicate *new_predicate,
1426 BOOL new_predicate_value)
1427 {
1428 SYNCHRONIZED;
1429 if(render_predicate.p != new_predicate || render_predicate_value != new_predicate_value)
1430 {
1431 render_predicate = new_predicate;
1432 render_predicate_value = new_predicate_value;
1433 set_render_condition();
1434 }
1435 }
1436
GetPredicationGalliumD3D11DeviceContext1437 virtual void STDMETHODCALLTYPE GetPredication(
1438 ID3D11Predicate **out_predicate,
1439 BOOL *out_predicate_value)
1440 {
1441 SYNCHRONIZED;
1442 if(out_predicate)
1443 *out_predicate = render_predicate.ref();
1444 if(out_predicate_value)
1445 *out_predicate_value = render_predicate_value;
1446 }
1447
d3d11_subresource_to_levelGalliumD3D11DeviceContext1448 static unsigned d3d11_subresource_to_level(struct pipe_resource* resource, unsigned subresource)
1449 {
1450 if(subresource <= resource->last_level)
1451 {
1452 return subresource;
1453 }
1454 else
1455 {
1456 unsigned levels = resource->last_level + 1;
1457 return subresource % levels;
1458 }
1459 }
1460
d3d11_subresource_to_layerGalliumD3D11DeviceContext1461 static unsigned d3d11_subresource_to_layer(struct pipe_resource* resource, unsigned subresource)
1462 {
1463 if(subresource <= resource->last_level)
1464 {
1465 return 0;
1466 }
1467 else
1468 {
1469 unsigned levels = resource->last_level + 1;
1470 return subresource / levels;
1471 }
1472 }
1473
1474
1475 /* TODO: deferred contexts will need a different implementation of this,
1476 * because we can't put the transfer info into the resource itself.
1477 * Also, there are very different restrictions, for obvious reasons.
1478 */
MapGalliumD3D11DeviceContext1479 virtual HRESULT STDMETHODCALLTYPE Map(
1480 ID3D11Resource *iresource,
1481 unsigned subresource,
1482 D3D11_MAP map_type,
1483 unsigned map_flags,
1484 D3D11_MAPPED_SUBRESOURCE *mapped_resource)
1485 {
1486 SYNCHRONIZED;
1487 GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource;
1488 if(resource->transfers.count(subresource))
1489 return E_FAIL;
1490 unsigned level = d3d11_subresource_to_level(resource->resource, subresource);
1491 unsigned layer = d3d11_subresource_to_layer(resource->resource, subresource);
1492 pipe_box box = d3d11_to_pipe_box(resource->resource, level, 0);
1493 box.z += layer;
1494 unsigned usage = 0;
1495 if(map_type == D3D11_MAP_READ)
1496 usage = PIPE_TRANSFER_READ;
1497 else if(map_type == D3D11_MAP_WRITE)
1498 usage = PIPE_TRANSFER_WRITE;
1499 else if(map_type == D3D11_MAP_READ_WRITE)
1500 usage = PIPE_TRANSFER_READ_WRITE;
1501 else if(map_type == D3D11_MAP_WRITE_DISCARD)
1502 usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD;
1503 else if(map_type == D3D11_MAP_WRITE_NO_OVERWRITE)
1504 usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED;
1505 else
1506 return E_INVALIDARG;
1507 if(map_type & D3D10_MAP_FLAG_DO_NOT_WAIT)
1508 usage |= PIPE_TRANSFER_DONTBLOCK;
1509 struct pipe_transfer* transfer = pipe->get_transfer(pipe, resource->resource, level, usage, &box);
1510 if(!transfer) {
1511 if(map_type & D3D10_MAP_FLAG_DO_NOT_WAIT)
1512 return DXGI_ERROR_WAS_STILL_DRAWING;
1513 else
1514 return E_FAIL;
1515 }
1516 resource->transfers[subresource] = transfer;
1517 mapped_resource->pData = pipe->transfer_map(pipe, transfer);
1518 mapped_resource->RowPitch = transfer->stride;
1519 mapped_resource->DepthPitch = transfer->layer_stride;
1520 return S_OK;
1521 }
1522
UnmapGalliumD3D11DeviceContext1523 virtual void STDMETHODCALLTYPE Unmap(
1524 ID3D11Resource *iresource,
1525 unsigned subresource)
1526 {
1527 SYNCHRONIZED;
1528 GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource;
1529 std::unordered_map<unsigned, pipe_transfer*>::iterator i = resource->transfers.find(subresource);
1530 if(i != resource->transfers.end())
1531 {
1532 pipe->transfer_unmap(pipe, i->second);
1533 pipe->transfer_destroy(pipe, i->second);
1534 resource->transfers.erase(i);
1535 }
1536 }
1537
CopySubresourceRegionGalliumD3D11DeviceContext1538 virtual void STDMETHODCALLTYPE CopySubresourceRegion(
1539 ID3D11Resource *dst_resource,
1540 unsigned dst_subresource,
1541 unsigned dst_x,
1542 unsigned dst_y,
1543 unsigned dst_z,
1544 ID3D11Resource *src_resource,
1545 unsigned src_subresource,
1546 const D3D11_BOX *src_box)
1547 {
1548 SYNCHRONIZED;
1549 GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource;
1550 GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource;
1551 unsigned dst_level = d3d11_subresource_to_level(dst->resource, dst_subresource);
1552 unsigned dst_layer = d3d11_subresource_to_layer(dst->resource, dst_subresource);
1553 unsigned src_level = d3d11_subresource_to_level(src->resource, src_subresource);
1554 unsigned src_layer = d3d11_subresource_to_layer(src->resource, src_subresource);
1555 pipe_box box = d3d11_to_pipe_box(src->resource, src_level, src_box);
1556 dst_z += dst_layer;
1557 box.z += src_layer;
1558 {
1559 pipe->resource_copy_region(pipe,
1560 dst->resource, dst_level, dst_x, dst_y, dst_z,
1561 src->resource, src_level, &box);
1562 }
1563 }
1564
CopyResourceGalliumD3D11DeviceContext1565 virtual void STDMETHODCALLTYPE CopyResource(
1566 ID3D11Resource *dst_resource,
1567 ID3D11Resource *src_resource)
1568 {
1569 SYNCHRONIZED;
1570 GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource;
1571 GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource;
1572 unsigned level;
1573 for(level = 0; level <= dst->resource->last_level; ++level)
1574 {
1575 pipe_box box;
1576 box.x = box.y = box.z = 0;
1577 box.width = u_minify(dst->resource->width0, level);
1578 box.height = u_minify(dst->resource->height0, level);
1579 if(dst->resource->target == PIPE_TEXTURE_3D)
1580 box.depth = u_minify(dst->resource->depth0, level);
1581 else
1582 box.depth = dst->resource->array_size;
1583 pipe->resource_copy_region(pipe,
1584 dst->resource, level, 0, 0, 0,
1585 src->resource, level, &box);
1586 }
1587 }
1588
UpdateSubresourceGalliumD3D11DeviceContext1589 virtual void STDMETHODCALLTYPE UpdateSubresource(
1590 ID3D11Resource *dst_resource,
1591 unsigned dst_subresource,
1592 const D3D11_BOX *pDstBox,
1593 const void *pSrcData,
1594 unsigned src_row_pitch,
1595 unsigned src_depth_pitch)
1596 {
1597 SYNCHRONIZED;
1598 GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource;
1599 unsigned dst_level = d3d11_subresource_to_level(dst->resource, dst_subresource);
1600 unsigned dst_layer = d3d11_subresource_to_layer(dst->resource, dst_subresource);
1601 pipe_box box = d3d11_to_pipe_box(dst->resource, dst_level, pDstBox);
1602 box.z += dst_layer;
1603 pipe->transfer_inline_write(pipe, dst->resource, dst_level, PIPE_TRANSFER_WRITE, &box, pSrcData, src_row_pitch, src_depth_pitch);
1604 }
1605
1606 #if API >= 11
CopyStructureCountGalliumD3D11DeviceContext1607 virtual void STDMETHODCALLTYPE CopyStructureCount(
1608 ID3D11Buffer *dst_buffer,
1609 unsigned dst_aligned_byte_offset,
1610 ID3D11UnorderedAccessView *src_view)
1611 {
1612 SYNCHRONIZED;
1613 }
1614 #endif
1615
ClearRenderTargetViewGalliumD3D11DeviceContext1616 virtual void STDMETHODCALLTYPE ClearRenderTargetView(
1617 ID3D11RenderTargetView *render_target_view,
1618 const float color[4])
1619 {
1620 SYNCHRONIZED;
1621 GalliumD3D11RenderTargetView* view = ((GalliumD3D11RenderTargetView*)render_target_view);
1622 union pipe_color_union cc;
1623 cc.f[0] = color[0];
1624 cc.f[1] = color[1];
1625 cc.f[2] = color[2];
1626 cc.f[3] = color[3];
1627 pipe->clear_render_target(pipe, view->object, &cc, 0, 0, view->object->width, view->object->height);
1628 }
1629
ClearDepthStencilViewGalliumD3D11DeviceContext1630 virtual void STDMETHODCALLTYPE ClearDepthStencilView(
1631 ID3D11DepthStencilView *depth_stencil_view,
1632 unsigned clear_flags,
1633 float depth,
1634 UINT8 stencil)
1635 {
1636 SYNCHRONIZED;
1637 GalliumD3D11DepthStencilView* view = ((GalliumD3D11DepthStencilView*)depth_stencil_view);
1638 unsigned flags = 0;
1639 if(clear_flags & D3D11_CLEAR_DEPTH)
1640 flags |= PIPE_CLEAR_DEPTH;
1641 if(clear_flags & D3D11_CLEAR_STENCIL)
1642 flags |= PIPE_CLEAR_STENCIL;
1643 pipe->clear_depth_stencil(pipe, view->object, flags, depth, stencil, 0, 0, view->object->width, view->object->height);
1644 }
1645
1646 #if API >= 11
ClearUnorderedAccessViewUintGalliumD3D11DeviceContext1647 virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewUint(
1648 ID3D11UnorderedAccessView *unordered_access_view,
1649 const unsigned values[4])
1650 {
1651 SYNCHRONIZED;
1652 }
1653
ClearUnorderedAccessViewFloatGalliumD3D11DeviceContext1654 virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat(
1655 ID3D11UnorderedAccessView *unordered_access_view,
1656 const float values[4])
1657 {
1658 SYNCHRONIZED;
1659 }
1660 #endif
1661
restore_gallium_state_blit_onlyGalliumD3D11DeviceContext1662 void restore_gallium_state_blit_only()
1663 {
1664 pipe->bind_blend_state(pipe, blend_state.p ? blend_state.p->object : default_blend);
1665 pipe->bind_depth_stencil_alpha_state(pipe, depth_stencil_state.p ? depth_stencil_state.p->object : default_depth_stencil);
1666 pipe->bind_rasterizer_state(pipe, rasterizer_state.p ? rasterizer_state.p->object : default_rasterizer);
1667 pipe->bind_vertex_elements_state(pipe, input_layout.p ? input_layout.p->object : default_input_layout);
1668 pipe->bind_fs_state(pipe, shaders[D3D11_STAGE_PS].p ? shaders[D3D11_STAGE_PS].p->object : default_shaders[PIPE_SHADER_FRAGMENT]);
1669 pipe->bind_vs_state(pipe, shaders[D3D11_STAGE_VS].p ? shaders[D3D11_STAGE_VS].p->object : default_shaders[PIPE_SHADER_VERTEX]);
1670 if(caps.gs)
1671 pipe->bind_gs_state(pipe, shaders[D3D11_STAGE_GS].p ? shaders[D3D11_STAGE_GS].p->object : default_shaders[PIPE_SHADER_GEOMETRY]);
1672 if(caps.so && num_so_targets)
1673 pipe->set_stream_output_targets(pipe, num_so_targets, so_targets, ~0);
1674 set_framebuffer();
1675 set_viewport();
1676 set_render_condition();
1677
1678 update_flags |= UPDATE_VERTEX_BUFFERS | (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_PS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_PS));
1679 }
1680
RestoreGalliumStateBlitOnlyGalliumD3D11DeviceContext1681 virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly()
1682 {
1683 SYNCHRONIZED;
1684 restore_gallium_state_blit_only();
1685 }
1686
GenerateMipsGalliumD3D11DeviceContext1687 virtual void STDMETHODCALLTYPE GenerateMips(
1688 ID3D11ShaderResourceView *shader_resource_view)
1689 {
1690 SYNCHRONIZED;
1691
1692 GalliumD3D11ShaderResourceView* view = (GalliumD3D11ShaderResourceView*)shader_resource_view;
1693 if(caps.gs)
1694 pipe->bind_gs_state(pipe, 0);
1695 if(caps.so && num_so_targets)
1696 pipe->set_stream_output_targets(pipe, 0, NULL, 0);
1697 if(pipe->render_condition)
1698 pipe->render_condition(pipe, 0, 0);
1699 for(unsigned layer = view->object->u.tex.first_layer; layer <= view->object->u.tex.last_layer; ++layer)
1700 util_gen_mipmap(gen_mipmap, view->object, layer, view->object->u.tex.first_level, view->object->u.tex.last_level, PIPE_TEX_FILTER_LINEAR);
1701 restore_gallium_state_blit_only();
1702 }
1703
RestoreGalliumStateGalliumD3D11DeviceContext1704 virtual void STDMETHODCALLTYPE RestoreGalliumState()
1705 {
1706 SYNCHRONIZED;
1707 restore_gallium_state_blit_only();
1708
1709 set_index_buffer();
1710 set_stencil_ref();
1711 pipe->set_blend_color(pipe, (struct pipe_blend_color*)blend_color);
1712 pipe->set_sample_mask(pipe, sample_mask);
1713
1714 for(unsigned s = 0; s < 3; ++s)
1715 {
1716 unsigned num = std::min(caps.constant_buffers[s], (unsigned)D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
1717 for(unsigned i = 0; i < num; ++i)
1718 pipe_set_constant_buffer(pipe, s, i, constant_buffers[s][i].p ? constant_buffers[s][i].p->resource : 0);
1719 }
1720
1721 update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_VS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_VS));
1722 update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_GS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_GS));
1723
1724 set_scissor();
1725 }
1726
1727 #if API >= 11
1728 /* TODO: hack SRVs or sampler states to handle this, or add to Gallium */
SetResourceMinLODGalliumD3D11DeviceContext1729 virtual void STDMETHODCALLTYPE SetResourceMinLOD(
1730 ID3D11Resource *iresource,
1731 float min_lod)
1732 {
1733 SYNCHRONIZED;
1734 GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource;
1735 if(resource->min_lod != min_lod)
1736 {
1737 // TODO: actually do anything?
1738 resource->min_lod = min_lod;
1739 }
1740 }
1741
GetResourceMinLODGalliumD3D11DeviceContext1742 virtual float STDMETHODCALLTYPE GetResourceMinLOD(
1743 ID3D11Resource *iresource)
1744 {
1745 SYNCHRONIZED;
1746 GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)iresource;
1747 return resource->min_lod;
1748 }
1749 #endif
1750
ResolveSubresourceGalliumD3D11DeviceContext1751 virtual void STDMETHODCALLTYPE ResolveSubresource(
1752 ID3D11Resource *dst_resource,
1753 unsigned dst_subresource,
1754 ID3D11Resource *src_resource,
1755 unsigned src_subresource,
1756 DXGI_FORMAT format)
1757 {
1758 SYNCHRONIZED;
1759 GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)dst_resource;
1760 GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)src_resource;
1761 struct pipe_resolve_info info;
1762
1763 info.dst.res = dst->resource;
1764 info.src.res = src->resource;
1765 info.dst.level = 0;
1766 info.dst.layer = d3d11_subresource_to_layer(dst->resource, dst_subresource);
1767 info.src.layer = d3d11_subresource_to_layer(src->resource, src_subresource);
1768
1769 info.src.x0 = 0;
1770 info.src.x1 = info.src.res->width0;
1771 info.src.y0 = 0;
1772 info.src.y1 = info.src.res->height0;
1773 info.dst.x0 = 0;
1774 info.dst.x1 = info.dst.res->width0;
1775 info.dst.y0 = 0;
1776 info.dst.y1 = info.dst.res->height0;
1777
1778 info.mask = PIPE_MASK_RGBA | PIPE_MASK_ZS;
1779
1780 pipe->resource_resolve(pipe, &info);
1781 }
1782
1783 #if API >= 11
ExecuteCommandListGalliumD3D11DeviceContext1784 virtual void STDMETHODCALLTYPE ExecuteCommandList(
1785 ID3D11CommandList *command_list,
1786 BOOL restore_context_state)
1787 {
1788 SYNCHRONIZED;
1789 }
1790
FinishCommandListGalliumD3D11DeviceContext1791 virtual HRESULT STDMETHODCALLTYPE FinishCommandList(
1792 BOOL restore_deferred_context_state,
1793 ID3D11CommandList **out_command_list)
1794 {
1795 SYNCHRONIZED;
1796 return E_NOTIMPL;
1797 }
1798 #endif
1799
ClearStateGalliumD3D11DeviceContext1800 virtual void STDMETHODCALLTYPE ClearState(void)
1801 {
1802 /* we don't take a lock here because we would deadlock otherwise
1803 * TODO: this is probably incorrect, because ClearState should likely be atomic.
1804 * However, I can't think of any correct usage that would be affected by this
1805 * being non-atomic, and making this atomic is quite expensive and complicates
1806 * the code
1807 */
1808
1809 // we qualify all calls so that we avoid virtual dispatch and might get them inlined
1810 // TODO: make sure all this gets inlined, which might require more compiler flags
1811 // TODO: optimize this
1812 #if API >= 11
1813 GalliumD3D11DeviceContext::PSSetShader(0, 0, 0);
1814 GalliumD3D11DeviceContext::GSSetShader(0, 0, 0);
1815 GalliumD3D11DeviceContext::VSSetShader(0, 0, 0);
1816 GalliumD3D11DeviceContext::HSSetShader(0, 0, 0);
1817 GalliumD3D11DeviceContext::DSSetShader(0, 0, 0);
1818 GalliumD3D11DeviceContext::CSSetShader(0, 0, 0);
1819 #else
1820 GalliumD3D11DeviceContext::PSSetShader(0);
1821 GalliumD3D11DeviceContext::GSSetShader(0);
1822 GalliumD3D11DeviceContext::VSSetShader(0);
1823 #endif
1824
1825 GalliumD3D11DeviceContext::IASetInputLayout(0);
1826 GalliumD3D11DeviceContext::IASetIndexBuffer(0, DXGI_FORMAT_UNKNOWN, 0);
1827 GalliumD3D11DeviceContext::RSSetState(0);
1828 GalliumD3D11DeviceContext::OMSetDepthStencilState(0, 0);
1829 GalliumD3D11DeviceContext::OMSetBlendState(0, (float*)zero_data, ~0);
1830 GalliumD3D11DeviceContext::SetPredication(0, 0);
1831 GalliumD3D11DeviceContext::IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED);
1832
1833 GalliumD3D11DeviceContext::PSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
1834 GalliumD3D11DeviceContext::GSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
1835 GalliumD3D11DeviceContext::VSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
1836 #if API >= 11
1837 GalliumD3D11DeviceContext::HSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
1838 GalliumD3D11DeviceContext::DSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
1839 GalliumD3D11DeviceContext::CSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
1840 #endif
1841
1842 GalliumD3D11DeviceContext::IASetVertexBuffers(0, num_vertex_buffers, (ID3D11Buffer**)zero_data, (unsigned*)zero_data, (unsigned*)zero_data);
1843 #if API >= 11
1844 GalliumD3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(0, 0, 0 , 0, 0, 0, 0);
1845 #else
1846 GalliumD3D11DeviceContext::OMSetRenderTargets(0, 0, 0 );
1847 #endif
1848 GalliumD3D11DeviceContext::SOSetTargets(0, 0, 0);
1849
1850 GalliumD3D11DeviceContext::PSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_PS], (ID3D11ShaderResourceView**)zero_data);
1851 GalliumD3D11DeviceContext::GSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_GS], (ID3D11ShaderResourceView**)zero_data);
1852 GalliumD3D11DeviceContext::VSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_VS], (ID3D11ShaderResourceView**)zero_data);
1853 #if API >= 11
1854 GalliumD3D11DeviceContext::HSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_HS], (ID3D11ShaderResourceView**)zero_data);
1855 GalliumD3D11DeviceContext::DSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_DS], (ID3D11ShaderResourceView**)zero_data);
1856 GalliumD3D11DeviceContext::CSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_CS], (ID3D11ShaderResourceView**)zero_data);
1857 #endif
1858
1859 GalliumD3D11DeviceContext::PSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_PS], (ID3D11SamplerState**)zero_data);
1860 GalliumD3D11DeviceContext::GSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_GS], (ID3D11SamplerState**)zero_data);
1861 GalliumD3D11DeviceContext::VSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_VS], (ID3D11SamplerState**)zero_data);
1862 #if API >= 11
1863 GalliumD3D11DeviceContext::HSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_HS], (ID3D11SamplerState**)zero_data);
1864 GalliumD3D11DeviceContext::DSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_DS], (ID3D11SamplerState**)zero_data);
1865 GalliumD3D11DeviceContext::CSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_CS], (ID3D11SamplerState**)zero_data);
1866 #endif
1867
1868 GalliumD3D11DeviceContext::RSSetViewports(0, 0);
1869 GalliumD3D11DeviceContext::RSSetScissorRects(0, 0);
1870 }
1871
FlushGalliumD3D11DeviceContext1872 virtual void STDMETHODCALLTYPE Flush(void)
1873 {
1874 SYNCHRONIZED;
1875 pipe->flush(pipe, 0);
1876 }
1877
1878 /* In Direct3D 10, if the reference count of an object drops to 0, it is automatically
1879 * cleanly unbound from the pipeline.
1880 * In Direct3D 11, the pipeline holds a reference.
1881 *
1882 * Note that instead of always scanning the pipeline on destruction, we could
1883 * maintain the internal reference count on DirectX 10 and use it to check if an
1884 * object is still bound.
1885 * Presumably, on average, scanning is faster if the application is well written.
1886 */
1887 #if API < 11
1888 #define IMPLEMENT_SIMPLE_UNBIND(name, member, gallium, def) \
1889 void Unbind##name(ID3D11##name* state) \
1890 { \
1891 SYNCHRONIZED; \
1892 if((void*)state == (void*)member.p) \
1893 { \
1894 member.p = 0; \
1895 pipe->bind_##gallium##_state(pipe, default_##def); \
1896 } \
1897 }
IMPLEMENT_SIMPLE_UNBINDGalliumD3D11DeviceContext1898 IMPLEMENT_SIMPLE_UNBIND(BlendState, blend_state, blend, blend)
1899 IMPLEMENT_SIMPLE_UNBIND(RasterizerState, rasterizer_state, rasterizer, rasterizer)
1900 IMPLEMENT_SIMPLE_UNBIND(DepthStencilState, depth_stencil_state, depth_stencil_alpha, depth_stencil)
1901 IMPLEMENT_SIMPLE_UNBIND(InputLayout, input_layout, vertex_elements, input_layout)
1902 IMPLEMENT_SIMPLE_UNBIND(PixelShader, shaders[D3D11_STAGE_PS], fs, shaders[D3D11_STAGE_PS])
1903 IMPLEMENT_SIMPLE_UNBIND(VertexShader, shaders[D3D11_STAGE_VS], vs, shaders[D3D11_STAGE_VS])
1904 IMPLEMENT_SIMPLE_UNBIND(GeometryShader, shaders[D3D11_STAGE_GS], gs, shaders[D3D11_STAGE_GS])
1905
1906 void UnbindPredicate(ID3D11Predicate* predicate)
1907 {
1908 SYNCHRONIZED;
1909 if(predicate == render_predicate)
1910 {
1911 render_predicate.p = NULL;
1912 render_predicate_value = 0;
1913 pipe->render_condition(pipe, 0, 0);
1914 }
1915 }
1916
UnbindSamplerStateGalliumD3D11DeviceContext1917 void UnbindSamplerState(ID3D11SamplerState* state)
1918 {
1919 SYNCHRONIZED;
1920 for(unsigned s = 0; s < D3D11_STAGES; ++s)
1921 {
1922 for(unsigned i = 0; i < num_samplers[s]; ++i)
1923 {
1924 if(samplers[s][i] == state)
1925 {
1926 samplers[s][i].p = NULL;
1927 sampler_csos[s][i] = NULL;
1928 update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + s));
1929 }
1930 }
1931 }
1932 }
1933
UnbindBufferGalliumD3D11DeviceContext1934 void UnbindBuffer(ID3D11Buffer* buffer)
1935 {
1936 SYNCHRONIZED;
1937 if(buffer == index_buffer)
1938 {
1939 index_buffer.p = 0;
1940 index_format = DXGI_FORMAT_UNKNOWN;
1941 index_offset = 0;
1942 struct pipe_index_buffer ib;
1943 memset(&ib, 0, sizeof(ib));
1944 pipe->set_index_buffer(pipe, &ib);
1945 }
1946
1947 for(unsigned i = 0; i < num_vertex_buffers; ++i)
1948 {
1949 if(buffer == input_buffers[i])
1950 {
1951 input_buffers[i].p = 0;
1952 memset(&vertex_buffers[num_vertex_buffers], 0, sizeof(vertex_buffers[num_vertex_buffers]));
1953 update_flags |= UPDATE_VERTEX_BUFFERS;
1954 }
1955 }
1956
1957 for(unsigned s = 0; s < D3D11_STAGES; ++s)
1958 {
1959 for(unsigned i = 0; i < sizeof(constant_buffers) / sizeof(constant_buffers[0]); ++i)
1960 {
1961 if(constant_buffers[s][i] == buffer)
1962 {
1963 constant_buffers[s][i] = (ID3D10Buffer*)NULL;
1964 pipe_set_constant_buffer(pipe, s, i, NULL);
1965 }
1966 }
1967 }
1968 }
1969
UnbindDepthStencilViewGalliumD3D11DeviceContext1970 void UnbindDepthStencilView(ID3D11DepthStencilView * view)
1971 {
1972 SYNCHRONIZED;
1973 if(view == depth_stencil_view)
1974 {
1975 depth_stencil_view.p = NULL;
1976 set_framebuffer();
1977 }
1978 }
1979
UnbindRenderTargetViewGalliumD3D11DeviceContext1980 void UnbindRenderTargetView(ID3D11RenderTargetView* view)
1981 {
1982 SYNCHRONIZED;
1983 bool any_bound = false;
1984 for(unsigned i = 0; i < num_render_target_views; ++i)
1985 {
1986 if(render_target_views[i] == view)
1987 {
1988 render_target_views[i].p = NULL;
1989 any_bound = true;
1990 }
1991 }
1992 if(any_bound)
1993 set_framebuffer();
1994 }
1995
UnbindShaderResourceViewGalliumD3D11DeviceContext1996 void UnbindShaderResourceView(ID3D11ShaderResourceView* view)
1997 {
1998 SYNCHRONIZED;
1999 for(unsigned s = 0; s < D3D11_STAGES; ++s)
2000 {
2001 for(unsigned i = 0; i < num_shader_resource_views[s]; ++i)
2002 {
2003 if(shader_resource_views[s][i] == view)
2004 {
2005 shader_resource_views[s][i].p = NULL;
2006 sampler_views[s][i] = NULL;
2007 update_flags |= (1 << (UPDATE_VIEWS_SHIFT + s));
2008 }
2009 }
2010 }
2011 }
2012 #endif
2013
2014 #undef SYNCHRONIZED
2015 };
2016
2017 #if API >= 11
2018 /* This approach serves two purposes.
2019 * First, we don't want to do an atomic operation to manipulate the reference
2020 * count every time something is bound/unbound to the pipeline, since they are
2021 * expensive.
2022 * Fortunately, the immediate context can only be used by a single thread, so
2023 * we don't have to use them, as long as a separate reference count is used
2024 * (see dual_refcnt_t).
2025 *
2026 * Second, we want to avoid the Device -> DeviceContext -> bound DeviceChild -> Device
2027 * garbage cycle.
2028 * To avoid it, DeviceChild doesn't hold a reference to Device as usual, but adds
2029 * one for each external reference count, while internal nonatomic_add_ref doesn't
2030 * add any.
2031 *
2032 * Note that ideally we would to eliminate the non-atomic op too, but this is more
2033 * complicated, since we would either need to use garbage collection and give up
2034 * deterministic destruction (especially bad for large textures), or scan the whole
2035 * pipeline state every time the reference count of object drops to 0, which risks
2036 * pathological slowdowns.
2037 *
2038 * Since this microoptimization should matter relatively little, let's avoid it for now.
2039 *
2040 * Note that deferred contexts don't use this, since as a whole, they must thread-safe.
2041 * Eliminating the atomic ops for deferred contexts seems substantially harder.
2042 * This might be a problem if they are used in a one-shot multithreaded rendering
2043 * fashion, where SMP cacheline bouncing on the reference count may be visible.
2044 *
2045 * The idea would be to attach a structure of reference counts indexed by deferred
2046 * context id to each object. Ideally, this should be organized like ext2 block pointers.
2047 *
2048 * Every deferred context would get a reference count in its own cacheline.
2049 * The external count is protected by a lock bit, and there is also a "lock bit" in each
2050 * internal count.
2051 *
2052 * When the external count has to be dropped to 0, the lock bit is taken and all internal
2053 * reference counts are scanned, taking a count of them. A flag would also be set on them.
2054 * Deferred context manipulation would notice the flag, and update the count.
2055 * Once the count goes to zero, the object is freed.
2056 *
2057 * The problem of this is that if the external reference count ping-pongs between
2058 * zero and non-zero, the scans will take a lot of time.
2059 *
2060 * The idea to solve this is to compute the scans in a binary-tree like fashion, where
2061 * each binary tree node would have a "determined bit", which would be invalidated
2062 * by manipulations.
2063 *
2064 * However, all this complexity might actually be a loss in most cases, so let's just
2065 * stick to a single atomic refcnt for now.
2066 *
2067 * Also, we don't even support deferred contexts yet, so this can wait.
2068 */
2069 struct nonatomic_device_child_ptr_traits
2070 {
add_refnonatomic_device_child_ptr_traits2071 static void add_ref(void* p)
2072 {
2073 if(p)
2074 ((GalliumD3D11DeviceChild<>*)p)->nonatomic_add_ref();
2075 }
2076
releasenonatomic_device_child_ptr_traits2077 static void release(void* p)
2078 {
2079 if(p)
2080 ((GalliumD3D11DeviceChild<>*)p)->nonatomic_release();
2081 }
2082 };
2083
2084 struct GalliumD3D11ImmediateDeviceContext
2085 : public GalliumD3D11DeviceContext<nonatomic_device_child_ptr_traits>
2086 {
2087 GalliumD3D11ImmediateDeviceContext(GalliumD3D11Screen* device, pipe_context* pipe, unsigned context_flags = 0)
2088 : GalliumD3D11DeviceContext<nonatomic_device_child_ptr_traits>(device, pipe, context_flags)
2089 {
2090 // not necessary, but tests that the API at least basically works
2091 ClearState();
2092 }
2093
2094 /* we do this since otherwise we would have a garbage cycle between this and the device */
AddRefGalliumD3D11ImmediateDeviceContext2095 virtual ULONG STDMETHODCALLTYPE AddRef()
2096 {
2097 return this->device->AddRef();
2098 }
2099
ReleaseGalliumD3D11ImmediateDeviceContext2100 virtual ULONG STDMETHODCALLTYPE Release()
2101 {
2102 return this->device->Release();
2103 }
2104
GetTypeGalliumD3D11ImmediateDeviceContext2105 virtual D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType()
2106 {
2107 return D3D11_DEVICE_CONTEXT_IMMEDIATE;
2108 }
2109 };
2110
GalliumD3D11ImmediateDeviceContext_Create(GalliumD3D11Screen * device,struct pipe_context * pipe,bool owns_pipe)2111 static ID3D11DeviceContext* GalliumD3D11ImmediateDeviceContext_Create(GalliumD3D11Screen* device, struct pipe_context* pipe, bool owns_pipe)
2112 {
2113 return new GalliumD3D11ImmediateDeviceContext(device, pipe, owns_pipe);
2114 }
2115
GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(ID3D11DeviceContext * context)2116 static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(ID3D11DeviceContext* context)
2117 {
2118 ((GalliumD3D11ImmediateDeviceContext*)context)->RestoreGalliumState();
2119 }
2120
GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(ID3D11DeviceContext * context)2121 static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(ID3D11DeviceContext* context)
2122 {
2123 ((GalliumD3D11ImmediateDeviceContext*)context)->RestoreGalliumStateBlitOnly();
2124 }
2125
GalliumD3D11ImmediateDeviceContext_Destroy(ID3D11DeviceContext * context)2126 static void GalliumD3D11ImmediateDeviceContext_Destroy(ID3D11DeviceContext* context)
2127 {
2128 delete (GalliumD3D11ImmediateDeviceContext*)context;
2129 }
2130 #endif
2131