1 #include "pipe/p_util.h"
2 #include "pipe/p_shader_tokens.h"
4 #include "draw/draw_context.h"
5 #include "draw/draw_vertex.h"
6 #include "draw/draw_private.h"
8 #include "nv40_context.h"
9 #define NV40_SHADER_NO_FUCKEDNESS
10 #include "nv40_shader.h"
12 /* Simple, but crappy, swtnl path, hopefully we wont need to hit this very
13 * often at all. Uses "quadro style" vertex submission + a fixed vertex
14 * layout to avoid the need to generate a vertex program or vtxfmt.
17 struct nv40_render_stage
{
18 struct draw_stage stage
;
19 struct nv40_context
*nv40
;
23 static INLINE
struct nv40_render_stage
*
24 nv40_render_stage(struct draw_stage
*stage
)
26 return (struct nv40_render_stage
*)stage
;
30 nv40_render_vertex(struct nv40_context
*nv40
, const struct vertex_header
*v
)
34 for (i
= 0; i
< nv40
->swtnl
.nr_attribs
; i
++) {
35 unsigned idx
= nv40
->swtnl
.draw
[i
];
36 unsigned hw
= nv40
->swtnl
.hw
[i
];
38 switch (nv40
->swtnl
.emit
[i
]) {
42 BEGIN_RING(curie
, 0x1e40 + (hw
* 4), 1);
43 OUT_RING (fui(v
->data
[idx
][0]));
46 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_2F_X(hw
), 2);
47 OUT_RING (fui(v
->data
[idx
][0]));
48 OUT_RING (fui(v
->data
[idx
][1]));
51 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_3F_X(hw
), 3);
52 OUT_RING (fui(v
->data
[idx
][0]));
53 OUT_RING (fui(v
->data
[idx
][1]));
54 OUT_RING (fui(v
->data
[idx
][2]));
57 BEGIN_RING(curie
, NV40TCL_VTX_ATTR_4F_X(hw
), 4);
58 OUT_RING (fui(v
->data
[idx
][0]));
59 OUT_RING (fui(v
->data
[idx
][1]));
60 OUT_RING (fui(v
->data
[idx
][2]));
61 OUT_RING (fui(v
->data
[idx
][3]));
64 BEGIN_RING(curie
, 0x1940 + (hw
* 4), 1);
65 OUT_RING (pack_ub4(float_to_ubyte(v
->data
[idx
][0]),
66 float_to_ubyte(v
->data
[idx
][1]),
67 float_to_ubyte(v
->data
[idx
][2]),
68 float_to_ubyte(v
->data
[idx
][3])));
78 nv40_render_prim(struct draw_stage
*stage
, struct prim_header
*prim
,
79 unsigned mode
, unsigned count
)
81 struct nv40_render_stage
*rs
= nv40_render_stage(stage
);
82 struct nv40_context
*nv40
= rs
->nv40
;
83 struct nouveau_pushbuf
*pb
= nv40
->nvws
->channel
->pushbuf
;
86 /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
87 if (pb
->remaining
< ((count
* 20) + 6)) {
88 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
89 NOUVEAU_ERR("AIII, missed flush\n");
93 nv40_state_emit(nv40
);
96 /* Switch primitive modes if necessary */
97 if (rs
->prim
!= mode
) {
98 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
99 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
100 OUT_RING (NV40TCL_BEGIN_END_STOP
);
103 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
108 /* Emit vertex data */
109 for (i
= 0; i
< count
; i
++)
110 nv40_render_vertex(nv40
, prim
->v
[i
]);
112 /* If it's likely we'll need to empty the push buffer soon, finish
113 * off the primitive now.
115 if (pb
->remaining
< ((count
* 20) + 6)) {
116 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
117 OUT_RING (NV40TCL_BEGIN_END_STOP
);
118 rs
->prim
= NV40TCL_BEGIN_END_STOP
;
123 nv40_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
125 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_POINTS
, 1);
129 nv40_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
131 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_LINES
, 2);
135 nv40_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
137 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_TRIANGLES
, 3);
141 nv40_render_flush(struct draw_stage
*draw
, unsigned flags
)
143 struct nv40_render_stage
*rs
= nv40_render_stage(draw
);
144 struct nv40_context
*nv40
= rs
->nv40
;
146 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
147 BEGIN_RING(curie
, NV40TCL_BEGIN_END
, 1);
148 OUT_RING (NV40TCL_BEGIN_END_STOP
);
149 rs
->prim
= NV40TCL_BEGIN_END_STOP
;
154 nv40_render_reset_stipple_counter(struct draw_stage
*draw
)
159 nv40_render_destroy(struct draw_stage
*draw
)
165 emit_mov(struct nv40_vertex_program
*vp
,
166 unsigned dst
, unsigned src
, unsigned vor
, unsigned mask
)
168 struct nv40_vertex_program_exec
*inst
;
170 vp
->insns
= realloc(vp
->insns
,
171 sizeof(struct nv40_vertex_program_exec
) *
173 inst
= &vp
->insns
[vp
->nr_insns
- 1];
175 inst
->data
[0] = 0x401f9c6c;
176 inst
->data
[1] = 0x0040000d | (src
<< 8);
177 inst
->data
[2] = 0x8106c083;
178 inst
->data
[3] = 0x6041ff80 | (dst
<< 2) | (mask
<< 13);
179 inst
->const_index
= -1;
180 inst
->has_branch_offset
= FALSE
;
182 vp
->ir
|= (1 << src
);
184 vp
->or |= (1 << vor
);
187 static struct nv40_vertex_program
*
188 create_drawvp(struct nv40_context
*nv40
)
190 struct nv40_vertex_program
*vp
= CALLOC_STRUCT(nv40_vertex_program
);
193 emit_mov(vp
, NV40_VP_INST_DEST_POS
, 0, ~0, 0xf);
194 emit_mov(vp
, NV40_VP_INST_DEST_COL0
, 3, 0, 0xf);
195 emit_mov(vp
, NV40_VP_INST_DEST_COL1
, 4, 1, 0xf);
196 emit_mov(vp
, NV40_VP_INST_DEST_BFC0
, 3, 2, 0xf);
197 emit_mov(vp
, NV40_VP_INST_DEST_BFC1
, 4, 3, 0xf);
198 emit_mov(vp
, NV40_VP_INST_DEST_FOGC
, 5, 4, 0x8);
199 for (i
= 0; i
< 8; i
++)
200 emit_mov(vp
, NV40_VP_INST_DEST_TC(i
), 8 + i
, 14 + i
, 0xf);
202 vp
->insns
[vp
->nr_insns
- 1].data
[3] |= 1;
203 vp
->translated
= TRUE
;
208 nv40_draw_render_stage(struct nv40_context
*nv40
)
210 struct nv40_render_stage
*render
= CALLOC_STRUCT(nv40_render_stage
);
212 if (!nv40
->swtnl
.vertprog
)
213 nv40
->swtnl
.vertprog
= create_drawvp(nv40
);
216 render
->stage
.draw
= nv40
->draw
;
217 render
->stage
.point
= nv40_render_point
;
218 render
->stage
.line
= nv40_render_line
;
219 render
->stage
.tri
= nv40_render_tri
;
220 render
->stage
.flush
= nv40_render_flush
;
221 render
->stage
.reset_stipple_counter
= nv40_render_reset_stipple_counter
;
222 render
->stage
.destroy
= nv40_render_destroy
;
224 return &render
->stage
;
228 nv40_draw_elements_swtnl(struct pipe_context
*pipe
,
229 struct pipe_buffer
*idxbuf
, unsigned idxbuf_size
,
230 unsigned mode
, unsigned start
, unsigned count
)
232 struct nv40_context
*nv40
= nv40_context(pipe
);
233 struct pipe_winsys
*ws
= pipe
->winsys
;
237 if (!nv40_state_validate_swtnl(nv40
))
239 nv40
->state
.dirty
&= ~(1ULL << NV40_STATE_VTXBUF
);
240 nv40_state_emit(nv40
);
242 for (i
= 0; i
< PIPE_ATTRIB_MAX
; i
++) {
243 if (!nv40
->vtxbuf
[i
].buffer
)
245 map
= ws
->buffer_map(ws
, nv40
->vtxbuf
[i
].buffer
,
246 PIPE_BUFFER_USAGE_CPU_READ
);
247 draw_set_mapped_vertex_buffer(nv40
->draw
, i
, map
);
251 map
= ws
->buffer_map(ws
, idxbuf
, PIPE_BUFFER_USAGE_CPU_READ
);
252 draw_set_mapped_element_buffer(nv40
->draw
, idxbuf_size
, map
);
254 draw_set_mapped_element_buffer(nv40
->draw
, 0, NULL
);
257 if (nv40
->constbuf
[PIPE_SHADER_VERTEX
]) {
258 map
= ws
->buffer_map(ws
, nv40
->constbuf
[PIPE_SHADER_VERTEX
],
259 PIPE_BUFFER_USAGE_CPU_READ
);
260 draw_set_mapped_constant_buffer(nv40
->draw
, map
);
263 draw_arrays(nv40
->draw
, mode
, start
, count
);
265 for (i
= 0; i
< PIPE_ATTRIB_MAX
; i
++) {
266 if (!nv40
->vtxbuf
[i
].buffer
)
268 ws
->buffer_unmap(ws
, nv40
->vtxbuf
[i
].buffer
);
272 ws
->buffer_unmap(ws
, idxbuf
);
274 if (nv40
->constbuf
[PIPE_SHADER_VERTEX
])
275 ws
->buffer_unmap(ws
, nv40
->constbuf
[PIPE_SHADER_VERTEX
]);
277 draw_flush(nv40
->draw
);
278 pipe
->flush(pipe
, 0, NULL
);
284 emit_attrib(struct nv40_context
*nv40
, unsigned hw
, unsigned emit
,
285 unsigned semantic
, unsigned index
)
287 unsigned draw_out
= draw_find_vs_output(nv40
->draw
, semantic
, index
);
288 unsigned a
= nv40
->swtnl
.nr_attribs
++;
290 nv40
->swtnl
.hw
[a
] = hw
;
291 nv40
->swtnl
.emit
[a
] = emit
;
292 nv40
->swtnl
.draw
[a
] = draw_out
;
296 nv40_state_vtxfmt_validate(struct nv40_context
*nv40
)
298 struct nv40_fragment_program
*fp
= nv40
->fragprog
;
299 unsigned colour
= 0, texcoords
= 0, fog
= 0, i
;
301 /* Determine needed fragprog inputs */
302 for (i
= 0; i
< fp
->info
.num_inputs
; i
++) {
303 switch (fp
->info
.input_semantic_name
[i
]) {
304 case TGSI_SEMANTIC_POSITION
:
306 case TGSI_SEMANTIC_COLOR
:
307 colour
|= (1 << fp
->info
.input_semantic_index
[i
]);
309 case TGSI_SEMANTIC_GENERIC
:
310 texcoords
|= (1 << fp
->info
.input_semantic_index
[i
]);
312 case TGSI_SEMANTIC_FOG
:
320 nv40
->swtnl
.nr_attribs
= 0;
322 /* Map draw vtxprog output to hw attribute IDs */
323 for (i
= 0; i
< 2; i
++) {
324 if (!(colour
& (1 << i
)))
326 emit_attrib(nv40
, 3 + i
, EMIT_4UB
, TGSI_SEMANTIC_COLOR
, i
);
329 for (i
= 0; i
< 8; i
++) {
330 if (!(texcoords
& (1 << i
)))
332 emit_attrib(nv40
, 8 + i
, EMIT_4F
, TGSI_SEMANTIC_GENERIC
, i
);
336 emit_attrib(nv40
, 5, EMIT_1F
, TGSI_SEMANTIC_FOG
, 0);
339 emit_attrib(nv40
, 0, EMIT_3F
, TGSI_SEMANTIC_POSITION
, 0);
344 struct nv40_state_entry nv40_state_vtxfmt
= {
345 .validate
= nv40_state_vtxfmt_validate
,
347 .pipe
= NV40_NEW_ARRAYS
| NV40_NEW_FRAGPROG
,