edb2aa73e162e95e082c17f3a0e1fc2775e8e1ad
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 if (vcache
->draw
->rasterizer
->flatshade_first
) {
197 vcache_triangle_flags( vcache
,
198 ( DRAW_PIPE_RESET_STIPPLE
|
199 DRAW_PIPE_EDGE_FLAG_0
|
200 DRAW_PIPE_EDGE_FLAG_1
),
203 vcache_triangle_flags( vcache
,
204 ( DRAW_PIPE_EDGE_FLAG_2
|
205 DRAW_PIPE_EDGE_FLAG_1
),
209 vcache_triangle_flags( vcache
,
210 ( DRAW_PIPE_RESET_STIPPLE
|
211 DRAW_PIPE_EDGE_FLAG_0
|
212 DRAW_PIPE_EDGE_FLAG_2
),
215 vcache_triangle_flags( vcache
,
216 ( DRAW_PIPE_EDGE_FLAG_0
|
217 DRAW_PIPE_EDGE_FLAG_1
),
222 /* At least for now, we're back to using a template include file for
223 * this. The two paths aren't too different though - it may be
224 * possible to reunify them.
226 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
227 #define QUAD(vc,i0,i1,i2,i3) vcache_ef_quad(vc,i0,i1,i2,i3)
228 #define LINE(vc,flags,i0,i1) vcache_line_flags(vc,flags,i0,i1)
229 #define POINT(vc,i0) vcache_point(vc,i0)
230 #define FUNC vcache_run_extras
231 #include "draw_pt_vcache_tmp.h"
233 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
234 #define QUAD(vc,i0,i1,i2,i3) vcache_quad(vc,i0,i1,i2,i3)
235 #define LINE(vc,flags,i0,i1) vcache_line(vc,i0,i1)
236 #define POINT(vc,i0) vcache_point(vc,i0)
237 #define FUNC vcache_run
238 #include "draw_pt_vcache_tmp.h"
241 rebase_uint_elts( const unsigned *src
,
248 for (i
= 0; i
< count
; i
++)
249 dest
[i
] = (ushort
)(src
[i
] + delta
);
253 rebase_ushort_elts( const ushort
*src
,
260 for (i
= 0; i
< count
; i
++)
261 dest
[i
] = (ushort
)(src
[i
] + delta
);
265 rebase_ubyte_elts( const ubyte
*src
,
272 for (i
= 0; i
< count
; i
++)
273 dest
[i
] = (ushort
)(src
[i
] + delta
);
279 translate_uint_elts( const unsigned *src
,
285 for (i
= 0; i
< count
; i
++)
286 dest
[i
] = (ushort
)(src
[i
]);
290 translate_ushort_elts( const ushort
*src
,
296 for (i
= 0; i
< count
; i
++)
297 dest
[i
] = (ushort
)(src
[i
]);
301 translate_ubyte_elts( const ubyte
*src
,
307 for (i
= 0; i
< count
; i
++)
308 dest
[i
] = (ushort
)(src
[i
]);
315 static INLINE
enum pipe_format
316 format_from_get_elt( pt_elt_func get_elt
)
318 switch (draw
->pt
.user
.eltSize
) {
319 case 1: return PIPE_FORMAT_R8_UNORM
;
320 case 2: return PIPE_FORMAT_R16_UNORM
;
321 case 4: return PIPE_FORMAT_R32_UNORM
;
322 default: return PIPE_FORMAT_NONE
;
328 vcache_check_run( struct draw_pt_front_end
*frontend
,
331 unsigned draw_count
)
333 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
334 struct draw_context
*draw
= vcache
->draw
;
335 unsigned min_index
= draw
->pt
.user
.min_index
;
336 unsigned max_index
= draw
->pt
.user
.max_index
;
337 unsigned index_size
= draw
->pt
.user
.eltSize
;
338 unsigned fetch_count
= max_index
+ 1 - min_index
;
339 const ushort
*transformed_elts
;
340 ushort
*storage
= NULL
;
344 if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count
,
348 if (max_index
== 0xffffffff ||
349 fetch_count
> draw_count
) {
350 if (0) debug_printf("fail\n");
354 if (vcache
->middle_prim
!= vcache
->input_prim
) {
355 vcache
->middle_prim
= vcache
->input_prim
;
356 vcache
->middle
->prepare( vcache
->middle
,
359 &vcache
->fetch_max
);
363 if (min_index
== 0 &&
366 transformed_elts
= (const ushort
*)elts
;
370 storage
= MALLOC( draw_count
* sizeof(ushort
) );
374 if (min_index
== 0) {
377 translate_ubyte_elts( (const ubyte
*)elts
,
383 translate_ushort_elts( (const ushort
*)elts
,
389 translate_uint_elts( (const uint
*)elts
,
402 rebase_ubyte_elts( (const ubyte
*)elts
,
409 rebase_ushort_elts( (const ushort
*)elts
,
416 rebase_uint_elts( (const uint
*)elts
,
427 transformed_elts
= storage
;
430 if (fetch_count
< UNDEFINED_VERTEX_ID
)
431 ok
= vcache
->middle
->run_linear_elts( vcache
->middle
,
432 min_index
, /* start */
442 debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
443 fetch_count
, draw_count
);
446 vcache_run( frontend
, get_elt
, elts
, draw_count
);
453 vcache_prepare( struct draw_pt_front_end
*frontend
,
455 struct draw_pt_middle_end
*middle
,
458 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
460 if (opt
& PT_PIPELINE
)
462 vcache
->base
.run
= vcache_run_extras
;
466 vcache
->base
.run
= vcache_check_run
;
469 vcache
->input_prim
= prim
;
470 vcache
->output_prim
= draw_pt_reduced_prim(prim
);
472 vcache
->middle
= middle
;
475 /* Have to run prepare here, but try and guess a good prim for
478 vcache
->middle_prim
= (opt
& PT_PIPELINE
) ? vcache
->output_prim
: vcache
->input_prim
;
479 middle
->prepare( middle
, vcache
->middle_prim
, opt
, &vcache
->fetch_max
);
486 vcache_finish( struct draw_pt_front_end
*frontend
)
488 struct vcache_frontend
*vcache
= (struct vcache_frontend
*)frontend
;
489 vcache
->middle
->finish( vcache
->middle
);
490 vcache
->middle
= NULL
;
494 vcache_destroy( struct draw_pt_front_end
*frontend
)
500 struct draw_pt_front_end
*draw_pt_vcache( struct draw_context
*draw
)
502 struct vcache_frontend
*vcache
= CALLOC_STRUCT( vcache_frontend
);
506 vcache
->base
.prepare
= vcache_prepare
;
507 vcache
->base
.run
= NULL
;
508 vcache
->base
.finish
= vcache_finish
;
509 vcache
->base
.destroy
= vcache_destroy
;
512 memset(vcache
->in
, ~0, sizeof(vcache
->in
));
514 return &vcache
->base
;