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 }