The program keys are updated accordingly, but the values are not used yet. Signed-off-by: Olivier Galibert <galibert at pobox.com> --- src/mesa/drivers/dri/i965/brw_clip.c | 90 ++++++++++++++++++++++++++++++- src/mesa/drivers/dri/i965/brw_clip.h | 1 + src/mesa/drivers/dri/i965/brw_context.h | 11 ++++ src/mesa/drivers/dri/i965/brw_sf.c | 5 +- src/mesa/drivers/dri/i965/brw_sf.h | 1 + src/mesa/drivers/dri/i965/brw_wm.c | 2 + src/mesa/drivers/dri/i965/brw_wm.h | 1 + 7 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_clip.c b/src/mesa/drivers/dri/i965/brw_clip.c index d411208..b4a2e0a 100644 --- a/src/mesa/drivers/dri/i965/brw_clip.c +++ b/src/mesa/drivers/dri/i965/brw_clip.c @@ -47,6 +47,86 @@ #define FRONT_UNFILLED_BIT 0x1 #define BACK_UNFILLED_BIT 0x2 +/** + * Lookup the interpolation mode information for every element in the + * vue. + */ +static void +brw_lookup_interpolation(struct brw_context *brw) +{ + /* pprog means "previous program", i.e. the last program before the + * fragment shader. It can only be the vertex shader for now, but + * it may be a geometry shader in the future. + */ + const struct gl_program *pprog = &brw->vertex_program->Base; + const struct gl_fragment_program *fprog = brw->fragment_program; + struct brw_vue_map *vue_map = &brw->vs.prog_data->vue_map; + + /* Default everything to INTERP_QUALIFIER_NONE */ + memset(brw->interpolation_mode, INTERP_QUALIFIER_NONE, BRW_VERT_RESULT_MAX); + + /* If there is no fragment shader, interpolation won't be needed, + * so defaulting to none is good. + */ + if (!fprog) + return; + + for (int i = 0; i < vue_map->num_slots; i++) { + /* First lookup the vert result, skip if there isn't one */ + int vert_result = vue_map->slot_to_vert_result[i]; + if (vert_result == BRW_VERT_RESULT_MAX) + continue; + + /* HPOS is special. In the clipper, it is handled specifically, + * so its value is irrelevant. In the sf, it's forced to + * linear. In the wm, it's special cased, irrelevant again. So + * force linear to remove the sf special case. + */ + if (vert_result == VERT_RESULT_HPOS) { + brw->interpolation_mode[i] = INTERP_QUALIFIER_NOPERSPECTIVE; + continue; + } + + /* There is a 1-1 mapping of vert result to frag attrib except + * for BackColor and vars + */ + int frag_attrib = vert_result; + if (vert_result >= VERT_RESULT_BFC0 && vert_result <= VERT_RESULT_BFC1) + frag_attrib = vert_result - VERT_RESULT_BFC0 + FRAG_ATTRIB_COL0; + else if(vert_result >= VERT_RESULT_VAR0) + frag_attrib = vert_result - VERT_RESULT_VAR0 + FRAG_ATTRIB_VAR0; + + /* If the output is not used by the fragment shader, skip it. */ + if (!(fprog->Base.InputsRead & BITFIELD64_BIT(frag_attrib))) + continue; + + /* Lookup the interpolation mode */ + enum glsl_interp_qualifier interpolation_mode = fprog->InterpQualifier[frag_attrib]; + + /* If the mode is not specified, then the default varies. Color + * values follow the shader model, while all the rest uses + * smooth. + */ + if (interpolation_mode == INTERP_QUALIFIER_NONE) { + if (frag_attrib >= FRAG_ATTRIB_COL0 && frag_attrib <= FRAG_ATTRIB_COL1) + interpolation_mode = brw->intel.ctx.Light.ShadeModel == GL_FLAT ? INTERP_QUALIFIER_FLAT : INTERP_QUALIFIER_SMOOTH; + else + interpolation_mode = INTERP_QUALIFIER_SMOOTH; + } + + /* Finally, if we have both a front color and a back color for + * the same channel, the selection will be done before + * interpolation and the back color copied over the front color + * if necessary. So interpolating the back color is + * unnecessary. + */ + if (vert_result >= VERT_RESULT_BFC0 && vert_result <= VERT_RESULT_BFC1) + if (pprog->OutputsWritten & BITFIELD64_BIT(vert_result - VERT_RESULT_BFC0 + VERT_RESULT_COL0)) + interpolation_mode = INTERP_QUALIFIER_NONE; + + brw->interpolation_mode[i] = interpolation_mode; + } +} static void compile_clip_prog( struct brw_context *brw, struct brw_clip_prog_key *key ) @@ -143,6 +223,10 @@ brw_upload_clip_prog(struct brw_context *brw) /* Populate the key: */ + + /* BRW_NEW_FRAGMENT_PROGRAM, _NEW_LIGHT */ + brw_lookup_interpolation(brw); + /* BRW_NEW_REDUCED_PRIMITIVE */ key.primitive = brw->intel.reduced_primitive; /* CACHE_NEW_VS_PROG (also part of VUE map) */ @@ -150,6 +234,10 @@ brw_upload_clip_prog(struct brw_context *brw) /* _NEW_LIGHT */ key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT); key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); + + /* BRW_NEW_FRAGMENT_PROGRAM, _NEW_LIGHT */ + memcpy(key.interpolation_mode, brw->interpolation_mode, BRW_VERT_RESULT_MAX); + /* _NEW_TRANSFORM (also part of VUE map)*/ key.nr_userclip = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); @@ -258,7 +346,7 @@ const struct brw_tracked_state brw_clip_prog = { _NEW_TRANSFORM | _NEW_POLYGON | _NEW_BUFFERS), - .brw = (BRW_NEW_REDUCED_PRIMITIVE), + .brw = (BRW_NEW_FRAGMENT_PROGRAM|BRW_NEW_REDUCED_PRIMITIVE), .cache = CACHE_NEW_VS_PROG }, .emit = brw_upload_clip_prog diff --git a/src/mesa/drivers/dri/i965/brw_clip.h b/src/mesa/drivers/dri/i965/brw_clip.h index 9185651..e78d074 100644 --- a/src/mesa/drivers/dri/i965/brw_clip.h +++ b/src/mesa/drivers/dri/i965/brw_clip.h @@ -43,6 +43,7 @@ */ struct brw_clip_prog_key { GLbitfield64 attrs; + unsigned char interpolation_mode[BRW_VERT_RESULT_MAX]; /* copy of the main context */ GLuint primitive:4; GLuint nr_userclip:4; GLuint do_flat_shading:1; diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index b4868fe..afafa47 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -1054,6 +1054,17 @@ struct brw_context uint32_t render_target_format[MESA_FORMAT_COUNT]; bool format_supported_as_render_target[MESA_FORMAT_COUNT]; + /* Interpolation modes, one byte per vue slot, values equal to + * glsl_interp_qualifier. + * + * Used on gen4/5 by the clipper, sf and wm stages. Given the + * update order, the clipper is responsible to update it. + * + * Ignored on gen 6+ + */ + + unsigned char interpolation_mode[BRW_VERT_RESULT_MAX]; + /* PrimitiveRestart */ struct { bool in_progress; diff --git a/src/mesa/drivers/dri/i965/brw_sf.c b/src/mesa/drivers/dri/i965/brw_sf.c index 791210f..26cbaf7 100644 --- a/src/mesa/drivers/dri/i965/brw_sf.c +++ b/src/mesa/drivers/dri/i965/brw_sf.c @@ -194,6 +194,9 @@ brw_upload_sf_prog(struct brw_context *brw) key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT); key.do_twoside_color = ctx->VertexProgram._TwoSideEnabled; + /* BRW_NEW_FRAGMENT_PROGRAM, _NEW_LIGHT */ + memcpy(key.interpolation_mode, brw->interpolation_mode, BRW_VERT_RESULT_MAX); + /* _NEW_POLYGON */ if (key.do_twoside_color) { /* If we're rendering to a FBO, we have to invert the polygon @@ -215,7 +218,7 @@ const struct brw_tracked_state brw_sf_prog = { .dirty = { .mesa = (_NEW_HINT | _NEW_LIGHT | _NEW_POLYGON | _NEW_POINT | _NEW_TRANSFORM | _NEW_BUFFERS), - .brw = (BRW_NEW_REDUCED_PRIMITIVE), + .brw = (BRW_NEW_FRAGMENT_PROGRAM|BRW_NEW_REDUCED_PRIMITIVE), .cache = CACHE_NEW_VS_PROG }, .emit = brw_upload_sf_prog diff --git a/src/mesa/drivers/dri/i965/brw_sf.h b/src/mesa/drivers/dri/i965/brw_sf.h index f908fc0..5e261fb 100644 --- a/src/mesa/drivers/dri/i965/brw_sf.h +++ b/src/mesa/drivers/dri/i965/brw_sf.h @@ -46,6 +46,7 @@ struct brw_sf_prog_key { GLbitfield64 attrs; + unsigned char interpolation_mode[BRW_VERT_RESULT_MAX]; /* copy of the main context */ uint8_t point_sprite_coord_replace; GLuint primitive:2; GLuint do_twoside_color:1; diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index 587cc35..b54f4b1 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -513,6 +513,8 @@ static void brw_wm_populate_key( struct brw_context *brw, /* _NEW_LIGHT */ key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT); + if (intel->gen < 6) + memcpy(key->interpolation_mode, brw->interpolation_mode, BRW_VERT_RESULT_MAX); /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */ key->clamp_fragment_color = ctx->Color._ClampFragmentColor; diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h index b976a60..add9dd6 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.h +++ b/src/mesa/drivers/dri/i965/brw_wm.h @@ -60,6 +60,7 @@ #define AA_ALWAYS 2 struct brw_wm_prog_key { + unsigned char interpolation_mode[BRW_VERT_RESULT_MAX]; /* copy of the main context */ uint8_t iz_lookup; GLuint stats_wm:1; GLuint flat_shade:1; -- 1.7.10.280.gaa39