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 * Post-transform vertex buffering. This is an optional part of the
30 * softpipe rendering pipeline.
31 * Probably not desired in general, but useful for testing/debuggin.
32 * Enabled/Disabled with SP_VBUF env var.
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
;
68 static struct softpipe_vbuf_render
*
69 softpipe_vbuf_render(struct vbuf_render
*vbr
)
71 return (struct softpipe_vbuf_render
*) vbr
;
75 static const struct vertex_info
*
76 sp_vbuf_get_vertex_info(struct vbuf_render
*vbr
)
78 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
79 return softpipe_get_vbuf_vertex_info(cvbr
->softpipe
);
84 sp_vbuf_allocate_vertices(struct vbuf_render
*vbr
,
85 ushort vertex_size
, ushort nr_vertices
)
87 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
88 assert(!cvbr
->vertex_buffer
);
89 cvbr
->vertex_buffer
= align_malloc(vertex_size
* nr_vertices
, 16);
90 cvbr
->vertex_size
= vertex_size
;
91 return cvbr
->vertex_buffer
;
96 sp_vbuf_release_vertices(struct vbuf_render
*vbr
, void *vertices
,
97 unsigned vertex_size
, unsigned vertices_used
)
99 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
100 align_free(vertices
);
101 assert(vertices
== cvbr
->vertex_buffer
);
102 cvbr
->vertex_buffer
= NULL
;
107 sp_vbuf_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
109 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
111 /* XXX: break this dependency - make setup_context live under
112 * softpipe, rename the old "setup" draw stage to something else.
114 struct setup_context
*setup_ctx
= sp_draw_setup_context(cvbr
->softpipe
->setup
);
116 setup_prepare( setup_ctx
);
126 static INLINE cptrf4
get_vert( const void *vertex_buffer
,
130 return (cptrf4
)((char *)vertex_buffer
+ index
* stride
);
135 sp_vbuf_draw(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
137 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
138 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
139 unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
141 const void *vertex_buffer
= cvbr
->vertex_buffer
;
143 /* XXX: break this dependency - make setup_context live under
144 * softpipe, rename the old "setup" draw stage to something else.
146 struct draw_stage
*setup
= softpipe
->setup
;
147 struct setup_context
*setup_ctx
= sp_draw_setup_context(softpipe
->setup
);
150 switch (cvbr
->prim
) {
151 case PIPE_PRIM_POINTS
:
152 for (i
= 0; i
< nr
; i
++) {
153 setup_point( setup_ctx
,
154 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
158 case PIPE_PRIM_LINES
:
159 for (i
= 1; i
< nr
; i
+= 2) {
160 setup_line( setup_ctx
,
161 get_vert(vertex_buffer
, indices
[i
-1], stride
),
162 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
166 case PIPE_PRIM_LINE_STRIP
:
167 for (i
= 1; i
< nr
; i
++) {
168 setup_line( setup_ctx
,
169 get_vert(vertex_buffer
, indices
[i
-1], stride
),
170 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
174 case PIPE_PRIM_LINE_LOOP
:
175 for (i
= 1; i
< nr
; i
++) {
176 setup_line( setup_ctx
,
177 get_vert(vertex_buffer
, indices
[i
-1], stride
),
178 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
181 setup_line( setup_ctx
,
182 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
183 get_vert(vertex_buffer
, indices
[0], stride
) );
188 case PIPE_PRIM_TRIANGLES
:
189 for (i
= 2; i
< nr
; i
+= 3) {
190 setup_tri( setup_ctx
,
191 get_vert(vertex_buffer
, indices
[i
-2], stride
),
192 get_vert(vertex_buffer
, indices
[i
-1], stride
),
193 get_vert(vertex_buffer
, indices
[i
-0], stride
));
197 case PIPE_PRIM_TRIANGLE_STRIP
:
198 for (i
= 2; i
< nr
; i
+= 1) {
199 setup_tri( setup_ctx
,
200 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
201 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
202 get_vert(vertex_buffer
, indices
[i
-0], stride
));
206 case PIPE_PRIM_TRIANGLE_FAN
:
207 case PIPE_PRIM_POLYGON
:
208 for (i
= 2; i
< nr
; i
+= 1) {
209 setup_tri( setup_ctx
,
210 get_vert(vertex_buffer
, indices
[0], stride
),
211 get_vert(vertex_buffer
, indices
[i
-1], stride
),
212 get_vert(vertex_buffer
, indices
[i
-0], stride
));
215 case PIPE_PRIM_QUADS
:
216 for (i
= 3; i
< nr
; i
+= 4) {
217 setup_tri( setup_ctx
,
218 get_vert(vertex_buffer
, indices
[i
-3], stride
),
219 get_vert(vertex_buffer
, indices
[i
-2], stride
),
220 get_vert(vertex_buffer
, indices
[i
-0], stride
));
222 setup_tri( setup_ctx
,
223 get_vert(vertex_buffer
, indices
[i
-2], stride
),
224 get_vert(vertex_buffer
, indices
[i
-1], stride
),
225 get_vert(vertex_buffer
, indices
[i
-0], stride
));
228 case PIPE_PRIM_QUAD_STRIP
:
229 for (i
= 3; i
< nr
; i
+= 2) {
230 setup_tri( setup_ctx
,
231 get_vert(vertex_buffer
, indices
[i
-3], stride
),
232 get_vert(vertex_buffer
, indices
[i
-2], stride
),
233 get_vert(vertex_buffer
, indices
[i
-0], stride
));
235 setup_tri( setup_ctx
,
236 get_vert(vertex_buffer
, indices
[i
-1], stride
),
237 get_vert(vertex_buffer
, indices
[i
-3], stride
),
238 get_vert(vertex_buffer
, indices
[i
-0], stride
));
245 /* XXX: why are we calling this??? If we had to call something, it
246 * would be a function in sp_setup.c:
248 sp_draw_flush( setup
);
253 * This function is hit when the draw module is working in pass-through mode.
254 * It's up to us to convert the vertex array into point/line/tri prims.
257 sp_vbuf_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
259 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
260 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
261 struct draw_stage
*setup
= softpipe
->setup
;
262 const void *vertex_buffer
= NULL
;
263 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
265 struct setup_context
*setup_ctx
= sp_draw_setup_context(setup
);
267 vertex_buffer
= (void *)get_vert(cvbr
->vertex_buffer
, start
, stride
);
269 switch (cvbr
->prim
) {
270 case PIPE_PRIM_POINTS
:
271 for (i
= 0; i
< nr
; i
++) {
272 setup_point( setup_ctx
,
273 get_vert(vertex_buffer
, i
-0, stride
) );
277 case PIPE_PRIM_LINES
:
278 for (i
= 1; i
< nr
; i
+= 2) {
279 setup_line( setup_ctx
,
280 get_vert(vertex_buffer
, i
-1, stride
),
281 get_vert(vertex_buffer
, i
-0, stride
) );
285 case PIPE_PRIM_LINE_STRIP
:
286 for (i
= 1; i
< nr
; i
++) {
287 setup_line( setup_ctx
,
288 get_vert(vertex_buffer
, i
-1, stride
),
289 get_vert(vertex_buffer
, i
-0, stride
) );
293 case PIPE_PRIM_LINE_LOOP
:
294 for (i
= 1; i
< nr
; i
++) {
295 setup_line( setup_ctx
,
296 get_vert(vertex_buffer
, i
-1, stride
),
297 get_vert(vertex_buffer
, i
-0, stride
) );
300 setup_line( setup_ctx
,
301 get_vert(vertex_buffer
, nr
-1, stride
),
302 get_vert(vertex_buffer
, 0, stride
) );
307 case PIPE_PRIM_TRIANGLES
:
308 for (i
= 2; i
< nr
; i
+= 3) {
309 setup_tri( setup_ctx
,
310 get_vert(vertex_buffer
, i
-2, stride
),
311 get_vert(vertex_buffer
, i
-1, stride
),
312 get_vert(vertex_buffer
, i
-0, stride
));
316 case PIPE_PRIM_TRIANGLE_STRIP
:
317 for (i
= 2; i
< nr
; i
+= 1) {
318 setup_tri( setup_ctx
,
319 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
320 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
321 get_vert(vertex_buffer
, i
-0, stride
));
325 case PIPE_PRIM_TRIANGLE_FAN
:
326 case PIPE_PRIM_POLYGON
:
327 for (i
= 2; i
< nr
; i
+= 1) {
328 setup_tri( setup_ctx
,
329 get_vert(vertex_buffer
, 0, stride
),
330 get_vert(vertex_buffer
, i
-1, stride
),
331 get_vert(vertex_buffer
, i
-0, stride
));
334 case PIPE_PRIM_QUADS
:
335 for (i
= 3; i
< nr
; i
+= 4) {
336 setup_tri( setup_ctx
,
337 get_vert(vertex_buffer
, i
-3, stride
),
338 get_vert(vertex_buffer
, i
-2, stride
),
339 get_vert(vertex_buffer
, i
-0, stride
));
341 setup_tri( setup_ctx
,
342 get_vert(vertex_buffer
, i
-2, stride
),
343 get_vert(vertex_buffer
, i
-1, stride
),
344 get_vert(vertex_buffer
, i
-0, stride
));
347 case PIPE_PRIM_QUAD_STRIP
:
348 for (i
= 3; i
< nr
; i
+= 2) {
349 setup_tri( setup_ctx
,
350 get_vert(vertex_buffer
, i
-3, stride
),
351 get_vert(vertex_buffer
, i
-2, stride
),
352 get_vert(vertex_buffer
, i
-0, stride
));
354 setup_tri( setup_ctx
,
355 get_vert(vertex_buffer
, i
-1, stride
),
356 get_vert(vertex_buffer
, i
-3, stride
),
357 get_vert(vertex_buffer
, i
-0, stride
));
368 sp_vbuf_destroy(struct vbuf_render
*vbr
)
370 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
371 cvbr
->softpipe
->vbuf_render
= NULL
;
377 * Initialize the post-transform vertex buffer information for the given
381 sp_init_vbuf(struct softpipe_context
*sp
)
385 sp
->vbuf_render
= CALLOC_STRUCT(softpipe_vbuf_render
);
387 sp
->vbuf_render
->base
.max_indices
= SP_MAX_VBUF_INDEXES
;
388 sp
->vbuf_render
->base
.max_vertex_buffer_bytes
= SP_MAX_VBUF_SIZE
;
390 sp
->vbuf_render
->base
.get_vertex_info
= sp_vbuf_get_vertex_info
;
391 sp
->vbuf_render
->base
.allocate_vertices
= sp_vbuf_allocate_vertices
;
392 sp
->vbuf_render
->base
.set_primitive
= sp_vbuf_set_primitive
;
393 sp
->vbuf_render
->base
.draw
= sp_vbuf_draw
;
394 sp
->vbuf_render
->base
.draw_arrays
= sp_vbuf_draw_arrays
;
395 sp
->vbuf_render
->base
.release_vertices
= sp_vbuf_release_vertices
;
396 sp
->vbuf_render
->base
.destroy
= sp_vbuf_destroy
;
398 sp
->vbuf_render
->softpipe
= sp
;
400 sp
->vbuf
= draw_vbuf_stage(sp
->draw
, &sp
->vbuf_render
->base
);
402 draw_set_rasterize_stage(sp
->draw
, sp
->vbuf
);
404 draw_set_render(sp
->draw
, &sp
->vbuf_render
->base
);