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 #include "util/u_math.h"
00029 #include "util/u_memory.h"
00030 #include "draw/draw_context.h"
00031 #include "draw/draw_vbuf.h"
00032 #include "draw/draw_vertex.h"
00033 #include "draw/draw_pt.h"
00034 #include "draw/draw_vs.h"
00035 #include "translate/translate.h"
00036 
00037 
00038 struct fetch_pipeline_middle_end {
00039    struct draw_pt_middle_end base;
00040    struct draw_context *draw;
00041 
00042    struct pt_emit *emit;
00043    struct pt_fetch *fetch;
00044    struct pt_post_vs *post_vs;
00045 
00046    unsigned vertex_data_offset;
00047    unsigned vertex_size;
00048    unsigned prim;
00049    unsigned opt;
00050 };
00051 
00052 
00053 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
00054                                     unsigned prim,
00055                                     unsigned opt,
00056                                     unsigned *max_vertices )
00057 {
00058    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
00059    struct draw_context *draw = fpme->draw;
00060    struct draw_vertex_shader *vs = draw->vs.vertex_shader;
00061 
00062    
00063 
00064 
00065    unsigned nr = MAX2( vs->info.num_inputs,
00066                        vs->info.num_outputs + 1 );
00067 
00068    fpme->prim = prim;
00069    fpme->opt = opt;
00070 
00071    
00072 
00073 
00074 
00075    fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
00076 
00077    
00078 
00079    draw_pt_fetch_prepare( fpme->fetch, 
00080                           fpme->vertex_size );
00081 
00082    
00083 
00084 
00085    draw_pt_post_vs_prepare( fpme->post_vs,
00086                             (boolean)draw->bypass_clipping,
00087                             (boolean)draw->identity_viewport,
00088                             (boolean)draw->rasterizer->gl_rasterization_rules );
00089                             
00090 
00091    if (!(opt & PT_PIPELINE)) {
00092       draw_pt_emit_prepare( fpme->emit, 
00093                             prim,
00094                             max_vertices );
00095 
00096       *max_vertices = MAX2( *max_vertices,
00097                             DRAW_PIPE_MAX_VERTICES );
00098    }
00099    else {
00100       *max_vertices = DRAW_PIPE_MAX_VERTICES; 
00101    }
00102 
00103    
00104    *max_vertices = *max_vertices & ~1;
00105 
00106    
00107 
00108    vs->prepare(vs, draw);
00109 }
00110 
00111 
00112 
00113 static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
00114                                 const unsigned *fetch_elts,
00115                                 unsigned fetch_count,
00116                                 const ushort *draw_elts,
00117                                 unsigned draw_count )
00118 {
00119    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
00120    struct draw_context *draw = fpme->draw;
00121    struct draw_vertex_shader *shader = draw->vs.vertex_shader;
00122    unsigned opt = fpme->opt;
00123    unsigned alloc_count = align( fetch_count, 4 );
00124 
00125    struct vertex_header *pipeline_verts = 
00126       (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
00127 
00128    if (!pipeline_verts) {
00129       
00130 
00131       assert(0);
00132       return;
00133    }
00134 
00135    
00136 
00137    draw_pt_fetch_run( fpme->fetch,
00138                       fetch_elts, 
00139                       fetch_count,
00140                       (char *)pipeline_verts );
00141 
00142    
00143 
00144 
00145 
00146 
00147    if (opt & PT_SHADE)
00148    {
00149       shader->run_linear(shader, 
00150                          (const float (*)[4])pipeline_verts->data,
00151                          (      float (*)[4])pipeline_verts->data,
00152                          (const float (*)[4])draw->pt.user.constants,
00153                          fetch_count,
00154                          fpme->vertex_size,
00155                          fpme->vertex_size);
00156    }
00157 
00158    if (draw_pt_post_vs_run( fpme->post_vs,
00159                             pipeline_verts,
00160                             fetch_count,
00161                             fpme->vertex_size ))
00162    {
00163       opt |= PT_PIPELINE;
00164    }
00165 
00166    
00167 
00168    if (opt & PT_PIPELINE) {
00169       draw_pipeline_run( fpme->draw,
00170                          fpme->prim,
00171                          pipeline_verts,
00172                          fetch_count,
00173                          fpme->vertex_size,
00174                          draw_elts,
00175                          draw_count );
00176    }
00177    else {
00178       draw_pt_emit( fpme->emit,
00179                     (const float (*)[4])pipeline_verts->data,
00180                     fetch_count,
00181                     fpme->vertex_size,
00182                     draw_elts,
00183                     draw_count );
00184    }
00185 
00186 
00187    FREE(pipeline_verts);
00188 }
00189 
00190 
00191 static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
00192                                        unsigned start,
00193                                        unsigned count)
00194 {
00195    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
00196    struct draw_context *draw = fpme->draw;
00197    struct draw_vertex_shader *shader = draw->vs.vertex_shader;
00198    unsigned opt = fpme->opt;
00199    unsigned alloc_count = align( count, 4 );
00200 
00201    struct vertex_header *pipeline_verts =
00202       (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
00203 
00204    if (!pipeline_verts) {
00205       
00206 
00207       assert(0);
00208       return;
00209    }
00210 
00211    
00212 
00213    draw_pt_fetch_run_linear( fpme->fetch,
00214                              start,
00215                              count,
00216                              (char *)pipeline_verts );
00217 
00218    
00219 
00220 
00221 
00222 
00223    if (opt & PT_SHADE)
00224    {
00225       shader->run_linear(shader,
00226                          (const float (*)[4])pipeline_verts->data,
00227                          (      float (*)[4])pipeline_verts->data,
00228                          (const float (*)[4])draw->pt.user.constants,
00229                          count,
00230                          fpme->vertex_size,
00231                          fpme->vertex_size);
00232    }
00233 
00234    if (draw_pt_post_vs_run( fpme->post_vs,
00235                             pipeline_verts,
00236                             count,
00237                             fpme->vertex_size ))
00238    {
00239       opt |= PT_PIPELINE;
00240    }
00241 
00242    
00243 
00244    if (opt & PT_PIPELINE) {
00245       draw_pipeline_run_linear( fpme->draw,
00246                                 fpme->prim,
00247                                 pipeline_verts,
00248                                 count,
00249                                 fpme->vertex_size);
00250    }
00251    else {
00252       draw_pt_emit_linear( fpme->emit,
00253                            (const float (*)[4])pipeline_verts->data,
00254                            count,
00255                            fpme->vertex_size,
00256                            0, 
00257                            count );
00258    }
00259 
00260    FREE(pipeline_verts);
00261 }
00262 
00263 
00264 
00265 static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
00266                                             unsigned start,
00267                                             unsigned count,
00268                                             const ushort *draw_elts,
00269                                             unsigned draw_count )
00270 {
00271    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
00272    struct draw_context *draw = fpme->draw;
00273    struct draw_vertex_shader *shader = draw->vs.vertex_shader;
00274    unsigned opt = fpme->opt;
00275    unsigned alloc_count = align( count, 4 );
00276 
00277    struct vertex_header *pipeline_verts =
00278       (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
00279 
00280    if (!pipeline_verts) 
00281       return FALSE;
00282 
00283    
00284 
00285    draw_pt_fetch_run_linear( fpme->fetch,
00286                              start,
00287                              count,
00288                              (char *)pipeline_verts );
00289 
00290    
00291 
00292 
00293 
00294 
00295    if (opt & PT_SHADE)
00296    {
00297       shader->run_linear(shader,
00298                          (const float (*)[4])pipeline_verts->data,
00299                          (      float (*)[4])pipeline_verts->data,
00300                          (const float (*)[4])draw->pt.user.constants,
00301                          count,
00302                          fpme->vertex_size,
00303                          fpme->vertex_size);
00304    }
00305 
00306    if (draw_pt_post_vs_run( fpme->post_vs,
00307                             pipeline_verts,
00308                             count,
00309                             fpme->vertex_size ))
00310    {
00311       opt |= PT_PIPELINE;
00312    }
00313 
00314    
00315 
00316    if (opt & PT_PIPELINE) {
00317       draw_pipeline_run( fpme->draw,
00318                          fpme->prim,
00319                          pipeline_verts,
00320                          count,
00321                          fpme->vertex_size,
00322                          draw_elts,
00323                          draw_count );
00324    }
00325    else {
00326       draw_pt_emit( fpme->emit,
00327                     (const float (*)[4])pipeline_verts->data,
00328                     count,
00329                     fpme->vertex_size,
00330                     draw_elts,
00331                     draw_count );
00332    }
00333 
00334    FREE(pipeline_verts);
00335    return TRUE;
00336 }
00337 
00338 
00339 
00340 static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
00341 {
00342    
00343 }
00344 
00345 static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
00346 {
00347    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
00348 
00349    if (fpme->fetch)
00350       draw_pt_fetch_destroy( fpme->fetch );
00351 
00352    if (fpme->emit)
00353       draw_pt_emit_destroy( fpme->emit );
00354 
00355    if (fpme->post_vs)
00356       draw_pt_post_vs_destroy( fpme->post_vs );
00357 
00358    FREE(middle);
00359 }
00360 
00361 
00362 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
00363 {
00364    struct fetch_pipeline_middle_end *fpme = CALLOC_STRUCT( fetch_pipeline_middle_end );
00365    if (!fpme)
00366       goto fail;
00367 
00368    fpme->base.prepare        = fetch_pipeline_prepare;
00369    fpme->base.run            = fetch_pipeline_run;
00370    fpme->base.run_linear     = fetch_pipeline_linear_run;
00371    fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
00372    fpme->base.finish         = fetch_pipeline_finish;
00373    fpme->base.destroy        = fetch_pipeline_destroy;
00374 
00375    fpme->draw = draw;
00376 
00377    fpme->fetch = draw_pt_fetch_create( draw );
00378    if (!fpme->fetch)
00379       goto fail;
00380 
00381    fpme->post_vs = draw_pt_post_vs_create( draw );
00382    if (!fpme->post_vs)
00383       goto fail;
00384 
00385    fpme->emit = draw_pt_emit_create( draw );
00386    if (!fpme->emit) 
00387       goto fail;
00388 
00389    return &fpme->base;
00390 
00391  fail:
00392    if (fpme)
00393       fetch_pipeline_destroy( &fpme->base );
00394 
00395    return NULL;
00396 }