1 #include "pipe/p_shader_tokens.h"
2 #include "util/u_inlines.h"
4 #include "util/u_pack_color.h"
6 #include "draw/draw_context.h"
7 #include "draw/draw_vertex.h"
8 #include "draw/draw_pipe.h"
10 #include "nv40_context.h"
11 #define NV40_SHADER_NO_FUCKEDNESS
12 #include "nv40_shader.h"
14 /* Simple, but crappy, swtnl path, hopefully we wont need to hit this very
15 * often at all. Uses "quadro style" vertex submission + a fixed vertex
16 * layout to avoid the need to generate a vertex program or vtxfmt.
19 struct nv40_render_stage
{
20 struct draw_stage stage
;
21 struct nv40_context
*nv40
;
25 static INLINE
struct nv40_render_stage
*
26 nv40_render_stage(struct draw_stage
*stage
)
28 return (struct nv40_render_stage
*)stage
;
32 nv40_render_vertex(struct nv40_context
*nv40
, const struct vertex_header
*v
)
34 struct nv40_screen
*screen
= nv40
->screen
;
35 struct nouveau_channel
*chan
= screen
->base
.channel
;
36 struct nouveau_grobj
*curie
= screen
->curie
;
39 for (i
= 0; i
< nv40
->swtnl
.nr_attribs
; i
++) {
40 unsigned idx
= nv40
->swtnl
.draw
[i
];
41 unsigned hw
= nv40
->swtnl
.hw
[i
];
43 switch (nv40
->swtnl
.emit
[i
]) {
47 BEGIN_RING(chan
, curie
, NV40TCL_VTX_ATTR_1F(hw
), 1);
48 OUT_RING (chan
, fui(v
->data
[idx
][0]));
51 BEGIN_RING(chan
, curie
, NV40TCL_VTX_ATTR_2F_X(hw
), 2);
52 OUT_RING (chan
, fui(v
->data
[idx
][0]));
53 OUT_RING (chan
, fui(v
->data
[idx
][1]));
56 BEGIN_RING(chan
, curie
, NV40TCL_VTX_ATTR_3F_X(hw
), 3);
57 OUT_RING (chan
, fui(v
->data
[idx
][0]));
58 OUT_RING (chan
, fui(v
->data
[idx
][1]));
59 OUT_RING (chan
, fui(v
->data
[idx
][2]));
62 BEGIN_RING(chan
, curie
, NV40TCL_VTX_ATTR_4F_X(hw
), 4);
63 OUT_RING (chan
, fui(v
->data
[idx
][0]));
64 OUT_RING (chan
, fui(v
->data
[idx
][1]));
65 OUT_RING (chan
, fui(v
->data
[idx
][2]));
66 OUT_RING (chan
, fui(v
->data
[idx
][3]));
69 BEGIN_RING(chan
, curie
, NV40TCL_VTX_ATTR_4UB(hw
), 1);
70 OUT_RING (chan
, pack_ub4(float_to_ubyte(v
->data
[idx
][0]),
71 float_to_ubyte(v
->data
[idx
][1]),
72 float_to_ubyte(v
->data
[idx
][2]),
73 float_to_ubyte(v
->data
[idx
][3])));
83 nv40_render_prim(struct draw_stage
*stage
, struct prim_header
*prim
,
84 unsigned mode
, unsigned count
)
86 struct nv40_render_stage
*rs
= nv40_render_stage(stage
);
87 struct nv40_context
*nv40
= rs
->nv40
;
89 struct nv40_screen
*screen
= nv40
->screen
;
90 struct nouveau_channel
*chan
= screen
->base
.channel
;
91 struct nouveau_grobj
*curie
= screen
->curie
;
94 /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
95 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
96 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
97 NOUVEAU_ERR("AIII, missed flush\n");
101 nv40_state_emit(nv40
);
104 /* Switch primitive modes if necessary */
105 if (rs
->prim
!= mode
) {
106 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
107 BEGIN_RING(chan
, curie
, NV40TCL_BEGIN_END
, 1);
108 OUT_RING (chan
, NV40TCL_BEGIN_END_STOP
);
111 BEGIN_RING(chan
, curie
, NV40TCL_BEGIN_END
, 1);
112 OUT_RING (chan
, mode
);
116 /* Emit vertex data */
117 for (i
= 0; i
< count
; i
++)
118 nv40_render_vertex(nv40
, prim
->v
[i
]);
120 /* If it's likely we'll need to empty the push buffer soon, finish
121 * off the primitive now.
123 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
124 BEGIN_RING(chan
, curie
, NV40TCL_BEGIN_END
, 1);
125 OUT_RING (chan
, NV40TCL_BEGIN_END_STOP
);
126 rs
->prim
= NV40TCL_BEGIN_END_STOP
;
131 nv40_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
133 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_POINTS
, 1);
137 nv40_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
139 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_LINES
, 2);
143 nv40_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
145 nv40_render_prim(draw
, prim
, NV40TCL_BEGIN_END_TRIANGLES
, 3);
149 nv40_render_flush(struct draw_stage
*draw
, unsigned flags
)
151 struct nv40_render_stage
*rs
= nv40_render_stage(draw
);
152 struct nv40_context
*nv40
= rs
->nv40
;
153 struct nv40_screen
*screen
= nv40
->screen
;
154 struct nouveau_channel
*chan
= screen
->base
.channel
;
155 struct nouveau_grobj
*curie
= screen
->curie
;
157 if (rs
->prim
!= NV40TCL_BEGIN_END_STOP
) {
158 BEGIN_RING(chan
, curie
, NV40TCL_BEGIN_END
, 1);
159 OUT_RING (chan
, NV40TCL_BEGIN_END_STOP
);
160 rs
->prim
= NV40TCL_BEGIN_END_STOP
;
165 nv40_render_reset_stipple_counter(struct draw_stage
*draw
)
170 nv40_render_destroy(struct draw_stage
*draw
)
176 emit_mov(struct nv40_vertex_program
*vp
,
177 unsigned dst
, unsigned src
, unsigned vor
, unsigned mask
)
179 struct nv40_vertex_program_exec
*inst
;
181 vp
->insns
= realloc(vp
->insns
,
182 sizeof(struct nv40_vertex_program_exec
) *
184 inst
= &vp
->insns
[vp
->nr_insns
- 1];
186 inst
->data
[0] = 0x401f9c6c;
187 inst
->data
[1] = 0x0040000d | (src
<< 8);
188 inst
->data
[2] = 0x8106c083;
189 inst
->data
[3] = 0x6041ff80 | (dst
<< 2) | (mask
<< 13);
190 inst
->const_index
= -1;
191 inst
->has_branch_offset
= FALSE
;
193 vp
->ir
|= (1 << src
);
195 vp
->or |= (1 << vor
);
198 static struct nv40_vertex_program
*
199 create_drawvp(struct nv40_context
*nv40
)
201 struct nv40_vertex_program
*vp
= CALLOC_STRUCT(nv40_vertex_program
);
204 emit_mov(vp
, NV40_VP_INST_DEST_POS
, 0, ~0, 0xf);
205 emit_mov(vp
, NV40_VP_INST_DEST_COL0
, 3, 0, 0xf);
206 emit_mov(vp
, NV40_VP_INST_DEST_COL1
, 4, 1, 0xf);
207 emit_mov(vp
, NV40_VP_INST_DEST_BFC0
, 3, 2, 0xf);
208 emit_mov(vp
, NV40_VP_INST_DEST_BFC1
, 4, 3, 0xf);
209 emit_mov(vp
, NV40_VP_INST_DEST_FOGC
, 5, 4, 0x8);
210 for (i
= 0; i
< 8; i
++)
211 emit_mov(vp
, NV40_VP_INST_DEST_TC(i
), 8 + i
, 14 + i
, 0xf);
213 vp
->insns
[vp
->nr_insns
- 1].data
[3] |= 1;
214 vp
->translated
= TRUE
;
219 nv40_draw_render_stage(struct nv40_context
*nv40
)
221 struct nv40_render_stage
*render
= CALLOC_STRUCT(nv40_render_stage
);
223 if (!nv40
->swtnl
.vertprog
)
224 nv40
->swtnl
.vertprog
= create_drawvp(nv40
);
227 render
->stage
.draw
= nv40
->draw
;
228 render
->stage
.point
= nv40_render_point
;
229 render
->stage
.line
= nv40_render_line
;
230 render
->stage
.tri
= nv40_render_tri
;
231 render
->stage
.flush
= nv40_render_flush
;
232 render
->stage
.reset_stipple_counter
= nv40_render_reset_stipple_counter
;
233 render
->stage
.destroy
= nv40_render_destroy
;
235 return &render
->stage
;
239 nv40_draw_elements_swtnl(struct pipe_context
*pipe
,
240 struct pipe_buffer
*idxbuf
, unsigned idxbuf_size
,
241 unsigned mode
, unsigned start
, unsigned count
)
243 struct nv40_context
*nv40
= nv40_context(pipe
);
244 struct pipe_screen
*pscreen
= pipe
->screen
;
248 if (!nv40_state_validate_swtnl(nv40
))
250 nv40
->state
.dirty
&= ~(1ULL << NV40_STATE_VTXBUF
);
251 nv40_state_emit(nv40
);
253 for (i
= 0; i
< nv40
->vtxbuf_nr
; i
++) {
254 map
= pipe_buffer_map(pscreen
, nv40
->vtxbuf
[i
].buffer
,
255 PIPE_BUFFER_USAGE_CPU_READ
);
256 draw_set_mapped_vertex_buffer(nv40
->draw
, i
, map
);
260 map
= pipe_buffer_map(pscreen
, idxbuf
,
261 PIPE_BUFFER_USAGE_CPU_READ
);
262 draw_set_mapped_element_buffer(nv40
->draw
, idxbuf_size
, map
);
264 draw_set_mapped_element_buffer(nv40
->draw
, 0, NULL
);
267 if (nv40
->constbuf
[PIPE_SHADER_VERTEX
]) {
268 const unsigned nr
= nv40
->constbuf_nr
[PIPE_SHADER_VERTEX
];
270 map
= pipe_buffer_map(pscreen
,
271 nv40
->constbuf
[PIPE_SHADER_VERTEX
],
272 PIPE_BUFFER_USAGE_CPU_READ
);
273 draw_set_mapped_constant_buffer(nv40
->draw
, PIPE_SHADER_VERTEX
, 0,
277 draw_arrays(nv40
->draw
, mode
, start
, count
);
279 for (i
= 0; i
< nv40
->vtxbuf_nr
; i
++)
280 pipe_buffer_unmap(pscreen
, nv40
->vtxbuf
[i
].buffer
);
283 pipe_buffer_unmap(pscreen
, idxbuf
);
285 if (nv40
->constbuf
[PIPE_SHADER_VERTEX
])
286 pipe_buffer_unmap(pscreen
, nv40
->constbuf
[PIPE_SHADER_VERTEX
]);
288 draw_flush(nv40
->draw
);
289 pipe
->flush(pipe
, 0, NULL
);
293 emit_attrib(struct nv40_context
*nv40
, unsigned hw
, unsigned emit
,
294 unsigned semantic
, unsigned index
)
296 unsigned draw_out
= draw_find_shader_output(nv40
->draw
, semantic
, index
);
297 unsigned a
= nv40
->swtnl
.nr_attribs
++;
299 nv40
->swtnl
.hw
[a
] = hw
;
300 nv40
->swtnl
.emit
[a
] = emit
;
301 nv40
->swtnl
.draw
[a
] = draw_out
;
305 nv40_state_vtxfmt_validate(struct nv40_context
*nv40
)
307 struct nv40_fragment_program
*fp
= nv40
->fragprog
;
308 unsigned colour
= 0, texcoords
= 0, fog
= 0, i
;
310 /* Determine needed fragprog inputs */
311 for (i
= 0; i
< fp
->info
.num_inputs
; i
++) {
312 switch (fp
->info
.input_semantic_name
[i
]) {
313 case TGSI_SEMANTIC_POSITION
:
315 case TGSI_SEMANTIC_COLOR
:
316 colour
|= (1 << fp
->info
.input_semantic_index
[i
]);
318 case TGSI_SEMANTIC_GENERIC
:
319 texcoords
|= (1 << fp
->info
.input_semantic_index
[i
]);
321 case TGSI_SEMANTIC_FOG
:
329 nv40
->swtnl
.nr_attribs
= 0;
331 /* Map draw vtxprog output to hw attribute IDs */
332 for (i
= 0; i
< 2; i
++) {
333 if (!(colour
& (1 << i
)))
335 emit_attrib(nv40
, 3 + i
, EMIT_4UB
, TGSI_SEMANTIC_COLOR
, i
);
338 for (i
= 0; i
< 8; i
++) {
339 if (!(texcoords
& (1 << i
)))
341 emit_attrib(nv40
, 8 + i
, EMIT_4F
, TGSI_SEMANTIC_GENERIC
, i
);
345 emit_attrib(nv40
, 5, EMIT_1F
, TGSI_SEMANTIC_FOG
, 0);
348 emit_attrib(nv40
, 0, EMIT_3F
, TGSI_SEMANTIC_POSITION
, 0);
353 struct nv40_state_entry nv40_state_vtxfmt
= {
354 .validate
= nv40_state_vtxfmt_validate
,
356 .pipe
= NV40_NEW_ARRAYS
| NV40_NEW_FRAGPROG
,