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 "nvfx_context.h"
11 #include "nvfx_resource.h"
13 struct nvfx_render_stage
{
14 struct draw_stage stage
;
15 struct nvfx_context
*nvfx
;
19 static INLINE
struct nvfx_render_stage
*
20 nvfx_render_stage(struct draw_stage
*stage
)
22 return (struct nvfx_render_stage
*)stage
;
26 nvfx_render_flush(struct draw_stage
*stage
, unsigned flags
)
28 struct nvfx_render_stage
*rs
= nvfx_render_stage(stage
);
29 struct nvfx_context
*nvfx
= rs
->nvfx
;
30 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
32 if (rs
->prim
!= NV30_3D_VERTEX_BEGIN_END_STOP
) {
33 assert(AVAIL_RING(chan
) >= 2);
34 OUT_RING(chan
, RING_3D(NV30_3D_VERTEX_BEGIN_END
, 1));
35 OUT_RING(chan
, NV30_3D_VERTEX_BEGIN_END_STOP
);
36 rs
->prim
= NV30_3D_VERTEX_BEGIN_END_STOP
;
41 nvfx_render_prim(struct draw_stage
*stage
, struct prim_header
*prim
,
42 unsigned mode
, unsigned count
)
44 struct nvfx_render_stage
*rs
= nvfx_render_stage(stage
);
45 struct nvfx_context
*nvfx
= rs
->nvfx
;
47 struct nvfx_screen
*screen
= nvfx
->screen
;
48 struct nouveau_channel
*chan
= screen
->base
.channel
;
49 boolean no_elements
= nvfx
->vertprog
->draw_no_elements
;
50 unsigned num_attribs
= nvfx
->vertprog
->draw_elements
;
52 /* we need to account the flush as well here even if it is done afterthis
55 if (AVAIL_RING(chan
) < ((1 + count
* num_attribs
* 4) + 6 + 64)) {
56 nvfx_render_flush(stage
, 0);
58 nvfx_state_emit(nvfx
);
60 assert(AVAIL_RING(chan
) >= ((1 + count
* num_attribs
* 4) + 6 + 64));
63 /* Switch primitive modes if necessary */
64 if (rs
->prim
!= mode
) {
65 if (rs
->prim
!= NV30_3D_VERTEX_BEGIN_END_STOP
) {
66 OUT_RING(chan
, RING_3D(NV30_3D_VERTEX_BEGIN_END
, 1));
67 OUT_RING(chan
, NV30_3D_VERTEX_BEGIN_END_STOP
);
70 /* XXX: any command a lot of times seems to (mostly) fix corruption that would otherwise happen */
71 /* this seems to cause issues on nv3x, and also be unneeded there */
75 for(i
= 0; i
< 32; ++i
)
77 OUT_RING(chan
, RING_3D(0x1dac, 1));
82 OUT_RING(chan
, RING_3D(NV30_3D_VERTEX_BEGIN_END
, 1));
83 OUT_RING (chan
, mode
);
87 OUT_RING(chan
, RING_3D_NI(NV30_3D_VERTEX_DATA
, num_attribs
* 4 * count
));
94 for (unsigned i
= 0; i
< count
; ++i
)
96 struct vertex_header
* v
= prim
->v
[i
];
97 /* TODO: disable divide where it's causing the problem, and remove this hack */
98 OUT_RING(chan
, fui(v
->data
[0][0] / v
->data
[0][3]));
99 OUT_RING(chan
, fui(v
->data
[0][1] / v
->data
[0][3]));
100 OUT_RING(chan
, fui(v
->data
[0][2] / v
->data
[0][3]));
101 OUT_RING(chan
, fui(1.0f
/ v
->data
[0][3]));
102 OUT_RINGp(chan
, &v
->data
[1][0], 4 * (num_attribs
- 1));
108 nvfx_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
110 nvfx_render_prim(draw
, prim
, NV30_3D_VERTEX_BEGIN_END_POINTS
, 1);
114 nvfx_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
116 nvfx_render_prim(draw
, prim
, NV30_3D_VERTEX_BEGIN_END_LINES
, 2);
120 nvfx_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
122 nvfx_render_prim(draw
, prim
, NV30_3D_VERTEX_BEGIN_END_TRIANGLES
, 3);
126 nvfx_render_reset_stipple_counter(struct draw_stage
*draw
)
128 /* this doesn't really seem to work, but it matters rather little */
129 nvfx_render_flush(draw
, 0);
133 nvfx_render_destroy(struct draw_stage
*draw
)
139 nvfx_draw_render_stage(struct nvfx_context
*nvfx
)
141 struct nvfx_render_stage
*render
= CALLOC_STRUCT(nvfx_render_stage
);
144 render
->stage
.draw
= nvfx
->draw
;
145 render
->stage
.point
= nvfx_render_point
;
146 render
->stage
.line
= nvfx_render_line
;
147 render
->stage
.tri
= nvfx_render_tri
;
148 render
->stage
.flush
= nvfx_render_flush
;
149 render
->stage
.reset_stipple_counter
= nvfx_render_reset_stipple_counter
;
150 render
->stage
.destroy
= nvfx_render_destroy
;
152 return &render
->stage
;
156 nvfx_draw_vbo_swtnl(struct pipe_context
*pipe
, const struct pipe_draw_info
* info
)
158 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
162 if (!nvfx_state_validate_swtnl(nvfx
))
165 nvfx_state_emit(nvfx
);
167 /* these must be passed without adding the offsets */
168 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++) {
169 map
= nvfx_buffer(nvfx
->vtxbuf
[i
].buffer
)->data
;
170 draw_set_mapped_vertex_buffer(nvfx
->draw
, i
, map
);
174 if (info
->indexed
&& nvfx
->idxbuf
.buffer
)
175 map
= nvfx_buffer(nvfx
->idxbuf
.buffer
)->data
;
176 draw_set_mapped_index_buffer(nvfx
->draw
, map
);
178 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
]) {
179 const unsigned nr
= nvfx
->constbuf_nr
[PIPE_SHADER_VERTEX
];
181 map
= nvfx_buffer(nvfx
->constbuf
[PIPE_SHADER_VERTEX
])->data
;
182 draw_set_mapped_constant_buffer(nvfx
->draw
, PIPE_SHADER_VERTEX
, 0,
186 draw_vbo(nvfx
->draw
, info
);
188 draw_flush(nvfx
->draw
);