nouveau: g8x winsys support, yay softpipe!
[mesa.git] / src / mesa / pipe / nv40 / nv40_vbo.c
1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "pipe/p_util.h"
4
5 #include "nv40_context.h"
6 #include "nv40_dma.h"
7 #include "nv40_state.h"
8 #include "nvgl_pipe.h"
9
10 boolean
11 nv40_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
12 unsigned count)
13 {
14 struct nv40_context *nv40 = (struct nv40_context *)pipe;
15 unsigned nr;
16
17 if (nv40->dirty)
18 nv40_emit_hw_state(nv40);
19
20 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
21 OUT_RING (nvgl_primitive(mode));
22
23 nr = (count & 0xff);
24 if (nr) {
25 BEGIN_RING(curie, NV40TCL_VB_VERTEX_BATCH, 1);
26 OUT_RING (((nr - 1) << 24) | start);
27 start += nr;
28 }
29
30 /*XXX: large arrays (nr>2047) will blow up */
31 nr = count >> 8;
32 if (nr) {
33 assert (nr <= 2047);
34
35 BEGIN_RING_NI(curie, NV40TCL_VB_VERTEX_BATCH, nr);
36 while (nr--) {
37 OUT_RING(((0x100 - 1) << 24) | start);
38 start += 0x100;
39 }
40 }
41
42 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
43 OUT_RING (0);
44
45 pipe->flush(pipe, PIPE_FLUSH_WAIT);
46 return TRUE;
47 }
48
49 static INLINE void
50 nv40_draw_elements_u08(struct nv40_context *nv40, void *ib,
51 unsigned start, unsigned count)
52 {
53 uint8_t *elts = (uint8_t *)ib + start;
54 int push, i;
55
56 if (count & 1) {
57 BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
58 OUT_RING (elts[0]);
59 elts++; count--;
60 }
61
62 while (count) {
63 push = MIN2(count, 2046);
64
65 BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push);
66 for (i = 0; i < push; i+=2)
67 OUT_RING((elts[i+1] << 16) | elts[i]);
68
69 count -= push;
70 elts += push;
71 }
72 }
73
74 static INLINE void
75 nv40_draw_elements_u16(struct nv40_context *nv40, void *ib,
76 unsigned start, unsigned count)
77 {
78 uint16_t *elts = (uint16_t *)ib + start;
79 int push, i;
80
81 if (count & 1) {
82 BEGIN_RING(curie, NV40TCL_VB_ELEMENT_U32, 1);
83 OUT_RING (elts[0]);
84 elts++; count--;
85 }
86
87 while (count) {
88 push = MIN2(count, 2046);
89
90 BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U16, push);
91 for (i = 0; i < push; i+=2)
92 OUT_RING((elts[i+1] << 16) | elts[i]);
93
94 count -= push;
95 elts += push;
96 }
97 }
98
99 static INLINE void
100 nv40_draw_elements_u32(struct nv40_context *nv40, void *ib,
101 unsigned start, unsigned count)
102 {
103 uint32_t *elts = (uint32_t *)ib + start;
104 int push;
105
106 while (count) {
107 push = MIN2(count, 2047);
108
109 BEGIN_RING_NI(curie, NV40TCL_VB_ELEMENT_U32, push);
110 OUT_RINGp (elts, push);
111
112 count -= push;
113 elts += push;
114 }
115 }
116
117 boolean
118 nv40_draw_elements(struct pipe_context *pipe,
119 struct pipe_buffer_handle *indexBuffer, unsigned indexSize,
120 unsigned mode, unsigned start, unsigned count)
121 {
122 struct nv40_context *nv40 = (struct nv40_context *)pipe;
123 void *ib;
124
125 if (nv40->dirty)
126 nv40_emit_hw_state(nv40);
127
128 ib = pipe->winsys->buffer_map(pipe->winsys, indexBuffer,
129 PIPE_BUFFER_FLAG_READ);
130 if (!ib) {
131 NOUVEAU_ERR("Couldn't map index buffer!!\n");
132 return FALSE;
133 }
134
135 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
136 OUT_RING (nvgl_primitive(mode));
137
138 switch (indexSize) {
139 case 1:
140 nv40_draw_elements_u08(nv40, ib, start, count);
141 break;
142 case 2:
143 nv40_draw_elements_u16(nv40, ib, start, count);
144 break;
145 case 4:
146 nv40_draw_elements_u32(nv40, ib, start, count);
147 break;
148 default:
149 NOUVEAU_ERR("unsupported elt size %d\n", indexSize);
150 break;
151 }
152
153 BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
154 OUT_RING (0);
155
156 pipe->winsys->buffer_unmap(pipe->winsys, ib);
157 pipe->flush(pipe, PIPE_FLUSH_WAIT);
158 return TRUE;
159 }
160
161 static INLINE int
162 nv40_vbo_format_to_ncomp(uint format)
163 {
164 switch (format) {
165 case PIPE_FORMAT_R32G32B32A32_FLOAT: return 4;
166 case PIPE_FORMAT_R32G32B32_FLOAT: return 3;
167 case PIPE_FORMAT_R32G32_FLOAT: return 2;
168 case PIPE_FORMAT_R32_FLOAT: return 1;
169 default:
170 NOUVEAU_ERR("AII, unknown vbo format %d\n", format);
171 return 1;
172 }
173 }
174
175 void
176 nv40_vbo_arrays_update(struct nv40_context *nv40)
177 {
178 struct nv40_vertex_program *vp = nv40->vertprog.active;
179 uint32_t inputs, vtxfmt[16];
180 int hw, num_hw;
181
182 inputs = vp->ir;
183 for (hw = 0; hw < 16 && inputs; hw++) {
184 if (inputs & (1 << hw)) {
185 num_hw = hw;
186 inputs &= ~(1 << hw);
187 }
188 }
189 num_hw++;
190
191 inputs = vp->ir;
192 BEGIN_RING(curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw);
193 for (hw = 0; hw < num_hw; hw++) {
194 struct pipe_vertex_element *ve;
195 struct pipe_vertex_buffer *vb;
196
197 if (!(inputs & (1 << hw))) {
198 OUT_RING(0);
199 vtxfmt[hw] = NV40TCL_VTXFMT_TYPE_FLOAT;
200 continue;
201 }
202
203 ve = &nv40->vtxelt[hw];
204 vb = &nv40->vtxbuf[ve->vertex_buffer_index];
205
206 OUT_RELOC(vb->buffer, vb->buffer_offset + ve->src_offset,
207 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW |
208 NOUVEAU_BO_OR | NOUVEAU_BO_RD, 0,
209 NV40TCL_VTXBUF_ADDRESS_DMA1);
210 vtxfmt[hw] = ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
211 (nv40_vbo_format_to_ncomp(ve->src_format) <<
212 NV40TCL_VTXFMT_SIZE_SHIFT) |
213 NV40TCL_VTXFMT_TYPE_FLOAT);
214 }
215
216 BEGIN_RING(curie, 0x1710, 1);
217 OUT_RING (0); /* vtx cache flush */
218 BEGIN_RING(curie, NV40TCL_VTXFMT(0), num_hw);
219 OUT_RINGp (vtxfmt, num_hw);
220 }
221