/* Overall we split things into: * - frontend -- prepare fetch_elts, draw_elts - eg vcache * - middle -- fetch, shade, cliptest, viewport * - pipeline -- the prim pipeline: clipping, wide lines, etc * - backend -- the vbuf_render provided by the driver. */ static boolean draw_pt_arrays(struct draw_context *draw, unsigned prim, unsigned start, unsigned count) { struct draw_pt_front_end *frontend = NULL; struct draw_pt_middle_end *middle = NULL; unsigned opt = 0; /* Sanitize primitive length: */ { unsigned first, incr; draw_pt_split_prim(prim, &first, &incr); count = trim(count, first, incr); if (count < first) return TRUE; } if (!draw->render) { opt |= PT_PIPELINE; } if (draw_need_pipeline(draw, draw->rasterizer, prim)) { opt |= PT_PIPELINE; } if (!draw->bypass_clipping && !draw->pt.test_fse) { opt |= PT_CLIPTEST; } if (!draw->rasterizer->bypass_vs) { opt |= PT_SHADE; } if (opt == 0) middle = draw->pt.middle.fetch_emit; else if (opt == PT_SHADE && !draw->pt.no_fse) middle = draw->pt.middle.fetch_shade_emit; else middle = draw->pt.middle.general; /* Pick the right frontend */ if (draw->pt.user.elts || (opt & PT_PIPELINE)) { frontend = draw->pt.front.vcache; } else { frontend = draw->pt.front.varray; } frontend->prepare( frontend, prim, middle, opt ); frontend->run(frontend, draw_pt_elt_func(draw), draw_pt_elt_ptr(draw, start), count); frontend->finish( frontend ); return TRUE; }
/* Overall we split things into: * - frontend -- prepare fetch_elts, draw_elts - eg vsplit * - middle -- fetch, shade, cliptest, viewport * - pipeline -- the prim pipeline: clipping, wide lines, etc * - backend -- the vbuf_render provided by the driver. */ static boolean draw_pt_arrays(struct draw_context *draw, unsigned prim, unsigned start, unsigned count) { struct draw_pt_front_end *frontend = NULL; struct draw_pt_middle_end *middle = NULL; unsigned opt = 0; /* Sanitize primitive length: */ { unsigned first, incr; draw_pt_split_prim(prim, &first, &incr); count = draw_pt_trim_count(count, first, incr); if (count < first) return TRUE; } if (!draw->force_passthrough) { unsigned gs_out_prim = (draw->gs.geometry_shader ? draw->gs.geometry_shader->output_primitive : prim); if (!draw->render) { opt |= PT_PIPELINE; } if (draw_need_pipeline(draw, draw->rasterizer, gs_out_prim)) { opt |= PT_PIPELINE; } if ((draw->clip_xy || draw->clip_z || draw->clip_user) && !draw->pt.test_fse) { opt |= PT_CLIPTEST; } opt |= PT_SHADE; } if (draw->pt.middle.llvm) { middle = draw->pt.middle.llvm; } else { if (opt == 0) middle = draw->pt.middle.fetch_emit; else if (opt == PT_SHADE && !draw->pt.no_fse) middle = draw->pt.middle.fetch_shade_emit; else middle = draw->pt.middle.general; } frontend = draw->pt.frontend; if (frontend ) { if (draw->pt.prim != prim || draw->pt.opt != opt) { /* In certain conditions switching primitives requires us to flush * and validate the different stages. One example is when smooth * lines are active but first drawn with triangles and then with * lines. */ draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); frontend = NULL; } else if (draw->pt.eltSize != draw->pt.user.eltSize) { /* Flush draw state if eltSize changed. * This could be improved so only the frontend is flushed since it * converts all indices to ushorts and the fetch part of the middle * always perpares both linear and indexed. */ frontend->flush( frontend, DRAW_FLUSH_STATE_CHANGE ); frontend = NULL; } } if (!frontend) { frontend = draw->pt.front.vsplit; frontend->prepare( frontend, prim, middle, opt ); draw->pt.frontend = frontend; draw->pt.eltSize = draw->pt.user.eltSize; draw->pt.prim = prim; draw->pt.opt = opt; } frontend->run( frontend, start, count ); return TRUE; }