2 #include "pipe/p_debug.h"
3 #include "pipe/p_inlines.h"
4 #include "pipe/p_winsys.h"
5 #include "pipe/p_compiler.h"
7 #include "draw/draw_vbuf.h"
9 #include "nv04_context.h"
10 #include "nv04_state.h"
12 #define VERTEX_SIZE 40
13 #define VERTEX_BUFFER_SIZE (4096*VERTEX_SIZE) // 4096 vertices of 40 bytes each
16 * Primitive renderer for nv04.
18 struct nv04_vbuf_render
{
19 struct vbuf_render base
;
21 struct nv04_context
*nv04
;
24 unsigned char* buffer
;
26 /** Vertex size in bytes */
29 /** Current primitive */
35 * Basically a cast wrapper.
37 static INLINE
struct nv04_vbuf_render
*
38 nv04_vbuf_render( struct vbuf_render
*render
)
41 return (struct nv04_vbuf_render
*)render
;
45 static const struct vertex_info
*
46 nv04_vbuf_render_get_vertex_info( struct vbuf_render
*render
)
48 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
49 struct nv04_context
*nv04
= nv04_render
->nv04
;
50 return &nv04
->vertex_info
;
55 nv04_vbuf_render_allocate_vertices( struct vbuf_render
*render
,
59 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
61 nv04_render
->buffer
= (unsigned char*) MALLOC(VERTEX_BUFFER_SIZE
);
62 assert(!nv04_render
->buffer
);
64 return nv04_render
->buffer
;
69 nv04_vbuf_render_set_primitive( struct vbuf_render
*render
,
72 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
74 if (prim
<= PIPE_PRIM_LINE_STRIP
)
77 nv04_render
->prim
= prim
;
81 static INLINE
void nv04_2triangles(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
, ushort v3
, ushort v4
, ushort v5
)
83 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
84 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
85 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
86 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
87 OUT_RINGp(buffer
+ VERTEX_SIZE
* v3
,8);
88 OUT_RINGp(buffer
+ VERTEX_SIZE
* v4
,8);
89 OUT_RINGp(buffer
+ VERTEX_SIZE
* v5
,8);
93 static INLINE
void nv04_1triangle(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
)
95 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
96 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
97 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
98 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
102 static INLINE
void nv04_1quad(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
, ushort v3
)
104 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
105 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
106 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
107 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
108 OUT_RINGp(buffer
+ VERTEX_SIZE
* v3
,8);
112 static void nv04_vbuf_render_triangles_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
114 unsigned char* buffer
= render
->buffer
;
115 struct nv04_context
* nv04
= render
->nv04
;
118 for( i
=0; i
< nr_indices
-5; i
+=6)
119 nv04_2triangles(nv04
,
139 NOUVEAU_ERR("Houston, we have lost some vertices\n");
142 static void nv04_vbuf_render_tri_strip_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
144 const uint32_t striptbl
[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
145 unsigned char* buffer
= render
->buffer
;
146 struct nv04_context
* nv04
= render
->nv04
;
149 for(i
= 0; i
<nr_indices
; i
+=14)
151 int numvert
= MIN2(16, nr_indices
- i
);
152 int numtri
= numvert
- 2;
156 BEGIN_RING( fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), numvert
*8 );
157 for(j
= 0; j
<numvert
; j
++)
158 OUT_RINGp( buffer
+ VERTEX_SIZE
* indices
[i
+j
], 8 );
160 BEGIN_RING_NI( fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri
+1)/2 );
161 for(j
= 0; j
<numtri
/2; j
++ )
162 OUT_RING(striptbl
[j
]);
164 OUT_RING(striptbl
[numtri
/2]&0xFFF);
168 static void nv04_vbuf_render_tri_fan_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
170 const uint32_t fantbl
[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
171 unsigned char* buffer
= render
->buffer
;
172 struct nv04_context
* nv04
= render
->nv04
;
175 BEGIN_RING(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), 8);
176 OUT_RINGp(buffer
+ VERTEX_SIZE
* indices
[0], 8);
178 for(i
= 1; i
<nr_indices
; i
+=14)
180 int numvert
=MIN2(15, nr_indices
- i
);
181 int numtri
=numvert
-2;
185 BEGIN_RING(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1), numvert
*8);
187 for(j
=0;j
<numvert
;j
++)
188 OUT_RINGp( buffer
+ VERTEX_SIZE
* indices
[ i
+j
], 8 );
190 BEGIN_RING_NI(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri
+1)/2);
191 for(j
= 0; j
<numtri
/2; j
++)
194 OUT_RING(fantbl
[numtri
/2]&0xFFF);
198 static void nv04_vbuf_render_quads_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
200 unsigned char* buffer
= render
->buffer
;
201 struct nv04_context
* nv04
= render
->nv04
;
204 for(i
= 0; i
< nr_indices
; i
+= 4)
216 nv04_vbuf_render_draw( struct vbuf_render
*render
,
217 const ushort
*indices
,
220 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
223 switch( nv04_render
->prim
)
225 case PIPE_PRIM_TRIANGLES
:
226 nv04_vbuf_render_triangles_elts(nv04_render
, indices
, nr_indices
);
228 case PIPE_PRIM_QUAD_STRIP
:
229 case PIPE_PRIM_TRIANGLE_STRIP
:
230 nv04_vbuf_render_tri_strip_elts(nv04_render
, indices
, nr_indices
);
232 case PIPE_PRIM_TRIANGLE_FAN
:
233 case PIPE_PRIM_POLYGON
:
234 nv04_vbuf_render_tri_fan_elts(nv04_render
, indices
, nr_indices
);
236 case PIPE_PRIM_QUADS
:
237 nv04_vbuf_render_quads_elts(nv04_render
, indices
, nr_indices
);
240 NOUVEAU_ERR("You have to implement primitive %d, young padawan\n", nv04_render
->prim
);
247 nv04_vbuf_render_release_vertices( struct vbuf_render
*render
,
249 unsigned vertex_size
,
250 unsigned vertices_used
)
252 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
254 free(nv04_render
->buffer
);
255 nv04_render
->buffer
= NULL
;
260 nv04_vbuf_render_destroy( struct vbuf_render
*render
)
262 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
268 * Create a new primitive render.
270 static struct vbuf_render
*
271 nv04_vbuf_render_create( struct nv04_context
*nv04
)
273 struct nv04_vbuf_render
*nv04_render
= CALLOC_STRUCT(nv04_vbuf_render
);
275 nv04_render
->nv04
= nv04
;
277 nv04_render
->base
.max_vertex_buffer_bytes
= VERTEX_BUFFER_SIZE
;
278 nv04_render
->base
.max_indices
= 65536;
279 nv04_render
->base
.get_vertex_info
= nv04_vbuf_render_get_vertex_info
;
280 nv04_render
->base
.allocate_vertices
= nv04_vbuf_render_allocate_vertices
;
281 nv04_render
->base
.set_primitive
= nv04_vbuf_render_set_primitive
;
282 nv04_render
->base
.draw
= nv04_vbuf_render_draw
;
283 nv04_render
->base
.release_vertices
= nv04_vbuf_render_release_vertices
;
284 nv04_render
->base
.destroy
= nv04_vbuf_render_destroy
;
286 return &nv04_render
->base
;
291 * Create a new primitive vbuf/render stage.
293 struct draw_stage
*nv04_draw_vbuf_stage( struct nv04_context
*nv04
)
295 struct vbuf_render
*render
;
296 struct draw_stage
*stage
;
298 render
= nv04_vbuf_render_create(nv04
);
302 stage
= draw_vbuf_stage( nv04
->draw
, render
);
304 render
->destroy(render
);