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 >= DRAW_PIPE_MAX_VERTICES ||
350
fetch_count >= UNDEFINED_VERTEX_ID ||
351
fetch_count > draw_count) {
352
if (0) debug_printf("fail\n");
356
if (vcache->middle_prim != vcache->input_prim) {
357
vcache->middle_prim = vcache->input_prim;
358
vcache->middle->prepare( vcache->middle,
361
&vcache->fetch_max );
365
if (min_index == 0 &&
368
transformed_elts = (const ushort *)elts;
372
storage = MALLOC( draw_count * sizeof(ushort) );
376
if (min_index == 0) {
379
translate_ubyte_elts( (const ubyte *)elts,
385
translate_ushort_elts( (const ushort *)elts,
391
translate_uint_elts( (const uint *)elts,
405
rebase_ubyte_elts( (const ubyte *)elts,
412
rebase_ushort_elts( (const ushort *)elts,
419
rebase_uint_elts( (const uint *)elts,
431
transformed_elts = storage;
434
if (fetch_count < UNDEFINED_VERTEX_ID)
435
ok = vcache->middle->run_linear_elts( vcache->middle,
436
min_index, /* start */
446
debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
447
fetch_count, draw_count);
450
vcache_run( frontend, get_elt, elts, draw_count );
457
vcache_prepare( struct draw_pt_front_end *frontend,
459
struct draw_pt_middle_end *middle,
462
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
464
if (opt & PT_PIPELINE)
466
vcache->base.run = vcache_run_extras;
470
vcache->base.run = vcache_check_run;
473
vcache->input_prim = prim;
474
vcache->output_prim = u_reduced_prim(prim);
476
vcache->middle = middle;
479
/* Have to run prepare here, but try and guess a good prim for
482
vcache->middle_prim = (opt & PT_PIPELINE) ? vcache->output_prim : vcache->input_prim;
483
middle->prepare( middle, vcache->middle_prim, opt, &vcache->fetch_max );
490
vcache_finish( struct draw_pt_front_end *frontend )
492
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
493
vcache->middle->finish( vcache->middle );
494
vcache->middle = NULL;
498
vcache_destroy( struct draw_pt_front_end *frontend )
504
struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw )
506
struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
510
vcache->base.prepare = vcache_prepare;
511
vcache->base.run = NULL;
512
vcache->base.finish = vcache_finish;
513
vcache->base.destroy = vcache_destroy;
516
memset(vcache->in, ~0, sizeof(vcache->in));
518
return &vcache->base;