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
;
63 uint vertex_buffer_size
;
69 static struct softpipe_vbuf_render
*
70 softpipe_vbuf_render(struct vbuf_render
*vbr
)
72 return (struct softpipe_vbuf_render
*) vbr
;
76 static const struct vertex_info
*
77 sp_vbuf_get_vertex_info(struct vbuf_render
*vbr
)
79 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
80 return softpipe_get_vbuf_vertex_info(cvbr
->softpipe
);
85 sp_vbuf_allocate_vertices(struct vbuf_render
*vbr
,
86 ushort vertex_size
, ushort nr_vertices
)
88 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
89 unsigned size
= vertex_size
* nr_vertices
;
91 if (cvbr
->vertex_buffer_size
< size
) {
92 align_free(cvbr
->vertex_buffer
);
93 cvbr
->vertex_buffer
= align_malloc(size
, 16);
94 cvbr
->vertex_buffer_size
= size
;
97 cvbr
->vertex_size
= vertex_size
;
98 return cvbr
->vertex_buffer
!= NULL
;
102 sp_vbuf_release_vertices(struct vbuf_render
*vbr
)
104 /* keep the old allocation for next time */
108 sp_vbuf_map_vertices(struct vbuf_render
*vbr
)
110 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
111 return cvbr
->vertex_buffer
;
115 sp_vbuf_unmap_vertices(struct vbuf_render
*vbr
,
119 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
120 assert( cvbr
->vertex_buffer_size
>= (max_index
+1) * cvbr
->vertex_size
);
126 sp_vbuf_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
128 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
130 /* XXX: break this dependency - make setup_context live under
131 * softpipe, rename the old "setup" draw stage to something else.
133 struct setup_context
*setup_ctx
= sp_draw_setup_context(cvbr
->softpipe
->setup
);
135 setup_prepare( setup_ctx
);
143 static INLINE cptrf4
get_vert( const void *vertex_buffer
,
147 return (cptrf4
)((char *)vertex_buffer
+ index
* stride
);
152 * draw elements / indexed primitives
155 sp_vbuf_draw(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
157 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
158 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
159 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
160 const void *vertex_buffer
= cvbr
->vertex_buffer
;
163 /* XXX: break this dependency - make setup_context live under
164 * softpipe, rename the old "setup" draw stage to something else.
166 struct draw_stage
*setup
= softpipe
->setup
;
167 struct setup_context
*setup_ctx
= sp_draw_setup_context(setup
);
169 switch (cvbr
->prim
) {
170 case PIPE_PRIM_POINTS
:
171 for (i
= 0; i
< nr
; i
++) {
172 setup_point( setup_ctx
,
173 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
177 case PIPE_PRIM_LINES
:
178 for (i
= 1; i
< nr
; i
+= 2) {
179 setup_line( setup_ctx
,
180 get_vert(vertex_buffer
, indices
[i
-1], stride
),
181 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
185 case PIPE_PRIM_LINE_STRIP
:
186 for (i
= 1; i
< nr
; i
++) {
187 setup_line( setup_ctx
,
188 get_vert(vertex_buffer
, indices
[i
-1], stride
),
189 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
193 case PIPE_PRIM_LINE_LOOP
:
194 for (i
= 1; i
< nr
; i
++) {
195 setup_line( setup_ctx
,
196 get_vert(vertex_buffer
, indices
[i
-1], stride
),
197 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
200 setup_line( setup_ctx
,
201 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
202 get_vert(vertex_buffer
, indices
[0], stride
) );
207 case PIPE_PRIM_TRIANGLES
:
208 for (i
= 2; i
< nr
; i
+= 3) {
209 setup_tri( setup_ctx
,
210 get_vert(vertex_buffer
, indices
[i
-2], stride
),
211 get_vert(vertex_buffer
, indices
[i
-1], stride
),
212 get_vert(vertex_buffer
, indices
[i
-0], stride
));
216 case PIPE_PRIM_TRIANGLE_STRIP
:
217 for (i
= 2; i
< nr
; i
+= 1) {
218 setup_tri( setup_ctx
,
219 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
220 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
221 get_vert(vertex_buffer
, indices
[i
-0], stride
));
225 case PIPE_PRIM_TRIANGLE_FAN
:
226 case PIPE_PRIM_POLYGON
:
227 for (i
= 2; i
< nr
; i
+= 1) {
228 setup_tri( setup_ctx
,
229 get_vert(vertex_buffer
, indices
[0], stride
),
230 get_vert(vertex_buffer
, indices
[i
-1], stride
),
231 get_vert(vertex_buffer
, indices
[i
-0], stride
));
234 case PIPE_PRIM_QUADS
:
235 for (i
= 3; i
< nr
; i
+= 4) {
236 setup_tri( setup_ctx
,
237 get_vert(vertex_buffer
, indices
[i
-3], stride
),
238 get_vert(vertex_buffer
, indices
[i
-2], stride
),
239 get_vert(vertex_buffer
, indices
[i
-0], stride
));
241 setup_tri( setup_ctx
,
242 get_vert(vertex_buffer
, indices
[i
-2], stride
),
243 get_vert(vertex_buffer
, indices
[i
-1], stride
),
244 get_vert(vertex_buffer
, indices
[i
-0], stride
));
247 case PIPE_PRIM_QUAD_STRIP
:
248 for (i
= 3; i
< nr
; i
+= 2) {
249 setup_tri( setup_ctx
,
250 get_vert(vertex_buffer
, indices
[i
-3], stride
),
251 get_vert(vertex_buffer
, indices
[i
-2], stride
),
252 get_vert(vertex_buffer
, indices
[i
-0], stride
));
254 setup_tri( setup_ctx
,
255 get_vert(vertex_buffer
, indices
[i
-1], stride
),
256 get_vert(vertex_buffer
, indices
[i
-3], stride
),
257 get_vert(vertex_buffer
, indices
[i
-0], stride
));
264 /* XXX: why are we calling this??? If we had to call something, it
265 * would be a function in sp_setup.c:
267 sp_draw_flush( setup
);
272 * This function is hit when the draw module is working in pass-through mode.
273 * It's up to us to convert the vertex array into point/line/tri prims.
276 sp_vbuf_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
278 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
279 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
280 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
281 const void *vertex_buffer
=
282 (void *) get_vert(cvbr
->vertex_buffer
, start
, stride
);
285 /* XXX: break this dependency - make setup_context live under
286 * softpipe, rename the old "setup" draw stage to something else.
288 struct draw_stage
*setup
= softpipe
->setup
;
289 struct setup_context
*setup_ctx
= sp_draw_setup_context(setup
);
291 switch (cvbr
->prim
) {
292 case PIPE_PRIM_POINTS
:
293 for (i
= 0; i
< nr
; i
++) {
294 setup_point( setup_ctx
,
295 get_vert(vertex_buffer
, i
-0, stride
) );
299 case PIPE_PRIM_LINES
:
300 for (i
= 1; i
< nr
; i
+= 2) {
301 setup_line( setup_ctx
,
302 get_vert(vertex_buffer
, i
-1, stride
),
303 get_vert(vertex_buffer
, i
-0, stride
) );
307 case PIPE_PRIM_LINE_STRIP
:
308 for (i
= 1; i
< nr
; i
++) {
309 setup_line( setup_ctx
,
310 get_vert(vertex_buffer
, i
-1, stride
),
311 get_vert(vertex_buffer
, i
-0, stride
) );
315 case PIPE_PRIM_LINE_LOOP
:
316 for (i
= 1; i
< nr
; i
++) {
317 setup_line( setup_ctx
,
318 get_vert(vertex_buffer
, i
-1, stride
),
319 get_vert(vertex_buffer
, i
-0, stride
) );
322 setup_line( setup_ctx
,
323 get_vert(vertex_buffer
, nr
-1, stride
),
324 get_vert(vertex_buffer
, 0, stride
) );
329 case PIPE_PRIM_TRIANGLES
:
330 for (i
= 2; i
< nr
; i
+= 3) {
331 setup_tri( setup_ctx
,
332 get_vert(vertex_buffer
, i
-2, stride
),
333 get_vert(vertex_buffer
, i
-1, stride
),
334 get_vert(vertex_buffer
, i
-0, stride
));
338 case PIPE_PRIM_TRIANGLE_STRIP
:
339 for (i
= 2; i
< nr
; i
+= 1) {
340 setup_tri( setup_ctx
,
341 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
342 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
343 get_vert(vertex_buffer
, i
-0, stride
));
347 case PIPE_PRIM_TRIANGLE_FAN
:
348 case PIPE_PRIM_POLYGON
:
349 for (i
= 2; i
< nr
; i
+= 1) {
350 setup_tri( setup_ctx
,
351 get_vert(vertex_buffer
, 0, stride
),
352 get_vert(vertex_buffer
, i
-1, stride
),
353 get_vert(vertex_buffer
, i
-0, stride
));
356 case PIPE_PRIM_QUADS
:
357 for (i
= 3; i
< nr
; i
+= 4) {
358 setup_tri( setup_ctx
,
359 get_vert(vertex_buffer
, i
-3, stride
),
360 get_vert(vertex_buffer
, i
-2, stride
),
361 get_vert(vertex_buffer
, i
-0, stride
));
363 setup_tri( setup_ctx
,
364 get_vert(vertex_buffer
, i
-2, stride
),
365 get_vert(vertex_buffer
, i
-1, stride
),
366 get_vert(vertex_buffer
, i
-0, stride
));
369 case PIPE_PRIM_QUAD_STRIP
:
370 for (i
= 3; i
< nr
; i
+= 2) {
371 setup_tri( setup_ctx
,
372 get_vert(vertex_buffer
, i
-3, stride
),
373 get_vert(vertex_buffer
, i
-2, stride
),
374 get_vert(vertex_buffer
, i
-0, stride
));
376 setup_tri( setup_ctx
,
377 get_vert(vertex_buffer
, i
-1, stride
),
378 get_vert(vertex_buffer
, i
-3, stride
),
379 get_vert(vertex_buffer
, i
-0, stride
));
390 sp_vbuf_destroy(struct vbuf_render
*vbr
)
392 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
393 cvbr
->softpipe
->vbuf_render
= NULL
;
399 * Initialize the post-transform vertex buffer information for the given
403 sp_init_vbuf(struct softpipe_context
*sp
)
407 sp
->vbuf_render
= CALLOC_STRUCT(softpipe_vbuf_render
);
409 sp
->vbuf_render
->base
.max_indices
= SP_MAX_VBUF_INDEXES
;
410 sp
->vbuf_render
->base
.max_vertex_buffer_bytes
= SP_MAX_VBUF_SIZE
;
412 sp
->vbuf_render
->base
.get_vertex_info
= sp_vbuf_get_vertex_info
;
413 sp
->vbuf_render
->base
.allocate_vertices
= sp_vbuf_allocate_vertices
;
414 sp
->vbuf_render
->base
.map_vertices
= sp_vbuf_map_vertices
;
415 sp
->vbuf_render
->base
.unmap_vertices
= sp_vbuf_unmap_vertices
;
416 sp
->vbuf_render
->base
.set_primitive
= sp_vbuf_set_primitive
;
417 sp
->vbuf_render
->base
.draw
= sp_vbuf_draw
;
418 sp
->vbuf_render
->base
.draw_arrays
= sp_vbuf_draw_arrays
;
419 sp
->vbuf_render
->base
.release_vertices
= sp_vbuf_release_vertices
;
420 sp
->vbuf_render
->base
.destroy
= sp_vbuf_destroy
;
422 sp
->vbuf_render
->softpipe
= sp
;
424 sp
->vbuf
= draw_vbuf_stage(sp
->draw
, &sp
->vbuf_render
->base
);
426 draw_set_rasterize_stage(sp
->draw
, sp
->vbuf
);
428 draw_set_render(sp
->draw
, &sp
->vbuf_render
->base
);