#include "brw_defines.h"
#include "brw_util.h"
#include "main/macros.h"
-#include "main/enums.h"
+#include "intel_batchbuffer.h"
-static void prepare_cc_vp( struct brw_context *brw )
+void
+brw_update_cc_vp(struct brw_context *brw)
{
- GLcontext *ctx = &brw->intel.ctx;
+ struct gl_context *ctx = &brw->intel.ctx;
struct brw_cc_viewport ccv;
memset(&ccv, 0, sizeof(ccv));
- /* _NEW_VIEWPORT */
- ccv.min_depth = ctx->Viewport.Near;
- ccv.max_depth = ctx->Viewport.Far;
+ /* _NEW_TRANSOFORM */
+ if (ctx->Transform.DepthClamp) {
+ /* _NEW_VIEWPORT */
+ ccv.min_depth = MIN2(ctx->Viewport.Near, ctx->Viewport.Far);
+ ccv.max_depth = MAX2(ctx->Viewport.Near, ctx->Viewport.Far);
+ } else {
+ ccv.min_depth = 0.0;
+ ccv.max_depth = 1.0;
+ }
- dri_bo_unreference(brw->cc.vp_bo);
- brw->cc.vp_bo = brw_cache_data( &brw->cache, BRW_CC_VP, &ccv, NULL, 0 );
+ drm_intel_bo_unreference(brw->cc.vp_bo);
+ brw->cc.vp_bo = brw_cache_data(&brw->cache, BRW_CC_VP, &ccv, sizeof(ccv));
}
-const struct brw_tracked_state brw_cc_vp = {
- .dirty = {
- .mesa = _NEW_VIEWPORT,
- .brw = BRW_NEW_CONTEXT,
- .cache = 0
- },
- .prepare = prepare_cc_vp
-};
-
-struct brw_cc_unit_key {
- GLboolean stencil, stencil_two_side, color_blend, alpha_enabled;
-
- GLenum stencil_func[2], stencil_fail_op[2];
- GLenum stencil_pass_depth_fail_op[2], stencil_pass_depth_pass_op[2];
- GLubyte stencil_ref[2], stencil_write_mask[2], stencil_test_mask[2];
- GLenum logic_op;
-
- GLenum blend_eq_rgb, blend_eq_a;
- GLenum blend_src_rgb, blend_src_a;
- GLenum blend_dst_rgb, blend_dst_a;
-
- GLenum alpha_func;
- GLclampf alpha_ref;
-
- GLboolean dither;
-
- GLboolean depth_test, depth_write;
- GLenum depth_func;
-};
-
-static void
-cc_unit_populate_key(struct brw_context *brw, struct brw_cc_unit_key *key)
+/**
+ * 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
+fix_xRGB_alpha(GLenum function)
{
- GLcontext *ctx = &brw->intel.ctx;
- const unsigned back = ctx->Stencil._BackFace;
-
- memset(key, 0, sizeof(*key));
-
- key->stencil = ctx->Stencil._Enabled;
- key->stencil_two_side = ctx->Stencil._TestTwoSide;
-
- if (key->stencil) {
- key->stencil_func[0] = ctx->Stencil.Function[0];
- key->stencil_fail_op[0] = ctx->Stencil.FailFunc[0];
- key->stencil_pass_depth_fail_op[0] = ctx->Stencil.ZFailFunc[0];
- key->stencil_pass_depth_pass_op[0] = ctx->Stencil.ZPassFunc[0];
- key->stencil_ref[0] = ctx->Stencil.Ref[0];
- key->stencil_write_mask[0] = ctx->Stencil.WriteMask[0];
- key->stencil_test_mask[0] = ctx->Stencil.ValueMask[0];
- }
- if (key->stencil_two_side) {
- key->stencil_func[1] = ctx->Stencil.Function[back];
- key->stencil_fail_op[1] = ctx->Stencil.FailFunc[back];
- key->stencil_pass_depth_fail_op[1] = ctx->Stencil.ZFailFunc[back];
- key->stencil_pass_depth_pass_op[1] = ctx->Stencil.ZPassFunc[back];
- key->stencil_ref[1] = ctx->Stencil.Ref[back];
- key->stencil_write_mask[1] = ctx->Stencil.WriteMask[back];
- key->stencil_test_mask[1] = ctx->Stencil.ValueMask[back];
- }
+ switch (function) {
+ case GL_DST_ALPHA:
+ return GL_ONE;
- if (ctx->Color._LogicOpEnabled)
- key->logic_op = ctx->Color.LogicOp;
- else
- key->logic_op = GL_COPY;
-
- key->color_blend = ctx->Color.BlendEnabled;
- if (key->color_blend) {
- key->blend_eq_rgb = ctx->Color.BlendEquationRGB;
- key->blend_eq_a = ctx->Color.BlendEquationA;
- key->blend_src_rgb = ctx->Color.BlendSrcRGB;
- key->blend_dst_rgb = ctx->Color.BlendDstRGB;
- key->blend_src_a = ctx->Color.BlendSrcA;
- key->blend_dst_a = ctx->Color.BlendDstA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ return GL_ZERO;
}
- key->alpha_enabled = ctx->Color.AlphaEnabled;
- if (key->alpha_enabled) {
- key->alpha_func = ctx->Color.AlphaFunc;
- key->alpha_ref = ctx->Color.AlphaRef;
- }
-
- key->dither = ctx->Color.DitherFlag;
+ return function;
+}
- key->depth_test = ctx->Depth.Test;
- if (key->depth_test) {
- key->depth_func = ctx->Depth.Func;
- key->depth_write = ctx->Depth.Mask;
- }
+static void prepare_cc_unit(struct brw_context *brw)
+{
+ brw_add_validated_bo(brw, brw->cc.vp_bo);
}
/**
* Creates the state cache entry for the given CC unit key.
*/
-static dri_bo *
-cc_unit_create_from_key(struct brw_context *brw, struct brw_cc_unit_key *key)
+static void upload_cc_unit(struct brw_context *brw)
{
- struct brw_cc_unit_state cc;
- dri_bo *bo;
+ struct intel_context *intel = &brw->intel;
+ struct gl_context *ctx = &brw->intel.ctx;
+ struct brw_cc_unit_state *cc;
- memset(&cc, 0, sizeof(cc));
+ cc = brw_state_batch(brw, sizeof(*cc), 64, &brw->cc.state_offset);
+ memset(cc, 0, sizeof(*cc));
/* _NEW_STENCIL */
- if (key->stencil) {
- cc.cc0.stencil_enable = 1;
- cc.cc0.stencil_func =
- intel_translate_compare_func(key->stencil_func[0]);
- cc.cc0.stencil_fail_op =
- intel_translate_stencil_op(key->stencil_fail_op[0]);
- cc.cc0.stencil_pass_depth_fail_op =
- intel_translate_stencil_op(key->stencil_pass_depth_fail_op[0]);
- cc.cc0.stencil_pass_depth_pass_op =
- intel_translate_stencil_op(key->stencil_pass_depth_pass_op[0]);
- cc.cc1.stencil_ref = key->stencil_ref[0];
- cc.cc1.stencil_write_mask = key->stencil_write_mask[0];
- cc.cc1.stencil_test_mask = key->stencil_test_mask[0];
-
- if (key->stencil_two_side) {
- cc.cc0.bf_stencil_enable = 1;
- cc.cc0.bf_stencil_func =
- intel_translate_compare_func(key->stencil_func[1]);
- cc.cc0.bf_stencil_fail_op =
- intel_translate_stencil_op(key->stencil_fail_op[1]);
- cc.cc0.bf_stencil_pass_depth_fail_op =
- intel_translate_stencil_op(key->stencil_pass_depth_fail_op[1]);
- cc.cc0.bf_stencil_pass_depth_pass_op =
- intel_translate_stencil_op(key->stencil_pass_depth_pass_op[1]);
- cc.cc1.bf_stencil_ref = key->stencil_ref[1];
- cc.cc2.bf_stencil_write_mask = key->stencil_write_mask[1];
- cc.cc2.bf_stencil_test_mask = key->stencil_test_mask[1];
+ if (ctx->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 = ctx->Stencil.Ref[0];
+ cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0];
+ cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0];
+
+ if (ctx->Stencil._TestTwoSide) {
+ 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 = ctx->Stencil.Ref[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 (key->stencil_write_mask[0] ||
- (key->stencil_two_side && key->stencil_write_mask[1]))
- cc.cc0.stencil_write_enable = 1;
+ if (ctx->Stencil.WriteMask[0] ||
+ (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back]))
+ cc->cc0.stencil_write_enable = 1;
}
/* _NEW_COLOR */
- if (key->logic_op != GL_COPY) {
- cc.cc2.logicop_enable = 1;
- cc.cc5.logicop_func = intel_translate_logic_op(key->logic_op);
- } else if (key->color_blend) {
- GLenum eqRGB = key->blend_eq_rgb;
- GLenum eqA = key->blend_eq_a;
- GLenum srcRGB = key->blend_src_rgb;
- GLenum dstRGB = key->blend_dst_rgb;
- GLenum srcA = key->blend_src_a;
- GLenum dstA = key->blend_dst_a;
+ if (ctx->Color._LogicOpEnabled && 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) {
+ 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 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.
+ */
+ if (ctx->DrawBuffer->Visual.alphaBits == 0) {
+ srcRGB = fix_xRGB_alpha(srcRGB);
+ srcA = fix_xRGB_alpha(srcA);
+ dstRGB = fix_xRGB_alpha(dstRGB);
+ dstA = fix_xRGB_alpha(dstA);
+ }
if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
srcRGB = dstRGB = GL_ONE;
srcA = dstA = GL_ONE;
}
- 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->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->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 ||
+ cc->cc3.blend_enable = 1;
+ cc->cc3.ia_blend_enable = (srcA != srcRGB ||
dstA != dstRGB ||
eqA != eqRGB);
}
- if (key->alpha_enabled) {
- cc.cc3.alpha_test = 1;
- cc.cc3.alpha_test_func = intel_translate_compare_func(key->alpha_func);
- cc.cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8;
+ if (ctx->Color.AlphaEnabled) {
+ 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], key->alpha_ref);
+ UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef);
}
- if (key->dither) {
- cc.cc5.dither_enable = 1;
- cc.cc6.y_dither_offset = 0;
- cc.cc6.x_dither_offset = 0;
+ if (ctx->Color.DitherFlag) {
+ cc->cc5.dither_enable = 1;
+ cc->cc6.y_dither_offset = 0;
+ cc->cc6.x_dither_offset = 0;
}
/* _NEW_DEPTH */
- if (key->depth_test) {
- cc.cc2.depth_test = 1;
- cc.cc2.depth_test_function = intel_translate_compare_func(key->depth_func);
- cc.cc2.depth_write_enable = key->depth_write;
+ 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 = ctx->Depth.Mask;
}
- /* CACHE_NEW_CC_VP */
- cc.cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */
+ if (intel->stats_wm || unlikely(INTEL_DEBUG & DEBUG_STATS))
+ cc->cc5.statistics_enable = 1;
- if (INTEL_DEBUG & DEBUG_STATS)
- cc.cc5.statistics_enable = 1;
+ /* CACHE_NEW_CC_VP */
+ cc->cc4.cc_viewport_state_offset = brw->cc.vp_bo->offset >> 5; /* reloc */
- bo = brw_upload_cache(&brw->cache, BRW_CC_UNIT,
- key, sizeof(*key),
- &brw->cc.vp_bo, 1,
- &cc, sizeof(cc),
- NULL, NULL);
+ brw->state.dirty.cache |= CACHE_NEW_CC_UNIT;
/* Emit CC viewport relocation */
- dri_bo_emit_reloc(bo,
- I915_GEM_DOMAIN_INSTRUCTION,
- 0,
- 0,
- offsetof(struct brw_cc_unit_state, cc4),
- brw->cc.vp_bo);
-
- return bo;
-}
-
-static void prepare_cc_unit( struct brw_context *brw )
-{
- struct brw_cc_unit_key key;
-
- cc_unit_populate_key(brw, &key);
-
- dri_bo_unreference(brw->cc.state_bo);
- brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_CC_UNIT,
- &key, sizeof(key),
- &brw->cc.vp_bo, 1,
- NULL);
-
- if (brw->cc.state_bo == NULL)
- brw->cc.state_bo = cc_unit_create_from_key(brw, &key);
+ drm_intel_bo_emit_reloc(brw->intel.batch.bo,
+ (brw->cc.state_offset +
+ offsetof(struct brw_cc_unit_state, cc4)),
+ brw->cc.vp_bo, 0,
+ I915_GEM_DOMAIN_INSTRUCTION, 0);
}
const struct brw_tracked_state brw_cc_unit = {
.dirty = {
.mesa = _NEW_STENCIL | _NEW_COLOR | _NEW_DEPTH,
- .brw = 0,
+ .brw = BRW_NEW_BATCH,
.cache = CACHE_NEW_CC_VP
},
.prepare = prepare_cc_unit,
+ .emit = upload_cc_unit,
};
+static void upload_blend_constant_color(struct brw_context *brw)
+{
+ struct intel_context *intel = &brw->intel;
+ struct gl_context *ctx = &intel->ctx;
+
+ BEGIN_BATCH(5);
+ OUT_BATCH(_3DSTATE_BLEND_CONSTANT_COLOR << 16 | (5-2));
+ OUT_BATCH_F(ctx->Color.BlendColor[0]);
+ OUT_BATCH_F(ctx->Color.BlendColor[1]);
+ OUT_BATCH_F(ctx->Color.BlendColor[2]);
+ OUT_BATCH_F(ctx->Color.BlendColor[3]);
+ CACHED_BATCH();
+}
-
+const struct brw_tracked_state brw_blend_constant_color = {
+ .dirty = {
+ .mesa = _NEW_COLOR,
+ .brw = BRW_NEW_CONTEXT,
+ .cache = 0
+ },
+ .emit = upload_blend_constant_color
+};