diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index a013aa127ee..6f6613cd807 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -480,7 +480,7 @@ brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key) /* _NEW_COLOR */ key->force_dual_color_blend = brw->dual_color_blend_by_location && - (ctx->Color.BlendEnabled & 1) && ctx->Color.Blend[0]._UsesDualSrc; + (ctx->Color.BlendEnabled & 1) && ctx->Color._BlendUsesDualSrc & 0x1; /* _NEW_MULTISAMPLE, _NEW_BUFFERS */ key->alpha_to_coverage = _mesa_is_alpha_to_coverage_enabled(ctx); diff --git a/src/mesa/drivers/dri/i965/genX_state_upload.c b/src/mesa/drivers/dri/i965/genX_state_upload.c index 65b1d82d09c..49aa197fcb3 100644 --- a/src/mesa/drivers/dri/i965/genX_state_upload.c +++ b/src/mesa/drivers/dri/i965/genX_state_upload.c @@ -1942,7 +1942,7 @@ genX(upload_wm)(struct brw_context *brw) #if GEN_GEN == 6 wm.DualSourceBlendEnable = wm_prog_data->dual_src_blend && (ctx->Color.BlendEnabled & 1) && - ctx->Color.Blend[0]._UsesDualSrc; + ctx->Color._BlendUsesDualSrc & 0x1; wm.oMaskPresenttoRenderTarget = wm_prog_data->uses_omask; wm.NumberofSFOutputAttributes = wm_prog_data->num_varying_inputs; @@ -2885,7 +2885,7 @@ set_blend_entry_bits(struct brw_context *brw, BLEND_ENTRY_GENXML *entry, int i, * We override SRC1_ALPHA to ONE and ONE_MINUS_SRC1_ALPHA to ZERO, * and leave it enabled anyway. */ - if (GEN_GEN >= 6 && ctx->Color.Blend[i]._UsesDualSrc && alpha_to_one) { + if (GEN_GEN >= 6 && ctx->Color._BlendUsesDualSrc & (1 << i) && alpha_to_one) { srcRGB = fix_dual_blend_alpha_to_one(srcRGB); srcA = fix_dual_blend_alpha_to_one(srcA); dstRGB = fix_dual_blend_alpha_to_one(dstRGB); @@ -2910,7 +2910,7 @@ set_blend_entry_bits(struct brw_context *brw, BLEND_ENTRY_GENXML *entry, int i, * so we just disable the blending to prevent possible issues. */ entry->ColorBufferBlendEnable = - !ctx->Color.Blend[0]._UsesDualSrc || wm_prog_data->dual_src_blend; + !(ctx->Color._BlendUsesDualSrc & 0x1) || wm_prog_data->dual_src_blend; entry->DestinationBlendFactor = blend_factor(dstRGB); entry->SourceBlendFactor = blend_factor(srcRGB); @@ -3926,7 +3926,7 @@ genX(upload_ps)(struct brw_context *brw) */ ps.DualSourceBlendEnable = prog_data->dual_src_blend && (ctx->Color.BlendEnabled & 1) && - ctx->Color.Blend[0]._UsesDualSrc; + ctx->Color._BlendUsesDualSrc & 0x1; /* BRW_NEW_FS_PROG_DATA */ ps.AttributeEnable = (prog_data->num_varying_inputs != 0); @@ -4818,7 +4818,7 @@ genX(upload_ps_blend)(struct brw_context *brw) /* Alpha to One doesn't work with Dual Color Blending. Override * SRC1_ALPHA to ONE and ONE_MINUS_SRC1_ALPHA to ZERO. */ - if (alpha_to_one && color->Blend[0]._UsesDualSrc) { + if (alpha_to_one && color->_BlendUsesDualSrc & 0x1) { srcRGB = fix_dual_blend_alpha_to_one(srcRGB); srcA = fix_dual_blend_alpha_to_one(srcA); dstRGB = fix_dual_blend_alpha_to_one(dstRGB); @@ -4843,7 +4843,7 @@ genX(upload_ps_blend)(struct brw_context *brw) * so we just disable the blending to prevent possible issues. */ pb.ColorBufferBlendEnable = - !color->Blend[0]._UsesDualSrc || wm_prog_data->dual_src_blend; + !(color->_BlendUsesDualSrc & 0x1) || wm_prog_data->dual_src_blend; pb.SourceAlphaBlendFactor = brw_translate_blend_factor(srcA); pb.DestinationAlphaBlendFactor = brw_translate_blend_factor(dstA); pb.SourceBlendFactor = brw_translate_blend_factor(srcRGB); diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c index 5bf1e42dda2..c622ea00b91 100644 --- a/src/mesa/main/blend.c +++ b/src/mesa/main/blend.c @@ -168,7 +168,7 @@ blend_factor_is_dual_src(GLenum factor) factor == GL_ONE_MINUS_SRC1_ALPHA); } -static void +static bool update_uses_dual_src(struct gl_context *ctx, int buf) { bool uses_dual_src = @@ -177,10 +177,14 @@ update_uses_dual_src(struct gl_context *ctx, int buf) blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcA) || blend_factor_is_dual_src(ctx->Color.Blend[buf].DstA)); - if (ctx->Color.Blend[buf]._UsesDualSrc != uses_dual_src) { - ctx->Color.Blend[buf]._UsesDualSrc = uses_dual_src; - _mesa_update_valid_to_render_state(ctx); + if (((ctx->Color._BlendUsesDualSrc >> buf) & 0x1) != uses_dual_src) { + if (uses_dual_src) + ctx->Color._BlendUsesDualSrc |= 1 << buf; + else + ctx->Color._BlendUsesDualSrc &= ~(1 << buf); + return true; /* changed state */ } + return false; /* no change */ } @@ -247,10 +251,16 @@ blend_func_separate(struct gl_context *ctx, ctx->Color.Blend[buf].DstA = dfactorA; } + GLbitfield old_blend_uses_dual_src = ctx->Color._BlendUsesDualSrc; update_uses_dual_src(ctx, 0); - for (unsigned buf = 1; buf < numBuffers; buf++) { - ctx->Color.Blend[buf]._UsesDualSrc = ctx->Color.Blend[0]._UsesDualSrc; - } + /* We have to replicate the bit to all color buffers. */ + if (ctx->Color._BlendUsesDualSrc & 0x1) + ctx->Color._BlendUsesDualSrc |= BITFIELD_RANGE(1, numBuffers - 1); + else + ctx->Color._BlendUsesDualSrc = 0; + + if (ctx->Color._BlendUsesDualSrc != old_blend_uses_dual_src) + _mesa_update_valid_to_render_state(ctx); ctx->Color._BlendFuncPerBuffer = GL_FALSE; @@ -404,7 +414,8 @@ blend_func_separatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB, ctx->Color.Blend[buf].DstRGB = dfactorRGB; ctx->Color.Blend[buf].SrcA = sfactorA; ctx->Color.Blend[buf].DstA = dfactorA; - update_uses_dual_src(ctx, buf); + if (update_uses_dual_src(ctx, buf)) + _mesa_update_valid_to_render_state(ctx); ctx->Color._BlendFuncPerBuffer = GL_TRUE; } diff --git a/src/mesa/main/draw_validate.c b/src/mesa/main/draw_validate.c index 77ea39dd6bc..1003ddcf918 100644 --- a/src/mesa/main/draw_validate.c +++ b/src/mesa/main/draw_validate.c @@ -96,11 +96,14 @@ _mesa_update_valid_to_render_state(struct gl_context *ctx) * has more than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active * color attachements." */ - for (unsigned i = ctx->Const.MaxDualSourceDrawBuffers; - i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { - if (ctx->Color.Blend[i]._UsesDualSrc) - return; - } + unsigned max_dual_source_buffers = ctx->Const.MaxDualSourceDrawBuffers; + unsigned num_color_buffers = ctx->DrawBuffer->_NumColorDrawBuffers; + + if (num_color_buffers > max_dual_source_buffers && + ctx->Color._BlendUsesDualSrc & + BITFIELD_RANGE(max_dual_source_buffers, + num_color_buffers - max_dual_source_buffers)) + return; if (ctx->Color.BlendEnabled && ctx->Color._AdvancedBlendMode != BLEND_NONE) { @@ -119,7 +122,7 @@ _mesa_update_valid_to_render_state(struct gl_context *ctx) if (ctx->DrawBuffer->ColorDrawBuffer[0] == GL_FRONT_AND_BACK) return; - for (unsigned i = 1; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { + for (unsigned i = 1; i < num_color_buffers; i++) { if (ctx->DrawBuffer->ColorDrawBuffer[i] != GL_NONE) return; } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 93f58956a1c..a6846cf76f1 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -399,12 +399,9 @@ struct gl_colorbuffer_attrib GLenum16 DstA; /**< Alpha blend dest term */ GLenum16 EquationRGB; /**< GL_ADD, GL_SUBTRACT, etc. */ GLenum16 EquationA; /**< GL_ADD, GL_SUBTRACT, etc. */ - /** - * Set if any blend factor uses SRC1. Computed at the time blend factors - * get set. - */ - GLboolean _UsesDualSrc; } Blend[MAX_DRAW_BUFFERS]; + /** Bitfield of color buffers with enabled dual source blending. */ + GLbitfield _BlendUsesDualSrc; /** Are the blend func terms currently different for each buffer/target? */ GLboolean _BlendFuncPerBuffer; /** Are the blend equations currently different for each buffer/target? */