1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54#include "vmwgfx_drv.h"
55#include "vmwgfx_binding.h"
56#include "device_include/svga3d_reg.h"
57
58#define VMW_BINDING_RT_BIT 0
59#define VMW_BINDING_PS_BIT 1
60#define VMW_BINDING_SO_BIT 2
61#define VMW_BINDING_VB_BIT 3
62#define VMW_BINDING_NUM_BITS 4
63
64#define VMW_BINDING_PS_SR_BIT 0
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92struct vmw_ctx_binding_state {
93 struct vmw_private *dev_priv;
94 struct list_head list;
95 struct vmw_ctx_bindinfo_view render_targets[SVGA3D_RT_MAX];
96 struct vmw_ctx_bindinfo_tex texture_units[SVGA3D_NUM_TEXTURE_UNITS];
97 struct vmw_ctx_bindinfo_view ds_view;
98 struct vmw_ctx_bindinfo_so so_targets[SVGA3D_DX_MAX_SOTARGETS];
99 struct vmw_ctx_bindinfo_vb vertex_buffers[SVGA3D_DX_MAX_VERTEXBUFFERS];
100 struct vmw_ctx_bindinfo_ib index_buffer;
101 struct vmw_dx_shader_bindings per_shader[SVGA3D_NUM_SHADERTYPE_DX10];
102
103 unsigned long dirty;
104 DECLARE_BITMAP(dirty_vb, SVGA3D_DX_MAX_VERTEXBUFFERS);
105
106 u32 bind_cmd_buffer[VMW_MAX_VIEW_BINDINGS];
107 u32 bind_cmd_count;
108 u32 bind_first_slot;
109};
110
111static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind);
112static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi,
113 bool rebind);
114static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, bool rebind);
115static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind);
116static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind);
117static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind);
118static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind);
119static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs);
120static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi,
121 bool rebind);
122static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind);
123static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind);
124static void vmw_binding_build_asserts(void) __attribute__ ((unused));
125
126typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool);
127
128
129
130
131
132
133
134
135
136
137
138
139
140struct vmw_binding_info {
141 size_t size;
142 const size_t *offsets;
143 vmw_scrub_func scrub_func;
144};
145
146
147
148
149
150static const size_t vmw_binding_shader_offsets[] = {
151 offsetof(struct vmw_ctx_binding_state, per_shader[0].shader),
152 offsetof(struct vmw_ctx_binding_state, per_shader[1].shader),
153 offsetof(struct vmw_ctx_binding_state, per_shader[2].shader),
154};
155static const size_t vmw_binding_rt_offsets[] = {
156 offsetof(struct vmw_ctx_binding_state, render_targets),
157};
158static const size_t vmw_binding_tex_offsets[] = {
159 offsetof(struct vmw_ctx_binding_state, texture_units),
160};
161static const size_t vmw_binding_cb_offsets[] = {
162 offsetof(struct vmw_ctx_binding_state, per_shader[0].const_buffers),
163 offsetof(struct vmw_ctx_binding_state, per_shader[1].const_buffers),
164 offsetof(struct vmw_ctx_binding_state, per_shader[2].const_buffers),
165};
166static const size_t vmw_binding_dx_ds_offsets[] = {
167 offsetof(struct vmw_ctx_binding_state, ds_view),
168};
169static const size_t vmw_binding_sr_offsets[] = {
170 offsetof(struct vmw_ctx_binding_state, per_shader[0].shader_res),
171 offsetof(struct vmw_ctx_binding_state, per_shader[1].shader_res),
172 offsetof(struct vmw_ctx_binding_state, per_shader[2].shader_res),
173};
174static const size_t vmw_binding_so_offsets[] = {
175 offsetof(struct vmw_ctx_binding_state, so_targets),
176};
177static const size_t vmw_binding_vb_offsets[] = {
178 offsetof(struct vmw_ctx_binding_state, vertex_buffers),
179};
180static const size_t vmw_binding_ib_offsets[] = {
181 offsetof(struct vmw_ctx_binding_state, index_buffer),
182};
183
184static const struct vmw_binding_info vmw_binding_infos[] = {
185 [vmw_ctx_binding_shader] = {
186 .size = sizeof(struct vmw_ctx_bindinfo_shader),
187 .offsets = vmw_binding_shader_offsets,
188 .scrub_func = vmw_binding_scrub_shader},
189 [vmw_ctx_binding_rt] = {
190 .size = sizeof(struct vmw_ctx_bindinfo_view),
191 .offsets = vmw_binding_rt_offsets,
192 .scrub_func = vmw_binding_scrub_render_target},
193 [vmw_ctx_binding_tex] = {
194 .size = sizeof(struct vmw_ctx_bindinfo_tex),
195 .offsets = vmw_binding_tex_offsets,
196 .scrub_func = vmw_binding_scrub_texture},
197 [vmw_ctx_binding_cb] = {
198 .size = sizeof(struct vmw_ctx_bindinfo_cb),
199 .offsets = vmw_binding_cb_offsets,
200 .scrub_func = vmw_binding_scrub_cb},
201 [vmw_ctx_binding_dx_shader] = {
202 .size = sizeof(struct vmw_ctx_bindinfo_shader),
203 .offsets = vmw_binding_shader_offsets,
204 .scrub_func = vmw_binding_scrub_dx_shader},
205 [vmw_ctx_binding_dx_rt] = {
206 .size = sizeof(struct vmw_ctx_bindinfo_view),
207 .offsets = vmw_binding_rt_offsets,
208 .scrub_func = vmw_binding_scrub_dx_rt},
209 [vmw_ctx_binding_sr] = {
210 .size = sizeof(struct vmw_ctx_bindinfo_view),
211 .offsets = vmw_binding_sr_offsets,
212 .scrub_func = vmw_binding_scrub_sr},
213 [vmw_ctx_binding_ds] = {
214 .size = sizeof(struct vmw_ctx_bindinfo_view),
215 .offsets = vmw_binding_dx_ds_offsets,
216 .scrub_func = vmw_binding_scrub_dx_rt},
217 [vmw_ctx_binding_so] = {
218 .size = sizeof(struct vmw_ctx_bindinfo_so),
219 .offsets = vmw_binding_so_offsets,
220 .scrub_func = vmw_binding_scrub_so},
221 [vmw_ctx_binding_vb] = {
222 .size = sizeof(struct vmw_ctx_bindinfo_vb),
223 .offsets = vmw_binding_vb_offsets,
224 .scrub_func = vmw_binding_scrub_vb},
225 [vmw_ctx_binding_ib] = {
226 .size = sizeof(struct vmw_ctx_bindinfo_ib),
227 .offsets = vmw_binding_ib_offsets,
228 .scrub_func = vmw_binding_scrub_ib},
229};
230
231
232
233
234
235
236
237
238
239
240
241
242
243static const struct vmw_resource *
244vmw_cbs_context(const struct vmw_ctx_binding_state *cbs)
245{
246 if (list_empty(&cbs->list))
247 return NULL;
248
249 return list_first_entry(&cbs->list, struct vmw_ctx_bindinfo,
250 ctx_list)->ctx;
251}
252
253
254
255
256
257
258
259
260
261static struct vmw_ctx_bindinfo *
262vmw_binding_loc(struct vmw_ctx_binding_state *cbs,
263 enum vmw_ctx_binding_type bt, u32 shader_slot, u32 slot)
264{
265 const struct vmw_binding_info *b = &vmw_binding_infos[bt];
266 size_t offset = b->offsets[shader_slot] + b->size*slot;
267
268 return (struct vmw_ctx_bindinfo *)((u8 *) cbs + offset);
269}
270
271
272
273
274
275
276
277
278
279
280static void vmw_binding_drop(struct vmw_ctx_bindinfo *bi)
281{
282 list_del(&bi->ctx_list);
283 if (!list_empty(&bi->res_list))
284 list_del(&bi->res_list);
285 bi->ctx = NULL;
286}
287
288
289
290
291
292
293
294
295
296
297void vmw_binding_add(struct vmw_ctx_binding_state *cbs,
298 const struct vmw_ctx_bindinfo *bi,
299 u32 shader_slot, u32 slot)
300{
301 struct vmw_ctx_bindinfo *loc =
302 vmw_binding_loc(cbs, bi->bt, shader_slot, slot);
303 const struct vmw_binding_info *b = &vmw_binding_infos[bi->bt];
304
305 if (loc->ctx != NULL)
306 vmw_binding_drop(loc);
307
308 memcpy(loc, bi, b->size);
309 loc->scrubbed = false;
310 list_add(&loc->ctx_list, &cbs->list);
311 INIT_LIST_HEAD(&loc->res_list);
312}
313
314
315
316
317
318
319
320
321static void vmw_binding_transfer(struct vmw_ctx_binding_state *cbs,
322 const struct vmw_ctx_binding_state *from,
323 const struct vmw_ctx_bindinfo *bi)
324{
325 size_t offset = (unsigned long)bi - (unsigned long)from;
326 struct vmw_ctx_bindinfo *loc = (struct vmw_ctx_bindinfo *)
327 ((unsigned long) cbs + offset);
328
329 if (loc->ctx != NULL) {
330 WARN_ON(bi->scrubbed);
331
332 vmw_binding_drop(loc);
333 }
334
335 if (bi->res != NULL) {
336 memcpy(loc, bi, vmw_binding_infos[bi->bt].size);
337 list_add_tail(&loc->ctx_list, &cbs->list);
338 list_add_tail(&loc->res_list, &loc->res->binding_head);
339 }
340}
341
342
343
344
345
346
347
348
349
350
351void vmw_binding_state_kill(struct vmw_ctx_binding_state *cbs)
352{
353 struct vmw_ctx_bindinfo *entry, *next;
354
355 vmw_binding_state_scrub(cbs);
356 list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
357 vmw_binding_drop(entry);
358}
359
360
361
362
363
364
365
366
367
368
369void vmw_binding_state_scrub(struct vmw_ctx_binding_state *cbs)
370{
371 struct vmw_ctx_bindinfo *entry;
372
373 list_for_each_entry(entry, &cbs->list, ctx_list) {
374 if (!entry->scrubbed) {
375 (void) vmw_binding_infos[entry->bt].scrub_func
376 (entry, false);
377 entry->scrubbed = true;
378 }
379 }
380
381 (void) vmw_binding_emit_dirty(cbs);
382}
383
384
385
386
387
388
389
390
391
392
393void vmw_binding_res_list_kill(struct list_head *head)
394{
395 struct vmw_ctx_bindinfo *entry, *next;
396
397 vmw_binding_res_list_scrub(head);
398 list_for_each_entry_safe(entry, next, head, res_list)
399 vmw_binding_drop(entry);
400}
401
402
403
404
405
406
407
408
409
410
411void vmw_binding_res_list_scrub(struct list_head *head)
412{
413 struct vmw_ctx_bindinfo *entry;
414
415 list_for_each_entry(entry, head, res_list) {
416 if (!entry->scrubbed) {
417 (void) vmw_binding_infos[entry->bt].scrub_func
418 (entry, false);
419 entry->scrubbed = true;
420 }
421 }
422
423 list_for_each_entry(entry, head, res_list) {
424 struct vmw_ctx_binding_state *cbs =
425 vmw_context_binding_state(entry->ctx);
426
427 (void) vmw_binding_emit_dirty(cbs);
428 }
429}
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444void vmw_binding_state_commit(struct vmw_ctx_binding_state *to,
445 struct vmw_ctx_binding_state *from)
446{
447 struct vmw_ctx_bindinfo *entry, *next;
448
449 list_for_each_entry_safe(entry, next, &from->list, ctx_list) {
450 vmw_binding_transfer(to, from, entry);
451 vmw_binding_drop(entry);
452 }
453}
454
455
456
457
458
459
460
461
462
463int vmw_binding_rebind_all(struct vmw_ctx_binding_state *cbs)
464{
465 struct vmw_ctx_bindinfo *entry;
466 int ret;
467
468 list_for_each_entry(entry, &cbs->list, ctx_list) {
469 if (likely(!entry->scrubbed))
470 continue;
471
472 if ((entry->res == NULL || entry->res->id ==
473 SVGA3D_INVALID_ID))
474 continue;
475
476 ret = vmw_binding_infos[entry->bt].scrub_func(entry, true);
477 if (unlikely(ret != 0))
478 return ret;
479
480 entry->scrubbed = false;
481 }
482
483 return vmw_binding_emit_dirty(cbs);
484}
485
486
487
488
489
490
491
492static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
493{
494 struct vmw_ctx_bindinfo_shader *binding =
495 container_of(bi, typeof(*binding), bi);
496 struct vmw_private *dev_priv = bi->ctx->dev_priv;
497 struct {
498 SVGA3dCmdHeader header;
499 SVGA3dCmdSetShader body;
500 } *cmd;
501
502 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
503 if (unlikely(cmd == NULL)) {
504 DRM_ERROR("Failed reserving FIFO space for shader "
505 "unbinding.\n");
506 return -ENOMEM;
507 }
508
509 cmd->header.id = SVGA_3D_CMD_SET_SHADER;
510 cmd->header.size = sizeof(cmd->body);
511 cmd->body.cid = bi->ctx->id;
512 cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
513 cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
514 vmw_fifo_commit(dev_priv, sizeof(*cmd));
515
516 return 0;
517}
518
519
520
521
522
523
524
525
526static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi,
527 bool rebind)
528{
529 struct vmw_ctx_bindinfo_view *binding =
530 container_of(bi, typeof(*binding), bi);
531 struct vmw_private *dev_priv = bi->ctx->dev_priv;
532 struct {
533 SVGA3dCmdHeader header;
534 SVGA3dCmdSetRenderTarget body;
535 } *cmd;
536
537 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
538 if (unlikely(cmd == NULL)) {
539 DRM_ERROR("Failed reserving FIFO space for render target "
540 "unbinding.\n");
541 return -ENOMEM;
542 }
543
544 cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET;
545 cmd->header.size = sizeof(cmd->body);
546 cmd->body.cid = bi->ctx->id;
547 cmd->body.type = binding->slot;
548 cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
549 cmd->body.target.face = 0;
550 cmd->body.target.mipmap = 0;
551 vmw_fifo_commit(dev_priv, sizeof(*cmd));
552
553 return 0;
554}
555
556
557
558
559
560
561
562
563
564
565static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi,
566 bool rebind)
567{
568 struct vmw_ctx_bindinfo_tex *binding =
569 container_of(bi, typeof(*binding), bi);
570 struct vmw_private *dev_priv = bi->ctx->dev_priv;
571 struct {
572 SVGA3dCmdHeader header;
573 struct {
574 SVGA3dCmdSetTextureState c;
575 SVGA3dTextureState s1;
576 } body;
577 } *cmd;
578
579 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
580 if (unlikely(cmd == NULL)) {
581 DRM_ERROR("Failed reserving FIFO space for texture "
582 "unbinding.\n");
583 return -ENOMEM;
584 }
585
586 cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE;
587 cmd->header.size = sizeof(cmd->body);
588 cmd->body.c.cid = bi->ctx->id;
589 cmd->body.s1.stage = binding->texture_stage;
590 cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
591 cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
592 vmw_fifo_commit(dev_priv, sizeof(*cmd));
593
594 return 0;
595}
596
597
598
599
600
601
602
603static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
604{
605 struct vmw_ctx_bindinfo_shader *binding =
606 container_of(bi, typeof(*binding), bi);
607 struct vmw_private *dev_priv = bi->ctx->dev_priv;
608 struct {
609 SVGA3dCmdHeader header;
610 SVGA3dCmdDXSetShader body;
611 } *cmd;
612
613 cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), bi->ctx->id);
614 if (unlikely(cmd == NULL)) {
615 DRM_ERROR("Failed reserving FIFO space for DX shader "
616 "unbinding.\n");
617 return -ENOMEM;
618 }
619 cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER;
620 cmd->header.size = sizeof(cmd->body);
621 cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
622 cmd->body.shaderId = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
623 vmw_fifo_commit(dev_priv, sizeof(*cmd));
624
625 return 0;
626}
627
628
629
630
631
632
633
634static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind)
635{
636 struct vmw_ctx_bindinfo_cb *binding =
637 container_of(bi, typeof(*binding), bi);
638 struct vmw_private *dev_priv = bi->ctx->dev_priv;
639 struct {
640 SVGA3dCmdHeader header;
641 SVGA3dCmdDXSetSingleConstantBuffer body;
642 } *cmd;
643
644 cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), bi->ctx->id);
645 if (unlikely(cmd == NULL)) {
646 DRM_ERROR("Failed reserving FIFO space for DX shader "
647 "unbinding.\n");
648 return -ENOMEM;
649 }
650
651 cmd->header.id = SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER;
652 cmd->header.size = sizeof(cmd->body);
653 cmd->body.slot = binding->slot;
654 cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
655 if (rebind) {
656 cmd->body.offsetInBytes = binding->offset;
657 cmd->body.sizeInBytes = binding->size;
658 cmd->body.sid = bi->res->id;
659 } else {
660 cmd->body.offsetInBytes = 0;
661 cmd->body.sizeInBytes = 0;
662 cmd->body.sid = SVGA3D_INVALID_ID;
663 }
664 vmw_fifo_commit(dev_priv, sizeof(*cmd));
665
666 return 0;
667}
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683static void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs,
684 const struct vmw_ctx_bindinfo *bi,
685 u32 max_num)
686{
687 const struct vmw_ctx_bindinfo_view *biv =
688 container_of(bi, struct vmw_ctx_bindinfo_view, bi);
689 unsigned long i;
690
691 cbs->bind_cmd_count = 0;
692 cbs->bind_first_slot = 0;
693
694 for (i = 0; i < max_num; ++i, ++biv) {
695 if (!biv->bi.ctx)
696 break;
697
698 cbs->bind_cmd_buffer[cbs->bind_cmd_count++] =
699 ((biv->bi.scrubbed) ?
700 SVGA3D_INVALID_ID : biv->bi.res->id);
701 }
702}
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718static void vmw_collect_dirty_view_ids(struct vmw_ctx_binding_state *cbs,
719 const struct vmw_ctx_bindinfo *bi,
720 unsigned long *dirty,
721 u32 max_num)
722{
723 const struct vmw_ctx_bindinfo_view *biv =
724 container_of(bi, struct vmw_ctx_bindinfo_view, bi);
725 unsigned long i, next_bit;
726
727 cbs->bind_cmd_count = 0;
728 i = find_first_bit(dirty, max_num);
729 next_bit = i;
730 cbs->bind_first_slot = i;
731
732 biv += i;
733 for (; i < max_num; ++i, ++biv) {
734 cbs->bind_cmd_buffer[cbs->bind_cmd_count++] =
735 ((!biv->bi.ctx || biv->bi.scrubbed) ?
736 SVGA3D_INVALID_ID : biv->bi.res->id);
737
738 if (next_bit == i) {
739 next_bit = find_next_bit(dirty, max_num, i + 1);
740 if (next_bit >= max_num)
741 break;
742 }
743 }
744}
745
746
747
748
749
750
751static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs,
752 int shader_slot)
753{
754 const struct vmw_ctx_bindinfo *loc =
755 &cbs->per_shader[shader_slot].shader_res[0].bi;
756 struct {
757 SVGA3dCmdHeader header;
758 SVGA3dCmdDXSetShaderResources body;
759 } *cmd;
760 size_t cmd_size, view_id_size;
761 const struct vmw_resource *ctx = vmw_cbs_context(cbs);
762
763 vmw_collect_dirty_view_ids(cbs, loc,
764 cbs->per_shader[shader_slot].dirty_sr,
765 SVGA3D_DX_MAX_SRVIEWS);
766 if (cbs->bind_cmd_count == 0)
767 return 0;
768
769 view_id_size = cbs->bind_cmd_count*sizeof(uint32);
770 cmd_size = sizeof(*cmd) + view_id_size;
771 cmd = vmw_fifo_reserve_dx(ctx->dev_priv, cmd_size, ctx->id);
772 if (unlikely(cmd == NULL)) {
773 DRM_ERROR("Failed reserving FIFO space for DX shader"
774 " resource binding.\n");
775 return -ENOMEM;
776 }
777
778 cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER_RESOURCES;
779 cmd->header.size = sizeof(cmd->body) + view_id_size;
780 cmd->body.type = shader_slot + SVGA3D_SHADERTYPE_MIN;
781 cmd->body.startView = cbs->bind_first_slot;
782
783 memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);
784
785 vmw_fifo_commit(ctx->dev_priv, cmd_size);
786 bitmap_clear(cbs->per_shader[shader_slot].dirty_sr,
787 cbs->bind_first_slot, cbs->bind_cmd_count);
788
789 return 0;
790}
791
792
793
794
795
796
797static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs)
798{
799 const struct vmw_ctx_bindinfo *loc = &cbs->render_targets[0].bi;
800 struct {
801 SVGA3dCmdHeader header;
802 SVGA3dCmdDXSetRenderTargets body;
803 } *cmd;
804 size_t cmd_size, view_id_size;
805 const struct vmw_resource *ctx = vmw_cbs_context(cbs);
806
807 vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS);
808 view_id_size = cbs->bind_cmd_count*sizeof(uint32);
809 cmd_size = sizeof(*cmd) + view_id_size;
810 cmd = vmw_fifo_reserve_dx(ctx->dev_priv, cmd_size, ctx->id);
811 if (unlikely(cmd == NULL)) {
812 DRM_ERROR("Failed reserving FIFO space for DX render-target"
813 " binding.\n");
814 return -ENOMEM;
815 }
816
817 cmd->header.id = SVGA_3D_CMD_DX_SET_RENDERTARGETS;
818 cmd->header.size = sizeof(cmd->body) + view_id_size;
819
820 if (cbs->ds_view.bi.ctx && !cbs->ds_view.bi.scrubbed)
821 cmd->body.depthStencilViewId = cbs->ds_view.bi.res->id;
822 else
823 cmd->body.depthStencilViewId = SVGA3D_INVALID_ID;
824
825 memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);
826
827 vmw_fifo_commit(ctx->dev_priv, cmd_size);
828
829 return 0;
830
831}
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs,
848 const struct vmw_ctx_bindinfo *bi,
849 u32 max_num)
850{
851 const struct vmw_ctx_bindinfo_so *biso =
852 container_of(bi, struct vmw_ctx_bindinfo_so, bi);
853 unsigned long i;
854 SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer;
855
856 cbs->bind_cmd_count = 0;
857 cbs->bind_first_slot = 0;
858
859 for (i = 0; i < max_num; ++i, ++biso, ++so_buffer,
860 ++cbs->bind_cmd_count) {
861 if (!biso->bi.ctx)
862 break;
863
864 if (!biso->bi.scrubbed) {
865 so_buffer->sid = biso->bi.res->id;
866 so_buffer->offset = biso->offset;
867 so_buffer->sizeInBytes = biso->size;
868 } else {
869 so_buffer->sid = SVGA3D_INVALID_ID;
870 so_buffer->offset = 0;
871 so_buffer->sizeInBytes = 0;
872 }
873 }
874}
875
876
877
878
879
880
881static int vmw_emit_set_so(struct vmw_ctx_binding_state *cbs)
882{
883 const struct vmw_ctx_bindinfo *loc = &cbs->so_targets[0].bi;
884 struct {
885 SVGA3dCmdHeader header;
886 SVGA3dCmdDXSetSOTargets body;
887 } *cmd;
888 size_t cmd_size, so_target_size;
889 const struct vmw_resource *ctx = vmw_cbs_context(cbs);
890
891 vmw_collect_so_targets(cbs, loc, SVGA3D_DX_MAX_SOTARGETS);
892 if (cbs->bind_cmd_count == 0)
893 return 0;
894
895 so_target_size = cbs->bind_cmd_count*sizeof(SVGA3dSoTarget);
896 cmd_size = sizeof(*cmd) + so_target_size;
897 cmd = vmw_fifo_reserve_dx(ctx->dev_priv, cmd_size, ctx->id);
898 if (unlikely(cmd == NULL)) {
899 DRM_ERROR("Failed reserving FIFO space for DX SO target"
900 " binding.\n");
901 return -ENOMEM;
902 }
903
904 cmd->header.id = SVGA_3D_CMD_DX_SET_SOTARGETS;
905 cmd->header.size = sizeof(cmd->body) + so_target_size;
906 memcpy(&cmd[1], cbs->bind_cmd_buffer, so_target_size);
907
908 vmw_fifo_commit(ctx->dev_priv, cmd_size);
909
910 return 0;
911
912}
913
914
915
916
917
918
919
920static int vmw_binding_emit_dirty_ps(struct vmw_ctx_binding_state *cbs)
921{
922 struct vmw_dx_shader_bindings *sb = &cbs->per_shader[0];
923 u32 i;
924 int ret;
925
926 for (i = 0; i < SVGA3D_NUM_SHADERTYPE_DX10; ++i, ++sb) {
927 if (!test_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty))
928 continue;
929
930 ret = vmw_emit_set_sr(cbs, i);
931 if (ret)
932 break;
933
934 __clear_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty);
935 }
936
937 return 0;
938}
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955static void vmw_collect_dirty_vbs(struct vmw_ctx_binding_state *cbs,
956 const struct vmw_ctx_bindinfo *bi,
957 unsigned long *dirty,
958 u32 max_num)
959{
960 const struct vmw_ctx_bindinfo_vb *biv =
961 container_of(bi, struct vmw_ctx_bindinfo_vb, bi);
962 unsigned long i, next_bit;
963 SVGA3dVertexBuffer *vbs = (SVGA3dVertexBuffer *) &cbs->bind_cmd_buffer;
964
965 cbs->bind_cmd_count = 0;
966 i = find_first_bit(dirty, max_num);
967 next_bit = i;
968 cbs->bind_first_slot = i;
969
970 biv += i;
971 for (; i < max_num; ++i, ++biv, ++vbs) {
972 if (!biv->bi.ctx || biv->bi.scrubbed) {
973 vbs->sid = SVGA3D_INVALID_ID;
974 vbs->stride = 0;
975 vbs->offset = 0;
976 } else {
977 vbs->sid = biv->bi.res->id;
978 vbs->stride = biv->stride;
979 vbs->offset = biv->offset;
980 }
981 cbs->bind_cmd_count++;
982 if (next_bit == i) {
983 next_bit = find_next_bit(dirty, max_num, i + 1);
984 if (next_bit >= max_num)
985 break;
986 }
987 }
988}
989
990
991
992
993
994
995
996static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs)
997{
998 const struct vmw_ctx_bindinfo *loc =
999 &cbs->vertex_buffers[0].bi;
1000 struct {
1001 SVGA3dCmdHeader header;
1002 SVGA3dCmdDXSetVertexBuffers body;
1003 } *cmd;
1004 size_t cmd_size, set_vb_size;
1005 const struct vmw_resource *ctx = vmw_cbs_context(cbs);
1006
1007 vmw_collect_dirty_vbs(cbs, loc, cbs->dirty_vb,
1008 SVGA3D_DX_MAX_VERTEXBUFFERS);
1009 if (cbs->bind_cmd_count == 0)
1010 return 0;
1011
1012 set_vb_size = cbs->bind_cmd_count*sizeof(SVGA3dVertexBuffer);
1013 cmd_size = sizeof(*cmd) + set_vb_size;
1014 cmd = vmw_fifo_reserve_dx(ctx->dev_priv, cmd_size, ctx->id);
1015 if (unlikely(cmd == NULL)) {
1016 DRM_ERROR("Failed reserving FIFO space for DX vertex buffer"
1017 " binding.\n");
1018 return -ENOMEM;
1019 }
1020
1021 cmd->header.id = SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS;
1022 cmd->header.size = sizeof(cmd->body) + set_vb_size;
1023 cmd->body.startBuffer = cbs->bind_first_slot;
1024
1025 memcpy(&cmd[1], cbs->bind_cmd_buffer, set_vb_size);
1026
1027 vmw_fifo_commit(ctx->dev_priv, cmd_size);
1028 bitmap_clear(cbs->dirty_vb,
1029 cbs->bind_first_slot, cbs->bind_cmd_count);
1030
1031 return 0;
1032}
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs)
1045{
1046 int ret = 0;
1047 unsigned long hit = 0;
1048
1049 while ((hit = find_next_bit(&cbs->dirty, VMW_BINDING_NUM_BITS, hit))
1050 < VMW_BINDING_NUM_BITS) {
1051
1052 switch (hit) {
1053 case VMW_BINDING_RT_BIT:
1054 ret = vmw_emit_set_rt(cbs);
1055 break;
1056 case VMW_BINDING_PS_BIT:
1057 ret = vmw_binding_emit_dirty_ps(cbs);
1058 break;
1059 case VMW_BINDING_SO_BIT:
1060 ret = vmw_emit_set_so(cbs);
1061 break;
1062 case VMW_BINDING_VB_BIT:
1063 ret = vmw_emit_set_vb(cbs);
1064 break;
1065 default:
1066 BUG();
1067 }
1068 if (ret)
1069 return ret;
1070
1071 __clear_bit(hit, &cbs->dirty);
1072 hit++;
1073 }
1074
1075 return 0;
1076}
1077
1078
1079
1080
1081
1082
1083
1084
1085static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind)
1086{
1087 struct vmw_ctx_bindinfo_view *biv =
1088 container_of(bi, struct vmw_ctx_bindinfo_view, bi);
1089 struct vmw_ctx_binding_state *cbs =
1090 vmw_context_binding_state(bi->ctx);
1091
1092 __set_bit(biv->slot, cbs->per_shader[biv->shader_slot].dirty_sr);
1093 __set_bit(VMW_BINDING_PS_SR_BIT,
1094 &cbs->per_shader[biv->shader_slot].dirty);
1095 __set_bit(VMW_BINDING_PS_BIT, &cbs->dirty);
1096
1097 return 0;
1098}
1099
1100
1101
1102
1103
1104
1105
1106
1107static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind)
1108{
1109 struct vmw_ctx_binding_state *cbs =
1110 vmw_context_binding_state(bi->ctx);
1111
1112 __set_bit(VMW_BINDING_RT_BIT, &cbs->dirty);
1113
1114 return 0;
1115}
1116
1117
1118
1119
1120
1121
1122
1123
1124static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind)
1125{
1126 struct vmw_ctx_binding_state *cbs =
1127 vmw_context_binding_state(bi->ctx);
1128
1129 __set_bit(VMW_BINDING_SO_BIT, &cbs->dirty);
1130
1131 return 0;
1132}
1133
1134
1135
1136
1137
1138
1139
1140
1141static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind)
1142{
1143 struct vmw_ctx_bindinfo_vb *bivb =
1144 container_of(bi, struct vmw_ctx_bindinfo_vb, bi);
1145 struct vmw_ctx_binding_state *cbs =
1146 vmw_context_binding_state(bi->ctx);
1147
1148 __set_bit(bivb->slot, cbs->dirty_vb);
1149 __set_bit(VMW_BINDING_VB_BIT, &cbs->dirty);
1150
1151 return 0;
1152}
1153
1154
1155
1156
1157
1158
1159
1160static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind)
1161{
1162 struct vmw_ctx_bindinfo_ib *binding =
1163 container_of(bi, typeof(*binding), bi);
1164 struct vmw_private *dev_priv = bi->ctx->dev_priv;
1165 struct {
1166 SVGA3dCmdHeader header;
1167 SVGA3dCmdDXSetIndexBuffer body;
1168 } *cmd;
1169
1170 cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), bi->ctx->id);
1171 if (unlikely(cmd == NULL)) {
1172 DRM_ERROR("Failed reserving FIFO space for DX index buffer "
1173 "binding.\n");
1174 return -ENOMEM;
1175 }
1176 cmd->header.id = SVGA_3D_CMD_DX_SET_INDEX_BUFFER;
1177 cmd->header.size = sizeof(cmd->body);
1178 if (rebind) {
1179 cmd->body.sid = bi->res->id;
1180 cmd->body.format = binding->format;
1181 cmd->body.offset = binding->offset;
1182 } else {
1183 cmd->body.sid = SVGA3D_INVALID_ID;
1184 cmd->body.format = 0;
1185 cmd->body.offset = 0;
1186 }
1187
1188 vmw_fifo_commit(dev_priv, sizeof(*cmd));
1189
1190 return 0;
1191}
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201struct vmw_ctx_binding_state *
1202vmw_binding_state_alloc(struct vmw_private *dev_priv)
1203{
1204 struct vmw_ctx_binding_state *cbs;
1205 int ret;
1206
1207 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), sizeof(*cbs),
1208 false, false);
1209 if (ret)
1210 return ERR_PTR(ret);
1211
1212 cbs = vzalloc(sizeof(*cbs));
1213 if (!cbs) {
1214 ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs));
1215 return ERR_PTR(-ENOMEM);
1216 }
1217
1218 cbs->dev_priv = dev_priv;
1219 INIT_LIST_HEAD(&cbs->list);
1220
1221 return cbs;
1222}
1223
1224
1225
1226
1227
1228
1229
1230void vmw_binding_state_free(struct vmw_ctx_binding_state *cbs)
1231{
1232 struct vmw_private *dev_priv = cbs->dev_priv;
1233
1234 vfree(cbs);
1235 ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs));
1236}
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247struct list_head *vmw_binding_state_list(struct vmw_ctx_binding_state *cbs)
1248{
1249 return &cbs->list;
1250}
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs)
1261{
1262 struct vmw_ctx_bindinfo *entry, *next;
1263
1264 list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
1265 vmw_binding_drop(entry);
1266}
1267
1268
1269
1270
1271
1272static void vmw_binding_build_asserts(void)
1273{
1274 BUILD_BUG_ON(SVGA3D_NUM_SHADERTYPE_DX10 != 3);
1275 BUILD_BUG_ON(SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS > SVGA3D_RT_MAX);
1276 BUILD_BUG_ON(sizeof(uint32) != sizeof(u32));
1277
1278
1279
1280
1281
1282 BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_RT_MAX);
1283 BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_SRVIEWS);
1284 BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_CONSTBUFFERS);
1285
1286
1287
1288
1289
1290 BUILD_BUG_ON(SVGA3D_DX_MAX_SOTARGETS*sizeof(SVGA3dSoTarget) >
1291 VMW_MAX_VIEW_BINDINGS*sizeof(u32));
1292 BUILD_BUG_ON(SVGA3D_DX_MAX_VERTEXBUFFERS*sizeof(SVGA3dVertexBuffer) >
1293 VMW_MAX_VIEW_BINDINGS*sizeof(u32));
1294}
1295