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
,
79 if (vcache
->draw_count
) {
80 vcache
->middle
->run( vcache
->middle
,
87 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
88 vcache
->fetch_count
= 0;
89 vcache
->draw_count
= 0;
93 vcache_check_flush( struct vcache_frontend
*vcache
)
95 if ( vcache
->draw_count
+ 6 >= DRAW_MAX
||
96 vcache
->fetch_count
+ 4 >= FETCH_MAX
)
98 vcache_flush( vcache
);
104 vcache_elt( struct vcache_frontend
*vcache
,
108 unsigned idx
= felt
% CACHE_MAX
;
110 if (vcache
->in
[idx
] != felt
) {
111 assert(vcache
->fetch_count
< FETCH_MAX
);
113 vcache
->in
[idx
] = felt
;
114 vcache
->out
[idx
] = (ushort
)vcache
->fetch_count
;
115 vcache
->fetch_elts
[vcache
->fetch_count
++] = felt
;
118 vcache
->draw_elts
[vcache
->draw_count
++] = vcache
->out
[idx
] | flags
;
124 vcache_triangle( struct vcache_frontend
*vcache
,
129 vcache_elt(vcache
, i0
, 0);
130 vcache_elt(vcache
, i1
, 0);
131 vcache_elt(vcache
, i2
, 0);
132 vcache_check_flush(vcache
);
137 vcache_triangle_flags( struct vcache_frontend
*vcache
,
143 vcache_elt(vcache
, i0
, flags
);
144 vcache_elt(vcache
, i1
, 0);
145 vcache_elt(vcache
, i2
, 0);
146 vcache_check_flush(vcache
);
150 vcache_line( struct vcache_frontend
*vcache
,
154 vcache_elt(vcache
, i0
, 0);
155 vcache_elt(vcache
, i1
, 0);
156 vcache_check_flush(vcache
);
161 vcache_line_flags( struct vcache_frontend
*vcache
,
166 vcache_elt(vcache
, i0
, flags
);
167 vcache_elt(vcache
, i1
, 0);
168 vcache_check_flush(vcache
);
173 vcache_point( struct vcache_frontend
*vcache
,
176 vcache_elt(vcache
, i0
, 0);
177 vcache_check_flush(vcache
);
181 vcache_quad( struct vcache_frontend
*vcache
,
187 if (vcache
->draw
->rasterizer
->flatshade_first
) {
188 /* pass last quad vertex as first triangle vertex */
189 vcache_triangle( vcache
, i3
, i0
, i1
);
190 vcache_triangle( vcache
, i3
, i1
, i2
);
193 /* pass last quad vertex as last triangle vertex */
194 vcache_triangle( vcache
, i0
, i1
, i3
);
195 vcache_triangle( vcache
, i1
, i2
, i3
);
200 vcache_ef_quad( struct vcache_frontend
*vcache
,
206 if (vcache
->draw
->rasterizer
->flatshade_first
) {
207 /* pass last quad vertex as first triangle vertex */
208 vcache_triangle_flags( vcache
,
209 ( DRAW_PIPE_RESET_STIPPLE
|
210 DRAW_PIPE_EDGE_FLAG_0
|
211 DRAW_PIPE_EDGE_FLAG_1
),
214 vcache_triangle_flags( vcache
,
215 ( DRAW_PIPE_EDGE_FLAG_1
|
216 DRAW_PIPE_EDGE_FLAG_2
),
220 /* pass last quad vertex as last triangle vertex */
221 vcache_triangle_flags( vcache
,
222 ( DRAW_PIPE_RESET_STIPPLE
|
223 DRAW_PIPE_EDGE_FLAG_0
|
224 DRAW_PIPE_EDGE_FLAG_2
),
227 vcache_triangle_flags( vcache
,
228 ( DRAW_PIPE_EDGE_FLAG_0
|
229 DRAW_PIPE_EDGE_FLAG_1
),
234 /* At least for now, we're back to using a template include file for
235 * this. The two paths aren't too different though - it may be
236 * possible to reunify them.
238 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
239 #define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
240 #define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
241 #define POINT(vc,i0) vcache_point(vc,i0)
242 #define FUNC vcache_run_extras
243 #include "draw_pt_vcache_tmp.h"
245 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
246 #define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
247 #define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
248 #define POINT(vc,i0) vcache_point(vc,i0)
249 #define FUNC vcache_run
250 #include "draw_pt_vcache_tmp.h"
253 rebase_uint_elts( const unsigned *src
,
260 for (i
= 0; i
< count
; i
++)
261 dest
[i
] = (ushort
)(src
[i
] + delta
);
265 rebase_ushort_elts( const ushort
*src
,
272 for (i
= 0; i
< count
; i
++)
273 dest
[i
] = (ushort
)(src
[i
] + delta
);
277 rebase_ubyte_elts( const ubyte
*src
,
284 for (i
= 0; i
< count
; i
++)
285 dest
[i
] = (ushort
)(src
[i
] + delta
);
291 translate_uint_elts( const unsigned *src
,
297 for (i
= 0; i
< count
; i
++)
298 dest
[i
] = (ushort
)(src
[i
]);
302 translate_ushort_elts( const ushort
*src
,
308 for (i
= 0; i
< count
; i
++)
309 dest
[i
] = (ushort
)(src
[i
]);
313 translate_ubyte_elts( const ubyte
*src
,
319 for (i
= 0; i
< count
; i
++)
320 dest
[i
] = (ushort
)(src
[i
]);
327 static INLINE
enum pipe_format
328 format_from_get_elt( pt_elt_func get_elt
)
330 switch (draw
->pt
.user
.eltSize
) {
331 case 1: return PIPE_FORMAT_R8_UNORM
;
332 case 2: return PIPE_FORMAT_R16_UNORM
;
333 case 4: return PIPE_FORMAT_R32_UNORM
;
334 default: return PIPE_FORMAT_NONE
;
340 vcache_check_run( struct draw_pt_front_end
*frontend
,
344 unsigned draw_count
)
346 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
347 struct draw_context
*draw
= vcache
->draw
;
348 unsigned min_index
= draw
->pt
.user
.min_index
;
349 unsigned max_index
= draw
->pt
.user
.max_index
;
350 unsigned index_size
= draw
->pt
.user
.eltSize
;
351 unsigned fetch_count
= max_index
+ 1 - min_index
;
352 const ushort
*transformed_elts
;
353 ushort
*storage
= NULL
;
357 if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count
,
361 if (elt_bias
+ max_index
>= DRAW_PIPE_MAX_VERTICES
||
362 fetch_count
>= UNDEFINED_VERTEX_ID
||
363 fetch_count
> draw_count
) {
364 if (0) debug_printf("fail\n");
368 if (vcache
->middle_prim
!= vcache
->input_prim
) {
369 vcache
->middle_prim
= vcache
->input_prim
;
370 vcache
->middle
->prepare( vcache
->middle
,
374 &vcache
->fetch_max
);
378 assert((elt_bias
>= 0 && min_index
+ elt_bias
>= min_index
) ||
379 (elt_bias
< 0 && min_index
+ elt_bias
< min_index
));
381 if (min_index
== 0 &&
384 transformed_elts
= (const ushort
*)elts
;
388 storage
= MALLOC( draw_count
* sizeof(ushort
) );
392 if (min_index
== 0) {
395 translate_ubyte_elts( (const ubyte
*)elts
,
401 translate_ushort_elts( (const ushort
*)elts
,
407 translate_uint_elts( (const uint
*)elts
,
421 rebase_ubyte_elts( (const ubyte
*)elts
,
428 rebase_ushort_elts( (const ushort
*)elts
,
435 rebase_uint_elts( (const uint
*)elts
,
447 transformed_elts
= storage
;
450 if (fetch_count
< UNDEFINED_VERTEX_ID
)
451 ok
= vcache
->middle
->run_linear_elts( vcache
->middle
,
452 min_index
+ elt_bias
, /* start */
462 debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
463 fetch_count
, draw_count
);
466 vcache_run( frontend
, get_elt
, elts
, elt_bias
, draw_count
);
473 vcache_prepare( struct draw_pt_front_end
*frontend
,
476 struct draw_pt_middle_end
*middle
,
479 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
481 if (opt
& PT_PIPELINE
)
483 vcache
->base
.run
= vcache_run_extras
;
487 vcache
->base
.run
= vcache_check_run
;
490 vcache
->input_prim
= in_prim
;
491 vcache
->output_prim
= u_reduced_prim(out_prim
);
493 vcache
->middle
= middle
;
496 /* Have to run prepare here, but try and guess a good prim for
499 vcache
->middle_prim
= (opt
& PT_PIPELINE
) ? vcache
->output_prim
: vcache
->input_prim
;
500 middle
->prepare( middle
, vcache
->input_prim
,
501 vcache
->middle_prim
, opt
, &vcache
->fetch_max
);
508 vcache_finish( struct draw_pt_front_end
*frontend
)
510 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
511 vcache
->middle
->finish( vcache
->middle
);
512 vcache
->middle
= NULL
;
516 vcache_destroy( struct draw_pt_front_end
*frontend
)
522 struct draw_pt_front_end
*draw_pt_vcache( struct draw_context
*draw
)
524 struct vcache_frontend
*vcache
= CALLOC_STRUCT( vcache_frontend
);
528 vcache
->base
.prepare
= vcache_prepare
;
529 vcache
->base
.run
= NULL
;
530 vcache
->base
.finish
= vcache_finish
;
531 vcache
->base
.destroy
= vcache_destroy
;
534 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
536 return &vcache
->base
;