00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028  
00029 
00030 
00031 
00032 
00033 #include "util/u_memory.h"
00034 #include "draw/draw_context.h"
00035 #include "draw/draw_private.h"
00036 #include "draw/draw_pt.h"
00037 
00038 
00039 #define CACHE_MAX 256
00040 #define FETCH_MAX 256
00041 #define DRAW_MAX (16*1024)
00042 
00043 struct vcache_frontend {
00044    struct draw_pt_front_end base;
00045    struct draw_context *draw;
00046 
00047    unsigned in[CACHE_MAX];
00048    ushort out[CACHE_MAX];
00049 
00050    ushort draw_elts[DRAW_MAX];
00051    unsigned fetch_elts[FETCH_MAX];
00052 
00053    unsigned draw_count;
00054    unsigned fetch_count;
00055    unsigned fetch_max;
00056    
00057    struct draw_pt_middle_end *middle;
00058 
00059    unsigned input_prim;
00060    unsigned output_prim;
00061 
00062    unsigned middle_prim;
00063    unsigned opt;
00064 };
00065 
00066 static INLINE void 
00067 vcache_flush( struct vcache_frontend *vcache )
00068 {
00069    if (vcache->middle_prim != vcache->output_prim) {
00070       vcache->middle_prim = vcache->output_prim;
00071       vcache->middle->prepare( vcache->middle, 
00072                                vcache->middle_prim, 
00073                                vcache->opt, 
00074                                &vcache->fetch_max );
00075    }
00076 
00077    if (vcache->draw_count) {
00078       vcache->middle->run( vcache->middle,
00079                            vcache->fetch_elts,
00080                            vcache->fetch_count,
00081                            vcache->draw_elts,
00082                            vcache->draw_count );
00083    }
00084 
00085    memset(vcache->in, ~0, sizeof(vcache->in));
00086    vcache->fetch_count = 0;
00087    vcache->draw_count = 0;
00088 }
00089 
00090 static INLINE void 
00091 vcache_check_flush( struct vcache_frontend *vcache )
00092 {
00093    if ( vcache->draw_count + 6 >= DRAW_MAX ||
00094         vcache->fetch_count + 4 >= FETCH_MAX )
00095    {
00096       vcache_flush( vcache );
00097    }
00098 }
00099 
00100 
00101 static INLINE void 
00102 vcache_elt( struct vcache_frontend *vcache,
00103             unsigned felt,
00104             ushort flags )
00105 {
00106    unsigned idx = felt % CACHE_MAX;
00107 
00108    if (vcache->in[idx] != felt) {
00109       assert(vcache->fetch_count < FETCH_MAX);
00110 
00111       vcache->in[idx] = felt;
00112       vcache->out[idx] = (ushort)vcache->fetch_count;
00113       vcache->fetch_elts[vcache->fetch_count++] = felt;
00114    }
00115 
00116    vcache->draw_elts[vcache->draw_count++] = vcache->out[idx] | flags;
00117 }
00118 
00119 
00120                    
00121 static INLINE void 
00122 vcache_triangle( struct vcache_frontend *vcache,
00123                  unsigned i0,
00124                  unsigned i1,
00125                  unsigned i2 )
00126 {
00127    vcache_elt(vcache, i0, 0);
00128    vcache_elt(vcache, i1, 0);
00129    vcache_elt(vcache, i2, 0);
00130    vcache_check_flush(vcache);
00131 }
00132 
00133                           
00134 static INLINE void 
00135 vcache_triangle_flags( struct vcache_frontend *vcache,
00136                        ushort flags,
00137                        unsigned i0,
00138                        unsigned i1,
00139                        unsigned i2 )
00140 {
00141    vcache_elt(vcache, i0, flags);
00142    vcache_elt(vcache, i1, 0);
00143    vcache_elt(vcache, i2, 0);
00144    vcache_check_flush(vcache);
00145 }
00146 
00147 static INLINE void 
00148 vcache_line( struct vcache_frontend *vcache,
00149              unsigned i0,
00150              unsigned i1 )
00151 {
00152    vcache_elt(vcache, i0, 0);
00153    vcache_elt(vcache, i1, 0);
00154    vcache_check_flush(vcache);
00155 }
00156 
00157 
00158 static INLINE void 
00159 vcache_line_flags( struct vcache_frontend *vcache,
00160                    ushort flags,
00161                    unsigned i0,
00162                    unsigned i1 )
00163 {
00164    vcache_elt(vcache, i0, flags);
00165    vcache_elt(vcache, i1, 0);
00166    vcache_check_flush(vcache);
00167 }
00168 
00169 
00170 static INLINE void 
00171 vcache_point( struct vcache_frontend *vcache,
00172               unsigned i0 )
00173 {
00174    vcache_elt(vcache, i0, 0);
00175    vcache_check_flush(vcache);
00176 }
00177 
00178 static INLINE void 
00179 vcache_quad( struct vcache_frontend *vcache,
00180              unsigned i0,
00181              unsigned i1,
00182              unsigned i2,
00183              unsigned i3 )
00184 {
00185    vcache_triangle( vcache, i0, i1, i3 );
00186    vcache_triangle( vcache, i1, i2, i3 );
00187 }
00188 
00189 static INLINE void 
00190 vcache_ef_quad( struct vcache_frontend *vcache,
00191                 unsigned i0,
00192                 unsigned i1,
00193                 unsigned i2,
00194                 unsigned i3 )
00195 {
00196    vcache_triangle_flags( vcache,
00197                           ( DRAW_PIPE_RESET_STIPPLE |
00198                             DRAW_PIPE_EDGE_FLAG_0 |
00199                             DRAW_PIPE_EDGE_FLAG_2 ),
00200                           i0, i1, i3 );
00201 
00202    vcache_triangle_flags( vcache,
00203                           ( DRAW_PIPE_EDGE_FLAG_0 |
00204                             DRAW_PIPE_EDGE_FLAG_1 ),
00205                           i1, i2, i3 );
00206 }
00207 
00208 
00209 
00210 
00211 
00212 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle_flags(vc,flags,i0,i1,i2)
00213 #define QUAD(vc,i0,i1,i2,i3)        vcache_ef_quad(vc,i0,i1,i2,i3)
00214 #define LINE(vc,flags,i0,i1)        vcache_line_flags(vc,flags,i0,i1)
00215 #define POINT(vc,i0)                vcache_point(vc,i0)
00216 #define FUNC vcache_run_extras
00217 #include "draw_pt_vcache_tmp.h"
00218 
00219 #define TRIANGLE(vc,flags,i0,i1,i2) vcache_triangle(vc,i0,i1,i2)
00220 #define QUAD(vc,i0,i1,i2,i3)        vcache_quad(vc,i0,i1,i2,i3)
00221 #define LINE(vc,flags,i0,i1)        vcache_line(vc,i0,i1)
00222 #define POINT(vc,i0)                vcache_point(vc,i0)
00223 #define FUNC vcache_run
00224 #include "draw_pt_vcache_tmp.h"
00225 
00226 static INLINE void 
00227 rebase_uint_elts( const unsigned *src,
00228                   unsigned count,
00229                   int delta,
00230                   ushort *dest )
00231 {
00232    unsigned i;
00233 
00234    for (i = 0; i < count; i++) 
00235       dest[i] = (ushort)(src[i] + delta);
00236 }
00237 
00238 static INLINE void 
00239 rebase_ushort_elts( const ushort *src,
00240                     unsigned count,
00241                     int delta,
00242                                 ushort *dest )
00243 {
00244    unsigned i;
00245 
00246    for (i = 0; i < count; i++) 
00247       dest[i] = (ushort)(src[i] + delta);
00248 }
00249 
00250 static INLINE void 
00251 rebase_ubyte_elts( const ubyte *src,
00252                    unsigned count,
00253                    int delta,
00254                    ushort *dest )
00255 {
00256    unsigned i;
00257 
00258    for (i = 0; i < count; i++) 
00259       dest[i] = (ushort)(src[i] + delta);
00260 }
00261 
00262 
00263 
00264 static INLINE void 
00265 translate_uint_elts( const unsigned *src,
00266                      unsigned count,
00267                      ushort *dest )
00268 {
00269    unsigned i;
00270 
00271    for (i = 0; i < count; i++) 
00272       dest[i] = (ushort)(src[i]);
00273 }
00274 
00275 static INLINE void 
00276 translate_ushort_elts( const ushort *src,
00277                        unsigned count,
00278                        ushort *dest )
00279 {
00280    unsigned i;
00281 
00282    for (i = 0; i < count; i++) 
00283       dest[i] = (ushort)(src[i]);
00284 }
00285 
00286 static INLINE void 
00287 translate_ubyte_elts( const ubyte *src,
00288                       unsigned count,
00289                       ushort *dest )
00290 {
00291    unsigned i;
00292 
00293    for (i = 0; i < count; i++) 
00294       dest[i] = (ushort)(src[i]);
00295 }
00296 
00297 
00298 
00299 
00300 #if 0
00301 static INLINE enum pipe_format 
00302 format_from_get_elt( pt_elt_func get_elt )
00303 {
00304    switch (draw->pt.user.eltSize) {
00305    case 1: return PIPE_FORMAT_R8_UNORM;
00306    case 2: return PIPE_FORMAT_R16_UNORM;
00307    case 4: return PIPE_FORMAT_R32_UNORM;
00308    default: return PIPE_FORMAT_NONE;
00309    }
00310 }
00311 #endif
00312 
00313 static INLINE void 
00314 vcache_check_run( struct draw_pt_front_end *frontend, 
00315                   pt_elt_func get_elt,
00316                   const void *elts,
00317                   unsigned draw_count )
00318 {
00319    struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; 
00320    struct draw_context *draw = vcache->draw;
00321    unsigned min_index = draw->pt.user.min_index;
00322    unsigned max_index = draw->pt.user.max_index;
00323    unsigned index_size = draw->pt.user.eltSize;
00324    unsigned fetch_count = max_index + 1 - min_index;
00325    const ushort *transformed_elts;
00326    ushort *storage = NULL;
00327    boolean ok;
00328 
00329 
00330    if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count, 
00331                        vcache->fetch_max,
00332                        draw_count);
00333       
00334    if (max_index == 0xffffffff ||
00335        fetch_count > draw_count) {
00336       if (0) debug_printf("fail\n");
00337       goto fail;
00338    }
00339       
00340    if (vcache->middle_prim != vcache->input_prim) {
00341       vcache->middle_prim = vcache->input_prim;
00342       vcache->middle->prepare( vcache->middle, 
00343                                vcache->middle_prim, 
00344                                vcache->opt, 
00345                                &vcache->fetch_max );
00346    }
00347 
00348 
00349    if (min_index == 0 &&
00350        index_size == 2) 
00351    {
00352       transformed_elts = (const ushort *)elts;
00353    }
00354    else 
00355    {
00356       storage = MALLOC( draw_count * sizeof(ushort) );
00357       if (!storage)
00358          goto fail;
00359       
00360       if (min_index == 0) {
00361          switch(index_size) {
00362          case 1:
00363             translate_ubyte_elts( (const ubyte *)elts,
00364                                   draw_count,
00365                                   storage );
00366             break;
00367 
00368          case 2:
00369             translate_ushort_elts( (const ushort *)elts,
00370                                    draw_count,
00371                                    storage );
00372             break;
00373 
00374          case 4:
00375             translate_uint_elts( (const uint *)elts,
00376                                  draw_count,
00377                                  storage );
00378             break;
00379 
00380          default:
00381             assert(0);
00382             return;
00383          }
00384       }
00385       else {
00386          switch(index_size) {
00387          case 1:
00388             rebase_ubyte_elts( (const ubyte *)elts,
00389                                   draw_count,
00390                                   0 - (int)min_index,
00391                                   storage );
00392             break;
00393 
00394          case 2:
00395             rebase_ushort_elts( (const ushort *)elts,
00396                                    draw_count,
00397                                    0 - (int)min_index,
00398                                    storage );
00399             break;
00400 
00401          case 4:
00402             rebase_uint_elts( (const uint *)elts,
00403                                  draw_count,
00404                                  0 - (int)min_index,
00405                                  storage );
00406             break;
00407 
00408          default:
00409             assert(0);
00410             return;
00411          }
00412       }
00413       transformed_elts = storage;
00414    }
00415 
00416    ok = vcache->middle->run_linear_elts( vcache->middle,
00417                                          min_index, 
00418                                          fetch_count,
00419                                          transformed_elts,
00420                                          draw_count );
00421    
00422    FREE(storage);
00423 
00424    if (ok)
00425       return;
00426 
00427    debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
00428                 fetch_count, draw_count);
00429 
00430  fail:
00431    vcache_run( frontend, get_elt, elts, draw_count );
00432 }
00433 
00434 
00435 
00436 
00437 static void 
00438 vcache_prepare( struct draw_pt_front_end *frontend,
00439                 unsigned prim,
00440                 struct draw_pt_middle_end *middle,
00441                 unsigned opt )
00442 {
00443    struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
00444 
00445    if (opt & PT_PIPELINE)
00446    {
00447       vcache->base.run = vcache_run_extras;
00448    }
00449    else 
00450    {
00451       vcache->base.run = vcache_check_run;
00452    }
00453 
00454    vcache->input_prim = prim;
00455    vcache->output_prim = draw_pt_reduced_prim(prim);
00456 
00457    vcache->middle = middle;
00458    vcache->opt = opt;
00459 
00460    
00461 
00462 
00463    vcache->middle_prim = (opt & PT_PIPELINE) ? vcache->output_prim : vcache->input_prim;
00464    middle->prepare( middle, vcache->middle_prim, opt, &vcache->fetch_max );
00465 }
00466 
00467 
00468 
00469 
00470 static void 
00471 vcache_finish( struct draw_pt_front_end *frontend )
00472 {
00473    struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
00474    vcache->middle->finish( vcache->middle );
00475    vcache->middle = NULL;
00476 }
00477 
00478 static void 
00479 vcache_destroy( struct draw_pt_front_end *frontend )
00480 {
00481    FREE(frontend);
00482 }
00483 
00484 
00485 struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw )
00486 {
00487    struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
00488    if (vcache == NULL)
00489       return NULL;
00490  
00491    vcache->base.prepare = vcache_prepare;
00492    vcache->base.run     = NULL;
00493    vcache->base.finish  = vcache_finish;
00494    vcache->base.destroy = vcache_destroy;
00495    vcache->draw = draw;
00496    
00497    memset(vcache->in, ~0, sizeof(vcache->in));
00498   
00499    return &vcache->base;
00500 }