draw->render = render;
}
-void draw_set_edgeflags( struct draw_context *draw,
- const unsigned *edgeflag )
-{
- draw->pt.user.edgeflag = edgeflag;
-}
-
-
/**
const void *buffer,
unsigned size );
-void draw_set_edgeflags( struct draw_context *draw,
- const unsigned *edgeflag );
-
/***********************************************************************
* draw_prim.c
/* user-space vertex data, buffers */
struct {
- const unsigned *edgeflag;
-
/** vertex element/index buffer (ex: glDrawElements) */
const void *elts;
/** bytes per index (0, 1, 2 or 4) */
struct draw_vertex_shader *vertex_shader;
uint num_vs_outputs; /**< convenience, from vertex_shader */
uint position_output;
+ uint edgeflag_output;
/** TGSI program interpreter runtime state */
struct tgsi_exec_machine *machine;
/* drawing done here: */
draw_pt_arrays(draw, prim, start, count);
}
-
-boolean draw_pt_get_edgeflag( struct draw_context *draw,
- unsigned idx )
-{
- if (draw->pt.user.edgeflag)
- return (draw->pt.user.edgeflag[idx/32] & (1 << (idx%32))) != 0;
- else
- return 1;
-}
struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw);
-/* More helpers:
- */
-boolean draw_pt_get_edgeflag( struct draw_context *draw,
- unsigned idx );
-
/*******************************************************************************
* HW vertex emit:
void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
boolean bypass_clipping,
boolean bypass_viewport,
- boolean opengl );
+ boolean opengl,
+ boolean need_edgeflags );
struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw );
struct translate *translate;
unsigned vertex_size;
- boolean need_edgeflags;
struct translate_cache *cache;
};
+
/* Perform the fetch from API vertex elements & vertex buffers, to a
* contiguous set of float[4] attributes as required for the
* vertex_shader->run_linear() method.
fetch->translate = translate_cache_find(fetch->cache, &key);
{
- static struct vertex_header vh = { 0, 1, 0, UNDEFINED_VERTEX_ID, { .0f, .0f, .0f, .0f } };
+ static struct vertex_header vh = { 0,
+ 1,
+ 0,
+ UNDEFINED_VERTEX_ID,
+ { .0f, .0f, .0f, .0f } };
+
fetch->translate->set_buffer(fetch->translate,
draw->pt.nr_vertex_buffers,
&vh,
}
}
- fetch->need_edgeflags = ((draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
- draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) &&
- draw->pt.user.edgeflag);
}
count,
verts );
- /* Edgeflags are hard to fit into a translate program, populate
- * them separately if required. In the setup above they are
- * defaulted to one, so only need this if there is reason to change
- * that default:
- */
- if (fetch->need_edgeflags) {
- for (i = 0; i < count; i++) {
- struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
- vh->edgeflag = draw_pt_get_edgeflag( draw, elts[i] );
- }
- }
}
start,
count,
verts );
-
- /* Edgeflags are hard to fit into a translate program, populate
- * them separately if required. In the setup above they are
- * defaulted to one, so only need this if there is reason to change
- * that default:
- */
- if (fetch->need_edgeflags) {
- for (i = 0; i < count; i++) {
- struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
- vh->edgeflag = draw_pt_get_edgeflag( draw, start + i );
- }
- }
}
draw_pt_post_vs_prepare( fpme->post_vs,
(boolean)draw->bypass_clipping,
(boolean)(draw->identity_viewport ||
- draw->rasterizer->bypass_vs_clip_and_viewport),
- (boolean)draw->rasterizer->gl_rasterization_rules );
-
+ draw->rasterizer->bypass_vs_clip_and_viewport),
+ (boolean)draw->rasterizer->gl_rasterization_rules,
+ (draw->vs.edgeflag_output ? true : false) );
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,
+/* As above plus edgeflags
+ */
+static boolean
+post_vs_cliptest_viewport_gl_edgeflag(struct pt_post_vs *pvs,
+ struct vertex_header *vertices,
+ unsigned count,
+ unsigned stride )
+{
+ unsigned j;
+ boolean needpipe;
+
+ needpipe = post_vs_cliptest_viewport_gl( pvs, vertices, count, stride);
+
+ /* If present, copy edgeflag VS output into vertex header.
+ * Otherwise, leave header as is.
+ */
+ if (pvs->draw->vs.edgeflag_output) {
+ struct vertex_header *out = vertices;
+ int ef = pvs->draw->vs.edgeflag_output;
+
+ for (j = 0; j < count; j++) {
+ const float *edgeflag = out->data[ef];
+ out->edgeflag = !(edgeflag[0] != 1.0f);
+ needpipe |= !out->edgeflag;
+ out = (struct vertex_header *)( (char *)out + stride );
+ }
+ }
+ return needpipe;
+}
+
+
+
+
/* If bypass_clipping is set, skip cliptest and rhw divide.
*/
static boolean post_vs_viewport( struct pt_post_vs *pvs,
void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
boolean bypass_clipping,
boolean bypass_viewport,
- boolean opengl )
+ boolean opengl,
+ boolean need_edgeflags )
{
- if (bypass_clipping) {
- if (bypass_viewport)
- pvs->run = post_vs_none;
- else
- pvs->run = post_vs_viewport;
+ if (!need_edgeflags) {
+ if (bypass_clipping) {
+ if (bypass_viewport)
+ pvs->run = post_vs_none;
+ else
+ pvs->run = post_vs_viewport;
+ }
+ else {
+ /* if (opengl) */
+ pvs->run = post_vs_cliptest_viewport_gl;
+ }
}
else {
- /* if (opengl) */
- pvs->run = post_vs_cliptest_viewport_gl;
+ /* If we need to copy edgeflags to the vertex header, it should
+ * mean we're running the primitive pipeline. Hence the bypass
+ * flags should be false.
+ */
+ assert(!bypass_clipping);
+ assert(!bypass_viewport);
+ pvs->run = post_vs_cliptest_viewport_gl_edgeflag;
}
}
if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
vs->info.output_semantic_index[i] == 0)
vs->position_output = i;
+ else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_EDGEFLAG &&
+ vs->info.output_semantic_index[i] == 0)
+ vs->edgeflag_output = i;
}
}
draw->vs.vertex_shader = dvs;
draw->vs.num_vs_outputs = dvs->info.num_outputs;
draw->vs.position_output = dvs->position_output;
+ draw->vs.edgeflag_output = dvs->edgeflag_output;
dvs->prepare( dvs, draw );
}
else {
struct tgsi_shader_info info;
unsigned position_output;
+ unsigned edgeflag_output;
/* Extracted from shader:
*/
"PSIZE",
"GENERIC",
"NORMAL",
- "FACE"
+ "FACE",
+ "EDGEFLAG"
};
static const char *immediate_type_names[] =
info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
info->num_outputs++;
- }
- /* special case */
- if (procType == TGSI_PROCESSOR_FRAGMENT &&
- file == TGSI_FILE_OUTPUT &&
- fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION) {
- info->writes_z = TRUE;
+ /* extra info for special outputs */
+ if (procType == TGSI_PROCESSOR_FRAGMENT &&
+ fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION) {
+ info->writes_z = TRUE;
+ }
+ if (procType == TGSI_PROCESSOR_VERTEX &&
+ fulldecl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) {
+ info->writes_edgeflag = TRUE;
+ }
}
- }
+
+ }
}
break;
uint opcode_count[TGSI_OPCODE_LAST]; /**< opcode histogram */
boolean writes_z; /**< does fragment shader write Z value? */
+ boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
boolean uses_kill; /**< KIL or KILP instruction used? */
boolean uses_fogcoord; /**< fragment shader uses fog coord? */
boolean uses_frontfacing; /**< fragment shader uses front/back-face flag? */
}
-static void
-cell_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags)
-{
- struct cell_context *cell = cell_context(pipe);
- draw_set_edgeflags(cell->draw, edgeflags);
-}
-
-
-
void
cell_init_draw_functions(struct cell_context *cell)
{
cell->pipe.draw_arrays = cell_draw_arrays;
cell->pipe.draw_elements = cell_draw_elements;
cell->pipe.draw_range_elements = cell_draw_range_elements;
- cell->pipe.set_edgeflags = cell_set_edgeflags;
}
}
-static void i915_set_edgeflags(struct pipe_context *pipe,
- const unsigned *bitfield)
-{
- /* TODO do something here */
-}
-
void
i915_init_state_functions( struct i915_context *i915 )
{
- i915->base.set_edgeflags = i915_set_edgeflags;
i915->base.create_blend_state = i915_create_blend_state;
i915->base.bind_blend_state = i915_bind_blend_state;
i915->base.delete_blend_state = i915_delete_blend_state;
free(id_pipe);
}
-static void
-identity_set_edgeflags(struct pipe_context *_pipe,
- const unsigned *bitfield)
-{
- struct identity_context *id_pipe = identity_context(_pipe);
- struct pipe_context *pipe = id_pipe->pipe;
-
- pipe->set_edgeflags(pipe,
- bitfield);
-}
-
static boolean
identity_draw_arrays(struct pipe_context *_pipe,
unsigned prim,
id_pipe->base.draw = NULL;
id_pipe->base.destroy = identity_destroy;
- id_pipe->base.set_edgeflags = identity_set_edgeflags;
id_pipe->base.draw_arrays = identity_draw_arrays;
id_pipe->base.draw_elements = identity_draw_elements;
id_pipe->base.draw_range_elements = identity_draw_range_elements;
llvmpipe->pipe.draw_arrays = llvmpipe_draw_arrays;
llvmpipe->pipe.draw_elements = llvmpipe_draw_elements;
llvmpipe->pipe.draw_range_elements = llvmpipe_draw_range_elements;
- llvmpipe->pipe.set_edgeflags = llvmpipe_set_edgeflags;
-
llvmpipe->pipe.clear = llvmpipe_clear;
llvmpipe->pipe.flush = llvmpipe_flush;
mode, start, count );
}
-
-void
-llvmpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags)
-{
- struct llvmpipe_context *lp = llvmpipe_context(pipe);
- draw_set_edgeflags(lp->draw, edgeflags);
-}
unsigned max_index,
unsigned mode, unsigned start, unsigned count);
-void
-llvmpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags);
-
-
void
llvmpipe_map_transfers(struct llvmpipe_context *lp);
FREE(nv04);
}
-static void
-nv04_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
-{
-}
-
static boolean
nv04_init_hwctx(struct nv04_context *nv04)
{
nv04->pipe.winsys = ws;
nv04->pipe.screen = pscreen;
nv04->pipe.destroy = nv04_destroy;
- nv04->pipe.set_edgeflags = nv04_set_edgeflags;
nv04->pipe.draw_arrays = nv04_draw_arrays;
nv04->pipe.draw_elements = nv04_draw_elements;
nv04->pipe.clear = nv04_clear;
FIRE_RING (NULL);
}
-static void
-nv10_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
-{
-}
-
struct pipe_context *
nv10_create(struct pipe_screen *pscreen, unsigned pctx_id)
{
nv10->pipe.winsys = ws;
nv10->pipe.screen = pscreen;
nv10->pipe.destroy = nv10_destroy;
- nv10->pipe.set_edgeflags = nv10_set_edgeflags;
nv10->pipe.draw_arrays = nv10_draw_arrays;
nv10->pipe.draw_elements = nv10_draw_elements;
nv10->pipe.clear = nv10_clear;
FIRE_RING (NULL);
}
-static void
-nv20_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
-{
-}
-
struct pipe_context *
nv20_create(struct pipe_screen *pscreen, unsigned pctx_id)
{
nv20->pipe.winsys = ws;
nv20->pipe.screen = pscreen;
nv20->pipe.destroy = nv20_destroy;
- nv20->pipe.set_edgeflags = nv20_set_edgeflags;
nv20->pipe.draw_arrays = nv20_draw_arrays;
nv20->pipe.draw_elements = nv20_draw_elements;
nv20->pipe.clear = nv20_clear;
return FALSE;
}
break;
+ case TGSI_SEMANTIC_EDGEFLAG:
+ NOUVEAU_ERR("cannot handle edgeflag output\n");
+ return FALSE;
default:
NOUVEAU_ERR("bad output semantic\n");
return FALSE;
unsigned vtxbuf_nr;
struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
unsigned vtxelt_nr;
- const unsigned *edgeflags;
};
static INLINE struct nv30_context *
/*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
}
-static void
-nv30_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
-{
- struct nv30_context *nv30 = nv30_context(pipe);
-
- nv30->edgeflags = bitfield;
- nv30->dirty |= NV30_NEW_ARRAYS;
- /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
-}
-
void
nv30_init_state_functions(struct nv30_context *nv30)
{
nv30->pipe.set_scissor_state = nv30_set_scissor_state;
nv30->pipe.set_viewport_state = nv30_set_viewport_state;
- nv30->pipe.set_edgeflags = nv30_set_edgeflags;
nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers;
nv30->pipe.set_vertex_elements = nv30_set_vertex_elements;
}
unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
int hw;
- if (nv30->edgeflags) {
- /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/
- return FALSE;
- }
-
vtxbuf = so_new(20, 18);
so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt_nr);
vtxfmt = so_new(17, 0);
return FALSE;
}
break;
+ case TGSI_SEMANTIC_EDGEFLAG:
+ NOUVEAU_ERR("cannot handle edgeflag output\n");
+ return FALSE;
default:
NOUVEAU_ERR("bad output semantic\n");
return FALSE;
unsigned vtxbuf_nr;
struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
unsigned vtxelt_nr;
- const unsigned *edgeflags;
};
static INLINE struct nv40_context *
nv40->draw_dirty |= NV40_NEW_ARRAYS;
}
-static void
-nv40_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
-{
- struct nv40_context *nv40 = nv40_context(pipe);
-
- nv40->edgeflags = bitfield;
- nv40->dirty |= NV40_NEW_ARRAYS;
- nv40->draw_dirty |= NV40_NEW_ARRAYS;
-}
-
void
nv40_init_state_functions(struct nv40_context *nv40)
{
nv40->pipe.set_scissor_state = nv40_set_scissor_state;
nv40->pipe.set_viewport_state = nv40_set_viewport_state;
- nv40->pipe.set_edgeflags = nv40_set_edgeflags;
nv40->pipe.set_vertex_buffers = nv40_set_vertex_buffers;
nv40->pipe.set_vertex_elements = nv40_set_vertex_elements;
}
draw_set_viewport_state(draw, &nv40->viewport);
if (nv40->draw_dirty & NV40_NEW_ARRAYS) {
- draw_set_edgeflags(draw, nv40->edgeflags);
draw_set_vertex_buffers(draw, nv40->vtxbuf_nr, nv40->vtxbuf);
draw_set_vertex_elements(draw, nv40->vtxelt_nr, nv40->vtxelt);
}
unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
int hw;
- if (nv40->edgeflags) {
- nv40->fallback_swtnl |= NV40_NEW_ARRAYS;
- return FALSE;
- }
-
vtxbuf = so_new(20, 18);
so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt_nr);
vtxfmt = so_new(17, 0);
return FALSE;
}
break;
+ case TGSI_SEMANTIC_EDGEFLAG:
+ /* not really an error just a fallback */
+ NOUVEAU_ERR("cannot handle edgeflag output\n");
+ return FALSE;
default:
NOUVEAU_ERR("bad output semantic\n");
return FALSE;
}
-static void
-nv50_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
-{
-}
-
struct pipe_context *
nv50_create(struct pipe_screen *pscreen, unsigned pctx_id)
{
nv50->pipe.destroy = nv50_destroy;
- nv50->pipe.set_edgeflags = nv50_set_edgeflags;
nv50->pipe.draw_arrays = nv50_draw_arrays;
nv50->pipe.draw_elements = nv50_draw_elements;
nv50->pipe.clear = nv50_clear;
FREE(state);
}
-static void r300_set_edgeflags(struct pipe_context* pipe,
- const unsigned* bitfield)
-{
- /* XXX you know it's bad when i915 has this blank too */
- /* XXX and even worse, I have no idea WTF the bitfield is */
-}
-
static void r300_set_scissor_regs(const struct pipe_scissor_state* state,
struct r300_scissor_regs *scissor,
boolean is_r500)
r300->context.bind_depth_stencil_alpha_state = r300_bind_dsa_state;
r300->context.delete_depth_stencil_alpha_state = r300_delete_dsa_state;
- r300->context.set_edgeflags = r300_set_edgeflags;
-
r300->context.set_framebuffer_state = r300_set_framebuffer_state;
r300->context.create_fs_state = r300_create_fs_state;
vs_outputs->fog = i;
break;
+ case TGSI_SEMANTIC_EDGEFLAG:
+ assert(index == 0);
+ fprintf(stderr, "r300 VP: cannot handle edgeflag output\n");
+ assert(0);
+ break;
default:
assert(0);
}
softpipe->pipe.draw_arrays = softpipe_draw_arrays;
softpipe->pipe.draw_elements = softpipe_draw_elements;
softpipe->pipe.draw_range_elements = softpipe_draw_range_elements;
- softpipe->pipe.set_edgeflags = softpipe_set_edgeflags;
-
softpipe->pipe.clear = softpipe_clear;
softpipe->pipe.flush = softpipe_flush;
0, 0xffffffff,
mode, start, count );
}
-
-
-void
-softpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags)
-{
- struct softpipe_context *sp = softpipe_context(pipe);
- draw_set_edgeflags(sp->draw, edgeflags);
-}
unsigned max_index,
unsigned mode, unsigned start, unsigned count);
-void
-softpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags);
-
-
void
softpipe_map_transfers(struct softpipe_context *sp);
struct pipe_clip_state clip;
struct pipe_viewport_state viewport;
- const unsigned *edgeflags;
-
unsigned num_samplers;
unsigned num_textures;
unsigned num_vertex_elements;
#define SVGA_NEW_NEED_SWTNL 0x400000
#define SVGA_NEW_FS_RESULT 0x800000
#define SVGA_NEW_VS_RESULT 0x1000000
-#define SVGA_NEW_EDGEFLAGS 0x2000000
-#define SVGA_NEW_ZERO_STRIDE 0x4000000
-#define SVGA_NEW_TEXTURE_FLAGS 0x8000000
+#define SVGA_NEW_ZERO_STRIDE 0x2000000
+#define SVGA_NEW_TEXTURE_FLAGS 0x4000000
}
-static void svga_set_edgeflags(struct pipe_context *pipe,
- const unsigned *bitfield)
-{
- struct svga_context *svga = svga_context(pipe);
-
- if (bitfield != NULL || svga->curr.edgeflags != NULL) {
- svga->curr.edgeflags = bitfield;
- svga->dirty |= SVGA_NEW_EDGEFLAGS;
- }
-}
-
-
void svga_cleanup_vertex_state( struct svga_context *svga )
{
unsigned i;
{
svga->pipe.set_vertex_buffers = svga_set_vertex_buffers;
svga->pipe.set_vertex_elements = svga_set_vertex_elements;
- svga->pipe.set_edgeflags = svga_set_edgeflags;
}
{
boolean need_pipeline = FALSE;
+ struct svga_vertex_shader *vs = svga->curr.vs;
/* SVGA_NEW_RAST, SVGA_NEW_REDUCED_PRIMITIVE
*/
need_pipeline = TRUE;
}
- /* SVGA_NEW_EDGEFLAGS
+ /* EDGEFLAGS
*/
- if (svga->curr.rast->hw_unfilled != PIPE_POLYGON_MODE_FILL &&
- svga->curr.reduced_prim == PIPE_PRIM_TRIANGLES &&
- svga->curr.edgeflags != NULL) {
+ if (vs->base.info.writes_edgeflag) {
SVGA_DBG(DEBUG_SWTNL, "%s: edgeflags\n", __FUNCTION__);
need_pipeline = TRUE;
}
"need pipeline",
(SVGA_NEW_RAST |
SVGA_NEW_CLIP |
+ SVGA_NEW_VS |
SVGA_NEW_REDUCED_PRIMITIVE),
update_need_pipeline
};
draw_set_mrd(svga->swtnl.draw,
svga->curr.depthscale);
- if (dirty & SVGA_NEW_EDGEFLAGS)
- draw_set_edgeflags( svga->swtnl.draw,
- svga->curr.edgeflags );
-
return 0;
}
SVGA_NEW_VIEWPORT |
SVGA_NEW_RAST |
SVGA_NEW_FRAME_BUFFER |
- SVGA_NEW_REDUCED_PRIMITIVE |
- SVGA_NEW_EDGEFLAGS),
+ SVGA_NEW_REDUCED_PRIMITIVE),
update_swtnl_draw
};
}
-static INLINE void
-trace_context_set_edgeflags(struct pipe_context *_pipe,
- const unsigned *bitfield)
-{
- struct trace_context *tr_ctx = trace_context(_pipe);
- struct pipe_context *pipe = tr_ctx->pipe;
-
- trace_dump_call_begin("pipe_context", "set_edgeflags");
-
- trace_dump_arg(ptr, pipe);
- /* FIXME: we don't know how big this array is */
- trace_dump_arg(ptr, bitfield);
-
- pipe->set_edgeflags(pipe, bitfield);
-
- trace_dump_call_end();
-}
-
-
static INLINE void
trace_context_draw_block(struct trace_context *tr_ctx, int flag)
{
tr_ctx->base.winsys = _screen->winsys;
tr_ctx->base.screen = _screen;
tr_ctx->base.destroy = trace_context_destroy;
- tr_ctx->base.set_edgeflags = trace_context_set_edgeflags;
tr_ctx->base.draw_arrays = trace_context_draw_arrays;
tr_ctx->base.draw_elements = trace_context_draw_elements;
tr_ctx->base.draw_range_elements = trace_context_draw_range_elements;
void (*destroy)( struct pipe_context * );
-
- /* Possible interface for setting edgeflags. These aren't really
- * vertex elements, so don't fit there.
- */
- void (*set_edgeflags)( struct pipe_context *,
- const unsigned *bitfield );
-
-
/**
* VBO drawing (return false on fallbacks (temporary??))
*/
#define TGSI_SEMANTIC_GENERIC 5
#define TGSI_SEMANTIC_NORMAL 6
#define TGSI_SEMANTIC_FACE 7
-#define TGSI_SEMANTIC_COUNT 8 /**< number of semantic values */
+#define TGSI_SEMANTIC_EDGEFLAG 8
+#define TGSI_SEMANTIC_COUNT 9 /**< number of semantic values */
struct tgsi_declaration_semantic
{
self.real.set_vertex_element(i, elements[i])
self.real.set_vertex_elements(num_elements)
- def set_edgeflags(self, bitfield):
- # FIXME
- pass
-
def dump_vertices(self, start, count):
if not self.interpreter.verbosity(2):
return
/* Nothing in our key yet. This will change:
*/
memset(&key, 0, sizeof key);
- key.dummy = 0;
+
+ /* When this is true, we will add an extra input to the vertex
+ * shader translation (for edgeflags), an extra output with
+ * edgeflag semantics, and extend the vertex shader to pass through
+ * the input to the output. We'll need to use similar logic to set
+ * up the extra vertex_element input for edgeflags.
+ * _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA
+ */
+ key.passthrough_edgeflags = (st->vertdata_edgeflags && (
+ st->ctx->Polygon.FrontMode != GL_FILL ||
+ st->ctx->Polygon.BackMode != GL_FILL));
+
/* Do we need to throw away old translations after a change in the
* GL program string?
const struct st_tracked_state st_update_vp = {
"st_update_vp", /* name */
{ /* dirty */
- 0, /* mesa */
- ST_NEW_VERTEX_PROGRAM /* st */
+ _NEW_POLYGON, /* mesa */
+ ST_NEW_VERTEX_PROGRAM | ST_NEW_EDGEFLAGS_DATA /* st */
},
update_vp /* update */
};
#define ST_NEW_FRAGMENT_PROGRAM 0x2
#define ST_NEW_VERTEX_PROGRAM 0x4
#define ST_NEW_FRAMEBUFFER 0x8
+#define ST_NEW_EDGEFLAGS_DATA 0x10
struct st_state_flags {
struct st_state_flags dirty;
GLboolean missing_textures;
+ GLboolean vertdata_edgeflags;
/** Mapping from VERT_RESULT_x to post-transformed vertex slot */
const GLuint *vertex_result_to_slot;
}
-/*
- * If edge flags are needed, setup an bitvector of flags and call
- * pipe->set_edgeflags().
- * XXX memleak: need to free the returned pointer at some point
- */
-static void *
-setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count,
- const struct gl_client_array *array)
-{
- struct pipe_context *pipe = ctx->st->pipe;
-
- if ((primMode == GL_TRIANGLES ||
- primMode == GL_QUADS ||
- primMode == GL_POLYGON) &&
- (ctx->Polygon.FrontMode != GL_FILL ||
- ctx->Polygon.BackMode != GL_FILL)) {
- /* need edge flags */
- GLint i;
- unsigned *vec;
- struct st_buffer_object *stobj = st_buffer_object(array->BufferObj);
- ubyte *map;
-
- if (!stobj || stobj->Base.Name == 0) {
- /* edge flags are not in a VBO */
- return NULL;
- }
-
- vec = (unsigned *) _mesa_calloc(sizeof(unsigned) * ((count + 31) / 32));
- if (!vec)
- return NULL;
-
- map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
- map = ADD_POINTERS(map, array->Ptr);
-
- for (i = 0; i < count; i++) {
- if (*((float *) map))
- vec[i/32] |= 1 << (i % 32);
-
- map += array->StrideB;
- }
- pipe_buffer_unmap(pipe->screen, stobj->buffer);
-
- pipe->set_edgeflags(pipe, vec);
-
- return vec;
- }
- else {
- /* edge flags not needed */
- pipe->set_edgeflags(pipe, NULL);
- return NULL;
- }
-}
/**
*/
static GLboolean
is_interleaved_arrays(const struct st_vertex_program *vp,
+ const struct st_vp_varient *vpv,
const struct gl_client_array **arrays,
GLboolean *userSpace)
{
GLuint num_client_arrays = 0;
const GLubyte *client_addr = NULL;
- for (attr = 0; attr < vp->num_inputs; attr++) {
+ for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj;
const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */
}
}
- *userSpace = (num_client_arrays == vp->num_inputs);
+ *userSpace = (num_client_arrays == vpv->num_inputs);
/* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */
return GL_TRUE;
*/
static void
get_arrays_bounds(const struct st_vertex_program *vp,
- const struct gl_client_array **arrays,
- GLuint max_index,
- const GLubyte **low, const GLubyte **high)
+ const struct st_vp_varient *vpv,
+ const struct gl_client_array **arrays,
+ GLuint max_index,
+ const GLubyte **low, const GLubyte **high)
{
const GLubyte *low_addr = NULL;
const GLubyte *high_addr = NULL;
GLuint attr;
- for (attr = 0; attr < vp->num_inputs; attr++) {
+ for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
const GLint stride = arrays[mesaAttr]->StrideB;
const GLubyte *start = arrays[mesaAttr]->Ptr;
static void
setup_interleaved_attribs(GLcontext *ctx,
const struct st_vertex_program *vp,
+ const struct st_vp_varient *vpv,
const struct gl_client_array **arrays,
GLuint max_index,
GLboolean userSpace,
GLuint attr;
const GLubyte *offset0 = NULL;
- for (attr = 0; attr < vp->num_inputs; attr++) {
+ for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
struct st_buffer_object *stobj = st_buffer_object(bufobj);
if (attr == 0) {
const GLubyte *low, *high;
- get_arrays_bounds(vp, arrays, max_index, &low, &high);
+ get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high);
/*printf("buffer range: %p %p %d\n", low, high, high-low);*/
offset0 = low;
static void
setup_non_interleaved_attribs(GLcontext *ctx,
const struct st_vertex_program *vp,
+ const struct st_vp_varient *vpv,
const struct gl_client_array **arrays,
GLuint max_index,
GLboolean *userSpace,
struct pipe_context *pipe = ctx->st->pipe;
GLuint attr;
- for (attr = 0; attr < vp->num_inputs; attr++) {
+ for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
GLsizei stride = arrays[mesaAttr]->StrideB;
{
struct pipe_context *pipe = ctx->st->pipe;
const struct st_vertex_program *vp;
+ const struct st_vp_varient *vpv;
const struct pipe_shader_state *vs;
struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
GLuint attr;
struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
unsigned num_vbuffers, num_velements;
GLboolean userSpace = GL_FALSE;
+ GLboolean vertDataEdgeFlags;
/* Gallium probably doesn't want this in some cases. */
if (!index_bounds_valid)
/* sanity check for pointer arithmetic below */
assert(sizeof(arrays[0]->Ptr[0]) == 1);
+ vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj &&
+ arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name;
+ if (vertDataEdgeFlags != ctx->st->vertdata_edgeflags) {
+ ctx->st->vertdata_edgeflags = vertDataEdgeFlags;
+ ctx->st->dirty.st |= ST_NEW_EDGEFLAGS_DATA;
+ }
+
st_validate_state(ctx->st);
/* must get these after state validation! */
vp = ctx->st->vp;
- vs = &ctx->st->vp_varient->state;
+ vpv = ctx->st->vp_varient;
+ vs = &vpv->state;
#if 0
if (MESA_VERBOSE & VERBOSE_GLSL) {
/*
* Setup the vbuffer[] and velements[] arrays.
*/
- if (is_interleaved_arrays(vp, arrays, &userSpace)) {
+ if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) {
/*printf("Draw interleaved\n");*/
- setup_interleaved_attribs(ctx, vp, arrays, max_index, userSpace,
+ setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace,
vbuffer, velements);
num_vbuffers = 1;
- num_velements = vp->num_inputs;
+ num_velements = vpv->num_inputs;
if (num_velements == 0)
num_vbuffers = 0;
}
else {
/*printf("Draw non-interleaved\n");*/
- setup_non_interleaved_attribs(ctx, vp, arrays, max_index,
+ setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index,
&userSpace, vbuffer, velements);
- num_vbuffers = vp->num_inputs;
- num_velements = vp->num_inputs;
+ num_vbuffers = vpv->num_inputs;
+ num_velements = vpv->num_inputs;
}
#if 0
* through to driver & draw module. These interfaces still
* need a bit of work...
*/
- setup_edgeflags(ctx, prims[i].mode,
- prims[i].start + indexOffset, prims[i].count,
- arrays[VERT_ATTRIB_EDGEFLAG]);
-
prim = translate_prim( ctx, prims[i].mode );
pipe->draw_range_elements(pipe, indexBuf, indexSize,
}
else {
for (i = 0; i < nr_prims; i++) {
- setup_edgeflags(ctx, prims[i].mode,
- prims[i].start + indexOffset, prims[i].count,
- arrays[VERT_ATTRIB_EDGEFLAG]);
-
prim = translate_prim( ctx, prims[i].mode );
pipe->draw_elements(pipe, indexBuf, indexSize,
GLuint prim;
for (i = 0; i < nr_prims; i++) {
- setup_edgeflags(ctx, prims[i].mode,
- prims[i].start, prims[i].count,
- arrays[VERT_ATTRIB_EDGEFLAG]);
-
prim = translate_prim( ctx, prims[i].mode );
pipe->draw_arrays(pipe, prim, prims[i].start, prims[i].count);
t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]] = ureg_src(face_temp);
}
+static void
+emit_edgeflags( struct st_translate *t,
+ const struct gl_program *program )
+{
+ struct ureg_program *ureg = t->ureg;
+ struct ureg_dst edge_dst = t->outputs[t->outputMapping[VERT_RESULT_EDGE]];
+ struct ureg_src edge_src = t->inputs[t->inputMapping[VERT_ATTRIB_EDGEFLAG]];
+
+ ureg_MOV( ureg, edge_dst, edge_src );
+}
/**
* Translate Mesa program to TGSI format.
*
* \return array of translated tokens, caller's responsibility to free
*/
-const struct tgsi_token *
+enum pipe_error
st_translate_mesa_program(
GLcontext *ctx,
uint procType,
+ struct ureg_program *ureg,
const struct gl_program *program,
GLuint numInputs,
const GLuint inputMapping[],
GLuint numOutputs,
const GLuint outputMapping[],
const ubyte outputSemanticName[],
- const ubyte outputSemanticIndex[] )
+ const ubyte outputSemanticIndex[],
+ boolean passthrough_edgeflags )
{
struct st_translate translate, *t;
- struct ureg_program *ureg;
- const struct tgsi_token *tokens = NULL;
unsigned i;
t = &translate;
t->procType = procType;
t->inputMapping = inputMapping;
t->outputMapping = outputMapping;
- t->ureg = ureg_create( procType );
- if (t->ureg == NULL)
- return NULL;
-
- ureg = t->ureg;
+ t->ureg = ureg;
/*_mesa_print_program(program);*/
outputSemanticName[i],
outputSemanticIndex[i] );
}
+ if (passthrough_edgeflags)
+ emit_edgeflags( t, program );
}
/* Declare address register.
t->insn[t->labels[i].branch_target] );
}
- tokens = ureg_get_tokens( ureg, NULL );
- ureg_destroy( ureg );
+ return PIPE_OK;
out:
FREE(t->insn);
if (t->error) {
debug_printf("%s: translate error flag set\n", __FUNCTION__);
- FREE((void *)tokens);
- tokens = NULL;
- }
-
- if (!tokens) {
- debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
- _mesa_print_program(program);
- debug_assert(0);
}
- return tokens;
+ return PIPE_ERROR_OUT_OF_MEMORY;
}
#define ST_MESA_TO_TGSI_H
#include "main/mtypes.h"
+#include "tgsi/tgsi_ureg.h"
#if defined __cplusplus
struct tgsi_token;
struct gl_program;
-const struct tgsi_token *
+enum pipe_error
st_translate_mesa_program(
GLcontext *ctx,
uint procType,
+ struct ureg_program *ureg,
const struct gl_program *program,
GLuint numInputs,
const GLuint inputMapping[],
GLuint numOutputs,
const GLuint outputMapping[],
const ubyte outputSemanticName[],
- const ubyte outputSemanticIndex[] );
+ const ubyte outputSemanticIndex[],
+ boolean passthrough_edgeflags );
void
st_free_tokens(const struct tgsi_token *tokens);
stvp->num_inputs++;
}
}
+ /* bit of a hack, presetup potentially unused edgeflag input */
+ stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs;
+ stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG;
/* Compute mapping of vertex program outputs to slots.
*/
}
}
}
+ /* similar hack to above, presetup potentially unused edgeflag output */
+ stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs;
+ stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
+ stvp->output_semantic_index[stvp->num_outputs] = 0;
}
{
struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient);
struct pipe_context *pipe = st->pipe;
+ struct ureg_program *ureg;
+ enum pipe_error error;
+ unsigned num_outputs;
+
+ ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
+ if (ureg == NULL)
+ return NULL;
+
+ vpv->num_inputs = stvp->num_inputs;
+ num_outputs = stvp->num_outputs;
+ if (key->passthrough_edgeflags) {
+ vpv->num_inputs++;
+ num_outputs++;
+ }
- vpv->state.tokens =
+ error =
st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_VERTEX,
+ ureg,
&stvp->Base.Base,
/* inputs */
- stvp->num_inputs,
+ vpv->num_inputs,
stvp->input_to_index,
NULL, /* input semantic name */
NULL, /* input semantic index */
NULL,
/* outputs */
- stvp->num_outputs,
+ num_outputs,
stvp->result_to_output,
stvp->output_semantic_name,
- stvp->output_semantic_index );
+ stvp->output_semantic_index,
+ key->passthrough_edgeflags );
+
+ if (error)
+ goto fail;
+
+ vpv->state.tokens = ureg_get_tokens( ureg, NULL );
+ if (!vpv->state.tokens)
+ goto fail;
+
+ ureg_destroy( ureg );
vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);
}
return vpv;
+
+fail:
+ debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
+ _mesa_print_program(&stvp->Base.Base);
+ debug_assert(0);
+
+ ureg_destroy( ureg );
+ return NULL;
}
GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
GLuint interpMode[16]; /* XXX size? */
GLuint attr;
+ enum pipe_error error;
const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
+ struct ureg_program *ureg;
GLuint vslot = 0;
uint fs_num_inputs = 0;
if (!inputMapping)
inputMapping = defaultInputMapping;
- stfp->state.tokens =
+ ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+ if (ureg == NULL)
+ return;
+
+
+ error =
st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_FRAGMENT,
+ ureg,
&stfp->Base.Base,
/* inputs */
fs_num_inputs,
fs_num_outputs,
outputMapping,
fs_output_semantic_name,
- fs_output_semantic_index );
+ fs_output_semantic_index, FALSE );
+ stfp->state.tokens = ureg_get_tokens( ureg, NULL );
+ ureg_destroy( ureg );
stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->state);
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
struct st_vp_varient_key
{
- char dummy; /* currently unused */
+ boolean passthrough_edgeflags;
};
/** Next in linked list */
struct st_vp_varient *next;
+
+ /** similar to that in st_vertex_program, but with information about edgeflags too */
+ GLuint num_inputs;
};