1 #include "pipe/p_shader_tokens.h"
3 #include "util/u_pack_color.h"
5 #include "draw/draw_context.h"
6 #include "draw/draw_vertex.h"
7 #include "draw/draw_pipe.h"
9 #include "nv40_context.h"
10 #define NV40_SHADER_NO_FUCKEDNESS
11 #include "nv40_shader.h"
13 /* Simple, but crappy, swtnl path, hopefully we wont need to hit this very
14 * often at all. Uses "quadro style" vertex submission + a fixed vertex
15 * layout to avoid the need to generate a vertex program or vtxfmt.
18 struct nv40_render_stage
{
19 struct draw_stage stage
;
20 struct nv40_context
*nv40
;
24 static INLINE
struct nv40_render_stage
*
25 nv40_render_stage(struct draw_stage
*stage
)
27 return (struct nv40_render_stage
*)stage
;
31 nv40_render_vertex(struct nv40_context
*nv40
, const struct vertex_header
*v
)
35 for (i
= 0; i
< nv40
->swtnl
.nr_attribs
; i
++) {
36 unsigned idx
= nv40
->swtnl
.draw
[i
];
37 unsigned hw
= nv40
->swtnl
.hw
[i
];
39 switch (nv40
->swtnl
.emit
[i
]) {
43 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_1F(hw
), 1);
44 OUT_RING (fui(v
->data
[idx
][0]));
47 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_2F_X(hw
), 2);
48 OUT_RING (fui(v
->data
[idx
][0]));
49 OUT_RING (fui(v
->data
[idx
][1]));
52 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_3F_X(hw
), 3);
53 OUT_RING (fui(v
->data
[idx
][0]));
54 OUT_RING (fui(v
->data
[idx
][1]));
55 OUT_RING (fui(v
->data
[idx
][2]));
58 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_4F_X(hw
), 4);
59 OUT_RING (fui(v
->data
[idx
][0]));
60 OUT_RING (fui(v
->data
[idx
][1]));
61 OUT_RING (fui(v
->data
[idx
][2]));
62 OUT_RING (fui(v
->data
[idx
][3]));
65 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_4UB(hw
), 1);
66 OUT_RING (pack_ub4(float_to_ubyte(v
->data
[idx
][0]),
67 float_to_ubyte(v
->data
[idx
][1]),
68 float_to_ubyte(v
->data
[idx
][2]),
69 float_to_ubyte(v
->data
[idx
][3])));
79 nv40_render_prim(struct draw_stage
*stage
, struct prim_header
*prim
,
80 unsigned mode
, unsigned count
)
82 struct nv40_render_stage
*rs
= nv40_render_stage(stage
);
83 struct nv40_context
*nv40
= rs
->nv40
;
84 struct nouveau_pushbuf
*pb
= nv40
->nvws
->channel
->pushbuf
;
87 /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
88 if (pb
->remaining
< ((count
* 20) + 6)) {
89 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
90 NOUVEAU_ERR("AIII, missed flush\n");
94 nv40_state_emit(nv40
);
97 /* Switch primitive modes if necessary */
98 if (rs
->prim
!= mode
) {
99 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
100 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
101 OUT_RING (NV40TCL_BEGIN_END_STOP
);
104 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
109 /* Emit vertex data */
110 for (i
= 0; i
< count
; i
++)
111 nv40_render_vertex(nv40
, prim
->v
[i
]);
113 /* If it's likely we'll need to empty the push buffer soon, finish
114 * off the primitive now.
116 if (pb
->remaining
< ((count
* 20) + 6)) {
117 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
118 OUT_RING (NV40TCL_BEGIN_END_STOP
);
119 rs
->prim
= NV40TCL_BEGIN_END_STOP
;
124 nv40_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
126 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_POINTS
, 1);
130 nv40_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
132 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_LINES
, 2);
136 nv40_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
138 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_TRIANGLES
, 3);
142 nv40_render_flush(struct draw_stage
*draw
, unsigned flags
)
144 struct nv40_render_stage
*rs
= nv40_render_stage(draw
);
145 struct nv40_context
*nv40
= rs
->nv40
;
147 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
148 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
149 OUT_RING (NV40TCL_BEGIN_END_STOP
);
150 rs
->prim
= NV40TCL_BEGIN_END_STOP
;
155 nv40_render_reset_stipple_counter(struct draw_stage
*draw
)
160 nv40_render_destroy(struct draw_stage
*draw
)
166 emit_mov(struct nv40_vertex_program
*vp
,
167 unsigned dst
, unsigned src
, unsigned vor
, unsigned mask
)
169 struct nv40_vertex_program_exec
*inst
;
171 vp
->insns
= realloc(vp
->insns
,
172 sizeof(struct nv40_vertex_program_exec
) *
174 inst
= &vp
->insns
[vp
->nr_insns
- 1];
176 inst
->data
[0] = 0x401f9c6c;
177 inst
->data
[1] = 0x0040000d | (src
<< 8);
178 inst
->data
[2] = 0x8106c083;
179 inst
->data
[3] = 0x6041ff80 | (dst
<< 2) | (mask
<< 13);
180 inst
->const_index
= -1;
181 inst
->has_branch_offset
= FALSE
;
183 vp
->ir
|= (1 << src
);
185 vp
->or |= (1 << vor
);
188 static struct nv40_vertex_program
*
189 create_drawvp(struct nv40_context
*nv40
)
191 struct nv40_vertex_program
*vp
= CALLOC_STRUCT(nv40_vertex_program
);
194 emit_mov(vp
, NV40_VP_INST_DEST_POS
, 0, ~0, 0xf);
195 emit_mov(vp
, NV40_VP_INST_DEST_COL0
, 3, 0, 0xf);
196 emit_mov(vp
, NV40_VP_INST_DEST_COL1
, 4, 1, 0xf);
197 emit_mov(vp
, NV40_VP_INST_DEST_BFC0
, 3, 2, 0xf);
198 emit_mov(vp
, NV40_VP_INST_DEST_BFC1
, 4, 3, 0xf);
199 emit_mov(vp
, NV40_VP_INST_DEST_FOGC
, 5, 4, 0x8);
200 for (i
= 0; i
< 8; i
++)
201 emit_mov(vp
, NV40_VP_INST_DEST_TC(i
), 8 + i
, 14 + i
, 0xf);
203 vp
->insns
[vp
->nr_insns
- 1].data
[3] |= 1;
204 vp
->translated
= TRUE
;
209 nv40_draw_render_stage(struct nv40_context
*nv40
)
211 struct nv40_render_stage
*render
= CALLOC_STRUCT(nv40_render_stage
);
213 if (!nv40
->swtnl
.vertprog
)
214 nv40
->swtnl
.vertprog
= create_drawvp(nv40
);
217 render
->stage
.draw
= nv40
->draw
;
218 render
->stage
.point
= nv40_render_point
;
219 render
->stage
.line
= nv40_render_line
;
220 render
->stage
.tri
= nv40_render_tri
;
221 render
->stage
.flush
= nv40_render_flush
;
222 render
->stage
.reset_stipple_counter
= nv40_render_reset_stipple_counter
;
223 render
->stage
.destroy
= nv40_render_destroy
;
225 return &render
->stage
;
229 nv40_draw_elements_swtnl(struct pipe_context
*pipe
,
230 struct pipe_buffer
*idxbuf
, unsigned idxbuf_size
,
231 unsigned mode
, unsigned start
, unsigned count
)
233 struct nv40_context
*nv40
= nv40_context(pipe
);
234 struct pipe_winsys
*ws
= pipe
->winsys
;
238 if (!nv40_state_validate_swtnl(nv40
))
240 nv40
->state
.dirty
&= ~(1ULL << NV40_STATE_VTXBUF
);
241 nv40_state_emit(nv40
);
243 for (i
= 0; i
< nv40
->vtxbuf_nr
; i
++) {
244 map
= ws
->buffer_map(ws
, nv40
->vtxbuf
[i
].buffer
,
245 PIPE_BUFFER_USAGE_CPU_READ
);
246 draw_set_mapped_vertex_buffer(nv40
->draw
, i
, map
);
250 map
= ws
->buffer_map(ws
, idxbuf
, PIPE_BUFFER_USAGE_CPU_READ
);
251 draw_set_mapped_element_buffer(nv40
->draw
, idxbuf_size
, map
);
253 draw_set_mapped_element_buffer(nv40
->draw
, 0, NULL
);
256 if (nv40
->constbuf
[PIPE_SHADER_VERTEX
]) {
257 const unsigned nr
= nv40
->constbuf_nr
[PIPE_SHADER_VERTEX
];
259 map
= ws
->buffer_map(ws
, nv40
->constbuf
[PIPE_SHADER_VERTEX
],
260 PIPE_BUFFER_USAGE_CPU_READ
);
261 draw_set_mapped_constant_buffer(nv40
->draw
, map
, nr
);
264 draw_arrays(nv40
->draw
, mode
, start
, count
);
266 for (i
= 0; i
< nv40
->vtxbuf_nr
; i
++)
267 ws
->buffer_unmap(ws
, nv40
->vtxbuf
[i
].buffer
);
270 ws
->buffer_unmap(ws
, idxbuf
);
272 if (nv40
->constbuf
[PIPE_SHADER_VERTEX
])
273 ws
->buffer_unmap(ws
, nv40
->constbuf
[PIPE_SHADER_VERTEX
]);
275 draw_flush(nv40
->draw
);
276 pipe
->flush(pipe
, 0, NULL
);
282 emit_attrib(struct nv40_context
*nv40
, unsigned hw
, unsigned emit
,
283 unsigned semantic
, unsigned index
)
285 unsigned draw_out
= draw_find_vs_output(nv40
->draw
, semantic
, index
);
286 unsigned a
= nv40
->swtnl
.nr_attribs
++;
288 nv40
->swtnl
.hw
[a
] = hw
;
289 nv40
->swtnl
.emit
[a
] = emit
;
290 nv40
->swtnl
.draw
[a
] = draw_out
;
294 nv40_state_vtxfmt_validate(struct nv40_context
*nv40
)
296 struct nv40_fragment_program
*fp
= nv40
->fragprog
;
297 unsigned colour
= 0, texcoords
= 0, fog
= 0, i
;
299 /* Determine needed fragprog inputs */
300 for (i
= 0; i
< fp
->info
.num_inputs
; i
++) {
301 switch (fp
->info
.input_semantic_name
[i
]) {
302 case TGSI_SEMANTIC_POSITION
:
304 case TGSI_SEMANTIC_COLOR
:
305 colour
|= (1 << fp
->info
.input_semantic_index
[i
]);
307 case TGSI_SEMANTIC_GENERIC
:
308 texcoords
|= (1 << fp
->info
.input_semantic_index
[i
]);
310 case TGSI_SEMANTIC_FOG
:
318 nv40
->swtnl
.nr_attribs
= 0;
320 /* Map draw vtxprog output to hw attribute IDs */
321 for (i
= 0; i
< 2; i
++) {
322 if (!(colour
& (1 << i
)))
324 emit_attrib(nv40
, 3 + i
, EMIT_4UB
, TGSI_SEMANTIC_COLOR
, i
);
327 for (i
= 0; i
< 8; i
++) {
328 if (!(texcoords
& (1 << i
)))
330 emit_attrib(nv40
, 8 + i
, EMIT_4F
, TGSI_SEMANTIC_GENERIC
, i
);
334 emit_attrib(nv40
, 5, EMIT_1F
, TGSI_SEMANTIC_FOG
, 0);
337 emit_attrib(nv40
, 0, EMIT_3F
, TGSI_SEMANTIC_POSITION
, 0);
342 struct nv40_state_entry nv40_state_vtxfmt
= {
343 .validate
= nv40_state_vtxfmt_validate
,
345 .pipe
= NV40_NEW_ARRAYS
| NV40_NEW_FRAGPROG
,