153055417d528b7e6ec230abd5c30a30fdae8af7
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 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "pipe/p_util.h"
34 #include "draw/draw_context.h"
35 #include "draw/draw_private.h"
36 //#include "draw/draw_vbuf.h"
37 //#include "draw/draw_vertex.h"
38 #include "draw/draw_pt.h"
43 #define DRAW_MAX (16*1024)
45 struct vcache_frontend
{
46 struct draw_pt_front_end base
;
47 struct draw_context
*draw
;
49 unsigned in
[CACHE_MAX
];
50 ushort out
[CACHE_MAX
];
52 ushort draw_elts
[DRAW_MAX
];
53 unsigned fetch_elts
[FETCH_MAX
];
58 struct draw_pt_middle_end
*middle
;
64 static void vcache_flush( struct vcache_frontend
*vcache
)
66 if (vcache
->draw_count
) {
67 vcache
->middle
->run( vcache
->middle
,
74 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
75 vcache
->fetch_count
= 0;
76 vcache
->draw_count
= 0;
79 static void vcache_check_flush( struct vcache_frontend
*vcache
)
81 if ( vcache
->draw_count
+ 6 >= DRAW_MAX
||
82 vcache
->fetch_count
+ 4 >= FETCH_MAX
)
84 vcache_flush( vcache
);
89 static void vcache_elt( struct vcache_frontend
*vcache
,
92 unsigned idx
= felt
% CACHE_MAX
;
94 if (vcache
->in
[idx
] != felt
) {
95 assert(vcache
->fetch_count
< FETCH_MAX
);
97 vcache
->in
[idx
] = felt
;
98 vcache
->out
[idx
] = (ushort
)vcache
->fetch_count
;
99 vcache
->fetch_elts
[vcache
->fetch_count
++] = felt
;
102 vcache
->draw_elts
[vcache
->draw_count
++] = vcache
->out
[idx
];
105 static unsigned add_edgeflag( struct vcache_frontend
*vcache
,
109 if (0 && mask
&& draw_pt_get_edgeflag(vcache
->draw
, idx
))
110 return idx
| DRAW_PT_EDGEFLAG
;
116 static unsigned add_reset_stipple( unsigned idx
,
120 return idx
| DRAW_PT_RESET_STIPPLE
;
126 static void vcache_triangle( struct vcache_frontend
*vcache
,
131 vcache_elt(vcache
, i0
/* | DRAW_PT_EDGEFLAG | DRAW_PT_RESET_STIPPLE */ );
132 vcache_elt(vcache
, i1
/* | DRAW_PT_EDGEFLAG */);
133 vcache_elt(vcache
, i2
/* | DRAW_PT_EDGEFLAG */);
134 vcache_check_flush(vcache
);
138 static void vcache_ef_triangle( struct vcache_frontend
*vcache
,
139 boolean reset_stipple
,
146 i0 = add_edgeflag( vcache, i0, (ef_mask >> 0) & 1 );
147 i1 = add_edgeflag( vcache, i1, (ef_mask >> 1) & 1 );
148 i2 = add_edgeflag( vcache, i2, (ef_mask >> 2) & 1 );
149 i0 = add_reset_stipple( i0, reset_stipple );
152 vcache_elt(vcache
, i0
);
153 vcache_elt(vcache
, i1
);
154 vcache_elt(vcache
, i2
);
155 vcache_check_flush(vcache
);
157 if (0) debug_printf("emit tri ef: %d %d %d\n",
158 !!(i0
& DRAW_PT_EDGEFLAG
),
159 !!(i1
& DRAW_PT_EDGEFLAG
),
160 !!(i2
& DRAW_PT_EDGEFLAG
));
165 static void vcache_line( struct vcache_frontend
*vcache
,
166 boolean reset_stipple
,
170 i0
= add_reset_stipple( i0
, reset_stipple
);
172 vcache_elt(vcache
, i0
);
173 vcache_elt(vcache
, i1
);
174 vcache_check_flush(vcache
);
178 static void vcache_point( struct vcache_frontend
*vcache
,
181 vcache_elt(vcache
, i0
);
182 vcache_check_flush(vcache
);
185 static void vcache_quad( struct vcache_frontend
*vcache
,
191 vcache_triangle( vcache
, i0
, i1
, i3
);
192 vcache_triangle( vcache
, i1
, i2
, i3
);
195 static void vcache_ef_quad( struct vcache_frontend
*vcache
,
201 const unsigned omitEdge2
= ~(1 << 1);
202 const unsigned omitEdge3
= ~(1 << 2);
203 vcache_ef_triangle( vcache
, 1, omitEdge2
, i0
, i1
, i3
);
204 vcache_ef_triangle( vcache
, 0, omitEdge3
, i1
, i2
, i3
);
210 static void vcache_run( struct draw_pt_front_end
*frontend
,
215 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
216 struct draw_context
*draw
= vcache
->draw
;
218 boolean unfilled
= (draw
->rasterizer
->fill_cw
!= PIPE_POLYGON_MODE_FILL
||
219 draw
->rasterizer
->fill_ccw
!= PIPE_POLYGON_MODE_FILL
);
221 boolean flatfirst
= (draw
->rasterizer
->flatshade
&&
222 draw
->rasterizer
->flatshade_first
);
225 // debug_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count );
227 switch (vcache
->input_prim
) {
228 case PIPE_PRIM_POINTS
:
229 for (i
= 0; i
< count
; i
++) {
230 vcache_point( vcache
,
231 get_elt(elts
, i
+ 0) );
235 case PIPE_PRIM_LINES
:
236 for (i
= 0; i
+1 < count
; i
+= 2) {
239 get_elt(elts
, i
+ 0),
240 get_elt(elts
, i
+ 1));
244 case PIPE_PRIM_LINE_LOOP
:
246 for (i
= 1; i
< count
; i
++) {
248 i
== 1, /* XXX: only if vb not split */
249 get_elt(elts
, i
- 1),
255 get_elt(elts
, count
- 1),
260 case PIPE_PRIM_LINE_STRIP
:
261 for (i
= 1; i
< count
; i
++) {
264 get_elt(elts
, i
- 1),
269 case PIPE_PRIM_TRIANGLES
:
271 for (i
= 0; i
+2 < count
; i
+= 3) {
272 vcache_ef_triangle( vcache
,
275 get_elt(elts
, i
+ 0),
276 get_elt(elts
, i
+ 1),
277 get_elt(elts
, i
+ 2 ));
281 for (i
= 0; i
+2 < count
; i
+= 3) {
282 vcache_triangle( vcache
,
283 get_elt(elts
, i
+ 0),
284 get_elt(elts
, i
+ 1),
285 get_elt(elts
, i
+ 2 ));
290 case PIPE_PRIM_TRIANGLE_STRIP
:
292 for (i
= 0; i
+2 < count
; i
++) {
294 vcache_triangle( vcache
,
295 get_elt(elts
, i
+ 0),
296 get_elt(elts
, i
+ 2),
297 get_elt(elts
, i
+ 1 ));
300 vcache_triangle( vcache
,
301 get_elt(elts
, i
+ 0),
302 get_elt(elts
, i
+ 1),
303 get_elt(elts
, i
+ 2 ));
308 for (i
= 0; i
+2 < count
; i
++) {
310 vcache_triangle( vcache
,
311 get_elt(elts
, i
+ 1),
312 get_elt(elts
, i
+ 0),
313 get_elt(elts
, i
+ 2 ));
316 vcache_triangle( vcache
,
317 get_elt(elts
, i
+ 0),
318 get_elt(elts
, i
+ 1),
319 get_elt(elts
, i
+ 2 ));
325 case PIPE_PRIM_TRIANGLE_FAN
:
328 for (i
= 0; i
+2 < count
; i
++) {
329 vcache_triangle( vcache
,
330 get_elt(elts
, i
+ 1),
331 get_elt(elts
, i
+ 2),
336 for (i
= 0; i
+2 < count
; i
++) {
337 vcache_triangle( vcache
,
339 get_elt(elts
, i
+ 1),
340 get_elt(elts
, i
+ 2 ));
347 case PIPE_PRIM_QUADS
:
349 for (i
= 0; i
+3 < count
; i
+= 4) {
350 vcache_ef_quad( vcache
,
351 get_elt(elts
, i
+ 0),
352 get_elt(elts
, i
+ 1),
353 get_elt(elts
, i
+ 2),
354 get_elt(elts
, i
+ 3));
358 for (i
= 0; i
+3 < count
; i
+= 4) {
360 get_elt(elts
, i
+ 0),
361 get_elt(elts
, i
+ 1),
362 get_elt(elts
, i
+ 2),
363 get_elt(elts
, i
+ 3));
368 case PIPE_PRIM_QUAD_STRIP
:
370 for (i
= 0; i
+3 < count
; i
+= 2) {
371 vcache_ef_quad( vcache
,
372 get_elt(elts
, i
+ 2),
373 get_elt(elts
, i
+ 0),
374 get_elt(elts
, i
+ 1),
375 get_elt(elts
, i
+ 3));
379 for (i
= 0; i
+3 < count
; i
+= 2) {
381 get_elt(elts
, i
+ 2),
382 get_elt(elts
, i
+ 0),
383 get_elt(elts
, i
+ 1),
384 get_elt(elts
, i
+ 3));
389 case PIPE_PRIM_POLYGON
:
391 /* These bitflags look a little odd because we submit the
392 * vertices as (1,2,0) to satisfy flatshade requirements.
394 const unsigned edge_first
= (1<<2);
395 const unsigned edge_middle
= (1<<0);
396 const unsigned edge_last
= (1<<1);
398 for (i
= 0; i
+2 < count
; i
++) {
399 unsigned ef_mask
= edge_middle
;
402 ef_mask
|= edge_first
;
405 ef_mask
|= edge_last
;
407 vcache_ef_triangle( vcache
,
410 get_elt(elts
, i
+ 1),
411 get_elt(elts
, i
+ 2),
416 for (i
= 0; i
+2 < count
; i
++) {
417 vcache_triangle( vcache
,
418 get_elt(elts
, i
+ 1),
419 get_elt(elts
, i
+ 2),
430 vcache_flush( vcache
);
435 static unsigned reduced_prim
[PIPE_PRIM_POLYGON
+ 1] = {
450 static void vcache_prepare( struct draw_pt_front_end
*frontend
,
452 struct draw_pt_middle_end
*middle
,
455 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
458 if (vcache->draw->rasterizer->flatshade_first)
459 vcache->base.run = vcache_run_pv0;
461 vcache->base.run = vcache_run_pv2;
464 vcache
->base
.run
= vcache_run
;
465 vcache
->input_prim
= prim
;
466 vcache
->output_prim
= reduced_prim
[prim
];
468 vcache
->middle
= middle
;
469 middle
->prepare( middle
, vcache
->output_prim
, opt
);
475 static void vcache_finish( struct draw_pt_front_end
*frontend
)
477 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
478 vcache
->middle
->finish( vcache
->middle
);
479 vcache
->middle
= NULL
;
482 static void vcache_destroy( struct draw_pt_front_end
*frontend
)
488 struct draw_pt_front_end
*draw_pt_vcache( struct draw_context
*draw
)
490 struct vcache_frontend
*vcache
= CALLOC_STRUCT( vcache_frontend
);
494 vcache
->base
.prepare
= vcache_prepare
;
495 vcache
->base
.run
= NULL
;
496 vcache
->base
.finish
= vcache_finish
;
497 vcache
->base
.destroy
= vcache_destroy
;
500 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
502 return &vcache
->base
;