1 #include "pipe/p_shader_tokens.h"
2 #include "util/u_inlines.h"
3 #include "tgsi/tgsi_ureg.h"
5 #include "util/u_pack_color.h"
7 #include "draw/draw_context.h"
8 #include "draw/draw_vertex.h"
9 #include "draw/draw_pipe.h"
11 #include "nvfx_context.h"
12 #include "nv30_vertprog.h"
13 #include "nv40_vertprog.h"
15 /* Simple, but crappy, swtnl path, hopefully we wont need to hit this very
16 * often at all. Uses "quadro style" vertex submission + a fixed vertex
17 * layout to avoid the need to generate a vertex program or vtxfmt.
20 struct nvfx_render_stage
{
21 struct draw_stage stage
;
22 struct nvfx_context
*nvfx
;
26 static INLINE
struct nvfx_render_stage
*
27 nvfx_render_stage(struct draw_stage
*stage
)
29 return (struct nvfx_render_stage
*)stage
;
33 nvfx_render_vertex(struct nvfx_context
*nvfx
, const struct vertex_header
*v
)
35 struct nvfx_screen
*screen
= nvfx
->screen
;
36 struct nouveau_channel
*chan
= screen
->base
.channel
;
37 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
40 for (i
= 0; i
< nvfx
->swtnl
.nr_attribs
; i
++) {
41 unsigned idx
= nvfx
->swtnl
.draw
[i
];
42 unsigned hw
= nvfx
->swtnl
.hw
[i
];
44 switch (nvfx
->swtnl
.emit
[i
]) {
48 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_1F(hw
), 1);
49 OUT_RING (chan
, fui(v
->data
[idx
][0]));
52 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_2F_X(hw
), 2);
53 OUT_RING (chan
, fui(v
->data
[idx
][0]));
54 OUT_RING (chan
, fui(v
->data
[idx
][1]));
57 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_3F_X(hw
), 3);
58 OUT_RING (chan
, fui(v
->data
[idx
][0]));
59 OUT_RING (chan
, fui(v
->data
[idx
][1]));
60 OUT_RING (chan
, fui(v
->data
[idx
][2]));
63 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4F_X(hw
), 4);
64 OUT_RING (chan
, fui(v
->data
[idx
][0]));
65 OUT_RING (chan
, fui(v
->data
[idx
][1]));
66 OUT_RING (chan
, fui(v
->data
[idx
][2]));
67 OUT_RING (chan
, fui(v
->data
[idx
][3]));
70 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4F_X(hw
), 4);
71 OUT_RING (chan
, fui(v
->data
[idx
][0] / v
->data
[idx
][3]));
72 OUT_RING (chan
, fui(v
->data
[idx
][1] / v
->data
[idx
][3]));
73 OUT_RING (chan
, fui(v
->data
[idx
][2] / v
->data
[idx
][3]));
74 OUT_RING (chan
, fui(1.0f
/ v
->data
[idx
][3]));
77 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4UB(hw
), 1);
78 OUT_RING (chan
, pack_ub4(float_to_ubyte(v
->data
[idx
][0]),
79 float_to_ubyte(v
->data
[idx
][1]),
80 float_to_ubyte(v
->data
[idx
][2]),
81 float_to_ubyte(v
->data
[idx
][3])));
83 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4UB(hw
), 1);
84 OUT_RING (chan
, pack_ub4(float_to_ubyte(v
->data
[idx
][2]),
85 float_to_ubyte(v
->data
[idx
][1]),
86 float_to_ubyte(v
->data
[idx
][0]),
87 float_to_ubyte(v
->data
[idx
][3])));
97 nvfx_render_prim(struct draw_stage
*stage
, struct prim_header
*prim
,
98 unsigned mode
, unsigned count
)
100 struct nvfx_render_stage
*rs
= nvfx_render_stage(stage
);
101 struct nvfx_context
*nvfx
= rs
->nvfx
;
103 struct nvfx_screen
*screen
= nvfx
->screen
;
104 struct nouveau_channel
*chan
= screen
->base
.channel
;
105 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
108 /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
109 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
110 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
111 NOUVEAU_ERR("AIII, missed flush\n");
115 nvfx_state_emit(nvfx
);
118 /* Switch primitive modes if necessary */
119 if (rs
->prim
!= mode
) {
120 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
121 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
122 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
125 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
126 OUT_RING (chan
, mode
);
130 /* Emit vertex data */
131 for (i
= 0; i
< count
; i
++)
132 nvfx_render_vertex(nvfx
, prim
->v
[i
]);
134 /* If it's likely we'll need to empty the push buffer soon, finish
135 * off the primitive now.
137 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
138 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
139 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
140 rs
->prim
= NV34TCL_VERTEX_BEGIN_END_STOP
;
145 nvfx_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
147 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_POINTS
, 1);
151 nvfx_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
153 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_LINES
, 2);
157 nvfx_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
159 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_TRIANGLES
, 3);
163 nvfx_render_flush(struct draw_stage
*draw
, unsigned flags
)
165 struct nvfx_render_stage
*rs
= nvfx_render_stage(draw
);
166 struct nvfx_context
*nvfx
= rs
->nvfx
;
167 struct nvfx_screen
*screen
= nvfx
->screen
;
168 struct nouveau_channel
*chan
= screen
->base
.channel
;
169 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
171 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
172 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
173 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
174 rs
->prim
= NV34TCL_VERTEX_BEGIN_END_STOP
;
179 nvfx_render_reset_stipple_counter(struct draw_stage
*draw
)
184 nvfx_render_destroy(struct draw_stage
*draw
)
189 static struct nvfx_vertex_program
*
190 nvfx_create_drawvp(struct nvfx_context
*nvfx
)
192 struct ureg_program
*ureg
;
195 ureg
= ureg_create( TGSI_PROCESSOR_VERTEX
);
199 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0), ureg_DECL_vs_input(ureg
, 0));
200 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0), ureg_DECL_vs_input(ureg
, 3));
201 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 1), ureg_DECL_vs_input(ureg
, 4));
202 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_BCOLOR
, 0), ureg_DECL_vs_input(ureg
, 3));
203 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_BCOLOR
, 1), ureg_DECL_vs_input(ureg
, 4));
205 ureg_writemask(ureg_DECL_output(ureg
, TGSI_SEMANTIC_FOG
, 1), TGSI_WRITEMASK_X
),
206 ureg_DECL_vs_input(ureg
, 5));
207 for (i
= 0; i
< 8; ++i
)
208 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, i
), ureg_DECL_vs_input(ureg
, 8 + i
));
212 return ureg_create_shader_and_destroy( ureg
, &nvfx
->pipe
);
216 nvfx_draw_render_stage(struct nvfx_context
*nvfx
)
218 struct nvfx_render_stage
*render
= CALLOC_STRUCT(nvfx_render_stage
);
220 if (!nvfx
->swtnl
.vertprog
)
221 nvfx
->swtnl
.vertprog
= nvfx_create_drawvp(nvfx
);
224 render
->stage
.draw
= nvfx
->draw
;
225 render
->stage
.point
= nvfx_render_point
;
226 render
->stage
.line
= nvfx_render_line
;
227 render
->stage
.tri
= nvfx_render_tri
;
228 render
->stage
.flush
= nvfx_render_flush
;
229 render
->stage
.reset_stipple_counter
= nvfx_render_reset_stipple_counter
;
230 render
->stage
.destroy
= nvfx_render_destroy
;
232 return &render
->stage
;
236 nvfx_draw_elements_swtnl(struct pipe_context
*pipe
,
237 struct pipe_resource
*idxbuf
, unsigned idxbuf_size
,
238 unsigned mode
, unsigned start
, unsigned count
)
240 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
241 struct pipe_transfer
*vb_transfer
[PIPE_MAX_ATTRIBS
];
242 struct pipe_transfer
*ib_transfer
= NULL
;
243 struct pipe_transfer
*cb_transfer
= NULL
;
247 if (!nvfx_state_validate_swtnl(nvfx
))
249 nvfx_state_emit(nvfx
);
251 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++) {
252 map
= pipe_buffer_map(pipe
, nvfx
->vtxbuf
[i
].buffer
,
255 draw_set_mapped_vertex_buffer(nvfx
->draw
, i
, map
);
259 map
= pipe_buffer_map(pipe
, idxbuf
,
262 draw_set_mapped_element_buffer(nvfx
->draw
, idxbuf_size
, map
);
264 draw_set_mapped_element_buffer(nvfx
->draw
, 0, NULL
);
267 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
]) {
268 const unsigned nr
= nvfx
->constbuf_nr
[PIPE_SHADER_VERTEX
];
270 map
= pipe_buffer_map(pipe
,
271 nvfx
->constbuf
[PIPE_SHADER_VERTEX
],
274 draw_set_mapped_constant_buffer(nvfx
->draw
, PIPE_SHADER_VERTEX
, 0,
278 draw_arrays(nvfx
->draw
, mode
, start
, count
);
280 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++)
281 pipe_buffer_unmap(pipe
, nvfx
->vtxbuf
[i
].buffer
, vb_transfer
[i
]);
284 pipe_buffer_unmap(pipe
, idxbuf
, ib_transfer
);
286 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
])
287 pipe_buffer_unmap(pipe
, nvfx
->constbuf
[PIPE_SHADER_VERTEX
],
290 draw_flush(nvfx
->draw
);
291 pipe
->flush(pipe
, 0, NULL
);
295 emit_attrib(struct nvfx_context
*nvfx
, unsigned hw
, unsigned emit
,
296 unsigned semantic
, unsigned index
)
298 unsigned draw_out
= draw_find_shader_output(nvfx
->draw
, semantic
, index
);
299 unsigned a
= nvfx
->swtnl
.nr_attribs
++;
301 nvfx
->swtnl
.hw
[a
] = hw
;
302 nvfx
->swtnl
.emit
[a
] = emit
;
303 nvfx
->swtnl
.draw
[a
] = draw_out
;
307 nvfx_state_vtxfmt_validate(struct nvfx_context
*nvfx
)
309 struct nvfx_fragment_program
*fp
= nvfx
->fragprog
;
310 unsigned colour
= 0, texcoords
= 0, fog
= 0, i
;
312 /* Determine needed fragprog inputs */
313 for (i
= 0; i
< fp
->info
.num_inputs
; i
++) {
314 switch (fp
->info
.input_semantic_name
[i
]) {
315 case TGSI_SEMANTIC_POSITION
:
317 case TGSI_SEMANTIC_COLOR
:
318 colour
|= (1 << fp
->info
.input_semantic_index
[i
]);
320 case TGSI_SEMANTIC_GENERIC
:
321 texcoords
|= (1 << fp
->info
.input_semantic_index
[i
]);
323 case TGSI_SEMANTIC_FOG
:
331 nvfx
->swtnl
.nr_attribs
= 0;
333 /* Map draw vtxprog output to hw attribute IDs */
334 for (i
= 0; i
< 2; i
++) {
335 if (!(colour
& (1 << i
)))
337 emit_attrib(nvfx
, 3 + i
, EMIT_4F
, TGSI_SEMANTIC_COLOR
, i
);
340 for (i
= 0; i
< 8; i
++) {
341 if (!(texcoords
& (1 << i
)))
343 emit_attrib(nvfx
, 8 + i
, EMIT_4F
, TGSI_SEMANTIC_GENERIC
, i
);
347 emit_attrib(nvfx
, 5, EMIT_1F
, TGSI_SEMANTIC_FOG
, 0);
350 emit_attrib(nvfx
, 0, 0xff, TGSI_SEMANTIC_POSITION
, 0);
355 struct nvfx_state_entry nvfx_state_vtxfmt
= {
356 .validate
= nvfx_state_vtxfmt_validate
,
358 .pipe
= NVFX_NEW_ARRAYS
| NVFX_NEW_FRAGPROG
,