6a48e61e624a1762e0f98229b0655ee06ae6dc99
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 if (vcache
->draw
->rasterizer
->flatshade_first
) {
187 /* pass last quad vertex as first triangle vertex */
188 vcache_triangle( vcache
, i3
, i0
, i1
);
189 vcache_triangle( vcache
, i3
, i1
, i2
);
192 /* pass last quad vertex as last triangle vertex */
193 vcache_triangle( vcache
, i0
, i1
, i3
);
194 vcache_triangle( vcache
, i1
, i2
, i3
);
199 vcache_ef_quad( struct vcache_frontend
*vcache
,
205 if (vcache
->draw
->rasterizer
->flatshade_first
) {
206 /* pass last quad vertex as first triangle vertex */
207 vcache_triangle_flags( vcache
,
208 ( DRAW_PIPE_RESET_STIPPLE
|
209 DRAW_PIPE_EDGE_FLAG_0
|
210 DRAW_PIPE_EDGE_FLAG_1
),
213 vcache_triangle_flags( vcache
,
214 ( DRAW_PIPE_EDGE_FLAG_1
|
215 DRAW_PIPE_EDGE_FLAG_2
),
219 /* pass last quad vertex as last triangle vertex */
220 vcache_triangle_flags( vcache
,
221 ( DRAW_PIPE_RESET_STIPPLE
|
222 DRAW_PIPE_EDGE_FLAG_0
|
223 DRAW_PIPE_EDGE_FLAG_2
),
226 vcache_triangle_flags( vcache
,
227 ( DRAW_PIPE_EDGE_FLAG_0
|
228 DRAW_PIPE_EDGE_FLAG_1
),
233 /* At least for now, we're back to using a template include file for
234 * this. The two paths aren't too different though - it may be
235 * possible to reunify them.
237 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
238 #define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
239 #define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
240 #define POINT(vc,i0) vcache_point(vc,i0)
241 #define FUNC vcache_run_extras
242 #include "draw_pt_vcache_tmp.h"
244 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
245 #define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
246 #define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
247 #define POINT(vc,i0) vcache_point(vc,i0)
248 #define FUNC vcache_run
249 #include "draw_pt_vcache_tmp.h"
252 rebase_uint_elts( const unsigned *src
,
259 for (i
= 0; i
< count
; i
++)
260 dest
[i
] = (ushort
)(src
[i
] + delta
);
264 rebase_ushort_elts( const ushort
*src
,
271 for (i
= 0; i
< count
; i
++)
272 dest
[i
] = (ushort
)(src
[i
] + delta
);
276 rebase_ubyte_elts( const ubyte
*src
,
283 for (i
= 0; i
< count
; i
++)
284 dest
[i
] = (ushort
)(src
[i
] + delta
);
290 translate_uint_elts( const unsigned *src
,
296 for (i
= 0; i
< count
; i
++)
297 dest
[i
] = (ushort
)(src
[i
]);
301 translate_ushort_elts( const ushort
*src
,
307 for (i
= 0; i
< count
; i
++)
308 dest
[i
] = (ushort
)(src
[i
]);
312 translate_ubyte_elts( const ubyte
*src
,
318 for (i
= 0; i
< count
; i
++)
319 dest
[i
] = (ushort
)(src
[i
]);
326 static INLINE
enum pipe_format
327 format_from_get_elt( pt_elt_func get_elt
)
329 switch (draw
->pt
.user
.eltSize
) {
330 case 1: return PIPE_FORMAT_R8_UNORM
;
331 case 2: return PIPE_FORMAT_R16_UNORM
;
332 case 4: return PIPE_FORMAT_R32_UNORM
;
333 default: return PIPE_FORMAT_NONE
;
339 vcache_check_run( struct draw_pt_front_end
*frontend
,
343 unsigned draw_count
)
345 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
346 struct draw_context
*draw
= vcache
->draw
;
347 unsigned min_index
= draw
->pt
.user
.min_index
;
348 unsigned max_index
= draw
->pt
.user
.max_index
;
349 unsigned index_size
= draw
->pt
.user
.eltSize
;
350 unsigned fetch_count
= max_index
+ 1 - min_index
;
351 const ushort
*transformed_elts
;
352 ushort
*storage
= NULL
;
356 if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count
,
360 if (elt_bias
+ max_index
>= DRAW_PIPE_MAX_VERTICES
||
361 fetch_count
>= UNDEFINED_VERTEX_ID
||
362 fetch_count
> draw_count
) {
363 if (0) debug_printf("fail\n");
367 if (vcache
->middle_prim
!= vcache
->input_prim
) {
368 vcache
->middle_prim
= vcache
->input_prim
;
369 vcache
->middle
->prepare( vcache
->middle
,
372 &vcache
->fetch_max
);
376 assert((elt_bias
>= 0 && min_index
+ elt_bias
>= min_index
) ||
377 (elt_bias
< 0 && min_index
+ elt_bias
< min_index
));
379 if (min_index
== 0 &&
382 transformed_elts
= (const ushort
*)elts
;
386 storage
= MALLOC( draw_count
* sizeof(ushort
) );
390 if (min_index
== 0) {
393 translate_ubyte_elts( (const ubyte
*)elts
,
399 translate_ushort_elts( (const ushort
*)elts
,
405 translate_uint_elts( (const uint
*)elts
,
419 rebase_ubyte_elts( (const ubyte
*)elts
,
426 rebase_ushort_elts( (const ushort
*)elts
,
433 rebase_uint_elts( (const uint
*)elts
,
445 transformed_elts
= storage
;
448 if (fetch_count
< UNDEFINED_VERTEX_ID
)
449 ok
= vcache
->middle
->run_linear_elts( vcache
->middle
,
450 min_index
+ elt_bias
, /* start */
460 debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
461 fetch_count
, draw_count
);
464 vcache_run( frontend
, get_elt
, elts
, elt_bias
, draw_count
);
471 vcache_prepare( struct draw_pt_front_end
*frontend
,
473 struct draw_pt_middle_end
*middle
,
476 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
478 if (opt
& PT_PIPELINE
)
480 vcache
->base
.run
= vcache_run_extras
;
484 vcache
->base
.run
= vcache_check_run
;
487 vcache
->input_prim
= prim
;
488 vcache
->output_prim
= u_reduced_prim(prim
);
490 vcache
->middle
= middle
;
493 /* Have to run prepare here, but try and guess a good prim for
496 vcache
->middle_prim
= (opt
& PT_PIPELINE
) ? vcache
->output_prim
: vcache
->input_prim
;
497 middle
->prepare( middle
, vcache
->middle_prim
, opt
, &vcache
->fetch_max
);
504 vcache_finish( struct draw_pt_front_end
*frontend
)
506 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
507 vcache
->middle
->finish( vcache
->middle
);
508 vcache
->middle
= NULL
;
512 vcache_destroy( struct draw_pt_front_end
*frontend
)
518 struct draw_pt_front_end
*draw_pt_vcache( struct draw_context
*draw
)
520 struct vcache_frontend
*vcache
= CALLOC_STRUCT( vcache_frontend
);
524 vcache
->base
.prepare
= vcache_prepare
;
525 vcache
->base
.run
= NULL
;
526 vcache
->base
.finish
= vcache_finish
;
527 vcache
->base
.destroy
= vcache_destroy
;
530 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
532 return &vcache
->base
;