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