2 #include "draw/draw_vbuf.h"
3 #include "pipe/p_debug.h"
4 #include "pipe/p_util.h"
5 #include "pipe/p_inlines.h"
6 #include "pipe/p_winsys.h"
8 #include "nv04_context.h"
9 #include "nv04_state.h"
11 #define VERTEX_SIZE 40
12 #define VERTEX_BUFFER_SIZE (4096*VERTEX_SIZE) // 4096 vertices of 40 bytes each
15 * Primitive renderer for nv04.
17 struct nv04_vbuf_render
{
18 struct vbuf_render base
;
20 struct nv04_context
*nv04
;
23 unsigned char* buffer
;
25 /** Vertex size in bytes */
28 /** Current primitive */
34 * Basically a cast wrapper.
36 static INLINE
struct nv04_vbuf_render
*
37 nv04_vbuf_render( struct vbuf_render
*render
)
40 return (struct nv04_vbuf_render
*)render
;
44 static const struct vertex_info
*
45 nv04_vbuf_render_get_vertex_info( struct vbuf_render
*render
)
47 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
48 struct nv04_context
*nv04
= nv04_render
->nv04
;
49 return &nv04
->vertex_info
;
54 nv04_vbuf_render_allocate_vertices( struct vbuf_render
*render
,
58 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
60 nv04_render
->buffer
= (unsigned char*) MALLOC(VERTEX_BUFFER_SIZE
);
61 assert(!nv04_render
->buffer
);
63 return nv04_render
->buffer
;
68 nv04_vbuf_render_set_primitive( struct vbuf_render
*render
,
71 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
73 if (prim
<= PIPE_PRIM_LINE_STRIP
)
76 nv04_render
->prim
= prim
;
80 static INLINE
void nv04_2triangles(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
, ushort v3
, ushort v4
, ushort v5
)
82 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
83 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
84 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
85 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
86 OUT_RINGp(buffer
+ VERTEX_SIZE
* v3
,8);
87 OUT_RINGp(buffer
+ VERTEX_SIZE
* v4
,8);
88 OUT_RINGp(buffer
+ VERTEX_SIZE
* v5
,8);
92 static INLINE
void nv04_1triangle(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
)
94 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
95 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
96 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
97 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
101 static INLINE
void nv04_1quad(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
, ushort v3
)
103 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
104 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
105 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
106 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
107 OUT_RINGp(buffer
+ VERTEX_SIZE
* v3
,8);
111 static void nv04_vbuf_render_triangles_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
113 unsigned char* buffer
= render
->buffer
;
114 struct nv04_context
* nv04
= render
->nv04
;
117 for( i
=0; i
< nr_indices
-5; i
+=6)
118 nv04_2triangles(nv04
,
138 NOUVEAU_ERR("Houston, we have lost some vertices\n");
141 static void nv04_vbuf_render_tri_strip_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
143 const uint32_t striptbl
[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
144 unsigned char* buffer
= render
->buffer
;
145 struct nv04_context
* nv04
= render
->nv04
;
148 for(i
= 0; i
<nr_indices
; i
+=14)
150 int numvert
= MIN2(16, nr_indices
- i
);
151 int numtri
= numvert
- 2;
155 BEGIN_RING( fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), numvert
*8 );
156 for(j
= 0; j
<numvert
; j
++)
157 OUT_RINGp( buffer
+ VERTEX_SIZE
* indices
[i
+j
], 8 );
159 BEGIN_RING_NI( fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri
+1)/2 );
160 for(j
= 0; j
<numtri
/2; j
++ )
161 OUT_RING(striptbl
[j
]);
163 OUT_RING(striptbl
[numtri
/2]&0xFFF);
167 static void nv04_vbuf_render_tri_fan_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
169 const uint32_t fantbl
[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
170 unsigned char* buffer
= render
->buffer
;
171 struct nv04_context
* nv04
= render
->nv04
;
174 BEGIN_RING(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), 8);
175 OUT_RINGp(buffer
+ VERTEX_SIZE
* indices
[0], 8);
177 for(i
= 1; i
<nr_indices
; i
+=14)
179 int numvert
=MIN2(15, nr_indices
- i
);
180 int numtri
=numvert
-2;
184 BEGIN_RING(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1), numvert
*8);
186 for(j
=0;j
<numvert
;j
++)
187 OUT_RINGp( buffer
+ VERTEX_SIZE
* indices
[ i
+j
], 8 );
189 BEGIN_RING_NI(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri
+1)/2);
190 for(j
= 0; j
<numtri
/2; j
++)
193 OUT_RING(fantbl
[numtri
/2]&0xFFF);
197 static void nv04_vbuf_render_quads_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
199 unsigned char* buffer
= render
->buffer
;
200 struct nv04_context
* nv04
= render
->nv04
;
203 for(i
= 0; i
< nr_indices
; i
+= 4)
215 nv04_vbuf_render_draw( struct vbuf_render
*render
,
216 const ushort
*indices
,
219 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
222 switch( nv04_render
->prim
)
224 case PIPE_PRIM_TRIANGLES
:
225 nv04_vbuf_render_triangles_elts(nv04_render
, indices
, nr_indices
);
227 case PIPE_PRIM_QUAD_STRIP
:
228 case PIPE_PRIM_TRIANGLE_STRIP
:
229 nv04_vbuf_render_tri_strip_elts(nv04_render
, indices
, nr_indices
);
231 case PIPE_PRIM_TRIANGLE_FAN
:
232 case PIPE_PRIM_POLYGON
:
233 nv04_vbuf_render_tri_fan_elts(nv04_render
, indices
, nr_indices
);
235 case PIPE_PRIM_QUADS
:
236 nv04_vbuf_render_quads_elts(nv04_render
, indices
, nr_indices
);
239 NOUVEAU_ERR("You have to implement primitive %d, young padawan\n", nv04_render
->prim
);
246 nv04_vbuf_render_release_vertices( struct vbuf_render
*render
,
248 unsigned vertex_size
,
249 unsigned vertices_used
)
251 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
253 free(nv04_render
->buffer
);
254 nv04_render
->buffer
= NULL
;
259 nv04_vbuf_render_destroy( struct vbuf_render
*render
)
261 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
267 * Create a new primitive render.
269 static struct vbuf_render
*
270 nv04_vbuf_render_create( struct nv04_context
*nv04
)
272 struct nv04_vbuf_render
*nv04_render
= CALLOC_STRUCT(nv04_vbuf_render
);
274 nv04_render
->nv04
= nv04
;
276 nv04_render
->base
.max_vertex_buffer_bytes
= VERTEX_BUFFER_SIZE
;
277 nv04_render
->base
.max_indices
= 65536;
278 nv04_render
->base
.get_vertex_info
= nv04_vbuf_render_get_vertex_info
;
279 nv04_render
->base
.allocate_vertices
= nv04_vbuf_render_allocate_vertices
;
280 nv04_render
->base
.set_primitive
= nv04_vbuf_render_set_primitive
;
281 nv04_render
->base
.draw
= nv04_vbuf_render_draw
;
282 nv04_render
->base
.release_vertices
= nv04_vbuf_render_release_vertices
;
283 nv04_render
->base
.destroy
= nv04_vbuf_render_destroy
;
285 return &nv04_render
->base
;
290 * Create a new primitive vbuf/render stage.
292 struct draw_stage
*nv04_draw_vbuf_stage( struct nv04_context
*nv04
)
294 struct vbuf_render
*render
;
295 struct draw_stage
*stage
;
297 render
= nv04_vbuf_render_create(nv04
);
301 stage
= draw_vbuf_stage( nv04
->draw
, render
);
303 render
->destroy(render
);