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 "draw/draw_context.h"
35 #include "draw/draw_private.h"
36 #include "draw/draw_pt.h"
41 #define DRAW_MAX (16*1024)
43 struct vcache_frontend
{
44 struct draw_pt_front_end base
;
45 struct draw_context
*draw
;
47 unsigned in
[CACHE_MAX
];
48 ushort out
[CACHE_MAX
];
50 ushort draw_elts
[DRAW_MAX
];
51 unsigned fetch_elts
[FETCH_MAX
];
57 struct draw_pt_middle_end
*middle
;
67 vcache_flush( struct vcache_frontend
*vcache
)
69 if (vcache
->middle_prim
!= vcache
->output_prim
) {
70 vcache
->middle_prim
= vcache
->output_prim
;
71 vcache
->middle
->prepare( vcache
->middle
,
77 if (vcache
->draw_count
) {
78 vcache
->middle
->run( vcache
->middle
,
85 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
86 vcache
->fetch_count
= 0;
87 vcache
->draw_count
= 0;
91 vcache_check_flush( struct vcache_frontend
*vcache
)
93 if ( vcache
->draw_count
+ 6 >= DRAW_MAX
||
94 vcache
->fetch_count
+ 4 >= FETCH_MAX
)
96 vcache_flush( vcache
);
102 vcache_elt( struct vcache_frontend
*vcache
,
106 unsigned idx
= felt
% CACHE_MAX
;
108 if (vcache
->in
[idx
] != felt
) {
109 assert(vcache
->fetch_count
< FETCH_MAX
);
111 vcache
->in
[idx
] = felt
;
112 vcache
->out
[idx
] = (ushort
)vcache
->fetch_count
;
113 vcache
->fetch_elts
[vcache
->fetch_count
++] = felt
;
116 vcache
->draw_elts
[vcache
->draw_count
++] = vcache
->out
[idx
] | flags
;
122 vcache_triangle( struct vcache_frontend
*vcache
,
127 vcache_elt(vcache
, i0
, 0);
128 vcache_elt(vcache
, i1
, 0);
129 vcache_elt(vcache
, i2
, 0);
130 vcache_check_flush(vcache
);
135 vcache_triangle_flags( struct vcache_frontend
*vcache
,
141 vcache_elt(vcache
, i0
, flags
);
142 vcache_elt(vcache
, i1
, 0);
143 vcache_elt(vcache
, i2
, 0);
144 vcache_check_flush(vcache
);
148 vcache_line( struct vcache_frontend
*vcache
,
152 vcache_elt(vcache
, i0
, 0);
153 vcache_elt(vcache
, i1
, 0);
154 vcache_check_flush(vcache
);
159 vcache_line_flags( struct vcache_frontend
*vcache
,
164 vcache_elt(vcache
, i0
, flags
);
165 vcache_elt(vcache
, i1
, 0);
166 vcache_check_flush(vcache
);
171 vcache_point( struct vcache_frontend
*vcache
,
174 vcache_elt(vcache
, i0
, 0);
175 vcache_check_flush(vcache
);
179 vcache_quad( struct vcache_frontend
*vcache
,
185 vcache_triangle( vcache
, i0
, i1
, i3
);
186 vcache_triangle( vcache
, i1
, i2
, i3
);
190 vcache_ef_quad( struct vcache_frontend
*vcache
,
196 vcache_triangle_flags( vcache
,
197 ( DRAW_PIPE_RESET_STIPPLE
|
198 DRAW_PIPE_EDGE_FLAG_0
|
199 DRAW_PIPE_EDGE_FLAG_2
),
202 vcache_triangle_flags( vcache
,
203 ( DRAW_PIPE_EDGE_FLAG_0
|
204 DRAW_PIPE_EDGE_FLAG_1
),
208 /* At least for now, we're back to using a template include file for
209 * this. The two paths aren't too different though - it may be
210 * possible to reunify them.
212 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
213 #define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
214 #define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
215 #define POINT(vc,i0) vcache_point(vc,i0)
216 #define FUNC vcache_run_extras
217 #include "draw_pt_vcache_tmp.h"
219 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
220 #define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
221 #define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
222 #define POINT(vc,i0) vcache_point(vc,i0)
223 #define FUNC vcache_run
224 #include "draw_pt_vcache_tmp.h"
227 rebase_uint_elts( const unsigned *src
,
234 for (i
= 0; i
< count
; i
++)
235 dest
[i
] = (ushort
)(src
[i
] + delta
);
239 rebase_ushort_elts( const ushort
*src
,
246 for (i
= 0; i
< count
; i
++)
247 dest
[i
] = (ushort
)(src
[i
] + delta
);
251 rebase_ubyte_elts( const ubyte
*src
,
258 for (i
= 0; i
< count
; i
++)
259 dest
[i
] = (ushort
)(src
[i
] + delta
);
265 translate_uint_elts( const unsigned *src
,
271 for (i
= 0; i
< count
; i
++)
272 dest
[i
] = (ushort
)(src
[i
]);
276 translate_ushort_elts( const ushort
*src
,
282 for (i
= 0; i
< count
; i
++)
283 dest
[i
] = (ushort
)(src
[i
]);
287 translate_ubyte_elts( const ubyte
*src
,
293 for (i
= 0; i
< count
; i
++)
294 dest
[i
] = (ushort
)(src
[i
]);
301 static INLINE
enum pipe_format
302 format_from_get_elt( pt_elt_func get_elt
)
304 switch (draw
->pt
.user
.eltSize
) {
305 case 1: return PIPE_FORMAT_R8_UNORM
;
306 case 2: return PIPE_FORMAT_R16_UNORM
;
307 case 4: return PIPE_FORMAT_R32_UNORM
;
308 default: return PIPE_FORMAT_NONE
;
314 vcache_check_run( struct draw_pt_front_end
*frontend
,
317 unsigned draw_count
)
319 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
320 struct draw_context
*draw
= vcache
->draw
;
321 unsigned min_index
= draw
->pt
.user
.min_index
;
322 unsigned max_index
= draw
->pt
.user
.max_index
;
323 unsigned index_size
= draw
->pt
.user
.eltSize
;
324 unsigned fetch_count
= max_index
+ 1 - min_index
;
325 const ushort
*transformed_elts
;
326 ushort
*storage
= NULL
;
330 if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count
,
334 if (max_index
== 0xffffffff ||
335 fetch_count
> draw_count
) {
336 if (0) debug_printf("fail\n");
340 if (vcache
->middle_prim
!= vcache
->input_prim
) {
341 vcache
->middle_prim
= vcache
->input_prim
;
342 vcache
->middle
->prepare( vcache
->middle
,
345 &vcache
->fetch_max
);
349 if (min_index
== 0 &&
352 transformed_elts
= (const ushort
*)elts
;
356 storage
= MALLOC( draw_count
* sizeof(ushort
) );
360 if (min_index
== 0) {
363 translate_ubyte_elts( (const ubyte
*)elts
,
369 translate_ushort_elts( (const ushort
*)elts
,
375 translate_uint_elts( (const uint
*)elts
,
388 rebase_ubyte_elts( (const ubyte
*)elts
,
395 rebase_ushort_elts( (const ushort
*)elts
,
402 rebase_uint_elts( (const uint
*)elts
,
413 transformed_elts
= storage
;
416 if (fetch_count
< UNDEFINED_VERTEX_ID
)
417 ok
= vcache
->middle
->run_linear_elts( vcache
->middle
,
418 min_index
, /* start */
428 debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
429 fetch_count
, draw_count
);
432 vcache_run( frontend
, get_elt
, elts
, draw_count
);
439 vcache_prepare( struct draw_pt_front_end
*frontend
,
441 struct draw_pt_middle_end
*middle
,
444 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
446 if (opt
& PT_PIPELINE
)
448 vcache
->base
.run
= vcache_run_extras
;
452 vcache
->base
.run
= vcache_check_run
;
455 vcache
->input_prim
= prim
;
456 vcache
->output_prim
= draw_pt_reduced_prim(prim
);
458 vcache
->middle
= middle
;
461 /* Have to run prepare here, but try and guess a good prim for
464 vcache
->middle_prim
= (opt
& PT_PIPELINE
) ? vcache
->output_prim
: vcache
->input_prim
;
465 middle
->prepare( middle
, vcache
->middle_prim
, opt
, &vcache
->fetch_max
);
472 vcache_finish( struct draw_pt_front_end
*frontend
)
474 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
475 vcache
->middle
->finish( vcache
->middle
);
476 vcache
->middle
= NULL
;
480 vcache_destroy( struct draw_pt_front_end
*frontend
)
486 struct draw_pt_front_end
*draw_pt_vcache( struct draw_context
*draw
)
488 struct vcache_frontend
*vcache
= CALLOC_STRUCT( vcache_frontend
);
492 vcache
->base
.prepare
= vcache_prepare
;
493 vcache
->base
.run
= NULL
;
494 vcache
->base
.finish
= vcache_finish
;
495 vcache
->base
.destroy
= vcache_destroy
;
498 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
500 return &vcache
->base
;