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 static void vbuf_alloc_vertices( struct draw_stage
*stage
,
88 unsigned new_vertex_size
);
92 overflow( void *map
, void *ptr
, unsigned bytes
, unsigned bufsz
)
94 unsigned long used
= (unsigned long) ((char *)ptr
- (char *)map
);
95 return (used
+ bytes
) > bufsz
;
100 check_space( struct vbuf_stage
*vbuf
, unsigned nr
)
102 if (vbuf
->nr_vertices
+ nr
> vbuf
->max_vertices
) {
103 vbuf_flush_vertices(&vbuf
->stage
);
104 vbuf_alloc_vertices(&vbuf
->stage
, vbuf
->vertex_size
);
107 if (vbuf
->nr_indices
+ nr
> vbuf
->max_indices
)
108 vbuf_flush_indices(&vbuf
->stage
);
113 * Extract the needed fields from vertex_header and emit i915 dwords.
114 * Recall that the vertices are constructed by the 'draw' module and
115 * have a couple of slots at the beginning (1-dword header, 4-dword
116 * clip pos) that we ignore here.
119 emit_vertex( struct vbuf_stage
*vbuf
,
120 struct vertex_header
*vertex
)
122 const struct vertex_info
*vinfo
= vbuf
->render
->get_vertex_info(vbuf
->render
);
125 uint count
= 0; /* for debug/sanity */
127 // fprintf(stderr, "emit vertex %d to %p\n",
128 // vbuf->nr_vertices, vbuf->vertex_ptr);
130 if(vertex
->vertex_id
!= UNDEFINED_VERTEX_ID
) {
131 if(vertex
->vertex_id
< vbuf
->nr_vertices
)
134 fprintf(stderr
, "Bad vertex id 0x%04x (>= 0x%04x)\n",
135 vertex
->vertex_id
, vbuf
->nr_vertices
);
139 vertex
->vertex_id
= vbuf
->nr_vertices
++;
141 for (i
= 0; i
< vinfo
->num_attribs
; i
++) {
142 uint j
= vinfo
->src_index
[i
];
143 switch (vinfo
->format
[i
]) {
148 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][0]);
152 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][0]);
153 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][1]);
157 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][0]);
158 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][1]);
159 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][2]);
163 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][0]);
164 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][1]);
165 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][2]);
166 *vbuf
->vertex_ptr
++ = fui(vertex
->data
[j
][3]);
170 *vbuf
->vertex_ptr
++ = pack_ub4(float_to_ubyte( vertex
->data
[j
][2] ),
171 float_to_ubyte( vertex
->data
[j
][1] ),
172 float_to_ubyte( vertex
->data
[j
][0] ),
173 float_to_ubyte( vertex
->data
[j
][3] ));
180 assert(count
== vinfo
->size
);
185 vbuf_tri( struct draw_stage
*stage
,
186 struct prim_header
*prim
)
188 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
191 check_space( vbuf
, 3 );
193 for (i
= 0; i
< 3; i
++) {
194 emit_vertex( vbuf
, prim
->v
[i
] );
196 vbuf
->indices
[vbuf
->nr_indices
++] = (ushort
) prim
->v
[i
]->vertex_id
;
202 vbuf_line( struct draw_stage
*stage
,
203 struct prim_header
*prim
)
205 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
208 check_space( vbuf
, 2 );
210 for (i
= 0; i
< 2; i
++) {
211 emit_vertex( vbuf
, prim
->v
[i
] );
213 vbuf
->indices
[vbuf
->nr_indices
++] = (ushort
) prim
->v
[i
]->vertex_id
;
219 vbuf_point( struct draw_stage
*stage
,
220 struct prim_header
*prim
)
222 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
224 check_space( vbuf
, 1 );
226 emit_vertex( vbuf
, prim
->v
[0] );
228 vbuf
->indices
[vbuf
->nr_indices
++] = (ushort
) prim
->v
[0]->vertex_id
;
233 vbuf_first_tri( struct draw_stage
*stage
,
234 struct prim_header
*prim
)
236 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
238 vbuf_flush_indices( stage
);
240 stage
->tri
= vbuf_tri
;
241 vbuf
->prim
= PIPE_PRIM_TRIANGLES
;
242 vbuf
->render
->set_primitive(vbuf
->render
, PIPE_PRIM_TRIANGLES
);
244 stage
->tri( stage
, prim
);
249 vbuf_first_line( struct draw_stage
*stage
,
250 struct prim_header
*prim
)
252 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
254 vbuf_flush_indices( stage
);
255 stage
->line
= vbuf_line
;
256 vbuf
->prim
= PIPE_PRIM_LINES
;
257 vbuf
->render
->set_primitive(vbuf
->render
, PIPE_PRIM_LINES
);
259 stage
->line( stage
, prim
);
264 vbuf_first_point( struct draw_stage
*stage
,
265 struct prim_header
*prim
)
267 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
269 vbuf_flush_indices( stage
);
271 stage
->point
= vbuf_point
;
272 vbuf
->prim
= PIPE_PRIM_POINTS
;
273 vbuf
->render
->set_primitive(vbuf
->render
, PIPE_PRIM_POINTS
);
275 stage
->point( stage
, prim
);
280 vbuf_flush_indices( struct draw_stage
*stage
)
282 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
284 if(!vbuf
->nr_indices
)
287 assert((uint
) (vbuf
->vertex_ptr
- vbuf
->vertices
) ==
288 vbuf
->nr_vertices
* vbuf
->vertex_size
/ sizeof(unsigned));
291 case PIPE_PRIM_POINTS
:
293 case PIPE_PRIM_LINES
:
294 assert(vbuf
->nr_indices
% 2 == 0);
296 case PIPE_PRIM_TRIANGLES
:
297 assert(vbuf
->nr_indices
% 3 == 0);
303 vbuf
->render
->draw(vbuf
->render
, vbuf
->indices
, vbuf
->nr_indices
);
305 vbuf
->nr_indices
= 0;
307 stage
->point
= vbuf_first_point
;
308 stage
->line
= vbuf_first_line
;
309 stage
->tri
= vbuf_first_tri
;
314 * Flush existing vertex buffer and allocate a new one.
316 * XXX: We separate flush-on-index-full and flush-on-vb-full, but may
317 * raise issues uploading vertices if the hardware wants to flush when
321 vbuf_flush_vertices( struct draw_stage
*stage
)
323 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
326 vbuf_flush_indices(stage
);
328 /* Reset temporary vertices ids */
329 if(vbuf
->nr_vertices
)
330 draw_reset_vertex_ids( vbuf
->stage
.draw
);
332 /* Free the vertex buffer */
333 vbuf
->render
->release_vertices(vbuf
->render
,
337 vbuf
->nr_vertices
= 0;
338 vbuf
->vertex_ptr
= vbuf
->vertices
= NULL
;
345 vbuf_alloc_vertices( struct draw_stage
*stage
,
346 unsigned new_vertex_size
)
348 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
350 assert(!vbuf
->nr_indices
);
351 assert(!vbuf
->vertices
);
353 /* Allocate a new vertex buffer */
354 vbuf
->vertex_size
= new_vertex_size
;
355 vbuf
->max_vertices
= vbuf
->render
->max_vertex_buffer_bytes
/ vbuf
->vertex_size
;
356 vbuf
->vertices
= vbuf
->render
->allocate_vertices(vbuf
->render
,
357 (ushort
) vbuf
->vertex_size
,
358 (ushort
) vbuf
->max_vertices
);
359 vbuf
->vertex_ptr
= vbuf
->vertices
;
364 vbuf_begin( struct draw_stage
*stage
)
366 struct vbuf_stage
*vbuf
= vbuf_stage(stage
);
367 const struct vertex_info
*vinfo
= vbuf
->render
->get_vertex_info(vbuf
->render
);
368 unsigned vertex_size
= vinfo
->size
* sizeof(float);
371 vbuf_alloc_vertices(&vbuf
->stage
, vertex_size
);
376 vbuf_end( struct draw_stage
*stage
)
378 // vbuf_flush_indices( stage );
380 vbuf_flush_vertices( stage
);
382 stage
->point
= vbuf_first_point
;
383 stage
->line
= vbuf_first_line
;
384 stage
->tri
= vbuf_first_tri
;
389 vbuf_reset_stipple_counter( struct draw_stage
*stage
)
394 static void vbuf_destroy( struct draw_stage
*stage
)
396 struct vbuf_stage
*vbuf
= vbuf_stage( stage
);
398 align_free( vbuf
->indices
);
404 * Create a new primitive vbuf/render stage.
406 struct draw_stage
*draw_vbuf_stage( struct draw_context
*draw
,
407 struct vbuf_render
*render
)
409 struct vbuf_stage
*vbuf
= CALLOC_STRUCT(vbuf_stage
);
411 vbuf
->stage
.draw
= draw
;
412 vbuf
->stage
.begin
= vbuf_begin
;
413 vbuf
->stage
.point
= vbuf_first_point
;
414 vbuf
->stage
.line
= vbuf_first_line
;
415 vbuf
->stage
.tri
= vbuf_first_tri
;
416 vbuf
->stage
.end
= vbuf_end
;
417 vbuf
->stage
.reset_stipple_counter
= vbuf_reset_stipple_counter
;
418 vbuf
->stage
.destroy
= vbuf_destroy
;
420 vbuf
->render
= render
;
422 assert(render
->max_indices
< UNDEFINED_VERTEX_ID
);
423 vbuf
->max_indices
= render
->max_indices
;
425 = align_malloc( vbuf
->max_indices
* sizeof(vbuf
->indices
[0]), 16 );
427 vbuf
->vertices
= NULL
;
428 vbuf
->vertex_ptr
= vbuf
->vertices
;