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 vcache
->draw
->vcache_flushing
= TRUE
;
67 if (vcache
->draw_count
) {
68 vcache
->middle
->run( vcache
->middle
,
75 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
76 vcache
->fetch_count
= 0;
77 vcache
->draw_count
= 0;
78 vcache
->draw
->vcache_flushing
= FALSE
;
81 static void vcache_check_flush( struct vcache_frontend
*vcache
)
83 if ( vcache
->draw_count
+ 6 >= DRAW_MAX
||
84 vcache
->fetch_count
+ 4 >= FETCH_MAX
)
86 vcache_flush( vcache
);
91 static void vcache_elt( struct vcache_frontend
*vcache
,
94 unsigned idx
= felt
% CACHE_MAX
;
96 if (vcache
->in
[idx
] != felt
) {
97 assert(vcache
->fetch_count
< FETCH_MAX
);
99 vcache
->in
[idx
] = felt
;
100 vcache
->out
[idx
] = (ushort
)vcache
->fetch_count
;
101 vcache
->fetch_elts
[vcache
->fetch_count
++] = felt
;
104 vcache
->draw_elts
[vcache
->draw_count
++] = vcache
->out
[idx
];
107 static unsigned add_edgeflag( struct vcache_frontend
*vcache
,
111 if (0 && mask
&& draw_pt_get_edgeflag(vcache
->draw
, idx
))
112 return idx
| DRAW_PT_EDGEFLAG
;
118 static unsigned add_reset_stipple( unsigned idx
,
122 return idx
| DRAW_PT_RESET_STIPPLE
;
128 static void vcache_triangle( struct vcache_frontend
*vcache
,
133 vcache_elt(vcache
, i0
/* | DRAW_PT_EDGEFLAG | DRAW_PT_RESET_STIPPLE */ );
134 vcache_elt(vcache
, i1
/* | DRAW_PT_EDGEFLAG */);
135 vcache_elt(vcache
, i2
/* | DRAW_PT_EDGEFLAG */);
136 vcache_check_flush(vcache
);
140 static void vcache_ef_triangle( struct vcache_frontend
*vcache
,
141 boolean reset_stipple
,
148 i0 = add_edgeflag( vcache, i0, (ef_mask >> 0) & 1 );
149 i1 = add_edgeflag( vcache, i1, (ef_mask >> 1) & 1 );
150 i2 = add_edgeflag( vcache, i2, (ef_mask >> 2) & 1 );
151 i0 = add_reset_stipple( i0, reset_stipple );
154 vcache_elt(vcache
, i0
);
155 vcache_elt(vcache
, i1
);
156 vcache_elt(vcache
, i2
);
157 vcache_check_flush(vcache
);
159 if (0) debug_printf("emit tri ef: %d %d %d\n",
160 !!(i0
& DRAW_PT_EDGEFLAG
),
161 !!(i1
& DRAW_PT_EDGEFLAG
),
162 !!(i2
& DRAW_PT_EDGEFLAG
));
167 static void vcache_line( struct vcache_frontend
*vcache
,
168 boolean reset_stipple
,
172 i0
= add_reset_stipple( i0
, reset_stipple
);
174 vcache_elt(vcache
, i0
);
175 vcache_elt(vcache
, i1
);
176 vcache_check_flush(vcache
);
180 static void vcache_point( struct vcache_frontend
*vcache
,
183 vcache_elt(vcache
, i0
);
184 vcache_check_flush(vcache
);
187 static void vcache_quad( struct vcache_frontend
*vcache
,
193 vcache_triangle( vcache
, i0
, i1
, i3
);
194 vcache_triangle( vcache
, i1
, i2
, i3
);
197 static void vcache_ef_quad( struct vcache_frontend
*vcache
,
203 const unsigned omitEdge2
= ~(1 << 1);
204 const unsigned omitEdge3
= ~(1 << 2);
205 vcache_ef_triangle( vcache
, 1, omitEdge2
, i0
, i1
, i3
);
206 vcache_ef_triangle( vcache
, 0, omitEdge3
, i1
, i2
, i3
);
212 static void vcache_run( struct draw_pt_front_end
*frontend
,
217 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
218 struct draw_context
*draw
= vcache
->draw
;
220 boolean unfilled
= (draw
->rasterizer
->fill_cw
!= PIPE_POLYGON_MODE_FILL
||
221 draw
->rasterizer
->fill_ccw
!= PIPE_POLYGON_MODE_FILL
);
223 boolean flatfirst
= (draw
->rasterizer
->flatshade
&&
224 draw
->rasterizer
->flatshade_first
);
227 // debug_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count );
229 switch (vcache
->input_prim
) {
230 case PIPE_PRIM_POINTS
:
231 for (i
= 0; i
< count
; i
++) {
232 vcache_point( vcache
,
233 get_elt(elts
, i
+ 0) );
237 case PIPE_PRIM_LINES
:
238 for (i
= 0; i
+1 < count
; i
+= 2) {
241 get_elt(elts
, i
+ 0),
242 get_elt(elts
, i
+ 1));
246 case PIPE_PRIM_LINE_LOOP
:
248 for (i
= 1; i
< count
; i
++) {
250 i
== 1, /* XXX: only if vb not split */
251 get_elt(elts
, i
- 1),
257 get_elt(elts
, count
- 1),
262 case PIPE_PRIM_LINE_STRIP
:
263 for (i
= 1; i
< count
; i
++) {
266 get_elt(elts
, i
- 1),
271 case PIPE_PRIM_TRIANGLES
:
273 for (i
= 0; i
+2 < count
; i
+= 3) {
274 vcache_ef_triangle( vcache
,
277 get_elt(elts
, i
+ 0),
278 get_elt(elts
, i
+ 1),
279 get_elt(elts
, i
+ 2 ));
283 for (i
= 0; i
+2 < count
; i
+= 3) {
284 vcache_triangle( vcache
,
285 get_elt(elts
, i
+ 0),
286 get_elt(elts
, i
+ 1),
287 get_elt(elts
, i
+ 2 ));
292 case PIPE_PRIM_TRIANGLE_STRIP
:
294 for (i
= 0; i
+2 < count
; i
++) {
296 vcache_triangle( vcache
,
297 get_elt(elts
, i
+ 0),
298 get_elt(elts
, i
+ 2),
299 get_elt(elts
, i
+ 1 ));
302 vcache_triangle( vcache
,
303 get_elt(elts
, i
+ 0),
304 get_elt(elts
, i
+ 1),
305 get_elt(elts
, i
+ 2 ));
310 for (i
= 0; i
+2 < count
; i
++) {
312 vcache_triangle( vcache
,
313 get_elt(elts
, i
+ 1),
314 get_elt(elts
, i
+ 0),
315 get_elt(elts
, i
+ 2 ));
318 vcache_triangle( vcache
,
319 get_elt(elts
, i
+ 0),
320 get_elt(elts
, i
+ 1),
321 get_elt(elts
, i
+ 2 ));
327 case PIPE_PRIM_TRIANGLE_FAN
:
330 for (i
= 0; i
+2 < count
; i
++) {
331 vcache_triangle( vcache
,
332 get_elt(elts
, i
+ 1),
333 get_elt(elts
, i
+ 2),
338 for (i
= 0; i
+2 < count
; i
++) {
339 vcache_triangle( vcache
,
341 get_elt(elts
, i
+ 1),
342 get_elt(elts
, i
+ 2 ));
349 case PIPE_PRIM_QUADS
:
351 for (i
= 0; i
+3 < count
; i
+= 4) {
352 vcache_ef_quad( vcache
,
353 get_elt(elts
, i
+ 0),
354 get_elt(elts
, i
+ 1),
355 get_elt(elts
, i
+ 2),
356 get_elt(elts
, i
+ 3));
360 for (i
= 0; i
+3 < count
; i
+= 4) {
362 get_elt(elts
, i
+ 0),
363 get_elt(elts
, i
+ 1),
364 get_elt(elts
, i
+ 2),
365 get_elt(elts
, i
+ 3));
370 case PIPE_PRIM_QUAD_STRIP
:
372 for (i
= 0; i
+3 < count
; i
+= 2) {
373 vcache_ef_quad( vcache
,
374 get_elt(elts
, i
+ 2),
375 get_elt(elts
, i
+ 0),
376 get_elt(elts
, i
+ 1),
377 get_elt(elts
, i
+ 3));
381 for (i
= 0; i
+3 < count
; i
+= 2) {
383 get_elt(elts
, i
+ 2),
384 get_elt(elts
, i
+ 0),
385 get_elt(elts
, i
+ 1),
386 get_elt(elts
, i
+ 3));
391 case PIPE_PRIM_POLYGON
:
393 /* These bitflags look a little odd because we submit the
394 * vertices as (1,2,0) to satisfy flatshade requirements.
396 const unsigned edge_first
= (1<<2);
397 const unsigned edge_middle
= (1<<0);
398 const unsigned edge_last
= (1<<1);
400 for (i
= 0; i
+2 < count
; i
++) {
401 unsigned ef_mask
= edge_middle
;
404 ef_mask
|= edge_first
;
407 ef_mask
|= edge_last
;
409 vcache_ef_triangle( vcache
,
412 get_elt(elts
, i
+ 1),
413 get_elt(elts
, i
+ 2),
418 for (i
= 0; i
+2 < count
; i
++) {
419 vcache_triangle( vcache
,
420 get_elt(elts
, i
+ 1),
421 get_elt(elts
, i
+ 2),
432 vcache_flush( vcache
);
437 static unsigned reduced_prim
[PIPE_PRIM_POLYGON
+ 1] = {
452 static void vcache_prepare( struct draw_pt_front_end
*frontend
,
454 struct draw_pt_middle_end
*middle
,
457 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
460 if (vcache->draw->rasterizer->flatshade_first)
461 vcache->base.run = vcache_run_pv0;
463 vcache->base.run = vcache_run_pv2;
466 vcache
->base
.run
= vcache_run
;
467 vcache
->input_prim
= prim
;
468 vcache
->output_prim
= reduced_prim
[prim
];
470 vcache
->middle
= middle
;
471 middle
->prepare( middle
, vcache
->output_prim
, opt
);
477 static void vcache_finish( struct draw_pt_front_end
*frontend
)
479 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
480 vcache
->middle
->finish( vcache
->middle
);
481 vcache
->middle
= NULL
;
484 static void vcache_destroy( struct draw_pt_front_end
*frontend
)
490 struct draw_pt_front_end
*draw_pt_vcache( struct draw_context
*draw
)
492 struct vcache_frontend
*vcache
= CALLOC_STRUCT( vcache_frontend
);
496 vcache
->base
.prepare
= vcache_prepare
;
497 vcache
->base
.run
= NULL
;
498 vcache
->base
.finish
= vcache_finish
;
499 vcache
->base
.destroy
= vcache_destroy
;
502 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
504 return &vcache
->base
;