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 "util/u_memory.h"
34 #include "util/u_prim.h"
35 #include "draw/draw_context.h"
36 #include "draw/draw_private.h"
37 #include "draw/draw_pt.h"
42 #define DRAW_MAX (16*1024)
44 struct vcache_frontend
{
45 struct draw_pt_front_end base
;
46 struct draw_context
*draw
;
48 unsigned in
[CACHE_MAX
];
49 ushort out
[CACHE_MAX
];
51 ushort draw_elts
[DRAW_MAX
];
52 unsigned fetch_elts
[FETCH_MAX
];
58 struct draw_pt_middle_end
*middle
;
68 vcache_flush( struct vcache_frontend
*vcache
)
70 if (vcache
->middle_prim
!= vcache
->output_prim
) {
71 vcache
->middle_prim
= vcache
->output_prim
;
72 vcache
->middle
->prepare( vcache
->middle
,
78 if (vcache
->draw_count
) {
79 vcache
->middle
->run( vcache
->middle
,
86 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
87 vcache
->fetch_count
= 0;
88 vcache
->draw_count
= 0;
92 vcache_check_flush( struct vcache_frontend
*vcache
)
94 if ( vcache
->draw_count
+ 6 >= DRAW_MAX
||
95 vcache
->fetch_count
+ 4 >= FETCH_MAX
)
97 vcache_flush( vcache
);
103 vcache_elt( struct vcache_frontend
*vcache
,
107 unsigned idx
= felt
% CACHE_MAX
;
109 if (vcache
->in
[idx
] != felt
) {
110 assert(vcache
->fetch_count
< FETCH_MAX
);
112 vcache
->in
[idx
] = felt
;
113 vcache
->out
[idx
] = (ushort
)vcache
->fetch_count
;
114 vcache
->fetch_elts
[vcache
->fetch_count
++] = felt
;
117 vcache
->draw_elts
[vcache
->draw_count
++] = vcache
->out
[idx
] | flags
;
123 vcache_triangle( struct vcache_frontend
*vcache
,
128 vcache_elt(vcache
, i0
, 0);
129 vcache_elt(vcache
, i1
, 0);
130 vcache_elt(vcache
, i2
, 0);
131 vcache_check_flush(vcache
);
136 vcache_triangle_flags( struct vcache_frontend
*vcache
,
142 vcache_elt(vcache
, i0
, flags
);
143 vcache_elt(vcache
, i1
, 0);
144 vcache_elt(vcache
, i2
, 0);
145 vcache_check_flush(vcache
);
149 vcache_line( struct vcache_frontend
*vcache
,
153 vcache_elt(vcache
, i0
, 0);
154 vcache_elt(vcache
, i1
, 0);
155 vcache_check_flush(vcache
);
160 vcache_line_flags( struct vcache_frontend
*vcache
,
165 vcache_elt(vcache
, i0
, flags
);
166 vcache_elt(vcache
, i1
, 0);
167 vcache_check_flush(vcache
);
172 vcache_point( struct vcache_frontend
*vcache
,
175 vcache_elt(vcache
, i0
, 0);
176 vcache_check_flush(vcache
);
180 vcache_quad( struct vcache_frontend
*vcache
,
186 vcache_triangle( vcache
, i0
, i1
, i3
);
187 vcache_triangle( vcache
, i1
, i2
, i3
);
191 vcache_ef_quad( struct vcache_frontend
*vcache
,
197 if (vcache
->draw
->rasterizer
->flatshade_first
) {
198 vcache_triangle_flags( vcache
,
199 ( DRAW_PIPE_RESET_STIPPLE
|
200 DRAW_PIPE_EDGE_FLAG_0
|
201 DRAW_PIPE_EDGE_FLAG_1
),
204 vcache_triangle_flags( vcache
,
205 ( DRAW_PIPE_EDGE_FLAG_2
|
206 DRAW_PIPE_EDGE_FLAG_1
),
210 vcache_triangle_flags( vcache
,
211 ( DRAW_PIPE_RESET_STIPPLE
|
212 DRAW_PIPE_EDGE_FLAG_0
|
213 DRAW_PIPE_EDGE_FLAG_2
),
216 vcache_triangle_flags( vcache
,
217 ( DRAW_PIPE_EDGE_FLAG_0
|
218 DRAW_PIPE_EDGE_FLAG_1
),
223 /* At least for now, we're back to using a template include file for
224 * this. The two paths aren't too different though - it may be
225 * possible to reunify them.
227 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
228 #define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
229 #define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
230 #define POINT(vc,i0) vcache_point(vc,i0)
231 #define FUNC vcache_run_extras
232 #include "draw_pt_vcache_tmp.h"
234 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
235 #define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
236 #define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
237 #define POINT(vc,i0) vcache_point(vc,i0)
238 #define FUNC vcache_run
239 #include "draw_pt_vcache_tmp.h"
242 rebase_uint_elts( const unsigned *src
,
249 for (i
= 0; i
< count
; i
++)
250 dest
[i
] = (ushort
)(src
[i
] + delta
);
254 rebase_ushort_elts( const ushort
*src
,
261 for (i
= 0; i
< count
; i
++)
262 dest
[i
] = (ushort
)(src
[i
] + delta
);
266 rebase_ubyte_elts( const ubyte
*src
,
273 for (i
= 0; i
< count
; i
++)
274 dest
[i
] = (ushort
)(src
[i
] + delta
);
280 translate_uint_elts( const unsigned *src
,
286 for (i
= 0; i
< count
; i
++)
287 dest
[i
] = (ushort
)(src
[i
]);
291 translate_ushort_elts( const ushort
*src
,
297 for (i
= 0; i
< count
; i
++)
298 dest
[i
] = (ushort
)(src
[i
]);
302 translate_ubyte_elts( const ubyte
*src
,
308 for (i
= 0; i
< count
; i
++)
309 dest
[i
] = (ushort
)(src
[i
]);
316 static INLINE
enum pipe_format
317 format_from_get_elt( pt_elt_func get_elt
)
319 switch (draw
->pt
.user
.eltSize
) {
320 case 1: return PIPE_FORMAT_R8_UNORM
;
321 case 2: return PIPE_FORMAT_R16_UNORM
;
322 case 4: return PIPE_FORMAT_R32_UNORM
;
323 default: return PIPE_FORMAT_NONE
;
329 vcache_check_run( struct draw_pt_front_end
*frontend
,
332 unsigned draw_count
)
334 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
335 struct draw_context
*draw
= vcache
->draw
;
336 unsigned min_index
= draw
->pt
.user
.min_index
;
337 unsigned max_index
= draw
->pt
.user
.max_index
;
338 unsigned index_size
= draw
->pt
.user
.eltSize
;
339 unsigned fetch_count
= max_index
+ 1 - min_index
;
340 const ushort
*transformed_elts
;
341 ushort
*storage
= NULL
;
345 if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count
,
349 if (max_index
== 0xffffffff ||
350 fetch_count
> draw_count
) {
351 if (0) debug_printf("fail\n");
355 if (vcache
->middle_prim
!= vcache
->input_prim
) {
356 vcache
->middle_prim
= vcache
->input_prim
;
357 vcache
->middle
->prepare( vcache
->middle
,
360 &vcache
->fetch_max
);
364 if (min_index
== 0 &&
367 transformed_elts
= (const ushort
*)elts
;
371 storage
= MALLOC( draw_count
* sizeof(ushort
) );
375 if (min_index
== 0) {
378 translate_ubyte_elts( (const ubyte
*)elts
,
384 translate_ushort_elts( (const ushort
*)elts
,
390 translate_uint_elts( (const uint
*)elts
,
404 rebase_ubyte_elts( (const ubyte
*)elts
,
411 rebase_ushort_elts( (const ushort
*)elts
,
418 rebase_uint_elts( (const uint
*)elts
,
430 transformed_elts
= storage
;
433 if (fetch_count
< UNDEFINED_VERTEX_ID
)
434 ok
= vcache
->middle
->run_linear_elts( vcache
->middle
,
435 min_index
, /* start */
445 debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
446 fetch_count
, draw_count
);
449 vcache_run( frontend
, get_elt
, elts
, draw_count
);
456 vcache_prepare( struct draw_pt_front_end
*frontend
,
458 struct draw_pt_middle_end
*middle
,
461 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
463 if (opt
& PT_PIPELINE
)
465 vcache
->base
.run
= vcache_run_extras
;
469 vcache
->base
.run
= vcache_check_run
;
472 vcache
->input_prim
= prim
;
473 vcache
->output_prim
= u_reduced_prim(prim
);
475 vcache
->middle
= middle
;
478 /* Have to run prepare here, but try and guess a good prim for
481 vcache
->middle_prim
= (opt
& PT_PIPELINE
) ? vcache
->output_prim
: vcache
->input_prim
;
482 middle
->prepare( middle
, vcache
->middle_prim
, opt
, &vcache
->fetch_max
);
489 vcache_finish( struct draw_pt_front_end
*frontend
)
491 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
492 vcache
->middle
->finish( vcache
->middle
);
493 vcache
->middle
= NULL
;
497 vcache_destroy( struct draw_pt_front_end
*frontend
)
503 struct draw_pt_front_end
*draw_pt_vcache( struct draw_context
*draw
)
505 struct vcache_frontend
*vcache
= CALLOC_STRUCT( vcache_frontend
);
509 vcache
->base
.prepare
= vcache_prepare
;
510 vcache
->base
.run
= NULL
;
511 vcache
->base
.finish
= vcache_finish
;
512 vcache
->base
.destroy
= vcache_destroy
;
515 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
517 return &vcache
->base
;