2 #include "util/u_debug.h"
3 #include "pipe/p_inlines.h"
4 #include "pipe/internal/p_winsys_screen.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
? TRUE
: FALSE
;
68 nv04_vbuf_render_map_vertices( struct vbuf_render
*render
)
70 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
71 return nv04_render
->buffer
;
75 nv04_vbuf_render_unmap_vertices( struct vbuf_render
*render
,
82 nv04_vbuf_render_set_primitive( struct vbuf_render
*render
,
85 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
87 if (prim
<= PIPE_PRIM_LINE_STRIP
)
90 nv04_render
->prim
= prim
;
94 static INLINE
void nv04_2triangles(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
, ushort v3
, ushort v4
, ushort v5
)
96 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
97 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
98 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
99 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
100 OUT_RINGp(buffer
+ VERTEX_SIZE
* v3
,8);
101 OUT_RINGp(buffer
+ VERTEX_SIZE
* v4
,8);
102 OUT_RINGp(buffer
+ VERTEX_SIZE
* v5
,8);
106 static INLINE
void nv04_1triangle(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
)
108 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
109 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
110 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
111 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
115 static INLINE
void nv04_1quad(struct nv04_context
* nv04
, unsigned char* buffer
, ushort v0
, ushort v1
, ushort v2
, ushort v3
)
117 BEGIN_RING(fahrenheit
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
118 OUT_RINGp(buffer
+ VERTEX_SIZE
* v0
,8);
119 OUT_RINGp(buffer
+ VERTEX_SIZE
* v1
,8);
120 OUT_RINGp(buffer
+ VERTEX_SIZE
* v2
,8);
121 OUT_RINGp(buffer
+ VERTEX_SIZE
* v3
,8);
125 static void nv04_vbuf_render_triangles_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
127 unsigned char* buffer
= render
->buffer
;
128 struct nv04_context
* nv04
= render
->nv04
;
131 for( i
=0; i
< nr_indices
-5; i
+=6)
132 nv04_2triangles(nv04
,
152 NOUVEAU_ERR("Houston, we have lost some vertices\n");
155 static void nv04_vbuf_render_tri_strip_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
157 const uint32_t striptbl
[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
158 unsigned char* buffer
= render
->buffer
;
159 struct nv04_context
* nv04
= render
->nv04
;
162 for(i
= 0; i
<nr_indices
; i
+=14)
164 int numvert
= MIN2(16, nr_indices
- i
);
165 int numtri
= numvert
- 2;
169 BEGIN_RING( fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), numvert
*8 );
170 for(j
= 0; j
<numvert
; j
++)
171 OUT_RINGp( buffer
+ VERTEX_SIZE
* indices
[i
+j
], 8 );
173 BEGIN_RING_NI( fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri
+1)/2 );
174 for(j
= 0; j
<numtri
/2; j
++ )
175 OUT_RING(striptbl
[j
]);
177 OUT_RING(striptbl
[numtri
/2]&0xFFF);
181 static void nv04_vbuf_render_tri_fan_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
183 const uint32_t fantbl
[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
184 unsigned char* buffer
= render
->buffer
;
185 struct nv04_context
* nv04
= render
->nv04
;
188 BEGIN_RING(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), 8);
189 OUT_RINGp(buffer
+ VERTEX_SIZE
* indices
[0], 8);
191 for(i
= 1; i
<nr_indices
; i
+=14)
193 int numvert
=MIN2(15, nr_indices
- i
);
194 int numtri
=numvert
-2;
198 BEGIN_RING(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1), numvert
*8);
200 for(j
=0;j
<numvert
;j
++)
201 OUT_RINGp( buffer
+ VERTEX_SIZE
* indices
[ i
+j
], 8 );
203 BEGIN_RING_NI(fahrenheit
, NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_DRAWPRIMITIVE(0), (numtri
+1)/2);
204 for(j
= 0; j
<numtri
/2; j
++)
207 OUT_RING(fantbl
[numtri
/2]&0xFFF);
211 static void nv04_vbuf_render_quads_elts(struct nv04_vbuf_render
* render
, const ushort
* indices
, uint nr_indices
)
213 unsigned char* buffer
= render
->buffer
;
214 struct nv04_context
* nv04
= render
->nv04
;
217 for(i
= 0; i
< nr_indices
; i
+= 4)
229 nv04_vbuf_render_draw( struct vbuf_render
*render
,
230 const ushort
*indices
,
233 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
236 switch( nv04_render
->prim
)
238 case PIPE_PRIM_TRIANGLES
:
239 nv04_vbuf_render_triangles_elts(nv04_render
, indices
, nr_indices
);
241 case PIPE_PRIM_QUAD_STRIP
:
242 case PIPE_PRIM_TRIANGLE_STRIP
:
243 nv04_vbuf_render_tri_strip_elts(nv04_render
, indices
, nr_indices
);
245 case PIPE_PRIM_TRIANGLE_FAN
:
246 case PIPE_PRIM_POLYGON
:
247 nv04_vbuf_render_tri_fan_elts(nv04_render
, indices
, nr_indices
);
249 case PIPE_PRIM_QUADS
:
250 nv04_vbuf_render_quads_elts(nv04_render
, indices
, nr_indices
);
253 NOUVEAU_ERR("You have to implement primitive %d, young padawan\n", nv04_render
->prim
);
260 nv04_vbuf_render_release_vertices( struct vbuf_render
*render
)
262 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
264 free(nv04_render
->buffer
);
265 nv04_render
->buffer
= NULL
;
270 nv04_vbuf_render_destroy( struct vbuf_render
*render
)
272 struct nv04_vbuf_render
*nv04_render
= nv04_vbuf_render(render
);
278 * Create a new primitive render.
280 static struct vbuf_render
*
281 nv04_vbuf_render_create( struct nv04_context
*nv04
)
283 struct nv04_vbuf_render
*nv04_render
= CALLOC_STRUCT(nv04_vbuf_render
);
285 nv04_render
->nv04
= nv04
;
287 nv04_render
->base
.max_vertex_buffer_bytes
= VERTEX_BUFFER_SIZE
;
288 nv04_render
->base
.max_indices
= 65536;
289 nv04_render
->base
.get_vertex_info
= nv04_vbuf_render_get_vertex_info
;
290 nv04_render
->base
.allocate_vertices
= nv04_vbuf_render_allocate_vertices
;
291 nv04_render
->base
.map_vertices
= nv04_vbuf_render_map_vertices
;
292 nv04_render
->base
.unmap_vertices
= nv04_vbuf_render_unmap_vertices
;
293 nv04_render
->base
.set_primitive
= nv04_vbuf_render_set_primitive
;
294 nv04_render
->base
.draw
= nv04_vbuf_render_draw
;
295 nv04_render
->base
.release_vertices
= nv04_vbuf_render_release_vertices
;
296 nv04_render
->base
.destroy
= nv04_vbuf_render_destroy
;
298 return &nv04_render
->base
;
303 * Create a new primitive vbuf/render stage.
305 struct draw_stage
*nv04_draw_vbuf_stage( struct nv04_context
*nv04
)
307 struct vbuf_render
*render
;
308 struct draw_stage
*stage
;
310 render
= nv04_vbuf_render_create(nv04
);
314 stage
= draw_vbuf_stage( nv04
->draw
, render
);
316 render
->destroy(render
);