}
-/**
- * Return true if we have the VERT_ATTRIB_EDGEFLAG array enabled.
- */
-static inline bool
-_mesa_draw_edge_flag_array_enabled(const struct gl_context *ctx)
-{
- return ctx->Array._DrawVAOEnabledAttribs & VERT_BIT_EDGEFLAG;
-}
-
-
#ifdef __cplusplus
}
#endif
src->VAO->IndexBufferObj ?
src->VAO->IndexBufferObj->Name : 0);
}
+
+ _mesa_update_edgeflag_state_vao(ctx);
}
if (*ptr != vao) {
_mesa_reference_vao_(ctx, ptr, vao);
+ _mesa_update_edgeflag_state_vao(ctx);
ctx->Array.NewVAO = true;
}
}
{
_mesa_reference_vao(ctx, &ctx->Array._DrawVAO, NULL);
ctx->Array._DrawVAO = saved;
+ _mesa_update_edgeflag_state_vao(ctx);
ctx->Array.NewVAO = true;
}
GLbitfield _DrawVAOEnabledAttribs;
/**
+ * Whether per-vertex edge flags are enabled and should be processed by
+ * the vertex shader.
+ */
+ bool _PerVertexEdgeFlagsEnabled;
+
+ /**
+ * Whether all edge flags are false, causing all points and lines generated
+ * by polygon mode to be not drawn. (i.e. culled)
+ */
+ bool _PolygonModeAlwaysCulls;
+
+ /**
* Whether the VAO has been changed.
*/
bool NewVAO;
#include "polygon.h"
#include "mtypes.h"
#include "api_exec_decl.h"
+#include "varray.h"
#include "state_tracker/st_context.h"
GL_POLYGON_BIT);
ctx->NewDriverState |= ST_NEW_RASTERIZER;
ctx->Polygon.FrontMode = mode;
+ _mesa_update_edgeflag_state_vao(ctx);
break;
case GL_FRONT_AND_BACK:
if (ctx->Polygon.FrontMode == mode && ctx->Polygon.BackMode == mode)
ctx->NewDriverState |= ST_NEW_RASTERIZER;
ctx->Polygon.FrontMode = mode;
ctx->Polygon.BackMode = mode;
+ _mesa_update_edgeflag_state_vao(ctx);
break;
case GL_BACK:
if (!no_error && ctx->API == API_OPENGL_CORE) {
GL_POLYGON_BIT);
ctx->NewDriverState |= ST_NEW_RASTERIZER;
ctx->Polygon.BackMode = mode;
+ _mesa_update_edgeflag_state_vao(ctx);
break;
default:
if (!no_error)
#include "main/dispatch.h"
#include "api_exec_decl.h"
+#include "state_tracker/st_atom.h"
+#include "state_tracker/st_util.h"
+
/** Used to do error checking for GL_EXT_vertex_array_bgra */
#define BGRA_OR_4 5
stride, GL_FALSE, GL_FALSE, GL_TRUE, ptr);
}
+/**
+ * Set the per-vertex edge flag enablement according to the "enable"
+ * parameter. If "enable" is false, the zero-stride edge flag attribute value
+ * will be used instead.
+ *
+ * This is used by VAOs, glBegin/End and display lists.
+ */
+void
+_mesa_update_edgeflag_state_explicit(struct gl_context *ctx,
+ bool per_vertex_enable)
+{
+ if (ctx->API != API_OPENGL_COMPAT)
+ return;
+
+ /* Edge flags take effect only if the polygon mode is not FILL, and they
+ * determine whether a line or point is drawn with that polygon mode.
+ */
+ bool edgeflags_have_effect = ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL;
+ per_vertex_enable &= edgeflags_have_effect;
+
+ if (per_vertex_enable != ctx->Array._PerVertexEdgeFlagsEnabled) {
+ ctx->Array._PerVertexEdgeFlagsEnabled = per_vertex_enable;
+
+ struct gl_program *vp = ctx->VertexProgram._Current;
+ if (vp) {
+ ctx->NewDriverState |= ST_NEW_VS_STATE |
+ ST_NEW_VERTEX_ARRAYS;
+ ctx->Array.NewVertexElements = true;
+ }
+ }
+
+ /* If there are no per-vertex edge flags and the zero-stride edge flag is
+ * false, all front and back points and lines generated by polygon mode
+ * are not drawn.
+ */
+ bool polygon_mode_always_culls = edgeflags_have_effect &&
+ !ctx->Array._PerVertexEdgeFlagsEnabled &&
+ !ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0];
+ if (polygon_mode_always_culls != ctx->Array._PolygonModeAlwaysCulls) {
+ ctx->Array._PolygonModeAlwaysCulls = polygon_mode_always_culls;
+ ctx->NewDriverState |= ST_NEW_RASTERIZER;
+ }
+}
+
+/**
+ * Set the edge flag state using the current VAO and the zero-stride
+ * edge flag attribute value if per-vertex edge flags are disabled.
+ */
+void
+_mesa_update_edgeflag_state_vao(struct gl_context *ctx)
+{
+ _mesa_update_edgeflag_state_explicit(ctx,
+ ctx->Array._DrawVAO->Enabled &
+ VERT_BIT_EDGEFLAG);
+}
void
_mesa_enable_vertex_array_attribs(struct gl_context *ctx,
if (attrib_bits & (VERT_BIT_POS|VERT_BIT_GENERIC0))
update_attribute_map_mode(ctx, vao);
+ if (attrib_bits & VERT_BIT_EDGEFLAG)
+ _mesa_update_edgeflag_state_vao(ctx);
+
vao->_EnabledWithMapMode =
_mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled);
}
if (attrib_bits & (VERT_BIT_POS|VERT_BIT_GENERIC0))
update_attribute_map_mode(ctx, vao);
+ if (attrib_bits & VERT_BIT_EDGEFLAG)
+ _mesa_update_edgeflag_state_vao(ctx);
+
vao->_EnabledWithMapMode =
_mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled);
}
extern void
_mesa_free_varray_data(struct gl_context *ctx);
+void
+_mesa_update_edgeflag_state_explicit(struct gl_context *ctx,
+ bool per_vertex_enable);
+
+void
+_mesa_update_edgeflag_state_vao(struct gl_context *ctx);
+
#endif
/* no-op */
}
-void st_update_edgeflags(struct st_context *st, bool per_vertex_edgeflags)
-{
- bool edgeflags_enabled = st->ctx->Polygon.FrontMode != GL_FILL ||
- st->ctx->Polygon.BackMode != GL_FILL;
- bool vertdata_edgeflags = edgeflags_enabled && per_vertex_edgeflags;
-
- if (vertdata_edgeflags != st->vertdata_edgeflags) {
- st->vertdata_edgeflags = vertdata_edgeflags;
-
- struct gl_program *vp = st->ctx->VertexProgram._Current;
- if (vp)
- st->dirty |= ST_NEW_VERTEX_PROGRAM(st->ctx, vp);
- }
-
- bool edgeflag_culls_prims = edgeflags_enabled && !vertdata_edgeflags &&
- !st->ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0];
- if (edgeflag_culls_prims != st->edgeflag_culls_prims) {
- st->edgeflag_culls_prims = edgeflag_culls_prims;
- st->dirty |= ST_NEW_RASTERIZER;
- }
-}
-
-static void check_attrib_edgeflag(struct st_context *st)
-{
- st_update_edgeflags(st, _mesa_draw_edge_flag_array_enabled(st->ctx));
-}
-
/***********************************************************************
* Update all derived state:
*/
switch (pipeline) {
case ST_PIPELINE_RENDER:
case ST_PIPELINE_RENDER_NO_VARRAYS:
- if (st->ctx->API == API_OPENGL_COMPAT)
- check_attrib_edgeflag(st);
-
if (pipeline == ST_PIPELINE_RENDER)
pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK;
else
void st_init_atoms( struct st_context *st );
void st_destroy_atoms( struct st_context *st );
void st_validate_state( struct st_context *st, enum st_pipeline pipeline );
-void st_update_edgeflags(struct st_context *st, bool per_vertex_edgeflags);
void
st_setup_arrays(struct st_context *st,
raster->tile_raster_order_increasing_y = ctx->TileRasterOrderIncreasingY;
}
- if (st->edgeflag_culls_prims) {
- /* All edge flags are FALSE. Cull the affected faces. */
+ if (ctx->Array._PolygonModeAlwaysCulls) {
if (raster->fill_front != PIPE_POLYGON_MODE_FILL)
raster->cull_face |= PIPE_FACE_FRONT;
if (raster->fill_back != PIPE_POLYGON_MODE_FILL)
assert(vp->Target == GL_VERTEX_PROGRAM_ARB);
if (st->shader_has_one_variant[MESA_SHADER_VERTEX] &&
- !st->vertdata_edgeflags) {
+ !st->ctx->Array._PerVertexEdgeFlagsEnabled) {
st->vp_variant = st_common_variant(vp->variants);
} else {
struct st_common_variant_key key;
* 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 = st->vertdata_edgeflags;
+ key.passthrough_edgeflags = st->ctx->Array._PerVertexEdgeFlagsEnabled;
key.clamp_color = st->clamp_vert_color_in_shader &&
st->ctx->Light._ClampVertexColor &&
/** This masks out unused shader resources. Only valid in draw calls. */
uint64_t active_states;
- GLboolean vertdata_edgeflags;
- GLboolean edgeflag_culls_prims;
-
/**
* The number of currently active queries (excluding timer queries).
* This is used to know if we need to pause any queries for meta ops.
bool per_vertex_edgeflags)
{
struct st_context *st = st_context(ctx);
- bool old_vertdata_edgeflags = st->vertdata_edgeflags;
-
- /* We don't flag any other states to make st_validate state update edge
- * flags, so we need to update them here.
- */
- st_update_edgeflags(st, per_vertex_edgeflags);
prepare_draw(st, ctx, ST_PIPELINE_RENDER_STATE_MASK_NO_VARRAYS,
ST_PIPELINE_RENDER_NO_VARRAYS);
}
}
}
-
- /* If per-vertex edge flags are different than the non-display-list state,
- * just flag ST_NEW_VERTEX_ARRAY, which will also completely revalidate
- * edge flags in st_validate_state.
- */
- if (st->vertdata_edgeflags != old_vertdata_edgeflags) {
- ctx->Array.NewVertexElements = true;
- st->dirty |= ST_NEW_VERTEX_ARRAYS;
- }
}
void
i == VBO_ATTRIB_MAT_BACK_SHININESS)
ctx->NewState |= _NEW_FF_VERT_PROGRAM;
} else {
+ if (i == VBO_ATTRIB_EDGEFLAG)
+ _mesa_update_edgeflag_state_vao(ctx);
+
ctx->NewState |= _NEW_CURRENT_ATTRIB;
ctx->PopAttribState |= GL_CURRENT_BIT;
}
current_index == VBO_ATTRIB_MAT_BACK_SHININESS)
ctx->NewState |= _NEW_FF_VERT_PROGRAM;
+ if (current_index == VBO_ATTRIB_EDGEFLAG)
+ _mesa_update_edgeflag_state_vao(ctx);
+
ctx->NewState |= state;
ctx->PopAttribState |= pop_state;
}
info.take_vertex_state_ownership = true;
}
+ /* Set edge flags. */
+ _mesa_update_edgeflag_state_explicit(ctx, enabled & VERT_BIT_EDGEFLAG);
+
/* Fast path using a pre-built gallium vertex buffer state. */
if (node->modes || node->num_draws > 1) {
ctx->Driver.DrawGalliumVertexState(ctx, state, info,
enabled & VERT_ATTRIB_EDGEFLAG);
}
+ /* Restore edge flag state. */
+ _mesa_update_edgeflag_state_vao(ctx);
+
if (copy_to_current)
playback_copy_to_current(ctx, node);
return DONE;