draw_pt_vcache.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028  /*
00029   * Authors:
00030   *   Keith Whitwell <keith@tungstengraphics.com>
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 /* At least for now, we're back to using a template include file for
00209  * this.  The two paths aren't too different though - it may be
00210  * possible to reunify them.
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, /* start */
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    /* Have to run prepare here, but try and guess a good prim for
00461     * doing so:
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 }

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4