1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Vertex buffer drawing stage.
32 * \author José Fonseca <jrfonsec@tungstengraphics.com>
33 * \author Keith Whitwell <keith@tungstengraphics.com>
39 #include "pipe/draw/draw_vbuf.h"
40 #include "pipe/draw/draw_private.h"
41 #include "pipe/draw/draw_vertex.h"
42 #include "pipe/p_util.h"
46 * Vertex buffer emit stage.
49 struct draw_stage stage
; /**< This must be first (base class) */
51 struct vbuf_render
*render
;
53 /** Vertex size in bytes */
56 /* FIXME: we have no guarantee that 'unsigned' is 32bit */
58 /** Vertices in hardware format */
61 unsigned max_vertices
;
75 * Basically a cast wrapper.
77 static INLINE
struct vbuf_stage
*
78 vbuf_stage( struct draw_stage
*stage
)
81 return (struct vbuf_stage
*)stage
;
85 static void vbuf_flush_indices( struct draw_stage
*stage
);
86 static void vbuf_flush_vertices( struct draw_stage
*stage
,
87 unsigned new_vertex_size
);
91 overflow( void *map
, void *ptr
, unsigned bytes
, unsigned bufsz
)
93 unsigned long used
= (unsigned long) ((char *)ptr
- (char *)map
);
94 return (used
+ bytes
) > bufsz
;
99 check_space( struct vbuf_stage
*vbuf
, unsigned nr
)
101 if (vbuf
->nr_vertices
+ nr
> vbuf
->max_vertices
)
102 vbuf_flush_vertices(&vbuf
->stage
, vbuf
->vertex_size
);
104 if (vbuf
->nr_indices
+ nr
> vbuf
->max_indices
)
105 vbuf_flush_indices(&vbuf
->stage
);
110 * Extract the needed fields from vertex_header and emit i915 dwords.
111 * Recall that the vertices are constructed by the 'draw' module and
112 * have a couple of slots at the beginning (1-dword header, 4-dword
113 * clip pos) that we ignore here.
116 emit_vertex( struct vbuf_stage
*vbuf
,
117 struct vertex_header
*vertex
)
119 const struct vertex_info
*vinfo
= vbuf
->render
->get_vertex_info(vbuf
->render
);
122 uint count
= 0; /* for debug/sanity */
124 // fprintf(stderr, "emit vertex %d to %p\n",
125 // vbuf->nr_vertices, vbuf->vertex_ptr);
127 if(vertex
->vertex_id
!= UNDEFINED_VERTEX_ID
) {
128 if(vertex
->vertex_id
< vbuf
->nr_vertices
)
131 fprintf(stderr
, "Bad vertex id 0x%04x (>= 0x%04x)\n",
132 vertex
->vertex_id
, vbuf
->nr_vertices
);
136 vertex
->vertex_id
= vbuf
->nr_vertices
++;
138 for (i
= 0; i
< vinfo
->num_attribs
; i
++) {
139 switch (vinfo
->format
[i
]) {
144 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][0]);
148 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][0]);
149 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][1]);
153 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][0]);
154 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][1]);
155 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][2]);
159 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][0]);
160 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][1]);
161 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][2]);
162 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[i
][3]);
166 *vbuf
->vertex_ptr
++ = pack_ub4(float_to_ubyte( vertex
->data
[i
][2] ),
167 float_to_ubyte( vertex
->data
[i
][1] ),
168 float_to_ubyte( vertex
->data
[i
][0] ),
169 float_to_ubyte( vertex
->data
[i
][3] ));
176 assert(count
== vinfo
->size
);
181 vbuf_tri( struct draw_stage
*stage
,
182 struct prim_header
*prim
)
184 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
187 check_space( vbuf
, 3 );
189 for (i
= 0; i
< 3; i
++) {
190 emit_vertex( vbuf
, prim
->v
[i
] );
192 vbuf
->indices
[vbuf
->nr_indices
++] = (ushort
) prim
->v
[i
]->vertex_id
;
198 vbuf_line( struct draw_stage
*stage
,
199 struct prim_header
*prim
)
201 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
204 check_space( vbuf
, 2 );
206 for (i
= 0; i
< 2; i
++) {
207 emit_vertex( vbuf
, prim
->v
[i
] );
209 vbuf
->indices
[vbuf
->nr_indices
++] = (ushort
) prim
->v
[i
]->vertex_id
;
215 vbuf_point( struct draw_stage
*stage
,
216 struct prim_header
*prim
)
218 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
220 check_space( vbuf
, 1 );
222 emit_vertex( vbuf
, prim
->v
[0] );
224 vbuf
->indices
[vbuf
->nr_indices
++] = (ushort
) prim
->v
[0]->vertex_id
;
229 vbuf_first_tri( struct draw_stage
*stage
,
230 struct prim_header
*prim
)
232 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
234 vbuf_flush_indices( stage
);
235 stage
->tri
= vbuf_tri
;
236 stage
->tri( stage
, prim
);
237 vbuf
->prim
= PIPE_PRIM_TRIANGLES
;
238 vbuf
->render
->set_primitive(vbuf
->render
, PIPE_PRIM_TRIANGLES
);
243 vbuf_first_line( struct draw_stage
*stage
,
244 struct prim_header
*prim
)
246 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
248 vbuf_flush_indices( stage
);
249 stage
->line
= vbuf_line
;
250 stage
->line( stage
, prim
);
251 vbuf
->prim
= PIPE_PRIM_LINES
;
252 vbuf
->render
->set_primitive(vbuf
->render
, PIPE_PRIM_LINES
);
257 vbuf_first_point( struct draw_stage
*stage
,
258 struct prim_header
*prim
)
260 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
262 vbuf_flush_indices( stage
);
263 stage
->point
= vbuf_point
;
264 stage
->point( stage
, prim
);
265 vbuf
->prim
= PIPE_PRIM_POINTS
;
266 vbuf
->render
->set_primitive(vbuf
->render
, PIPE_PRIM_POINTS
);
271 vbuf_flush_indices( struct draw_stage
*stage
)
273 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
275 if(!vbuf
->nr_indices
)
278 assert((uint
) (vbuf
->vertex_ptr
- vbuf
->vertices
) ==
279 vbuf
->nr_vertices
* vbuf
->vertex_size
/ sizeof(unsigned));
282 case PIPE_PRIM_POINTS
:
284 case PIPE_PRIM_LINES
:
285 assert(vbuf
->nr_indices
% 2 == 0);
287 case PIPE_PRIM_TRIANGLES
:
288 assert(vbuf
->nr_indices
% 3 == 0);
294 vbuf
->render
->draw( vbuf
->render
,
302 vbuf
->nr_indices
= 0;
307 * Flush existing vertex buffer and allocate a new one.
309 * XXX: We separate flush-on-index-full and flush-on-vb-full, but may
310 * raise issues uploading vertices if the hardware wants to flush when
314 vbuf_flush_vertices( struct draw_stage
*stage
,
315 unsigned new_vertex_size
)
317 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
320 vbuf_flush_indices(stage
);
322 /* Reset temporary vertices ids */
323 if(vbuf
->nr_vertices
)
324 draw_reset_vertex_ids( vbuf
->stage
.draw
);
326 /* Free the vertex buffer */
327 vbuf
->render
->release_vertices(vbuf
->render
,
331 vbuf
->nr_vertices
= 0;
332 vbuf
->vertex_ptr
= vbuf
->vertices
= NULL
;
336 assert(!vbuf
->nr_indices
);
338 /* Allocate a new vertex buffer */
339 vbuf
->vertex_size
= new_vertex_size
;
340 vbuf
->max_vertices
= vbuf
->render
->max_vertex_buffer_bytes
/ vbuf
->vertex_size
;
341 vbuf
->vertices
= vbuf
->render
->allocate_vertices(vbuf
->render
,
343 vbuf
->max_vertices
) ;
344 vbuf
->vertex_ptr
= vbuf
->vertices
;
349 vbuf_begin( struct draw_stage
*stage
)
351 struct vbuf_stage
*vbuf
= vbuf_stage(stage
);
352 const struct vertex_info
*vinfo
= vbuf
->render
->get_vertex_info(vbuf
->render
);
353 unsigned vertex_size
= vinfo
->size
* sizeof(float);
355 if(vbuf
->vertex_size
!= vertex_size
)
356 vbuf_flush_vertices(&vbuf
->stage
, vertex_size
);
361 vbuf_end( struct draw_stage
*stage
)
365 vbuf_flush_indices( stage
);
367 /* By flushing vertices we avoid having the vertex buffer grow and grow */
368 struct vbuf_stage
*vbuf
= vbuf_stage(stage
);
369 vbuf_flush_vertices( stage
, vbuf
->vertex_size
);
372 stage
->point
= vbuf_first_point
;
373 stage
->line
= vbuf_first_line
;
374 stage
->tri
= vbuf_first_tri
;
379 vbuf_reset_stipple_counter( struct draw_stage
*stage
)
384 static void vbuf_destroy( struct draw_stage
*stage
)
386 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
388 align_free( vbuf
->indices
);
394 * Create a new primitive vbuf/render stage.
396 struct draw_stage
*draw_vbuf_stage( struct draw_context
*draw
,
397 struct vbuf_render
*render
)
399 struct vbuf_stage
*vbuf
= CALLOC_STRUCT(vbuf_stage
);
401 vbuf
->stage
.draw
= draw
;
402 vbuf
->stage
.begin
= vbuf_begin
;
403 vbuf
->stage
.point
= vbuf_first_point
;
404 vbuf
->stage
.line
= vbuf_first_line
;
405 vbuf
->stage
.tri
= vbuf_first_tri
;
406 vbuf
->stage
.end
= vbuf_end
;
407 vbuf
->stage
.reset_stipple_counter
= vbuf_reset_stipple_counter
;
408 vbuf
->stage
.destroy
= vbuf_destroy
;
410 vbuf
->render
= render
;
412 assert(render
->max_indices
< UNDEFINED_VERTEX_ID
);
413 vbuf
->max_indices
= render
->max_indices
;
415 = align_malloc( vbuf
->max_indices
* sizeof(vbuf
->indices
[0]), 16 );
417 vbuf
->vertices
= NULL
;
418 vbuf
->vertex_ptr
= vbuf
->vertices
;