#include "main/stencil.h"
#include "intel_batchbuffer.h"
-/**
- * Modify blend function to force destination alpha to 1.0
- *
- * If \c function specifies a blend function that uses destination alpha,
- * replace it with a function that hard-wires destination alpha to 1.0. This
- * is used when rendering to xRGB targets.
- */
-GLenum
-brw_fix_xRGB_alpha(GLenum function)
-{
- switch (function) {
- case GL_DST_ALPHA:
- return GL_ONE;
-
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_SRC_ALPHA_SATURATE:
- return GL_ZERO;
- }
-
- return function;
-}
-
-/**
- * Creates a CC unit packet from the current blend state.
- */
-static void upload_cc_unit(struct brw_context *brw)
-{
- struct gl_context *ctx = &brw->ctx;
- struct brw_cc_unit_state *cc;
-
- cc = brw_state_batch(brw, sizeof(*cc), 64, &brw->cc.state_offset);
- memset(cc, 0, sizeof(*cc));
-
- /* _NEW_STENCIL | _NEW_BUFFERS */
- if (brw->stencil_enabled) {
- const unsigned back = ctx->Stencil._BackFace;
-
- cc->cc0.stencil_enable = 1;
- cc->cc0.stencil_func =
- intel_translate_compare_func(ctx->Stencil.Function[0]);
- cc->cc0.stencil_fail_op =
- intel_translate_stencil_op(ctx->Stencil.FailFunc[0]);
- cc->cc0.stencil_pass_depth_fail_op =
- intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]);
- cc->cc0.stencil_pass_depth_pass_op =
- intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]);
- cc->cc1.stencil_ref = _mesa_get_stencil_ref(ctx, 0);
- cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0];
- cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0];
-
- if (brw->stencil_two_sided) {
- cc->cc0.bf_stencil_enable = 1;
- cc->cc0.bf_stencil_func =
- intel_translate_compare_func(ctx->Stencil.Function[back]);
- cc->cc0.bf_stencil_fail_op =
- intel_translate_stencil_op(ctx->Stencil.FailFunc[back]);
- cc->cc0.bf_stencil_pass_depth_fail_op =
- intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]);
- cc->cc0.bf_stencil_pass_depth_pass_op =
- intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]);
- cc->cc1.bf_stencil_ref = _mesa_get_stencil_ref(ctx, back);
- cc->cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back];
- cc->cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back];
- }
-
- /* Not really sure about this:
- */
- if (ctx->Stencil.WriteMask[0] ||
- (brw->stencil_two_sided && ctx->Stencil.WriteMask[back]))
- cc->cc0.stencil_write_enable = 1;
- }
-
- /* _NEW_COLOR */
- if (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY) {
- cc->cc2.logicop_enable = 1;
- cc->cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp);
- } else if (ctx->Color.BlendEnabled && !ctx->Color._AdvancedBlendMode) {
- GLenum eqRGB = ctx->Color.Blend[0].EquationRGB;
- GLenum eqA = ctx->Color.Blend[0].EquationA;
- GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
- GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
- GLenum srcA = ctx->Color.Blend[0].SrcA;
- GLenum dstA = ctx->Color.Blend[0].DstA;
-
- if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
- srcRGB = dstRGB = GL_ONE;
- }
-
- if (eqA == GL_MIN || eqA == GL_MAX) {
- srcA = dstA = GL_ONE;
- }
-
- /* If the renderbuffer is XRGB, we have to frob the blend function to
- * force the destination alpha to 1.0. This means replacing GL_DST_ALPHA
- * with GL_ONE and GL_ONE_MINUS_DST_ALPHA with GL_ZERO.
- */
- const struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
- if (rb && !_mesa_base_format_has_channel(rb->_BaseFormat,
- GL_TEXTURE_ALPHA_TYPE)) {
- srcRGB = brw_fix_xRGB_alpha(srcRGB);
- srcA = brw_fix_xRGB_alpha(srcA);
- dstRGB = brw_fix_xRGB_alpha(dstRGB);
- dstA = brw_fix_xRGB_alpha(dstA);
- }
-
- cc->cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB);
- cc->cc6.src_blend_factor = brw_translate_blend_factor(srcRGB);
- cc->cc6.blend_function = brw_translate_blend_equation(eqRGB);
-
- cc->cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
- cc->cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA);
- cc->cc5.ia_blend_function = brw_translate_blend_equation(eqA);
-
- cc->cc3.blend_enable = 1;
- cc->cc3.ia_blend_enable = (srcA != srcRGB ||
- dstA != dstRGB ||
- eqA != eqRGB);
- }
-
- /* _NEW_BUFFERS */
- if (ctx->Color.AlphaEnabled && ctx->DrawBuffer->_NumColorDrawBuffers <= 1) {
- cc->cc3.alpha_test = 1;
- cc->cc3.alpha_test_func =
- intel_translate_compare_func(ctx->Color.AlphaFunc);
- cc->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
-
- UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef);
- }
-
- if (ctx->Color.DitherFlag) {
- cc->cc5.dither_enable = 1;
- cc->cc6.y_dither_offset = 0;
- cc->cc6.x_dither_offset = 0;
- }
-
- /* _NEW_DEPTH */
- if (ctx->Depth.Test) {
- cc->cc2.depth_test = 1;
- cc->cc2.depth_test_function =
- intel_translate_compare_func(ctx->Depth.Func);
- cc->cc2.depth_write_enable = brw_depth_writes_enabled(brw);
- }
-
- if (brw->stats_wm)
- cc->cc5.statistics_enable = 1;
-
- /* BRW_NEW_CC_VP */
- cc->cc4.cc_viewport_state_offset = (brw->batch.bo->offset64 +
- brw->cc.vp_offset) >> 5; /* reloc */
-
- brw->ctx.NewDriverState |= BRW_NEW_GEN4_UNIT_STATE;
-
- /* Emit CC viewport relocation */
- brw_emit_reloc(&brw->batch,
- (brw->cc.state_offset +
- offsetof(struct brw_cc_unit_state, cc4)),
- brw->batch.bo, brw->cc.vp_offset,
- I915_GEM_DOMAIN_INSTRUCTION, 0);
-}
-
-const struct brw_tracked_state brw_cc_unit = {
- .dirty = {
- .mesa = _NEW_BUFFERS |
- _NEW_COLOR |
- _NEW_DEPTH |
- _NEW_STENCIL,
- .brw = BRW_NEW_BATCH |
- BRW_NEW_BLORP |
- BRW_NEW_CC_VP |
- BRW_NEW_STATS_WM,
- },
- .emit = upload_cc_unit,
-};
-
static void upload_blend_constant_color(struct brw_context *brw)
{
struct gl_context *ctx = &brw->ctx;
enum intel_msaa_layout;
extern const struct brw_tracked_state brw_blend_constant_color;
-extern const struct brw_tracked_state brw_cc_unit;
extern const struct brw_tracked_state brw_clip_unit;
extern const struct brw_tracked_state brw_vs_pull_constants;
extern const struct brw_tracked_state brw_tcs_pull_constants;
float viewport_ymax;
};
-struct brw_cc_unit_state
-{
- struct
- {
- unsigned pad0:3;
- unsigned bf_stencil_pass_depth_pass_op:3;
- unsigned bf_stencil_pass_depth_fail_op:3;
- unsigned bf_stencil_fail_op:3;
- unsigned bf_stencil_func:3;
- unsigned bf_stencil_enable:1;
- unsigned pad1:2;
- unsigned stencil_write_enable:1;
- unsigned stencil_pass_depth_pass_op:3;
- unsigned stencil_pass_depth_fail_op:3;
- unsigned stencil_fail_op:3;
- unsigned stencil_func:3;
- unsigned stencil_enable:1;
- } cc0;
-
-
- struct
- {
- unsigned bf_stencil_ref:8;
- unsigned stencil_write_mask:8;
- unsigned stencil_test_mask:8;
- unsigned stencil_ref:8;
- } cc1;
-
-
- struct
- {
- unsigned logicop_enable:1;
- unsigned pad0:10;
- unsigned depth_write_enable:1;
- unsigned depth_test_function:3;
- unsigned depth_test:1;
- unsigned bf_stencil_write_mask:8;
- unsigned bf_stencil_test_mask:8;
- } cc2;
-
-
- struct
- {
- unsigned pad0:8;
- unsigned alpha_test_func:3;
- unsigned alpha_test:1;
- unsigned blend_enable:1;
- unsigned ia_blend_enable:1;
- unsigned pad1:1;
- unsigned alpha_test_format:1;
- unsigned pad2:16;
- } cc3;
-
- struct
- {
- unsigned pad0:5;
- unsigned cc_viewport_state_offset:27; /* Offset from GENERAL_STATE_BASE */
- } cc4;
-
- struct
- {
- unsigned pad0:2;
- unsigned ia_dest_blend_factor:5;
- unsigned ia_src_blend_factor:5;
- unsigned ia_blend_function:3;
- unsigned statistics_enable:1;
- unsigned logicop_func:4;
- unsigned pad1:11;
- unsigned dither_enable:1;
- } cc5;
-
- struct
- {
- unsigned clamp_post_alpha_blend:1;
- unsigned clamp_pre_alpha_blend:1;
- unsigned clamp_range:2;
- unsigned pad0:11;
- unsigned y_dither_offset:2;
- unsigned x_dither_offset:2;
- unsigned dest_blend_factor:5;
- unsigned src_blend_factor:5;
- unsigned blend_function:3;
- } cc6;
-
- struct {
- union {
- float f;
- uint8_t ub[4];
- } alpha_ref;
- } cc7;
-};
-
struct brw_gs_unit_state
{
struct thread0 thread0;
extern GLuint brw_translate_blend_factor( GLenum factor );
extern GLuint brw_translate_blend_equation( GLenum mode );
-extern GLenum brw_fix_xRGB_alpha(GLenum function);
static inline float
brw_get_line_width(struct brw_context *brw)
intel_translate_stencil_op(stencil->ZFailFunc[b]);
}
-#if GEN_GEN >= 9
+#if GEN_GEN <= 5 || GEN_GEN >= 9
ds->StencilReferenceValue = _mesa_get_stencil_ref(ctx, 0);
ds->BackfaceStencilReferenceValue = _mesa_get_stencil_ref(ctx, b);
#endif
#define blend_factor(x) brw_translate_blend_factor(x)
#define blend_eqn(x) brw_translate_blend_equation(x)
+/**
+ * Modify blend function to force destination alpha to 1.0
+ *
+ * If \c function specifies a blend function that uses destination alpha,
+ * replace it with a function that hard-wires destination alpha to 1.0. This
+ * is used when rendering to xRGB targets.
+ */
+static GLenum
+brw_fix_xRGB_alpha(GLenum function)
+{
+ switch (function) {
+ case GL_DST_ALPHA:
+ return GL_ONE;
+
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ return GL_ZERO;
+ }
+
+ return function;
+}
+
#if GEN_GEN >= 6
typedef struct GENX(BLEND_STATE_ENTRY) BLEND_ENTRY_GENXML;
#else
*/
const bool integer = ctx->DrawBuffer->_IntegerBuffers & (0x1 << i);
+ const unsigned blend_enabled = GEN_GEN >= 6 ?
+ ctx->Color.BlendEnabled & (1 << i) : ctx->Color.BlendEnabled;
+
/* _NEW_COLOR */
if (ctx->Color.ColorLogicOpEnabled) {
GLenum rb_type = rb ? _mesa_get_format_datatype(rb->Format)
entry->LogicOpFunction =
intel_translate_logic_op(ctx->Color.LogicOp);
}
- } else if (ctx->Color.BlendEnabled & (1 << i) && !integer &&
- !ctx->Color._AdvancedBlendMode) {
+ } else if (blend_enabled && !ctx->Color._AdvancedBlendMode
+ && (GEN_GEN <= 5 || !integer)) {
GLenum eqRGB = ctx->Color.Blend[i].EquationRGB;
GLenum eqA = ctx->Color.Blend[i].EquationA;
GLenum srcRGB = ctx->Color.Blend[i].SrcRGB;
/* ---------------------------------------------------------------------- */
-#if GEN_GEN >= 6
static void
genX(upload_color_calc_state)(struct brw_context *brw)
{
struct gl_context *ctx = &brw->ctx;
brw_state_emit(brw, GENX(COLOR_CALC_STATE), 64, &brw->cc.state_offset, cc) {
+#if GEN_GEN <= 5
+ cc.IndependentAlphaBlendEnable =
+ set_blend_entry_bits(brw, &cc, 0, false);
+ set_depth_stencil_bits(brw, &cc);
+
+ if (ctx->Color.AlphaEnabled &&
+ ctx->DrawBuffer->_NumColorDrawBuffers <= 1) {
+ cc.AlphaTestEnable = true;
+ cc.AlphaTestFunction =
+ intel_translate_compare_func(ctx->Color.AlphaFunc);
+ }
+
+ cc.ColorDitherEnable = ctx->Color.DitherFlag;
+
+ cc.StatisticsEnable = brw->stats_wm;
+
+ cc.CCViewportStatePointer =
+ instruction_ro_bo(brw->batch.bo, brw->cc.vp_offset);
+#else
/* _NEW_COLOR */
- cc.AlphaTestFormat = ALPHATEST_UNORM8;
- UNCLAMPED_FLOAT_TO_UBYTE(cc.AlphaReferenceValueAsUNORM8,
- ctx->Color.AlphaRef);
+ cc.BlendConstantColorRed = ctx->Color.BlendColorUnclamped[0];
+ cc.BlendConstantColorGreen = ctx->Color.BlendColorUnclamped[1];
+ cc.BlendConstantColorBlue = ctx->Color.BlendColorUnclamped[2];
+ cc.BlendConstantColorAlpha = ctx->Color.BlendColorUnclamped[3];
#if GEN_GEN < 9
/* _NEW_STENCIL */
cc.StencilReferenceValue = _mesa_get_stencil_ref(ctx, 0);
cc.BackfaceStencilReferenceValue =
_mesa_get_stencil_ref(ctx, ctx->Stencil._BackFace);
+#endif
+
#endif
/* _NEW_COLOR */
- cc.BlendConstantColorRed = ctx->Color.BlendColorUnclamped[0];
- cc.BlendConstantColorGreen = ctx->Color.BlendColorUnclamped[1];
- cc.BlendConstantColorBlue = ctx->Color.BlendColorUnclamped[2];
- cc.BlendConstantColorAlpha = ctx->Color.BlendColorUnclamped[3];
+ UNCLAMPED_FLOAT_TO_UBYTE(cc.AlphaReferenceValueAsUNORM8,
+ ctx->Color.AlphaRef);
}
+#if GEN_GEN >= 6
brw_batch_emit(brw, GENX(3DSTATE_CC_STATE_POINTERS), ptr) {
ptr.ColorCalcStatePointer = brw->cc.state_offset;
#if GEN_GEN != 7
ptr.ColorCalcStatePointerValid = true;
#endif
}
+#else
+ brw->ctx.NewDriverState |= BRW_NEW_GEN4_UNIT_STATE;
+#endif
}
static const struct brw_tracked_state genX(color_calc_state) = {
.dirty = {
.mesa = _NEW_COLOR |
- _NEW_STENCIL,
+ _NEW_STENCIL |
+ (GEN_GEN <= 5 ? _NEW_BUFFERS |
+ _NEW_DEPTH
+ : 0),
.brw = BRW_NEW_BATCH |
BRW_NEW_BLORP |
- BRW_NEW_CC_STATE |
- BRW_NEW_STATE_BASE_ADDRESS,
+ (GEN_GEN <= 5 ? BRW_NEW_CC_VP |
+ BRW_NEW_STATS_WM
+ : BRW_NEW_CC_STATE |
+ BRW_NEW_STATE_BASE_ADDRESS),
},
.emit = genX(upload_color_calc_state),
};
-#endif
/* ---------------------------------------------------------------------- */
&brw_recalculate_urb_fence,
&genX(cc_vp),
- &brw_cc_unit,
+ &genX(color_calc_state),
/* Surface state setup. Must come before the VS/WM unit. The binding
* table upload must be last.