3f0b66ae3659cff30e601c01c6a3a272ad731153
[mesa.git] / src / gallium / drivers / nv50 / nv50_vbo.c
1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "pipe/p_util.h"
4
5 #include "nv50_context.h"
6
7 static INLINE unsigned
8 nv50_prim(unsigned mode)
9 {
10 switch (mode) {
11 case PIPE_PRIM_POINTS: return NV50TCL_VERTEX_BEGIN_POINTS;
12 case PIPE_PRIM_LINES: return NV50TCL_VERTEX_BEGIN_LINES;
13 case PIPE_PRIM_LINE_LOOP: return NV50TCL_VERTEX_BEGIN_LINE_LOOP;
14 case PIPE_PRIM_LINE_STRIP: return NV50TCL_VERTEX_BEGIN_LINE_STRIP;
15 case PIPE_PRIM_TRIANGLES: return NV50TCL_VERTEX_BEGIN_TRIANGLES;
16 case PIPE_PRIM_TRIANGLE_STRIP:
17 return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP;
18 case PIPE_PRIM_TRIANGLE_FAN: return NV50TCL_VERTEX_BEGIN_TRIANGLE_FAN;
19 case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS;
20 case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP;
21 case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON;
22 default:
23 break;
24 }
25
26 NOUVEAU_ERR("invalid primitive type %d\n", mode);
27 return NV50TCL_VERTEX_BEGIN_POINTS;
28 }
29
30 boolean
31 nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
32 unsigned count)
33 {
34 struct nv50_context *nv50 = nv50_context(pipe);
35
36 nv50_state_validate(nv50);
37
38 BEGIN_RING(tesla, 0x142c, 1);
39 OUT_RING (0);
40 BEGIN_RING(tesla, 0x142c, 1);
41 OUT_RING (0);
42
43 BEGIN_RING(tesla, NV50TCL_VERTEX_BEGIN, 1);
44 OUT_RING (nv50_prim(mode));
45 BEGIN_RING(tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2);
46 OUT_RING (start);
47 OUT_RING (count);
48 BEGIN_RING(tesla, NV50TCL_VERTEX_END, 1);
49 OUT_RING (0);
50
51 pipe->flush(pipe, 0, NULL);
52 return TRUE;
53 }
54
55 static INLINE void
56 nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map,
57 unsigned start, unsigned count)
58 {
59 map += start;
60
61 if (count & 1) {
62 BEGIN_RING(tesla, 0x15e8, 1);
63 OUT_RING (map[0]);
64 map++;
65 count--;
66 }
67
68 while (count) {
69 unsigned nr = count > 2046 ? 2046 : count;
70 int i;
71
72 BEGIN_RING(tesla, 0x400015f0, nr >> 1);
73 for (i = 0; i < nr; i += 2)
74 OUT_RING ((map[1] << 16) | map[0]);
75
76 count -= nr;
77 map += nr;
78 }
79 }
80
81 static INLINE void
82 nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map,
83 unsigned start, unsigned count)
84 {
85 map += start;
86
87 if (count & 1) {
88 BEGIN_RING(tesla, 0x15e8, 1);
89 OUT_RING (map[0]);
90 map++;
91 count--;
92 }
93
94 while (count) {
95 unsigned nr = count > 2046 ? 2046 : count;
96 int i;
97
98 BEGIN_RING(tesla, 0x400015f0, nr >> 1);
99 for (i = 0; i < nr; i += 2)
100 OUT_RING ((map[1] << 16) | map[0]);
101
102 count -= nr;
103 map += nr;
104 }
105 }
106
107 static INLINE void
108 nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint8_t *map,
109 unsigned start, unsigned count)
110 {
111 map += start;
112
113 while (count) {
114 unsigned nr = count > 2047 ? 2047 : count;
115
116 BEGIN_RING(tesla, 0x400015e8, nr);
117 OUT_RINGp (map, nr);
118
119 count -= nr;
120 map += nr;
121 }
122 }
123
124 boolean
125 nv50_draw_elements(struct pipe_context *pipe,
126 struct pipe_buffer *indexBuffer, unsigned indexSize,
127 unsigned mode, unsigned start, unsigned count)
128 {
129 struct nv50_context *nv50 = nv50_context(pipe);
130 struct pipe_winsys *ws = pipe->winsys;
131 void *map = ws->buffer_map(ws, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ);
132
133 nv50_state_validate(nv50);
134
135 BEGIN_RING(tesla, 0x142c, 1);
136 OUT_RING (0);
137 BEGIN_RING(tesla, 0x142c, 1);
138 OUT_RING (0);
139
140 BEGIN_RING(tesla, NV50TCL_VERTEX_BEGIN, 1);
141 OUT_RING (nv50_prim(mode));
142 switch (indexSize) {
143 case 1:
144 nv50_draw_elements_inline_u08(nv50, map, start, count);
145 break;
146 case 2:
147 nv50_draw_elements_inline_u16(nv50, map, start, count);
148 break;
149 case 4:
150 nv50_draw_elements_inline_u32(nv50, map, start, count);
151 break;
152 default:
153 assert(0);
154 }
155 BEGIN_RING(tesla, NV50TCL_VERTEX_END, 1);
156 OUT_RING (0);
157
158 pipe->flush(pipe, 0, NULL);
159 return TRUE;
160 }
161
162 void
163 nv50_vbo_validate(struct nv50_context *nv50)
164 {
165 struct nouveau_grobj *tesla = nv50->screen->tesla;
166 struct nouveau_stateobj *vtxbuf, *vtxfmt;
167 int i, vpi = 0;
168
169 vtxbuf = so_new(nv50->vtxelt_nr * 4, nv50->vtxelt_nr * 2);
170 vtxfmt = so_new(nv50->vtxelt_nr + 1, 0);
171 so_method(vtxfmt, tesla, 0x1ac0, nv50->vtxelt_nr);
172
173 for (i = 0; i < nv50->vtxelt_nr; i++) {
174 struct pipe_vertex_element *ve = &nv50->vtxelt[i];
175 struct pipe_vertex_buffer *vb =
176 &nv50->vtxbuf[ve->vertex_buffer_index];
177
178 switch (ve->src_format) {
179 case PIPE_FORMAT_R32G32B32A32_FLOAT:
180 so_data(vtxfmt, 0x7e080000 | i);
181 break;
182 case PIPE_FORMAT_R32G32B32_FLOAT:
183 so_data(vtxfmt, 0x7e100000 | i);
184 break;
185 case PIPE_FORMAT_R32G32_FLOAT:
186 so_data(vtxfmt, 0x7e200000 | i);
187 break;
188 case PIPE_FORMAT_R8G8B8A8_UNORM:
189 so_data(vtxfmt, 0x24500000 | i);
190 break;
191 default:
192 {
193 char fmt[128];
194 pf_sprint_name(fmt, ve->src_format);
195 NOUVEAU_ERR("invalid vbo format %s\n", fmt);
196 assert(0);
197 return;
198 }
199 }
200
201 so_method(vtxbuf, tesla, 0x900 + (i * 16), 3);
202 so_data (vtxbuf, 0x20000000 | vb->pitch);
203 so_reloc (vtxbuf, vb->buffer, vb->buffer_offset +
204 ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
205 NOUVEAU_BO_HIGH, 0, 0);
206 so_reloc (vtxbuf, vb->buffer, vb->buffer_offset +
207 ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
208 NOUVEAU_BO_LOW, 0, 0);
209 }
210
211 so_ref (vtxfmt, &nv50->state.vtxfmt);
212 so_ref (vtxbuf, &nv50->state.vtxbuf);
213 }
214