|
|
@@ -36,146 +36,58 @@ |
|
|
|
#include "draw/draw_pt.h" |
|
|
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
static boolean too_many_elts( struct draw_context *draw, |
|
|
|
unsigned elts ) |
|
|
|
{ |
|
|
|
return elts > (8 * 1024); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
static INLINE unsigned reduced_prim(unsigned prim) |
|
|
|
{ |
|
|
|
/*FIXME*/ |
|
|
|
return prim; |
|
|
|
} |
|
|
|
|
|
|
|
static INLINE boolean good_prim(unsigned prim) |
|
|
|
{ |
|
|
|
/*FIXME*/ |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
/* 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. |
|
|
|
*/ |
|
|
|
boolean |
|
|
|
draw_pt_arrays(struct draw_context *draw, |
|
|
|
unsigned prim, |
|
|
|
unsigned start, |
|
|
|
unsigned count) |
|
|
|
{ |
|
|
|
const boolean pipeline = draw_need_pipeline(draw, prim); |
|
|
|
const boolean cliptest = !draw->rasterizer->bypass_clipping; |
|
|
|
const boolean shading = !draw->rasterizer->bypass_vs; |
|
|
|
struct draw_pt_front_end *frontend = NULL; |
|
|
|
struct draw_pt_middle_end *middle = NULL; |
|
|
|
unsigned opt = 0; |
|
|
|
|
|
|
|
if (!draw->render) |
|
|
|
return FALSE; |
|
|
|
/*debug_printf("XXXXXXXXXX needs_pipeline = %d\n", pipeline);*/ |
|
|
|
|
|
|
|
/* Overall we do: |
|
|
|
* - 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. |
|
|
|
*/ |
|
|
|
|
|
|
|
if (shading && !draw->use_pt_shaders) |
|
|
|
return FALSE; |
|
|
|
|
|
|
|
|
|
|
|
if (!cliptest && !pipeline && !shading) { |
|
|
|
/* This is the 'passthrough' path: |
|
|
|
*/ |
|
|
|
/* Fetch user verts, emit hw verts: |
|
|
|
*/ |
|
|
|
middle = draw->pt.middle.fetch_emit; |
|
|
|
} |
|
|
|
else if (!cliptest && !shading) { |
|
|
|
/* This is the 'passthrough' path targetting the pipeline backend. |
|
|
|
*/ |
|
|
|
/* Fetch user verts, emit pipeline verts, run pipeline: |
|
|
|
*/ |
|
|
|
middle = draw->pt.middle.fetch_pipeline; |
|
|
|
} |
|
|
|
else if (!cliptest && !pipeline) { |
|
|
|
/* Fetch user verts, run vertex shader, emit hw verts: |
|
|
|
*/ |
|
|
|
middle = draw->pt.middle.fetch_shade_emit; |
|
|
|
} |
|
|
|
else if (!pipeline) { |
|
|
|
/* Even though !pipeline, we have to run it to get clipping. We |
|
|
|
* do know that the pipeline is just the clipping operation, but |
|
|
|
* that probably doesn't help much. |
|
|
|
* |
|
|
|
* This is going to be the most important path for a lot of |
|
|
|
* swtnl cards. |
|
|
|
*/ |
|
|
|
/* Fetch user verts, |
|
|
|
* run vertex shader, |
|
|
|
* cliptest and viewport trasform |
|
|
|
* if no clipped vertices, |
|
|
|
* emit hw verts |
|
|
|
* else |
|
|
|
* run pipline |
|
|
|
*/ |
|
|
|
middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit; |
|
|
|
} |
|
|
|
else { |
|
|
|
/* This is what we're currently always doing: |
|
|
|
*/ |
|
|
|
/* Fetch user verts, run vertex shader, cliptest, run pipeline |
|
|
|
* or |
|
|
|
* Fetch user verts, run vertex shader, run pipeline |
|
|
|
*/ |
|
|
|
middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit; |
|
|
|
if (draw_need_pipeline(draw, prim)) { |
|
|
|
opt |= PT_PIPELINE; |
|
|
|
} |
|
|
|
|
|
|
|
if (!draw->rasterizer->bypass_clipping) { |
|
|
|
opt |= PT_CLIPTEST; |
|
|
|
} |
|
|
|
|
|
|
|
/* If !pipeline, need to make sure we respect the driver's limited |
|
|
|
* capabilites to receive blocks of vertex data and elements. |
|
|
|
*/ |
|
|
|
#if 0 |
|
|
|
if (!pipeline) { |
|
|
|
unsigned vertex_mode = passthrough; |
|
|
|
unsigned nr_verts = count_vertices( draw, start, count ); |
|
|
|
unsigned hw_prim = prim; |
|
|
|
|
|
|
|
if (is_elts(draw)) { |
|
|
|
frontend = draw->pt.front.vcache; |
|
|
|
hw_prim = reduced_prim(prim); |
|
|
|
} |
|
|
|
#if 0 |
|
|
|
if (too_many_verts(nr_verts)) { |
|
|
|
/* if (is_verts(draw) && can_split(prim)) { |
|
|
|
draw = draw_arrays_split; |
|
|
|
} |
|
|
|
else */ { |
|
|
|
frontend = draw->pt.front.vcache; |
|
|
|
hw_prim = reduced_prim(prim); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
if (!draw->rasterizer->bypass_vs) { |
|
|
|
opt |= PT_SHADE; |
|
|
|
|
|
|
|
if (too_many_elts(count)) { |
|
|
|
if (!draw->use_pt_shaders) |
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
/* if (is_elts(draw) && can_split(prim)) { |
|
|
|
draw = draw_elts_split; |
|
|
|
} |
|
|
|
else */ { |
|
|
|
frontend = draw->pt.front.vcache; |
|
|
|
hw_prim = reduced_prim(prim); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!good_prim(hw_prim)) { |
|
|
|
frontend = draw->pt.front.vcache; |
|
|
|
} |
|
|
|
if (draw->pt.middle.opt[opt] == NULL) { |
|
|
|
opt = PT_PIPELINE | PT_CLIPTEST | PT_SHADE; |
|
|
|
} |
|
|
|
#else |
|
|
|
|
|
|
|
middle = draw->pt.middle.opt[opt]; |
|
|
|
assert(middle); |
|
|
|
|
|
|
|
/* May create a short-circuited version of this for small primitives: |
|
|
|
*/ |
|
|
|
frontend = draw->pt.front.vcache; |
|
|
|
#endif |
|
|
|
|
|
|
|
frontend->prepare( frontend, prim, middle ); |
|
|
|
|
|
|
|
frontend->prepare( frontend, prim, middle, opt ); |
|
|
|
|
|
|
|
frontend->run( frontend, |
|
|
|
draw_pt_elt_func( draw ), |
|
|
@@ -190,21 +102,19 @@ draw_pt_arrays(struct draw_context *draw, |
|
|
|
|
|
|
|
boolean draw_pt_init( struct draw_context *draw ) |
|
|
|
{ |
|
|
|
draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw ); |
|
|
|
if (!draw->pt.middle.fetch_emit) |
|
|
|
return FALSE; |
|
|
|
|
|
|
|
draw->pt.middle.fetch_pipeline = draw_pt_fetch_pipeline( draw ); |
|
|
|
if (!draw->pt.middle.fetch_pipeline) |
|
|
|
draw->pt.front.vcache = draw_pt_vcache( draw ); |
|
|
|
if (!draw->pt.front.vcache) |
|
|
|
return FALSE; |
|
|
|
|
|
|
|
draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit = |
|
|
|
draw->pt.middle.opt[0] = draw_pt_fetch_emit( draw ); |
|
|
|
draw->pt.middle.opt[PT_PIPELINE] = draw_pt_fetch_pipeline( draw ); |
|
|
|
// draw->pt.middle.opt[PT_SHADE] = draw_pt_shade_emit( draw ); |
|
|
|
// draw->pt.middle.opt[PT_SHADE | PT_PIPELINE] = draw_pt_shade_pipeline( draw ); |
|
|
|
// draw->pt.middle.opt[PT_SHADE | PT_CLIPTEST] = draw_pt_shade_clip_either( draw ); |
|
|
|
draw->pt.middle.opt[PT_SHADE | PT_CLIPTEST | PT_PIPELINE] = |
|
|
|
draw_pt_fetch_pipeline_or_emit( draw ); |
|
|
|
if (!draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit) |
|
|
|
return FALSE; |
|
|
|
|
|
|
|
draw->pt.front.vcache = draw_pt_vcache( draw ); |
|
|
|
if (!draw->pt.front.vcache) |
|
|
|
if (!draw->pt.middle.opt[PT_SHADE | PT_CLIPTEST | PT_PIPELINE]) |
|
|
|
return FALSE; |
|
|
|
|
|
|
|
return TRUE; |
|
|
@@ -213,21 +123,13 @@ boolean draw_pt_init( struct draw_context *draw ) |
|
|
|
|
|
|
|
void draw_pt_destroy( struct draw_context *draw ) |
|
|
|
{ |
|
|
|
if (draw->pt.middle.fetch_emit) { |
|
|
|
draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit ); |
|
|
|
draw->pt.middle.fetch_emit = NULL; |
|
|
|
} |
|
|
|
int i; |
|
|
|
|
|
|
|
if (draw->pt.middle.fetch_pipeline) { |
|
|
|
draw->pt.middle.fetch_pipeline->destroy( draw->pt.middle.fetch_pipeline ); |
|
|
|
draw->pt.middle.fetch_pipeline = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit) { |
|
|
|
draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit->destroy( |
|
|
|
draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit ); |
|
|
|
draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit = NULL; |
|
|
|
} |
|
|
|
for (i = 0; i < PT_MAX_MIDDLE; i++) |
|
|
|
if (draw->pt.middle.opt[i]) { |
|
|
|
draw->pt.middle.opt[i]->destroy( draw->pt.middle.opt[i] ); |
|
|
|
draw->pt.middle.opt[i] = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (draw->pt.front.vcache) { |
|
|
|
draw->pt.front.vcache->destroy( draw->pt.front.vcache ); |