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 **************************************************************************/
29 * Interface between 'draw' module's output and the softpipe rasterizer/setup
30 * code. When the 'draw' module has finished filling a vertex buffer, the
31 * draw_arrays() functions below will be called. Loop over the vertices and
32 * call the point/line/tri setup functions.
39 #include "sp_context.h"
41 #include "sp_prim_vbuf.h"
42 #include "sp_prim_setup.h"
44 #include "draw/draw_context.h"
45 #include "draw/draw_vbuf.h"
46 #include "util/u_memory.h"
49 #define SP_MAX_VBUF_INDEXES 1024
50 #define SP_MAX_VBUF_SIZE 4096
52 typedef const float (*cptrf4
)[4];
55 * Subclass of vbuf_render.
57 struct softpipe_vbuf_render
59 struct vbuf_render base
;
60 struct softpipe_context
*softpipe
;
64 uint vertex_buffer_size
;
70 static struct softpipe_vbuf_render
*
71 softpipe_vbuf_render(struct vbuf_render
*vbr
)
73 return (struct softpipe_vbuf_render
*) vbr
;
77 static const struct vertex_info
*
78 sp_vbuf_get_vertex_info(struct vbuf_render
*vbr
)
80 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
81 return softpipe_get_vbuf_vertex_info(cvbr
->softpipe
);
86 sp_vbuf_allocate_vertices(struct vbuf_render
*vbr
,
87 ushort vertex_size
, ushort nr_vertices
)
89 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
90 unsigned size
= vertex_size
* nr_vertices
;
92 if (cvbr
->vertex_buffer_size
< size
) {
93 align_free(cvbr
->vertex_buffer
);
94 cvbr
->vertex_buffer
= align_malloc(size
, 16);
95 cvbr
->vertex_buffer_size
= size
;
98 cvbr
->vertex_size
= vertex_size
;
99 cvbr
->nr_vertices
= nr_vertices
;
101 return cvbr
->vertex_buffer
!= NULL
;
105 sp_vbuf_release_vertices(struct vbuf_render
*vbr
)
109 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
110 const struct vertex_info
*info
=
111 softpipe_get_vbuf_vertex_info(cvbr
->softpipe
);
112 const float *vtx
= (const float *) cvbr
->vertex_buffer
;
114 debug_printf("%s (vtx_size = %u, vtx_used = %u)\n",
115 __FUNCTION__
, cvbr
->vertex_size
, cvbr
->nr_vertices
);
116 for (i
= 0; i
< cvbr
->nr_vertices
; i
++) {
117 for (j
= 0; j
< info
->num_attribs
; j
++) {
119 switch (info
->attrib
[j
].emit
) {
120 case EMIT_4F
: k
= 4; break;
121 case EMIT_3F
: k
= 3; break;
122 case EMIT_2F
: k
= 2; break;
123 case EMIT_1F
: k
= 1; break;
126 debug_printf("Vert %u attr %u: ", i
, j
);
128 debug_printf("%g ", vtx
[0]);
137 /* keep the old allocation for next time */
141 sp_vbuf_map_vertices(struct vbuf_render
*vbr
)
143 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
144 return cvbr
->vertex_buffer
;
148 sp_vbuf_unmap_vertices(struct vbuf_render
*vbr
,
152 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
153 assert( cvbr
->vertex_buffer_size
>= (max_index
+1) * cvbr
->vertex_size
);
159 sp_vbuf_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
161 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
163 /* XXX: break this dependency - make setup_context live under
164 * softpipe, rename the old "setup" draw stage to something else.
166 struct setup_context
*setup_ctx
= sp_draw_setup_context(cvbr
->softpipe
->setup
);
168 setup_prepare( setup_ctx
);
176 static INLINE cptrf4
get_vert( const void *vertex_buffer
,
180 return (cptrf4
)((char *)vertex_buffer
+ index
* stride
);
185 * draw elements / indexed primitives
188 sp_vbuf_draw(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
190 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
191 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
192 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
193 const void *vertex_buffer
= cvbr
->vertex_buffer
;
196 /* XXX: break this dependency - make setup_context live under
197 * softpipe, rename the old "setup" draw stage to something else.
199 struct draw_stage
*setup
= softpipe
->setup
;
200 struct setup_context
*setup_ctx
= sp_draw_setup_context(setup
);
202 switch (cvbr
->prim
) {
203 case PIPE_PRIM_POINTS
:
204 for (i
= 0; i
< nr
; i
++) {
205 setup_point( setup_ctx
,
206 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
210 case PIPE_PRIM_LINES
:
211 for (i
= 1; i
< nr
; i
+= 2) {
212 setup_line( setup_ctx
,
213 get_vert(vertex_buffer
, indices
[i
-1], stride
),
214 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
218 case PIPE_PRIM_LINE_STRIP
:
219 for (i
= 1; i
< nr
; i
++) {
220 setup_line( setup_ctx
,
221 get_vert(vertex_buffer
, indices
[i
-1], stride
),
222 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
226 case PIPE_PRIM_LINE_LOOP
:
227 for (i
= 1; i
< nr
; i
++) {
228 setup_line( setup_ctx
,
229 get_vert(vertex_buffer
, indices
[i
-1], stride
),
230 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
233 setup_line( setup_ctx
,
234 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
235 get_vert(vertex_buffer
, indices
[0], stride
) );
239 case PIPE_PRIM_TRIANGLES
:
240 for (i
= 2; i
< nr
; i
+= 3) {
241 if (softpipe
->rasterizer
->flatshade_first
) {
242 setup_tri( setup_ctx
,
243 get_vert(vertex_buffer
, indices
[i
-1], stride
),
244 get_vert(vertex_buffer
, indices
[i
-0], stride
),
245 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
248 setup_tri( setup_ctx
,
249 get_vert(vertex_buffer
, indices
[i
-2], stride
),
250 get_vert(vertex_buffer
, indices
[i
-1], stride
),
251 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
256 case PIPE_PRIM_TRIANGLE_STRIP
:
257 for (i
= 2; i
< nr
; i
+= 1) {
258 if (softpipe
->rasterizer
->flatshade_first
) {
259 setup_tri( setup_ctx
,
260 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
261 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
),
262 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
265 setup_tri( setup_ctx
,
266 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
267 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
268 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
273 case PIPE_PRIM_TRIANGLE_FAN
:
274 for (i
= 2; i
< nr
; i
+= 1) {
275 if (softpipe
->rasterizer
->flatshade_first
) {
276 setup_tri( setup_ctx
,
277 get_vert(vertex_buffer
, indices
[i
-0], stride
),
278 get_vert(vertex_buffer
, indices
[0], stride
),
279 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
282 setup_tri( setup_ctx
,
283 get_vert(vertex_buffer
, indices
[0], stride
),
284 get_vert(vertex_buffer
, indices
[i
-1], stride
),
285 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
290 case PIPE_PRIM_QUADS
:
291 for (i
= 3; i
< nr
; i
+= 4) {
292 if (softpipe
->rasterizer
->flatshade_first
) {
293 setup_tri( setup_ctx
,
294 get_vert(vertex_buffer
, indices
[i
-2], stride
),
295 get_vert(vertex_buffer
, indices
[i
-1], stride
),
296 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
297 setup_tri( setup_ctx
,
298 get_vert(vertex_buffer
, indices
[i
-1], stride
),
299 get_vert(vertex_buffer
, indices
[i
-0], stride
),
300 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
303 setup_tri( setup_ctx
,
304 get_vert(vertex_buffer
, indices
[i
-3], stride
),
305 get_vert(vertex_buffer
, indices
[i
-2], stride
),
306 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
308 setup_tri( setup_ctx
,
309 get_vert(vertex_buffer
, indices
[i
-2], stride
),
310 get_vert(vertex_buffer
, indices
[i
-1], stride
),
311 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
316 case PIPE_PRIM_QUAD_STRIP
:
317 for (i
= 3; i
< nr
; i
+= 2) {
318 if (softpipe
->rasterizer
->flatshade_first
) {
319 setup_tri( setup_ctx
,
320 get_vert(vertex_buffer
, indices
[i
-0], stride
),
321 get_vert(vertex_buffer
, indices
[i
-1], stride
),
322 get_vert(vertex_buffer
, indices
[i
-3], stride
));
323 setup_tri( setup_ctx
,
324 get_vert(vertex_buffer
, indices
[i
-2], stride
),
325 get_vert(vertex_buffer
, indices
[i
-0], stride
),
326 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
329 setup_tri( setup_ctx
,
330 get_vert(vertex_buffer
, indices
[i
-3], stride
),
331 get_vert(vertex_buffer
, indices
[i
-2], stride
),
332 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
333 setup_tri( setup_ctx
,
334 get_vert(vertex_buffer
, indices
[i
-1], stride
),
335 get_vert(vertex_buffer
, indices
[i
-3], stride
),
336 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
341 case PIPE_PRIM_POLYGON
:
342 /* Almost same as tri fan but the _first_ vertex specifies the flat
343 * shading color. Note that the first polygon vertex is passed as
344 * the last triangle vertex here.
345 * flatshade_first state makes no difference.
347 for (i
= 2; i
< nr
; i
+= 1) {
348 setup_tri( setup_ctx
,
349 get_vert(vertex_buffer
, indices
[i
-0], stride
),
350 get_vert(vertex_buffer
, indices
[i
-1], stride
),
351 get_vert(vertex_buffer
, indices
[0], stride
) );
359 /* XXX: why are we calling this??? If we had to call something, it
360 * would be a function in sp_setup.c:
362 sp_draw_flush( setup
);
367 * This function is hit when the draw module is working in pass-through mode.
368 * It's up to us to convert the vertex array into point/line/tri prims.
371 sp_vbuf_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
373 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
374 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
375 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
376 const void *vertex_buffer
=
377 (void *) get_vert(cvbr
->vertex_buffer
, start
, stride
);
380 /* XXX: break this dependency - make setup_context live under
381 * softpipe, rename the old "setup" draw stage to something else.
383 struct draw_stage
*setup
= softpipe
->setup
;
384 struct setup_context
*setup_ctx
= sp_draw_setup_context(setup
);
386 switch (cvbr
->prim
) {
387 case PIPE_PRIM_POINTS
:
388 for (i
= 0; i
< nr
; i
++) {
389 setup_point( setup_ctx
,
390 get_vert(vertex_buffer
, i
-0, stride
) );
394 case PIPE_PRIM_LINES
:
395 for (i
= 1; i
< nr
; i
+= 2) {
396 setup_line( setup_ctx
,
397 get_vert(vertex_buffer
, i
-1, stride
),
398 get_vert(vertex_buffer
, i
-0, stride
) );
402 case PIPE_PRIM_LINE_STRIP
:
403 for (i
= 1; i
< nr
; i
++) {
404 setup_line( setup_ctx
,
405 get_vert(vertex_buffer
, i
-1, stride
),
406 get_vert(vertex_buffer
, i
-0, stride
) );
410 case PIPE_PRIM_LINE_LOOP
:
411 for (i
= 1; i
< nr
; i
++) {
412 setup_line( setup_ctx
,
413 get_vert(vertex_buffer
, i
-1, stride
),
414 get_vert(vertex_buffer
, i
-0, stride
) );
417 setup_line( setup_ctx
,
418 get_vert(vertex_buffer
, nr
-1, stride
),
419 get_vert(vertex_buffer
, 0, stride
) );
423 case PIPE_PRIM_TRIANGLES
:
424 for (i
= 2; i
< nr
; i
+= 3) {
425 if (softpipe
->rasterizer
->flatshade_first
) {
426 setup_tri( setup_ctx
,
427 get_vert(vertex_buffer
, i
-1, stride
),
428 get_vert(vertex_buffer
, i
-0, stride
),
429 get_vert(vertex_buffer
, i
-2, stride
) );
432 setup_tri( setup_ctx
,
433 get_vert(vertex_buffer
, i
-2, stride
),
434 get_vert(vertex_buffer
, i
-1, stride
),
435 get_vert(vertex_buffer
, i
-0, stride
) );
440 case PIPE_PRIM_TRIANGLE_STRIP
:
441 for (i
= 2; i
< nr
; i
++) {
442 if (softpipe
->rasterizer
->flatshade_first
) {
443 setup_tri( setup_ctx
,
444 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
445 get_vert(vertex_buffer
, i
-(i
&1), stride
),
446 get_vert(vertex_buffer
, i
-2, stride
) );
449 setup_tri( setup_ctx
,
450 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
451 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
452 get_vert(vertex_buffer
, i
-0, stride
) );
457 case PIPE_PRIM_TRIANGLE_FAN
:
458 for (i
= 2; i
< nr
; i
+= 1) {
459 if (softpipe
->rasterizer
->flatshade_first
) {
460 setup_tri( setup_ctx
,
461 get_vert(vertex_buffer
, i
-0, stride
),
462 get_vert(vertex_buffer
, 0, stride
),
463 get_vert(vertex_buffer
, i
-1, stride
) );
466 setup_tri( setup_ctx
,
467 get_vert(vertex_buffer
, 0, stride
),
468 get_vert(vertex_buffer
, i
-1, stride
),
469 get_vert(vertex_buffer
, i
-0, stride
) );
474 case PIPE_PRIM_QUADS
:
475 for (i
= 3; i
< nr
; i
+= 4) {
476 if (softpipe
->rasterizer
->flatshade_first
) {
477 setup_tri( setup_ctx
,
478 get_vert(vertex_buffer
, i
-2, stride
),
479 get_vert(vertex_buffer
, i
-1, stride
),
480 get_vert(vertex_buffer
, i
-3, stride
) );
481 setup_tri( setup_ctx
,
482 get_vert(vertex_buffer
, i
-1, stride
),
483 get_vert(vertex_buffer
, i
-0, stride
),
484 get_vert(vertex_buffer
, i
-3, stride
) );
487 setup_tri( setup_ctx
,
488 get_vert(vertex_buffer
, i
-3, stride
),
489 get_vert(vertex_buffer
, i
-2, stride
),
490 get_vert(vertex_buffer
, i
-0, stride
) );
491 setup_tri( setup_ctx
,
492 get_vert(vertex_buffer
, i
-2, stride
),
493 get_vert(vertex_buffer
, i
-1, stride
),
494 get_vert(vertex_buffer
, i
-0, stride
) );
499 case PIPE_PRIM_QUAD_STRIP
:
500 for (i
= 3; i
< nr
; i
+= 2) {
501 if (softpipe
->rasterizer
->flatshade_first
) {
502 setup_tri( setup_ctx
,
503 get_vert(vertex_buffer
, i
-0, stride
),
504 get_vert(vertex_buffer
, i
-1, stride
),
505 get_vert(vertex_buffer
, i
-3, stride
) );
506 setup_tri( setup_ctx
,
507 get_vert(vertex_buffer
, i
-2, stride
),
508 get_vert(vertex_buffer
, i
-0, stride
),
509 get_vert(vertex_buffer
, i
-3, stride
) );
512 setup_tri( setup_ctx
,
513 get_vert(vertex_buffer
, i
-3, stride
),
514 get_vert(vertex_buffer
, i
-2, stride
),
515 get_vert(vertex_buffer
, i
-0, stride
) );
516 setup_tri( setup_ctx
,
517 get_vert(vertex_buffer
, i
-1, stride
),
518 get_vert(vertex_buffer
, i
-3, stride
),
519 get_vert(vertex_buffer
, i
-0, stride
) );
524 case PIPE_PRIM_POLYGON
:
525 /* Almost same as tri fan but the _first_ vertex specifies the flat
526 * shading color. Note that the first polygon vertex is passed as
527 * the last triangle vertex here.
528 * flatshade_first state makes no difference.
530 for (i
= 2; i
< nr
; i
+= 1) {
531 setup_tri( setup_ctx
,
532 get_vert(vertex_buffer
, i
-1, stride
),
533 get_vert(vertex_buffer
, i
-0, stride
),
534 get_vert(vertex_buffer
, 0, stride
) );
546 sp_vbuf_destroy(struct vbuf_render
*vbr
)
548 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
549 cvbr
->softpipe
->vbuf_render
= NULL
;
555 * Initialize the post-transform vertex buffer information for the given
559 sp_init_vbuf(struct softpipe_context
*sp
)
563 sp
->vbuf_render
= CALLOC_STRUCT(softpipe_vbuf_render
);
565 sp
->vbuf_render
->base
.max_indices
= SP_MAX_VBUF_INDEXES
;
566 sp
->vbuf_render
->base
.max_vertex_buffer_bytes
= SP_MAX_VBUF_SIZE
;
568 sp
->vbuf_render
->base
.get_vertex_info
= sp_vbuf_get_vertex_info
;
569 sp
->vbuf_render
->base
.allocate_vertices
= sp_vbuf_allocate_vertices
;
570 sp
->vbuf_render
->base
.map_vertices
= sp_vbuf_map_vertices
;
571 sp
->vbuf_render
->base
.unmap_vertices
= sp_vbuf_unmap_vertices
;
572 sp
->vbuf_render
->base
.set_primitive
= sp_vbuf_set_primitive
;
573 sp
->vbuf_render
->base
.draw
= sp_vbuf_draw
;
574 sp
->vbuf_render
->base
.draw_arrays
= sp_vbuf_draw_arrays
;
575 sp
->vbuf_render
->base
.release_vertices
= sp_vbuf_release_vertices
;
576 sp
->vbuf_render
->base
.destroy
= sp_vbuf_destroy
;
578 sp
->vbuf_render
->softpipe
= sp
;
580 sp
->vbuf
= draw_vbuf_stage(sp
->draw
, &sp
->vbuf_render
->base
);
582 draw_set_rasterize_stage(sp
->draw
, sp
->vbuf
);
584 draw_set_render(sp
->draw
, &sp
->vbuf_render
->base
);