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 "nvfx_resource.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 nvfx_render_stage
{
20 struct draw_stage stage
;
21 struct nvfx_context
*nvfx
;
25 static INLINE
struct nvfx_render_stage
*
26 nvfx_render_stage(struct draw_stage
*stage
)
28 return (struct nvfx_render_stage
*)stage
;
32 nvfx_render_vertex(struct nvfx_context
*nvfx
, const struct vertex_header
*v
)
34 struct nvfx_screen
*screen
= nvfx
->screen
;
35 struct nouveau_channel
*chan
= screen
->base
.channel
;
36 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
39 for (i
= 0; i
< nvfx
->swtnl
.nr_attribs
; i
++) {
40 unsigned idx
= nvfx
->swtnl
.draw
[i
];
41 unsigned hw
= nvfx
->swtnl
.hw
[i
];
44 switch (nvfx
->swtnl
.emit
[i
]) {
48 nvfx_emit_vtx_attr(chan
, hw
, v
->data
[idx
], 1);
51 nvfx_emit_vtx_attr(chan
, hw
, v
->data
[idx
], 2);
54 nvfx_emit_vtx_attr(chan
, hw
, v
->data
[idx
], 3);
57 nvfx_emit_vtx_attr(chan
, hw
, v
->data
[idx
], 4);
60 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4F_X(hw
), 4);
61 OUT_RING (chan
, fui(v
->data
[idx
][0] / v
->data
[idx
][3]));
62 OUT_RING (chan
, fui(v
->data
[idx
][1] / v
->data
[idx
][3]));
63 OUT_RING (chan
, fui(v
->data
[idx
][2] / v
->data
[idx
][3]));
64 OUT_RING (chan
, fui(1.0f
/ v
->data
[idx
][3]));
67 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4UB(hw
), 1);
68 OUT_RING (chan
, pack_ub4(float_to_ubyte(v
->data
[idx
][0]),
69 float_to_ubyte(v
->data
[idx
][1]),
70 float_to_ubyte(v
->data
[idx
][2]),
71 float_to_ubyte(v
->data
[idx
][3])));
73 BEGIN_RING(chan
, eng3d
, NV34TCL_VTX_ATTR_4UB(hw
), 1);
74 OUT_RING (chan
, pack_ub4(float_to_ubyte(v
->data
[idx
][2]),
75 float_to_ubyte(v
->data
[idx
][1]),
76 float_to_ubyte(v
->data
[idx
][0]),
77 float_to_ubyte(v
->data
[idx
][3])));
87 nvfx_render_prim(struct draw_stage
*stage
, struct prim_header
*prim
,
88 unsigned mode
, unsigned count
)
90 struct nvfx_render_stage
*rs
= nvfx_render_stage(stage
);
91 struct nvfx_context
*nvfx
= rs
->nvfx
;
93 struct nvfx_screen
*screen
= nvfx
->screen
;
94 struct nouveau_channel
*chan
= screen
->base
.channel
;
95 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
98 /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
99 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
100 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
101 NOUVEAU_ERR("AIII, missed flush\n");
105 nvfx_state_emit(nvfx
);
108 /* Switch primitive modes if necessary */
109 if (rs
->prim
!= mode
) {
110 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
111 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
112 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
115 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
116 OUT_RING (chan
, mode
);
120 /* Emit vertex data */
121 for (i
= 0; i
< count
; i
++)
122 nvfx_render_vertex(nvfx
, prim
->v
[i
]);
124 /* If it's likely we'll need to empty the push buffer soon, finish
125 * off the primitive now.
127 if (AVAIL_RING(chan
) < ((count
* 20) + 6)) {
128 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
129 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
130 rs
->prim
= NV34TCL_VERTEX_BEGIN_END_STOP
;
135 nvfx_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
137 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_POINTS
, 1);
141 nvfx_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
143 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_LINES
, 2);
147 nvfx_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
149 nvfx_render_prim(draw
, prim
, NV34TCL_VERTEX_BEGIN_END_TRIANGLES
, 3);
153 nvfx_render_flush(struct draw_stage
*draw
, unsigned flags
)
155 struct nvfx_render_stage
*rs
= nvfx_render_stage(draw
);
156 struct nvfx_context
*nvfx
= rs
->nvfx
;
157 struct nvfx_screen
*screen
= nvfx
->screen
;
158 struct nouveau_channel
*chan
= screen
->base
.channel
;
159 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
161 if (rs
->prim
!= NV34TCL_VERTEX_BEGIN_END_STOP
) {
162 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
163 OUT_RING (chan
, NV34TCL_VERTEX_BEGIN_END_STOP
);
164 rs
->prim
= NV34TCL_VERTEX_BEGIN_END_STOP
;
169 nvfx_render_reset_stipple_counter(struct draw_stage
*draw
)
174 nvfx_render_destroy(struct draw_stage
*draw
)
179 static struct nvfx_vertex_program
*
180 nvfx_create_drawvp(struct nvfx_context
*nvfx
)
182 struct ureg_program
*ureg
;
185 ureg
= ureg_create( TGSI_PROCESSOR_VERTEX
);
189 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0), ureg_DECL_vs_input(ureg
, 0));
190 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0), ureg_DECL_vs_input(ureg
, 3));
191 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 1), ureg_DECL_vs_input(ureg
, 4));
192 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_BCOLOR
, 0), ureg_DECL_vs_input(ureg
, 3));
193 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_BCOLOR
, 1), ureg_DECL_vs_input(ureg
, 4));
195 ureg_writemask(ureg_DECL_output(ureg
, TGSI_SEMANTIC_FOG
, 1), TGSI_WRITEMASK_X
),
196 ureg_DECL_vs_input(ureg
, 5));
197 for (i
= 0; i
< 8; ++i
)
198 ureg_MOV(ureg
, ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, i
), ureg_DECL_vs_input(ureg
, 8 + i
));
202 return ureg_create_shader_and_destroy( ureg
, &nvfx
->pipe
);
206 nvfx_draw_render_stage(struct nvfx_context
*nvfx
)
208 struct nvfx_render_stage
*render
= CALLOC_STRUCT(nvfx_render_stage
);
210 if (!nvfx
->swtnl
.vertprog
)
211 nvfx
->swtnl
.vertprog
= nvfx_create_drawvp(nvfx
);
214 render
->stage
.draw
= nvfx
->draw
;
215 render
->stage
.point
= nvfx_render_point
;
216 render
->stage
.line
= nvfx_render_line
;
217 render
->stage
.tri
= nvfx_render_tri
;
218 render
->stage
.flush
= nvfx_render_flush
;
219 render
->stage
.reset_stipple_counter
= nvfx_render_reset_stipple_counter
;
220 render
->stage
.destroy
= nvfx_render_destroy
;
222 return &render
->stage
;
226 nvfx_draw_vbo_swtnl(struct pipe_context
*pipe
, const struct pipe_draw_info
* info
)
228 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
232 if (!nvfx_state_validate_swtnl(nvfx
))
234 nvfx_state_emit(nvfx
);
236 /* these must be passed without adding the offsets */
237 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++) {
238 map
= nvfx_buffer(nvfx
->vtxbuf
[i
].buffer
)->data
;
239 draw_set_mapped_vertex_buffer(nvfx
->draw
, i
, map
);
243 map
= nvfx_buffer(nvfx
->idxbuf
.buffer
)->data
+ nvfx
->idxbuf
.offset
;
244 draw_set_mapped_element_buffer_range(nvfx
->draw
, nvfx
->idxbuf
.index_size
, info
->index_bias
, info
->min_index
, info
->max_index
, map
);
246 draw_set_mapped_element_buffer(nvfx
->draw
, 0, 0, NULL
);
249 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
]) {
250 const unsigned nr
= nvfx
->constbuf_nr
[PIPE_SHADER_VERTEX
];
252 map
= nvfx_buffer(nvfx
->constbuf
[PIPE_SHADER_VERTEX
])->data
;
253 draw_set_mapped_constant_buffer(nvfx
->draw
, PIPE_SHADER_VERTEX
, 0,
257 draw_arrays_instanced(nvfx
->draw
, info
->mode
, info
->start
, info
->count
, info
->start_instance
, info
->instance_count
);
259 draw_flush(nvfx
->draw
);
263 emit_attrib(struct nvfx_context
*nvfx
, unsigned hw
, unsigned emit
,
264 unsigned semantic
, unsigned index
)
266 unsigned draw_out
= draw_find_shader_output(nvfx
->draw
, semantic
, index
);
267 unsigned a
= nvfx
->swtnl
.nr_attribs
++;
269 nvfx
->swtnl
.hw
[a
] = hw
;
270 nvfx
->swtnl
.emit
[a
] = emit
;
271 nvfx
->swtnl
.draw
[a
] = draw_out
;
275 nvfx_vtxfmt_validate(struct nvfx_context
*nvfx
)
277 struct nvfx_fragment_program
*fp
= nvfx
->fragprog
;
278 unsigned colour
= 0, texcoords
= 0, fog
= 0, i
;
280 /* Determine needed fragprog inputs */
281 for (i
= 0; i
< fp
->info
.num_inputs
; i
++) {
282 switch (fp
->info
.input_semantic_name
[i
]) {
283 case TGSI_SEMANTIC_POSITION
:
285 case TGSI_SEMANTIC_COLOR
:
286 colour
|= (1 << fp
->info
.input_semantic_index
[i
]);
288 case TGSI_SEMANTIC_GENERIC
:
289 texcoords
|= (1 << fp
->info
.input_semantic_index
[i
]);
291 case TGSI_SEMANTIC_FOG
:
299 nvfx
->swtnl
.nr_attribs
= 0;
301 /* Map draw vtxprog output to hw attribute IDs */
302 for (i
= 0; i
< 2; i
++) {
303 if (!(colour
& (1 << i
)))
305 emit_attrib(nvfx
, 3 + i
, EMIT_4F
, TGSI_SEMANTIC_COLOR
, i
);
308 for (i
= 0; i
< 8; i
++) {
309 if (!(texcoords
& (1 << i
)))
311 emit_attrib(nvfx
, 8 + i
, EMIT_4F
, TGSI_SEMANTIC_GENERIC
, i
);
315 emit_attrib(nvfx
, 5, EMIT_1F
, TGSI_SEMANTIC_FOG
, 0);
318 emit_attrib(nvfx
, 0, 0xff, TGSI_SEMANTIC_POSITION
, 0);