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"
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 nvfx_render_stage
{
19 struct draw_stage stage
;
20 struct nvfx_context
*nvfx
;
24 static INLINE
struct nvfx_render_stage
*
25 nvfx_render_stage(struct draw_stage
*stage
)
27 return (struct nvfx_render_stage
*)stage
;
31 nvfx_render_vertex(struct nvfx_context
*nvfx
, const struct vertex_header
*v
)
33 struct nvfx_screen
*screen
= nvfx
->screen
;
34 struct nouveau_channel
*chan
= screen
->base
.channel
;
35 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
38 for (i
= 0; i
< nvfx
->swtnl
.nr_attribs
; i
++) {
39 unsigned idx
= nvfx
->swtnl
.draw
[i
];
40 unsigned hw
= nvfx
->swtnl
.hw
[i
];
42 switch (nvfx
->swtnl
.emit
[i
]) {
46 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_1F(hw
), 1);
47 OUT_RING (chan
, fui(v
->data
[idx
][0]));
50 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_2F_X(hw
), 2);
51 OUT_RING (chan
, fui(v
->data
[idx
][0]));
52 OUT_RING (chan
, fui(v
->data
[idx
][1]));
55 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_3F_X(hw
), 3);
56 OUT_RING (chan
, fui(v
->data
[idx
][0]));
57 OUT_RING (chan
, fui(v
->data
[idx
][1]));
58 OUT_RING (chan
, fui(v
->data
[idx
][2]));
61 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4F_X(hw
), 4);
62 OUT_RING (chan
, fui(v
->data
[idx
][0]));
63 OUT_RING (chan
, fui(v
->data
[idx
][1]));
64 OUT_RING (chan
, fui(v
->data
[idx
][2]));
65 OUT_RING (chan
, fui(v
->data
[idx
][3]));
68 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4F_X(hw
), 4);
69 OUT_RING (chan
, fui(v
->data
[idx
][0] / v
->data
[idx
][3]));
70 OUT_RING (chan
, fui(v
->data
[idx
][1] / v
->data
[idx
][3]));
71 OUT_RING (chan
, fui(v
->data
[idx
][2] / v
->data
[idx
][3]));
72 OUT_RING (chan
, fui(1.0f
/ v
->data
[idx
][3]));
75 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4UB(hw
), 1);
76 OUT_RING (chan
, pack_ub4(float_to_ubyte(v
->data
[idx
][0]),
77 float_to_ubyte(v
->data
[idx
][1]),
78 float_to_ubyte(v
->data
[idx
][2]),
79 float_to_ubyte(v
->data
[idx
][3])));
81 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4UB(hw
), 1);
82 OUT_RING (chan
, pack_ub4(float_to_ubyte(v
->data
[idx
][2]),
83 float_to_ubyte(v
->data
[idx
][1]),
84 float_to_ubyte(v
->data
[idx
][0]),
85 float_to_ubyte(v
->data
[idx
][3])));
95 nvfx_render_prim(struct draw_stage
*stage
, struct prim_header
*prim
,
96 unsigned mode
, unsigned count
)
98 struct nvfx_render_stage
*rs
= nvfx_render_stage(stage
);
99 struct nvfx_context
*nvfx
= rs
->nvfx
;
101 struct nvfx_screen
*screen
= nvfx
->screen
;
102 struct nouveau_channel
*chan
= screen
->base
.channel
;
103 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
106 /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
107 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
108 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
109 NOUVEAU_ERR("AIII, missed flush\n");
113 nvfx_state_emit(nvfx
);
116 /* Switch primitive modes if necessary */
117 if (rs
->prim
!= mode
) {
118 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
119 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
120 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
123 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
124 OUT_RING (chan
, mode
);
128 /* Emit vertex data */
129 for (i
= 0; i
< count
; i
++)
130 nvfx_render_vertex(nvfx
, prim
->v
[i
]);
132 /* If it's likely we'll need to empty the push buffer soon, finish
133 * off the primitive now.
135 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
136 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
137 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
138 rs
->prim
= NV34TCL_VERTEX_BEGIN_END_STOP
;
143 nvfx_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
145 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_POINTS
, 1);
149 nvfx_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
151 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_LINES
, 2);
155 nvfx_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
157 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_TRIANGLES
, 3);
161 nvfx_render_flush(struct draw_stage
*draw
, unsigned flags
)
163 struct nvfx_render_stage
*rs
= nvfx_render_stage(draw
);
164 struct nvfx_context
*nvfx
= rs
->nvfx
;
165 struct nvfx_screen
*screen
= nvfx
->screen
;
166 struct nouveau_channel
*chan
= screen
->base
.channel
;
167 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
169 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
170 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
171 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
172 rs
->prim
= NV34TCL_VERTEX_BEGIN_END_STOP
;
177 nvfx_render_reset_stipple_counter(struct draw_stage
*draw
)
182 nvfx_render_destroy(struct draw_stage
*draw
)
187 static struct nvfx_vertex_program
*
188 nvfx_create_drawvp(struct nvfx_context
*nvfx
)
190 struct ureg_program
*ureg
;
193 ureg
= ureg_create( TGSI_PROCESSOR_VERTEX
);
197 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0), ureg_DECL_vs_input(ureg
, 0));
198 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0), ureg_DECL_vs_input(ureg
, 3));
199 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 1), ureg_DECL_vs_input(ureg
, 4));
200 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_BCOLOR
, 0), ureg_DECL_vs_input(ureg
, 3));
201 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_BCOLOR
, 1), ureg_DECL_vs_input(ureg
, 4));
203 ureg_writemask(ureg_DECL_output(ureg
, TGSI_SEMANTIC_FOG
, 1), TGSI_WRITEMASK_X
),
204 ureg_DECL_vs_input(ureg
, 5));
205 for (i
= 0; i
< 8; ++i
)
206 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, i
), ureg_DECL_vs_input(ureg
, 8 + i
));
210 return ureg_create_shader_and_destroy( ureg
, &nvfx
->pipe
);
214 nvfx_draw_render_stage(struct nvfx_context
*nvfx
)
216 struct nvfx_render_stage
*render
= CALLOC_STRUCT(nvfx_render_stage
);
218 if (!nvfx
->swtnl
.vertprog
)
219 nvfx
->swtnl
.vertprog
= nvfx_create_drawvp(nvfx
);
222 render
->stage
.draw
= nvfx
->draw
;
223 render
->stage
.point
= nvfx_render_point
;
224 render
->stage
.line
= nvfx_render_line
;
225 render
->stage
.tri
= nvfx_render_tri
;
226 render
->stage
.flush
= nvfx_render_flush
;
227 render
->stage
.reset_stipple_counter
= nvfx_render_reset_stipple_counter
;
228 render
->stage
.destroy
= nvfx_render_destroy
;
230 return &render
->stage
;
234 nvfx_draw_elements_swtnl(struct pipe_context
*pipe
,
235 struct pipe_resource
*idxbuf
,
236 unsigned idxbuf_size
, int idxbuf_bias
,
237 unsigned mode
, unsigned start
, unsigned count
)
239 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
240 struct pipe_transfer
*vb_transfer
[PIPE_MAX_ATTRIBS
];
241 struct pipe_transfer
*ib_transfer
= NULL
;
242 struct pipe_transfer
*cb_transfer
= NULL
;
246 if (!nvfx_state_validate_swtnl(nvfx
))
248 nvfx_state_emit(nvfx
);
250 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++) {
251 map
= pipe_buffer_map(pipe
, nvfx
->vtxbuf
[i
].buffer
,
254 draw_set_mapped_vertex_buffer(nvfx
->draw
, i
, map
);
258 map
= pipe_buffer_map(pipe
, idxbuf
,
261 draw_set_mapped_element_buffer(nvfx
->draw
, idxbuf_size
, idxbuf_bias
, map
);
263 draw_set_mapped_element_buffer(nvfx
->draw
, 0, 0, NULL
);
266 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
]) {
267 const unsigned nr
= nvfx
->constbuf_nr
[PIPE_SHADER_VERTEX
];
269 map
= pipe_buffer_map(pipe
,
270 nvfx
->constbuf
[PIPE_SHADER_VERTEX
],
273 draw_set_mapped_constant_buffer(nvfx
->draw
, PIPE_SHADER_VERTEX
, 0,
277 draw_arrays(nvfx
->draw
, mode
, start
, count
);
279 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++)
280 pipe_buffer_unmap(pipe
, nvfx
->vtxbuf
[i
].buffer
, vb_transfer
[i
]);
283 pipe_buffer_unmap(pipe
, idxbuf
, ib_transfer
);
285 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
])
286 pipe_buffer_unmap(pipe
, nvfx
->constbuf
[PIPE_SHADER_VERTEX
],
289 draw_flush(nvfx
->draw
);
290 pipe
->flush(pipe
, 0, NULL
);
294 emit_attrib(struct nvfx_context
*nvfx
, unsigned hw
, unsigned emit
,
295 unsigned semantic
, unsigned index
)
297 unsigned draw_out
= draw_find_shader_output(nvfx
->draw
, semantic
, index
);
298 unsigned a
= nvfx
->swtnl
.nr_attribs
++;
300 nvfx
->swtnl
.hw
[a
] = hw
;
301 nvfx
->swtnl
.emit
[a
] = emit
;
302 nvfx
->swtnl
.draw
[a
] = draw_out
;
306 nvfx_vtxfmt_validate(struct nvfx_context
*nvfx
)
308 struct nvfx_fragment_program
*fp
= nvfx
->fragprog
;
309 unsigned colour
= 0, texcoords
= 0, fog
= 0, i
;
311 /* Determine needed fragprog inputs */
312 for (i
= 0; i
< fp
->info
.num_inputs
; i
++) {
313 switch (fp
->info
.input_semantic_name
[i
]) {
314 case TGSI_SEMANTIC_POSITION
:
316 case TGSI_SEMANTIC_COLOR
:
317 colour
|= (1 << fp
->info
.input_semantic_index
[i
]);
319 case TGSI_SEMANTIC_GENERIC
:
320 texcoords
|= (1 << fp
->info
.input_semantic_index
[i
]);
322 case TGSI_SEMANTIC_FOG
:
330 nvfx
->swtnl
.nr_attribs
= 0;
332 /* Map draw vtxprog output to hw attribute IDs */
333 for (i
= 0; i
< 2; i
++) {
334 if (!(colour
& (1 << i
)))
336 emit_attrib(nvfx
, 3 + i
, EMIT_4F
, TGSI_SEMANTIC_COLOR
, i
);
339 for (i
= 0; i
< 8; i
++) {
340 if (!(texcoords
& (1 << i
)))
342 emit_attrib(nvfx
, 8 + i
, EMIT_4F
, TGSI_SEMANTIC_GENERIC
, i
);
346 emit_attrib(nvfx
, 5, EMIT_1F
, TGSI_SEMANTIC_FOG
, 0);
349 emit_attrib(nvfx
, 0, 0xff, TGSI_SEMANTIC_POSITION
, 0);