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
;
31 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
33 if (rs
->prim
!= NV30_3D_VERTEX_BEGIN_END_STOP
) {
34 BEGIN_RING(chan
, eng3d
, 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 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
50 boolean no_elements
= nvfx
->vertprog
->draw_no_elements
;
51 unsigned num_attribs
= nvfx
->vertprog
->draw_elements
;
53 /* we need to account the flush as well here even if it is done afterthis
56 if (AVAIL_RING(chan
) < ((1 + count
* num_attribs
* 4) + 6 + 64)) {
57 nvfx_render_flush(stage
, 0);
59 nvfx_state_emit(nvfx
);
61 assert(AVAIL_RING(chan
) >= ((1 + count
* num_attribs
* 4) + 6 + 64));
64 /* Switch primitive modes if necessary */
65 if (rs
->prim
!= mode
) {
66 if (rs
->prim
!= NV30_3D_VERTEX_BEGIN_END_STOP
) {
67 BEGIN_RING(chan
, eng3d
, NV30_3D_VERTEX_BEGIN_END
, 1);
68 OUT_RING(chan
, NV30_3D_VERTEX_BEGIN_END_STOP
);
71 /* XXX: any command a lot of times seems to (mostly) fix corruption that would otherwise happen */
72 /* this seems to cause issues on nv3x, and also be unneeded there */
76 for(i
= 0; i
< 32; ++i
)
78 BEGIN_RING(chan
, eng3d
, 0x1dac, 1);
83 BEGIN_RING(chan
, eng3d
, NV30_3D_VERTEX_BEGIN_END
, 1);
84 OUT_RING (chan
, mode
);
89 BEGIN_RING_NI(chan
, eng3d
, NV30_3D_VERTEX_DATA
, 4);
95 BEGIN_RING_NI(chan
, eng3d
, NV30_3D_VERTEX_DATA
, num_attribs
* 4 * count
);
96 for (unsigned i
= 0; i
< count
; ++i
)
98 struct vertex_header
* v
= prim
->v
[i
];
99 /* TODO: disable divide where it's causing the problem, and remove this hack */
100 OUT_RING(chan
, fui(v
->data
[0][0] / v
->data
[0][3]));
101 OUT_RING(chan
, fui(v
->data
[0][1] / v
->data
[0][3]));
102 OUT_RING(chan
, fui(v
->data
[0][2] / v
->data
[0][3]));
103 OUT_RING(chan
, fui(1.0f
/ v
->data
[0][3]));
104 OUT_RINGp(chan
, &v
->data
[1][0], 4 * (num_attribs
- 1));
110 nvfx_render_point(struct draw_stage
*draw
, struct prim_header
*prim
)
112 nvfx_render_prim(draw
, prim
, NV30_3D_VERTEX_BEGIN_END_POINTS
, 1);
116 nvfx_render_line(struct draw_stage
*draw
, struct prim_header
*prim
)
118 nvfx_render_prim(draw
, prim
, NV30_3D_VERTEX_BEGIN_END_LINES
, 2);
122 nvfx_render_tri(struct draw_stage
*draw
, struct prim_header
*prim
)
124 nvfx_render_prim(draw
, prim
, NV30_3D_VERTEX_BEGIN_END_TRIANGLES
, 3);
128 nvfx_render_reset_stipple_counter(struct draw_stage
*draw
)
130 /* this doesn't really seem to work, but it matters rather little */
131 nvfx_render_flush(draw
, 0);
135 nvfx_render_destroy(struct draw_stage
*draw
)
141 nvfx_draw_render_stage(struct nvfx_context
*nvfx
)
143 struct nvfx_render_stage
*render
= CALLOC_STRUCT(nvfx_render_stage
);
146 render
->stage
.draw
= nvfx
->draw
;
147 render
->stage
.point
= nvfx_render_point
;
148 render
->stage
.line
= nvfx_render_line
;
149 render
->stage
.tri
= nvfx_render_tri
;
150 render
->stage
.flush
= nvfx_render_flush
;
151 render
->stage
.reset_stipple_counter
= nvfx_render_reset_stipple_counter
;
152 render
->stage
.destroy
= nvfx_render_destroy
;
154 return &render
->stage
;
158 nvfx_draw_vbo_swtnl(struct pipe_context
*pipe
, const struct pipe_draw_info
* info
)
160 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
164 if (!nvfx_state_validate_swtnl(nvfx
))
167 nvfx_state_emit(nvfx
);
169 /* these must be passed without adding the offsets */
170 for (i
= 0; i
< nvfx
->vtxbuf_nr
; i
++) {
171 map
= nvfx_buffer(nvfx
->vtxbuf
[i
].buffer
)->data
;
172 draw_set_mapped_vertex_buffer(nvfx
->draw
, i
, map
);
176 if (info
->indexed
&& nvfx
->idxbuf
.buffer
)
177 map
= nvfx_buffer(nvfx
->idxbuf
.buffer
)->data
;
178 draw_set_mapped_index_buffer(nvfx
->draw
, map
);
180 if (nvfx
->constbuf
[PIPE_SHADER_VERTEX
]) {
181 const unsigned nr
= nvfx
->constbuf_nr
[PIPE_SHADER_VERTEX
];
183 map
= nvfx_buffer(nvfx
->constbuf
[PIPE_SHADER_VERTEX
])->data
;
184 draw_set_mapped_constant_buffer(nvfx
->draw
, PIPE_SHADER_VERTEX
, 0,
188 draw_vbo(nvfx
->draw
, info
);
190 draw_flush(nvfx
->draw
);