summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keithw@vmware.com>2009-12-09 19:03:10 +0100
committerRoland Scheidegger <sroland@vmware.com>2009-12-09 19:03:10 +0100
commita08e348a84f57ed5e8bf5888f1ce13934d2ce8fa (patch)
tree595ffc983588c5441c39ff11c3a089e521f94e53
parent59f6af51b858340139fe2139e2698fef8a5ad62f (diff)
gallium: first steps to treat edgeflags as regular vertex element
The idea here is to eliminate the set_edgeflags() call in pipe_context by treating edgeflags as a regular vertex element. Edgeflags provoke special treatment in hardware, which means we need to label them in some way, in this case we'll be passing them through the vertex shader and labelling the vertex shader output with a new TGSI semantic (TGSI_SEMANTIC_EDGEFLAG).
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c7
-rw-r--r--src/gallium/auxiliary/draw/draw_context.h3
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.h5
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c32
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c3
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_post_vs.c53
-rw-r--r--src/gallium/include/pipe/p_context.h8
-rw-r--r--src/gallium/include/pipe/p_shader_tokens.h3
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c11
-rw-r--r--src/mesa/state_tracker/st_draw.c64
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c13
-rw-r--r--src/mesa/state_tracker/st_program.c32
-rw-r--r--src/mesa/state_tracker/st_program.h2
15 files changed, 111 insertions, 131 deletions
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index a4f1fcddc1..cc5f7f0105 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -366,13 +366,6 @@ void draw_set_render( struct draw_context *draw,
draw->render = render;
}
-void draw_set_edgeflags( struct draw_context *draw,
- const unsigned *edgeflag )
-{
- draw->pt.user.edgeflag = edgeflag;
-}
-
-
/**
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index d529e4e9a2..465b8f10c6 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -143,9 +143,6 @@ void draw_set_mapped_constant_buffer(struct draw_context *draw,
const void *buffer,
unsigned size );
-void draw_set_edgeflags( struct draw_context *draw,
- const unsigned *edgeflag );
-
/***********************************************************************
* draw_prim.c
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 41fcb16a0a..0750e6e379 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -142,8 +142,6 @@ struct draw_context
/* 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) */
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 4865a2d854..139ae1fe55 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -318,8 +318,10 @@ draw_arrays(struct draw_context *draw, unsigned prim,
boolean draw_pt_get_edgeflag( struct draw_context *draw,
unsigned idx )
{
- if (draw->pt.user.edgeflag)
+ if (draw->pt.user.edgeflag) {
+ float *ef = draw->pt.verted_buffer[idx]
return (draw->pt.user.edgeflag[idx/32] & (1 << (idx%32))) != 0;
+ }
else
return 1;
}
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 7a17a9fb6b..b5c8c82f4a 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -149,11 +149,6 @@ struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw );
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:
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index 65c3a34c34..cb609f8c41 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -120,7 +120,12 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
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,
@@ -128,9 +133,6 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
}
}
- fetch->need_edgeflags = ((draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
- draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) &&
- draw->pt.user.edgeflag);
}
@@ -158,16 +160,10 @@ void draw_pt_fetch_run( struct pt_fetch *fetch,
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:
+ /* Extract edgeflag values from vertex data into the header.
*/
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] );
- }
+ extract_edge_flags( fetch, count );
}
}
@@ -194,16 +190,12 @@ void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
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:
+ /* Extract edgeflag values from vertex data into the header. XXX:
+ * this should be done after the vertex shader is run.
+ * Bypass-vs-and-clip interaction with pipeline???
*/
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 );
- }
+ extract_edge_flags( fetch, count );
}
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index df6c265b7e..d41436858a 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -86,7 +86,8 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->bypass_clipping,
(boolean)(draw->identity_viewport ||
draw->rasterizer->bypass_vs_clip_and_viewport),
- (boolean)draw->rasterizer->gl_rasterization_rules );
+ (boolean)draw->rasterizer->gl_rasterization_rules,
+ need_edgeflags );
if (!(opt & PT_PIPELINE)) {
diff --git a/src/gallium/auxiliary/draw/draw_pt_post_vs.c b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
index 6c1cb48e8b..0745b168de 100644
--- a/src/gallium/auxiliary/draw/draw_pt_post_vs.c
+++ b/src/gallium/auxiliary/draw/draw_pt_post_vs.c
@@ -147,6 +147,34 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
+/* 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 )
+{
+ if (!post_vs_cliptest_viewport_gl( pvs, vertices, count, stride))
+ return FALSE;
+
+ /* 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);
+ }
+ }
+}
+
+
+
+
/* If bypass_clipping is set, skip cliptest and rhw divide.
*/
static boolean post_vs_viewport( struct pt_post_vs *pvs,
@@ -203,15 +231,26 @@ void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
boolean bypass_viewport,
boolean opengl )
{
- 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;
}
}
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index f896001eb1..11bcdc0a24 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -57,14 +57,6 @@ struct pipe_context {
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??))
*/
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 588ca5e026..c051d4dae8 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -127,7 +127,8 @@ struct tgsi_declaration_range
#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
{
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index 09baff875b..e209634c90 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -106,7 +106,16 @@ find_translated_vp(struct st_context *st,
/* 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.
+ */
+ key.passthrough_edgeflags = (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL);
+
/* Do we need to throw away old translations after a change in the
* GL program string?
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index e13ae57a0e..773a3f17cd 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -217,59 +217,7 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
}
-/*
- * 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;
- }
-}
/**
@@ -671,10 +619,6 @@ st_draw_vbo(GLcontext *ctx,
* 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]);
-
pipe->draw_range_elements(pipe, indexBuf, indexSize,
min_index,
max_index,
@@ -683,10 +627,6 @@ st_draw_vbo(GLcontext *ctx,
}
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]);
-
pipe->draw_elements(pipe, indexBuf, indexSize,
prims[i].mode,
prims[i].start + indexOffset, prims[i].count);
@@ -699,10 +639,6 @@ st_draw_vbo(GLcontext *ctx,
/* non-indexed */
GLuint i;
for (i = 0; i < nr_prims; i++) {
- setup_edgeflags(ctx, prims[i].mode,
- prims[i].start, prims[i].count,
- arrays[VERT_ATTRIB_EDGEFLAG]);
-
pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
}
}
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index 1611d53e2f..9fd670cac2 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -741,6 +741,7 @@ emit_face_var( struct st_translate *t,
const struct tgsi_token *
st_translate_mesa_program(
GLcontext *ctx,
+ struct ureg_program *ureg;
uint procType,
const struct gl_program *program,
GLuint numInputs,
@@ -754,7 +755,6 @@ st_translate_mesa_program(
const ubyte outputSemanticIndex[] )
{
struct st_translate translate, *t;
- struct ureg_program *ureg;
const struct tgsi_token *tokens = NULL;
unsigned i;
@@ -764,11 +764,7 @@ st_translate_mesa_program(
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);*/
@@ -899,8 +895,7 @@ st_translate_mesa_program(
t->insn[t->labels[i].branch_target] );
}
- tokens = ureg_get_tokens( ureg, NULL );
- ureg_destroy( ureg );
+ return PIPE_OK;
out:
FREE(t->insn);
@@ -919,7 +914,7 @@ out:
debug_assert(0);
}
- return tokens;
+ return PIPE_ERROR_OUT_OF_MEMORY;
}
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 5c81a033f9..876d92539e 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -192,10 +192,16 @@ st_translate_vertex_program(struct st_context *st,
{
struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient);
struct pipe_context *pipe = st->pipe;
+ struct ureg_program *ureg;
- vpv->state.tokens =
+ ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
+ if (ureg == NULL)
+ return NULL;
+
+ error =
st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_VERTEX,
+ ureg,
&stvp->Base.Base,
/* inputs */
stvp->num_inputs,
@@ -209,6 +215,20 @@ st_translate_vertex_program(struct st_context *st,
stvp->output_semantic_name,
stvp->output_semantic_index );
+ if (ret)
+ goto fail;
+
+ /* Edgeflags will be the last input:
+ */
+ if (key.passthrough_edgeflags) {
+ ureg_MOV( ureg,
+ ureg_DECL_output( ureg, TGSI_SEMANTIC_EDGEFLAG, 0 ),
+ ureg_DECL_next_vs_input(ureg));
+ }
+
+ tokens = ureg_get_tokens( ureg, NULL );
+ ureg_destroy( ureg );
+
vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
@@ -222,6 +242,10 @@ st_translate_vertex_program(struct st_context *st,
}
return vpv;
+
+fail:
+ ureg_destroy( ureg );
+ return NULL;
}
@@ -243,6 +267,7 @@ st_translate_fragment_program(struct st_context *st,
GLuint interpMode[16]; /* XXX size? */
GLuint attr;
const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
+ struct ureg_program *ureg;
GLuint vslot = 0;
uint fs_num_inputs = 0;
@@ -377,6 +402,11 @@ st_translate_fragment_program(struct st_context *st,
if (!inputMapping)
inputMapping = defaultInputMapping;
+ ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+ if (ureg == NULL)
+ return NULL;
+
+
stfp->state.tokens =
st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_FRAGMENT,
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index 88aadbd751..91392785e5 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -73,7 +73,7 @@ struct st_fragment_program
struct st_vp_varient_key
{
- char dummy; /* currently unused */
+ boolean passthrough_edgeflags;
};