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])));
91 nvfx_render_prim(struct draw_stage
*stage
, struct prim_header
*prim
,
92 unsigned mode
, unsigned count
)
94 struct nvfx_render_stage
*rs
= nvfx_render_stage(stage
);
95 struct nvfx_context
*nvfx
= rs
->nvfx
;
97 struct nvfx_screen
*screen
= nvfx
->screen
;
98 struct nouveau_channel
*chan
= screen
->base
.channel
;
99 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
102 /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
103 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
104 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
105 NOUVEAU_ERR("AIII, missed flush\n");
109 nvfx_state_emit(nvfx
);
112 /* Switch primitive modes if necessary */
113 if (rs
->prim
!= mode
) {
114 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
115 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
116 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
119 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
120 OUT_RING (chan
, mode
);
124 /* Emit vertex data */
125 for (i
= 0; i
< count
; i
++)
126 nvfx_render_vertex(nvfx
, prim
->v
[i
]);
128 /* If it's likely we'll need to empty the push buffer soon, finish
129 * off the primitive now.
131 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
132 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
133 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
134 rs
->prim
= NV34TCL_VERTEX_BEGIN_END_STOP
;
139 nvfx_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
141 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_POINTS
, 1);
145 nvfx_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
147 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_LINES
, 2);
151 nvfx_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
153 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_TRIANGLES
, 3);
157 nvfx_render_flush(struct draw_stage
*draw
, unsigned flags
)
159 struct nvfx_render_stage
*rs
= nvfx_render_stage(draw
);
160 struct nvfx_context
*nvfx
= rs
->nvfx
;
161 struct nvfx_screen
*screen
= nvfx
->screen
;
162 struct nouveau_channel
*chan
= screen
->base
.channel
;
163 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
165 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
166 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
167 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
168 rs
->prim
= NV34TCL_VERTEX_BEGIN_END_STOP
;
173 nvfx_render_reset_stipple_counter(struct draw_stage
*draw
)
178 nvfx_render_destroy(struct draw_stage
*draw
)
183 static struct nvfx_vertex_program
*
184 nvfx_create_drawvp(struct nvfx_context
*nvfx
)
186 struct ureg_program
*ureg
;
189 ureg
= ureg_create( TGSI_PROCESSOR_VERTEX
);
193 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0), ureg_DECL_vs_input(ureg
, 0));
194 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0), ureg_DECL_vs_input(ureg
, 3));
195 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 1), ureg_DECL_vs_input(ureg
, 4));
196 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_BCOLOR
, 0), ureg_DECL_vs_input(ureg
, 3));
197 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_BCOLOR
, 1), ureg_DECL_vs_input(ureg
, 4));
199 ureg_writemask(ureg_DECL_output(ureg
, TGSI_SEMANTIC_FOG
, 1), TGSI_WRITEMASK_X
),
200 ureg_DECL_vs_input(ureg
, 5));
201 for (i
= 0; i
< 8; ++i
)
202 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, i
), ureg_DECL_vs_input(ureg
, 8 + i
));
206 return ureg_create_shader_and_destroy( ureg
, &nvfx
->pipe
);
210 nvfx_draw_render_stage(struct nvfx_context
*nvfx
)
212 struct nvfx_render_stage
*render
= CALLOC_STRUCT(nvfx_render_stage
);
214 if (!nvfx
->swtnl
.vertprog
)
215 nvfx
->swtnl
.vertprog
= nvfx_create_drawvp(nvfx
);
218 render
->stage
.draw
= nvfx
->draw
;
219 render
->stage
.point
= nvfx_render_point
;
220 render
->stage
.line
= nvfx_render_line
;
221 render
->stage
.tri
= nvfx_render_tri
;
222 render
->stage
.flush
= nvfx_render_flush
;
223 render
->stage
.reset_stipple_counter
= nvfx_render_reset_stipple_counter
;
224 render
->stage
.destroy
= nvfx_render_destroy
;
226 return &render
->stage
;
230 nvfx_draw_elements_swtnl(struct pipe_context
*pipe
,
231 struct pipe_buffer
*idxbuf
, unsigned idxbuf_size
,
232 unsigned mode
, unsigned start
, unsigned count
)
234 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
235 struct pipe_screen
*pscreen
= pipe
->screen
;
239 if (!nvfx_state_validate_swtnl(nvfx
))
241 nvfx
->state
.dirty
&= ~(1ULL << NVFX_STATE_VTXBUF
);
242 nvfx_state_emit(nvfx
);
244 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++) {
245 map
= pipe_buffer_map(pscreen
, nvfx
->vtxbuf
[i
].buffer
,
246 PIPE_BUFFER_USAGE_CPU_READ
);
247 draw_set_mapped_vertex_buffer(nvfx
->draw
, i
, map
);
251 map
= pipe_buffer_map(pscreen
, idxbuf
,
252 PIPE_BUFFER_USAGE_CPU_READ
);
253 draw_set_mapped_element_buffer(nvfx
->draw
, idxbuf_size
, map
);
255 draw_set_mapped_element_buffer(nvfx
->draw
, 0, NULL
);
258 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
]) {
259 const unsigned nr
= nvfx
->constbuf_nr
[PIPE_SHADER_VERTEX
];
261 map
= pipe_buffer_map(pscreen
,
262 nvfx
->constbuf
[PIPE_SHADER_VERTEX
],
263 PIPE_BUFFER_USAGE_CPU_READ
);
264 draw_set_mapped_constant_buffer(nvfx
->draw
, PIPE_SHADER_VERTEX
, 0,
268 draw_arrays(nvfx
->draw
, mode
, start
, count
);
270 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++)
271 pipe_buffer_unmap(pscreen
, nvfx
->vtxbuf
[i
].buffer
);
274 pipe_buffer_unmap(pscreen
, idxbuf
);
276 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
])
277 pipe_buffer_unmap(pscreen
, nvfx
->constbuf
[PIPE_SHADER_VERTEX
]);
279 draw_flush(nvfx
->draw
);
280 pipe
->flush(pipe
, 0, NULL
);
284 emit_attrib(struct nvfx_context
*nvfx
, unsigned hw
, unsigned emit
,
285 unsigned semantic
, unsigned index
)
287 unsigned draw_out
= draw_find_shader_output(nvfx
->draw
, semantic
, index
);
288 unsigned a
= nvfx
->swtnl
.nr_attribs
++;
290 nvfx
->swtnl
.hw
[a
] = hw
;
291 nvfx
->swtnl
.emit
[a
] = emit
;
292 nvfx
->swtnl
.draw
[a
] = draw_out
;
296 nvfx_state_vtxfmt_validate(struct nvfx_context
*nvfx
)
298 struct nvfx_fragment_program
*fp
= nvfx
->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 nvfx
->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(nvfx
, 3 + i
, EMIT_4F
, TGSI_SEMANTIC_COLOR
, i
);
329 for (i
= 0; i
< 8; i
++) {
330 if (!(texcoords
& (1 << i
)))
332 emit_attrib(nvfx
, 8 + i
, EMIT_4F
, TGSI_SEMANTIC_GENERIC
, i
);
336 emit_attrib(nvfx
, 5, EMIT_1F
, TGSI_SEMANTIC_FOG
, 0);
339 emit_attrib(nvfx
, 0, 0xff, TGSI_SEMANTIC_POSITION
, 0);
344 struct nvfx_state_entry nvfx_state_vtxfmt
= {
345 .validate
= nvfx_state_vtxfmt_validate
,
347 .pipe
= NVFX_NEW_ARRAYS
| NVFX_NEW_FRAGPROG
,