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