Merge branch 'upstream-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 #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 nouveau_winsys *nvws = nv40->nvws;
179 struct nv40_vertex_program *vp = nv40->vertprog.vp;
180 uint32_t inputs, vtxfmt[16];
181 int hw, num_hw;
182
183 inputs = vp->ir;
184 for (hw = 0; hw < 16 && inputs; hw++) {
185 if (inputs & (1 << hw)) {
186 num_hw = hw;
187 inputs &= ~(1 << hw);
188 }
189 }
190 num_hw++;
191
192 inputs = vp->ir;
193 BEGIN_RING(curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw);
194 for (hw = 0; hw < num_hw; hw++) {
195 struct pipe_vertex_element *ve;
196 struct pipe_vertex_buffer *vb;
197
198 if (!(inputs & (1 << hw))) {
199 OUT_RING(0);
200 vtxfmt[hw] = NV40TCL_VTXFMT_TYPE_FLOAT;
201 continue;
202 }
203
204 ve = &nv40->vtxelt[hw];
205 vb = &nv40->vtxbuf[ve->vertex_buffer_index];
206
207 OUT_RELOC(vb->buffer, vb->buffer_offset + ve->src_offset,
208 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW |
209 NOUVEAU_BO_OR | NOUVEAU_BO_RD, 0,
210 NV40TCL_VTXBUF_ADDRESS_DMA1);
211 vtxfmt[hw] = ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
212 (nv40_vbo_format_to_ncomp(ve->src_format) <<
213 NV40TCL_VTXFMT_SIZE_SHIFT) |
214 NV40TCL_VTXFMT_TYPE_FLOAT);
215 }
216
217 BEGIN_RING(curie, 0x1710, 1);
218 OUT_RING (0); /* vtx cache flush */
219 BEGIN_RING(curie, NV40TCL_VTXFMT(0), num_hw);
220 OUT_RINGp (vtxfmt, num_hw);
221 }
222