summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Antognolli <[email protected]>2017-03-27 15:52:10 -0700
committerKenneth Graunke <[email protected]>2017-05-03 18:57:52 -0700
commit98cce55317de58114fd84af77e3c3e5af3d180f9 (patch)
tree06c28beb5c557bb45162fd131efa1b0ab1ca053d
parentbc1ff4509dea8fe0a324f85df1cc2c48a50b2484 (diff)
i965: Port gen6+ blend state code to genxml.
Upload blend states using GENX(BLEND_STATE_ENTRY_pack), generated from genxml. v3: - style fixes (Ken) - cleanup to remove excessive #ifdef's (Ken) - remove memset (Ken) - disable blend.AlphaToCoverageDitherEnable on gen6 (Ken) Signed-off-by: Rafael Antognolli <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r--src/mesa/drivers/dri/i965/Makefile.sources1
-rw-r--r--src/mesa/drivers/dri/i965/brw_state.h3
-rw-r--r--src/mesa/drivers/dri/i965/gen6_cc.c216
-rw-r--r--src/mesa/drivers/dri/i965/gen8_blend_state.c298
-rw-r--r--src/mesa/drivers/dri/i965/genX_state_upload.c316
5 files changed, 312 insertions, 522 deletions
diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources
index 3f0c66a7221..0c671707345 100644
--- a/src/mesa/drivers/dri/i965/Makefile.sources
+++ b/src/mesa/drivers/dri/i965/Makefile.sources
@@ -99,7 +99,6 @@ i965_FILES = \
gen7_te_state.c \
gen7_urb.c \
gen7_wm_surface_state.c \
- gen8_blend_state.c \
gen8_depth_state.c \
gen8_draw_upload.c \
gen8_multisample_state.c \
diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h
index b6e8abc4f66..cf043a027a4 100644
--- a/src/mesa/drivers/dri/i965/brw_state.h
+++ b/src/mesa/drivers/dri/i965/brw_state.h
@@ -108,7 +108,6 @@ extern const struct brw_tracked_state brw_index_buffer;
extern const struct brw_tracked_state brw_cs_state;
extern const struct brw_tracked_state gen7_cs_push_constants;
extern const struct brw_tracked_state gen6_binding_table_pointers;
-extern const struct brw_tracked_state gen6_blend_state;
extern const struct brw_tracked_state gen6_color_calc_state;
extern const struct brw_tracked_state gen6_gs_push_constants;
extern const struct brw_tracked_state gen6_gs_binding_table;
@@ -130,11 +129,9 @@ extern const struct brw_tracked_state gen7_te_state;
extern const struct brw_tracked_state gen7_tes_push_constants;
extern const struct brw_tracked_state gen7_urb;
extern const struct brw_tracked_state haswell_cut_index;
-extern const struct brw_tracked_state gen8_blend_state;
extern const struct brw_tracked_state gen8_index_buffer;
extern const struct brw_tracked_state gen8_multisample_state;
extern const struct brw_tracked_state gen8_pma_fix;
-extern const struct brw_tracked_state gen8_ps_blend;
extern const struct brw_tracked_state gen8_vertices;
extern const struct brw_tracked_state gen8_vf_topology;
extern const struct brw_tracked_state brw_cs_work_groups_surface;
diff --git a/src/mesa/drivers/dri/i965/gen6_cc.c b/src/mesa/drivers/dri/i965/gen6_cc.c
index 0e0d05e8146..688362fcc59 100644
--- a/src/mesa/drivers/dri/i965/gen6_cc.c
+++ b/src/mesa/drivers/dri/i965/gen6_cc.c
@@ -36,222 +36,6 @@
#include "main/stencil.h"
static void
-gen6_upload_blend_state(struct brw_context *brw)
-{
- bool is_buffer_zero_integer_format = false;
- struct gl_context *ctx = &brw->ctx;
- struct gen6_blend_state *blend;
- int b;
- int nr_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
- int size;
-
- /* We need at least one BLEND_STATE written, because we might do
- * thread dispatch even if _NumColorDrawBuffers is 0 (for example
- * for computed depth or alpha test), which will do an FB write
- * with render target 0, which will reference BLEND_STATE[0] for
- * alpha test enable.
- */
- if (nr_draw_buffers == 0)
- nr_draw_buffers = 1;
-
- size = sizeof(*blend) * nr_draw_buffers;
- blend = brw_state_batch(brw, size, 64, &brw->cc.blend_state_offset);
-
- memset(blend, 0, size);
-
- for (b = 0; b < nr_draw_buffers; b++) {
- /* _NEW_BUFFERS */
- struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[b];
- GLenum rb_type;
- bool integer;
-
- if (rb)
- rb_type = _mesa_get_format_datatype(rb->Format);
- else
- rb_type = GL_UNSIGNED_NORMALIZED;
-
- /* Used for implementing the following bit of GL_EXT_texture_integer:
- * "Per-fragment operations that require floating-point color
- * components, including multisample alpha operations, alpha test,
- * blending, and dithering, have no effect when the corresponding
- * colors are written to an integer color buffer."
- */
- integer = (rb_type == GL_INT || rb_type == GL_UNSIGNED_INT);
-
- if(b == 0 && integer)
- is_buffer_zero_integer_format = true;
-
- /* _NEW_COLOR */
- if (ctx->Color.ColorLogicOpEnabled) {
- /* Floating point RTs should have no effect from LogicOp,
- * except for disabling of blending, but other types should.
- *
- * However, from the Sandy Bridge PRM, Vol 2 Par 1, Section 8.1.11,
- * "Logic Ops",
- *
- * "Logic Ops are only supported on *_UNORM surfaces (excluding
- * _SRGB variants), otherwise Logic Ops must be DISABLED."
- */
- WARN_ONCE(ctx->Color.LogicOp != GL_COPY &&
- rb_type != GL_UNSIGNED_NORMALIZED &&
- rb_type != GL_FLOAT, "Ignoring %s logic op on %s "
- "renderbuffer\n",
- _mesa_enum_to_string(ctx->Color.LogicOp),
- _mesa_enum_to_string(rb_type));
- if (rb_type == GL_UNSIGNED_NORMALIZED) {
- blend[b].blend1.logic_op_enable = 1;
- blend[b].blend1.logic_op_func =
- intel_translate_logic_op(ctx->Color.LogicOp);
- }
- } else if (ctx->Color.BlendEnabled & (1 << b) && !integer &&
- !ctx->Color._AdvancedBlendMode) {
- GLenum eqRGB = ctx->Color.Blend[b].EquationRGB;
- GLenum eqA = ctx->Color.Blend[b].EquationA;
- GLenum srcRGB = ctx->Color.Blend[b].SrcRGB;
- GLenum dstRGB = ctx->Color.Blend[b].DstRGB;
- GLenum srcA = ctx->Color.Blend[b].SrcA;
- GLenum dstA = ctx->Color.Blend[b].DstA;
-
- if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
- srcRGB = dstRGB = GL_ONE;
- }
-
- if (eqA == GL_MIN || eqA == GL_MAX) {
- srcA = dstA = GL_ONE;
- }
-
- /* Due to hardware limitations, the destination may have information
- * in an alpha channel even when the format specifies no alpha
- * channel. In order to avoid getting any incorrect blending due to
- * that alpha channel, coerce the blend factors to values that will
- * not read the alpha channel, but will instead use the correct
- * implicit value for alpha.
- */
- 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);
- }
-
- blend[b].blend0.dest_blend_factor = brw_translate_blend_factor(dstRGB);
- blend[b].blend0.source_blend_factor = brw_translate_blend_factor(srcRGB);
- blend[b].blend0.blend_func = brw_translate_blend_equation(eqRGB);
-
- blend[b].blend0.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
- blend[b].blend0.ia_source_blend_factor = brw_translate_blend_factor(srcA);
- blend[b].blend0.ia_blend_func = brw_translate_blend_equation(eqA);
-
- blend[b].blend0.blend_enable = 1;
- blend[b].blend0.ia_blend_enable = (srcA != srcRGB ||
- dstA != dstRGB ||
- eqA != eqRGB);
- }
-
- /* See section 8.1.6 "Pre-Blend Color Clamping" of the
- * SandyBridge PRM Volume 2 Part 1 for HW requirements.
- *
- * We do our ARB_color_buffer_float CLAMP_FRAGMENT_COLOR
- * clamping in the fragment shader. For its clamping of
- * blending, the spec says:
- *
- * "RESOLVED: For fixed-point color buffers, the inputs and
- * the result of the blending equation are clamped. For
- * floating-point color buffers, no clamping occurs."
- *
- * So, generally, we want clamping to the render target's range.
- * And, good news, the hardware tables for both pre- and
- * post-blend color clamping are either ignored, or any are
- * allowed, or clamping is required but RT range clamping is a
- * valid option.
- */
- blend[b].blend1.pre_blend_clamp_enable = 1;
- blend[b].blend1.post_blend_clamp_enable = 1;
- blend[b].blend1.clamp_range = BRW_RENDERTARGET_CLAMPRANGE_FORMAT;
-
- /* _NEW_COLOR */
- if (ctx->Color.AlphaEnabled && !integer) {
- blend[b].blend1.alpha_test_enable = 1;
- blend[b].blend1.alpha_test_func =
- intel_translate_compare_func(ctx->Color.AlphaFunc);
-
- }
-
- /* _NEW_COLOR */
- if (ctx->Color.DitherFlag && !integer) {
- blend[b].blend1.dither_enable = 1;
- blend[b].blend1.y_dither_offset = 0;
- blend[b].blend1.x_dither_offset = 0;
- }
-
- blend[b].blend1.write_disable_r = !ctx->Color.ColorMask[b][0];
- blend[b].blend1.write_disable_g = !ctx->Color.ColorMask[b][1];
- blend[b].blend1.write_disable_b = !ctx->Color.ColorMask[b][2];
- blend[b].blend1.write_disable_a = !ctx->Color.ColorMask[b][3];
-
- /* OpenGL specification 3.3 (page 196), section 4.1.3 says:
- * "If drawbuffer zero is not NONE and the buffer it references has an
- * integer format, the SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_ALPHA_TO_ONE
- * operations are skipped."
- */
- if(!is_buffer_zero_integer_format) {
- /* _NEW_MULTISAMPLE */
- blend[b].blend1.alpha_to_coverage =
- _mesa_is_multisample_enabled(ctx) && ctx->Multisample.SampleAlphaToCoverage;
-
- /* From SandyBridge PRM, volume 2 Part 1, section 8.2.3, BLEND_STATE:
- * DWord 1, Bit 30 (AlphaToOne Enable):
- * "If Dual Source Blending is enabled, this bit must be disabled"
- */
- WARN_ONCE(ctx->Color.Blend[b]._UsesDualSrc &&
- _mesa_is_multisample_enabled(ctx) &&
- ctx->Multisample.SampleAlphaToOne,
- "HW workaround: disabling alpha to one with dual src "
- "blending\n");
- if (ctx->Color.Blend[b]._UsesDualSrc)
- blend[b].blend1.alpha_to_one = false;
- else
- blend[b].blend1.alpha_to_one =
- _mesa_is_multisample_enabled(ctx) && ctx->Multisample.SampleAlphaToOne;
-
- blend[b].blend1.alpha_to_coverage_dither = (brw->gen >= 7);
- }
- else {
- blend[b].blend1.alpha_to_coverage = false;
- blend[b].blend1.alpha_to_one = false;
- }
- }
-
- /* Point the GPU at the new indirect state. */
- if (brw->gen == 6) {
- BEGIN_BATCH(4);
- OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2));
- OUT_BATCH(brw->cc.blend_state_offset | 1);
- OUT_BATCH(0);
- OUT_BATCH(0);
- ADVANCE_BATCH();
- } else {
- BEGIN_BATCH(2);
- OUT_BATCH(_3DSTATE_BLEND_STATE_POINTERS << 16 | (2 - 2));
- OUT_BATCH(brw->cc.blend_state_offset | 1);
- ADVANCE_BATCH();
- }
-}
-
-const struct brw_tracked_state gen6_blend_state = {
- .dirty = {
- .mesa = _NEW_BUFFERS |
- _NEW_COLOR |
- _NEW_MULTISAMPLE,
- .brw = BRW_NEW_BATCH |
- BRW_NEW_BLORP |
- BRW_NEW_STATE_BASE_ADDRESS,
- },
- .emit = gen6_upload_blend_state,
-};
-
-static void
gen6_upload_color_calc_state(struct brw_context *brw)
{
struct gl_context *ctx = &brw->ctx;
diff --git a/src/mesa/drivers/dri/i965/gen8_blend_state.c b/src/mesa/drivers/dri/i965/gen8_blend_state.c
deleted file mode 100644
index 1fa8ba23fb3..00000000000
--- a/src/mesa/drivers/dri/i965/gen8_blend_state.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright © 2012 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "brw_context.h"
-#include "brw_state.h"
-#include "brw_defines.h"
-#include "brw_util.h"
-#include "brw_wm.h"
-#include "intel_batchbuffer.h"
-#include "main/macros.h"
-#include "main/enums.h"
-#include "main/glformats.h"
-
-#define blend_factor(x) brw_translate_blend_factor(x)
-#define blend_eqn(x) brw_translate_blend_equation(x)
-
-static void
-gen8_upload_blend_state(struct brw_context *brw)
-{
- struct gl_context *ctx = &brw->ctx;
-
- /* We need at least one BLEND_STATE written, because we might do
- * thread dispatch even if _NumColorDrawBuffers is 0 (for example
- * for computed depth or alpha test), which will do an FB write
- * with render target 0, which will reference BLEND_STATE[0] for
- * alpha test enable.
- */
- int nr_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
- if (nr_draw_buffers == 0 && ctx->Color.AlphaEnabled)
- nr_draw_buffers = 1;
-
- int size = 4 + 8 * nr_draw_buffers;
- uint32_t *blend =
- brw_state_batch(brw, size, 64, &brw->cc.blend_state_offset);
- memset(blend, 0, size);
-
- /* OpenGL specification 3.3 (page 196), section 4.1.3 says:
- * "If drawbuffer zero is not NONE and the buffer it references has an
- * integer format, the SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_ALPHA_TO_ONE
- * operations are skipped."
- */
- if (!(ctx->DrawBuffer->_IntegerBuffers & 0x1)) {
- /* _NEW_MULTISAMPLE */
- if (_mesa_is_multisample_enabled(ctx)) {
- if (ctx->Multisample.SampleAlphaToCoverage) {
- blend[0] |= GEN8_BLEND_ALPHA_TO_COVERAGE_ENABLE;
- blend[0] |= GEN8_BLEND_ALPHA_TO_COVERAGE_DITHER_ENABLE;
- }
- if (ctx->Multisample.SampleAlphaToOne)
- blend[0] |= GEN8_BLEND_ALPHA_TO_ONE_ENABLE;
- }
-
- /* _NEW_COLOR */
- if (ctx->Color.AlphaEnabled) {
- blend[0] |=
- GEN8_BLEND_ALPHA_TEST_ENABLE |
- SET_FIELD(intel_translate_compare_func(ctx->Color.AlphaFunc),
- GEN8_BLEND_ALPHA_TEST_FUNCTION);
- }
-
- if (ctx->Color.DitherFlag) {
- blend[0] |= GEN8_BLEND_COLOR_DITHER_ENABLE;
- }
- }
-
- for (int i = 0; i < nr_draw_buffers; i++) {
- /* _NEW_BUFFERS */
- struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
-
- /* Used for implementing the following bit of GL_EXT_texture_integer:
- * "Per-fragment operations that require floating-point color
- * components, including multisample alpha operations, alpha test,
- * blending, and dithering, have no effect when the corresponding
- * colors are written to an integer color buffer."
- */
- bool integer = ctx->DrawBuffer->_IntegerBuffers & (0x1 << i);
-
- /* _NEW_COLOR */
- if (ctx->Color.ColorLogicOpEnabled) {
- blend[1 + 2*i+1] |=
- GEN8_BLEND_LOGIC_OP_ENABLE |
- SET_FIELD(intel_translate_logic_op(ctx->Color.LogicOp),
- GEN8_BLEND_LOGIC_OP_FUNCTION);
- } else if (ctx->Color.BlendEnabled & (1 << i) && !integer &&
- !ctx->Color._AdvancedBlendMode) {
- GLenum eqRGB = ctx->Color.Blend[i].EquationRGB;
- GLenum eqA = ctx->Color.Blend[i].EquationA;
- GLenum srcRGB = ctx->Color.Blend[i].SrcRGB;
- GLenum dstRGB = ctx->Color.Blend[i].DstRGB;
- GLenum srcA = ctx->Color.Blend[i].SrcA;
- GLenum dstA = ctx->Color.Blend[i].DstA;
-
- if (eqRGB == GL_MIN || eqRGB == GL_MAX)
- srcRGB = dstRGB = GL_ONE;
-
- if (eqA == GL_MIN || eqA == GL_MAX)
- srcA = dstA = GL_ONE;
-
- /* Due to hardware limitations, the destination may have information
- * in an alpha channel even when the format specifies no alpha
- * channel. In order to avoid getting any incorrect blending due to
- * that alpha channel, coerce the blend factors to values that will
- * not read the alpha channel, but will instead use the correct
- * implicit value for alpha.
- */
- 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);
- }
-
- blend[1 + 2*i] |=
- GEN8_BLEND_COLOR_BUFFER_BLEND_ENABLE |
- SET_FIELD(blend_factor(dstRGB), GEN8_BLEND_DST_BLEND_FACTOR) |
- SET_FIELD(blend_factor(srcRGB), GEN8_BLEND_SRC_BLEND_FACTOR) |
- SET_FIELD(blend_factor(dstA), GEN8_BLEND_DST_ALPHA_BLEND_FACTOR) |
- SET_FIELD(blend_factor(srcA), GEN8_BLEND_SRC_ALPHA_BLEND_FACTOR) |
- SET_FIELD(blend_eqn(eqRGB), GEN8_BLEND_COLOR_BLEND_FUNCTION) |
- SET_FIELD(blend_eqn(eqA), GEN8_BLEND_ALPHA_BLEND_FUNCTION);
-
- if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB)
- blend[0] |= GEN8_BLEND_INDEPENDENT_ALPHA_BLEND_ENABLE;
- }
-
- /* See section 8.1.6 "Pre-Blend Color Clamping" of the
- * SandyBridge PRM Volume 2 Part 1 for HW requirements.
- *
- * We do our ARB_color_buffer_float CLAMP_FRAGMENT_COLOR
- * clamping in the fragment shader. For its clamping of
- * blending, the spec says:
- *
- * "RESOLVED: For fixed-point color buffers, the inputs and
- * the result of the blending equation are clamped. For
- * floating-point color buffers, no clamping occurs."
- *
- * So, generally, we want clamping to the render target's range.
- * And, good news, the hardware tables for both pre- and
- * post-blend color clamping are either ignored, or any are
- * allowed, or clamping is required but RT range clamping is a
- * valid option.
- */
- blend[1 + 2*i+1] |=
- GEN8_BLEND_PRE_BLEND_COLOR_CLAMP_ENABLE |
- GEN8_BLEND_POST_BLEND_COLOR_CLAMP_ENABLE |
- GEN8_BLEND_COLOR_CLAMP_RANGE_RTFORMAT;
-
- if (!ctx->Color.ColorMask[i][0])
- blend[1 + 2*i] |= GEN8_BLEND_WRITE_DISABLE_RED;
- if (!ctx->Color.ColorMask[i][1])
- blend[1 + 2*i] |= GEN8_BLEND_WRITE_DISABLE_GREEN;
- if (!ctx->Color.ColorMask[i][2])
- blend[1 + 2*i] |= GEN8_BLEND_WRITE_DISABLE_BLUE;
- if (!ctx->Color.ColorMask[i][3])
- blend[1 + 2*i] |= GEN8_BLEND_WRITE_DISABLE_ALPHA;
-
- /* From the BLEND_STATE docs, DWord 0, Bit 29 (AlphaToOne Enable):
- * "If Dual Source Blending is enabled, this bit must be disabled."
- */
- WARN_ONCE(ctx->Color.Blend[i]._UsesDualSrc &&
- _mesa_is_multisample_enabled(ctx) &&
- ctx->Multisample.SampleAlphaToOne,
- "HW workaround: disabling alpha to one with dual src "
- "blending\n");
- if (ctx->Color.Blend[i]._UsesDualSrc)
- blend[0] &= ~GEN8_BLEND_ALPHA_TO_ONE_ENABLE;
- }
-
- BEGIN_BATCH(2);
- OUT_BATCH(_3DSTATE_BLEND_STATE_POINTERS << 16 | (2 - 2));
- OUT_BATCH(brw->cc.blend_state_offset | 1);
- ADVANCE_BATCH();
-}
-
-const struct brw_tracked_state gen8_blend_state = {
- .dirty = {
- .mesa = _NEW_BUFFERS |
- _NEW_COLOR |
- _NEW_MULTISAMPLE,
- .brw = BRW_NEW_BATCH |
- BRW_NEW_BLORP |
- BRW_NEW_STATE_BASE_ADDRESS,
- },
- .emit = gen8_upload_blend_state,
-};
-
-static void
-gen8_upload_ps_blend(struct brw_context *brw)
-{
- struct gl_context *ctx = &brw->ctx;
- uint32_t dw1 = 0;
-
- /* _NEW_BUFFERS */
- struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
- const bool buffer0_is_integer = ctx->DrawBuffer->_IntegerBuffers & 0x1;
-
- /* BRW_NEW_FRAGMENT_PROGRAM | _NEW_BUFFERS | _NEW_COLOR */
- if (brw_color_buffer_write_enabled(brw))
- dw1 |= GEN8_PS_BLEND_HAS_WRITEABLE_RT;
-
- if (!buffer0_is_integer) {
- /* _NEW_COLOR */
- if (ctx->Color.AlphaEnabled)
- dw1 |= GEN8_PS_BLEND_ALPHA_TEST_ENABLE;
-
- /* _NEW_MULTISAMPLE */
- if (_mesa_is_multisample_enabled(ctx) &&
- ctx->Multisample.SampleAlphaToCoverage)
- dw1 |= GEN8_PS_BLEND_ALPHA_TO_COVERAGE_ENABLE;
- }
-
- /* Used for implementing the following bit of GL_EXT_texture_integer:
- * "Per-fragment operations that require floating-point color
- * components, including multisample alpha operations, alpha test,
- * blending, and dithering, have no effect when the corresponding
- * colors are written to an integer color buffer."
- *
- * The OpenGL specification 3.3 (page 196), section 4.1.3 says:
- * "If drawbuffer zero is not NONE and the buffer it references has an
- * integer format, the SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_ALPHA_TO_ONE
- * operations are skipped."
- */
- if (rb && !buffer0_is_integer && (ctx->Color.BlendEnabled & 1)) {
- 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;
-
- /* Due to hardware limitations, the destination may have information
- * in an alpha channel even when the format specifies no alpha
- * channel. In order to avoid getting any incorrect blending due to
- * that alpha channel, coerce the blend factors to values that will
- * not read the alpha channel, but will instead use the correct
- * implicit value for alpha.
- */
- if (!_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);
- }
-
- dw1 |=
- GEN8_PS_BLEND_COLOR_BUFFER_BLEND_ENABLE |
- SET_FIELD(blend_factor(dstRGB), GEN8_PS_BLEND_DST_BLEND_FACTOR) |
- SET_FIELD(blend_factor(srcRGB), GEN8_PS_BLEND_SRC_BLEND_FACTOR) |
- SET_FIELD(blend_factor(dstA), GEN8_PS_BLEND_DST_ALPHA_BLEND_FACTOR) |
- SET_FIELD(blend_factor(srcA), GEN8_PS_BLEND_SRC_ALPHA_BLEND_FACTOR);
-
- if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB)
- dw1 |= GEN8_PS_BLEND_INDEPENDENT_ALPHA_BLEND_ENABLE;
- }
-
- BEGIN_BATCH(2);
- OUT_BATCH(_3DSTATE_PS_BLEND << 16 | (2 - 2));
- OUT_BATCH(dw1);
- ADVANCE_BATCH();
-}
-
-const struct brw_tracked_state gen8_ps_blend = {
- .dirty = {
- .mesa = _NEW_BUFFERS |
- _NEW_COLOR |
- _NEW_MULTISAMPLE,
- .brw = BRW_NEW_BLORP |
- BRW_NEW_CONTEXT |
- BRW_NEW_FRAGMENT_PROGRAM,
- },
- .emit = gen8_upload_ps_blend
-};
diff --git a/src/mesa/drivers/dri/i965/genX_state_upload.c b/src/mesa/drivers/dri/i965/genX_state_upload.c
index dd7db7ad57c..f51036d41fd 100644
--- a/src/mesa/drivers/dri/i965/genX_state_upload.c
+++ b/src/mesa/drivers/dri/i965/genX_state_upload.c
@@ -38,8 +38,10 @@
#include "intel_buffer_objects.h"
#include "intel_fbo.h"
+#include "main/enums.h"
#include "main/fbobject.h"
#include "main/framebuffer.h"
+#include "main/glformats.h"
#include "main/stencil.h"
#include "main/transformfeedback.h"
#include "main/viewport.h"
@@ -1449,6 +1451,221 @@ static const struct brw_tracked_state genX(gs_state) = {
.emit = genX(upload_gs_state),
};
+/* ---------------------------------------------------------------------- */
+
+#define blend_factor(x) brw_translate_blend_factor(x)
+#define blend_eqn(x) brw_translate_blend_equation(x)
+
+static void
+genX(upload_blend_state)(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->ctx;
+ int size;
+
+ /* We need at least one BLEND_STATE written, because we might do
+ * thread dispatch even if _NumColorDrawBuffers is 0 (for example
+ * for computed depth or alpha test), which will do an FB write
+ * with render target 0, which will reference BLEND_STATE[0] for
+ * alpha test enable.
+ */
+ int nr_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
+ if (nr_draw_buffers == 0 && ctx->Color.AlphaEnabled)
+ nr_draw_buffers = 1;
+
+ size = GENX(BLEND_STATE_ENTRY_length) * 4 * nr_draw_buffers;
+#if GEN_GEN >= 8
+ size += GENX(BLEND_STATE_length) * 4;
+#endif
+
+ uint32_t *blend_map;
+ blend_map = brw_state_batch(brw, size, 64, &brw->cc.blend_state_offset);
+
+#if GEN_GEN >= 8
+ struct GENX(BLEND_STATE) blend = { 0 };
+ {
+#else
+ for (int i = 0; i < nr_draw_buffers; i++) {
+ struct GENX(BLEND_STATE_ENTRY) entry = { 0 };
+#define blend entry
+#endif
+ /* OpenGL specification 3.3 (page 196), section 4.1.3 says:
+ * "If drawbuffer zero is not NONE and the buffer it references has an
+ * integer format, the SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_ALPHA_TO_ONE
+ * operations are skipped."
+ */
+ if (!(ctx->DrawBuffer->_IntegerBuffers & 0x1)) {
+ /* _NEW_MULTISAMPLE */
+ if (_mesa_is_multisample_enabled(ctx)) {
+ if (ctx->Multisample.SampleAlphaToCoverage) {
+ blend.AlphaToCoverageEnable = true;
+ blend.AlphaToCoverageDitherEnable = GEN_GEN >= 7;
+ }
+ if (ctx->Multisample.SampleAlphaToOne)
+ blend.AlphaToOneEnable = true;
+ }
+
+ /* _NEW_COLOR */
+ if (ctx->Color.AlphaEnabled) {
+ blend.AlphaTestEnable = true;
+ blend.AlphaTestFunction =
+ intel_translate_compare_func(ctx->Color.AlphaFunc);
+ }
+
+ if (ctx->Color.DitherFlag) {
+ blend.ColorDitherEnable = true;
+ }
+ }
+
+#if GEN_GEN >= 8
+ for (int i = 0; i < nr_draw_buffers; i++) {
+ struct GENX(BLEND_STATE_ENTRY) entry = { 0 };
+#else
+ {
+#endif
+
+ /* _NEW_BUFFERS */
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+
+ /* Used for implementing the following bit of GL_EXT_texture_integer:
+ * "Per-fragment operations that require floating-point color
+ * components, including multisample alpha operations, alpha test,
+ * blending, and dithering, have no effect when the corresponding
+ * colors are written to an integer color buffer."
+ */
+ bool integer = ctx->DrawBuffer->_IntegerBuffers & (0x1 << i);
+
+ /* _NEW_COLOR */
+ if (ctx->Color.ColorLogicOpEnabled) {
+ GLenum rb_type = rb ? _mesa_get_format_datatype(rb->Format)
+ : GL_UNSIGNED_NORMALIZED;
+ WARN_ONCE(ctx->Color.LogicOp != GL_COPY &&
+ rb_type != GL_UNSIGNED_NORMALIZED &&
+ rb_type != GL_FLOAT, "Ignoring %s logic op on %s "
+ "renderbuffer\n",
+ _mesa_enum_to_string(ctx->Color.LogicOp),
+ _mesa_enum_to_string(rb_type));
+ if (GEN_GEN >= 8 || rb_type == GL_UNSIGNED_NORMALIZED) {
+ entry.LogicOpEnable = true;
+ entry.LogicOpFunction =
+ intel_translate_logic_op(ctx->Color.LogicOp);
+ }
+ } else if (ctx->Color.BlendEnabled & (1 << i) && !integer &&
+ !ctx->Color._AdvancedBlendMode) {
+ GLenum eqRGB = ctx->Color.Blend[i].EquationRGB;
+ GLenum eqA = ctx->Color.Blend[i].EquationA;
+ GLenum srcRGB = ctx->Color.Blend[i].SrcRGB;
+ GLenum dstRGB = ctx->Color.Blend[i].DstRGB;
+ GLenum srcA = ctx->Color.Blend[i].SrcA;
+ GLenum dstA = ctx->Color.Blend[i].DstA;
+
+ if (eqRGB == GL_MIN || eqRGB == GL_MAX)
+ srcRGB = dstRGB = GL_ONE;
+
+ if (eqA == GL_MIN || eqA == GL_MAX)
+ srcA = dstA = GL_ONE;
+
+ /* Due to hardware limitations, the destination may have information
+ * in an alpha channel even when the format specifies no alpha
+ * channel. In order to avoid getting any incorrect blending due to
+ * that alpha channel, coerce the blend factors to values that will
+ * not read the alpha channel, but will instead use the correct
+ * implicit value for alpha.
+ */
+ 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);
+ }
+
+ entry.ColorBufferBlendEnable = true;
+ entry.DestinationBlendFactor = blend_factor(dstRGB);
+ entry.SourceBlendFactor = blend_factor(srcRGB);
+ entry.DestinationAlphaBlendFactor = blend_factor(dstA);
+ entry.SourceAlphaBlendFactor = blend_factor(srcA);
+ entry.ColorBlendFunction = blend_eqn(eqRGB);
+ entry.AlphaBlendFunction = blend_eqn(eqA);
+
+ if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB)
+ blend.IndependentAlphaBlendEnable = true;
+ }
+
+ /* See section 8.1.6 "Pre-Blend Color Clamping" of the
+ * SandyBridge PRM Volume 2 Part 1 for HW requirements.
+ *
+ * We do our ARB_color_buffer_float CLAMP_FRAGMENT_COLOR
+ * clamping in the fragment shader. For its clamping of
+ * blending, the spec says:
+ *
+ * "RESOLVED: For fixed-point color buffers, the inputs and
+ * the result of the blending equation are clamped. For
+ * floating-point color buffers, no clamping occurs."
+ *
+ * So, generally, we want clamping to the render target's range.
+ * And, good news, the hardware tables for both pre- and
+ * post-blend color clamping are either ignored, or any are
+ * allowed, or clamping is required but RT range clamping is a
+ * valid option.
+ */
+ entry.PreBlendColorClampEnable = true;
+ entry.PostBlendColorClampEnable = true;
+ entry.ColorClampRange = COLORCLAMP_RTFORMAT;
+
+ entry.WriteDisableRed = !ctx->Color.ColorMask[i][0];
+ entry.WriteDisableGreen = !ctx->Color.ColorMask[i][1];
+ entry.WriteDisableBlue = !ctx->Color.ColorMask[i][2];
+ entry.WriteDisableAlpha = !ctx->Color.ColorMask[i][3];
+
+ /* From the BLEND_STATE docs, DWord 0, Bit 29 (AlphaToOne Enable):
+ * "If Dual Source Blending is enabled, this bit must be disabled."
+ */
+ WARN_ONCE(ctx->Color.Blend[i]._UsesDualSrc &&
+ _mesa_is_multisample_enabled(ctx) &&
+ ctx->Multisample.SampleAlphaToOne,
+ "HW workaround: disabling alpha to one with dual src "
+ "blending\n");
+ if (ctx->Color.Blend[i]._UsesDualSrc)
+ blend.AlphaToOneEnable = false;
+#if GEN_GEN >= 8
+ GENX(BLEND_STATE_ENTRY_pack)(NULL, &blend_map[1 + i * 2], &entry);
+#else
+ GENX(BLEND_STATE_ENTRY_pack)(NULL, &blend_map[i * 2], &entry);
+#endif
+ }
+ }
+
+#if GEN_GEN >= 8
+ GENX(BLEND_STATE_pack)(NULL, blend_map, &blend);
+#endif
+
+#if GEN_GEN < 7
+ brw_batch_emit(brw, GENX(3DSTATE_CC_STATE_POINTERS), ptr) {
+ ptr.PointertoBLEND_STATE = brw->cc.blend_state_offset;
+ ptr.BLEND_STATEChange = true;
+ }
+#else
+ brw_batch_emit(brw, GENX(3DSTATE_BLEND_STATE_POINTERS), ptr) {
+ ptr.BlendStatePointer = brw->cc.blend_state_offset;
+#if GEN_GEN >= 8
+ ptr.BlendStatePointerValid = true;
+#endif
+ }
+#endif
+}
+
+static const struct brw_tracked_state genX(blend_state) = {
+ .dirty = {
+ .mesa = _NEW_BUFFERS |
+ _NEW_COLOR |
+ _NEW_MULTISAMPLE,
+ .brw = BRW_NEW_BATCH |
+ BRW_NEW_BLORP |
+ BRW_NEW_STATE_BASE_ADDRESS,
+ },
+ .emit = genX(upload_blend_state),
+};
+
#endif
/* ---------------------------------------------------------------------- */
@@ -2297,6 +2514,97 @@ const struct brw_tracked_state genX(ps_extra) = {
},
.emit = genX(upload_ps_extra),
};
+
+/* ---------------------------------------------------------------------- */
+
+static void
+genX(upload_ps_blend)(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->ctx;
+
+ /* _NEW_BUFFERS */
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+ const bool buffer0_is_integer = ctx->DrawBuffer->_IntegerBuffers & 0x1;
+
+ /* _NEW_COLOR */
+ struct gl_colorbuffer_attrib *color = &ctx->Color;
+
+ brw_batch_emit(brw, GENX(3DSTATE_PS_BLEND), pb) {
+ /* BRW_NEW_FRAGMENT_PROGRAM | _NEW_BUFFERS | _NEW_COLOR */
+ pb.HasWriteableRT = brw_color_buffer_write_enabled(brw);
+
+ if (!buffer0_is_integer) {
+ /* _NEW_MULTISAMPLE */
+ pb.AlphaToCoverageEnable =
+ _mesa_is_multisample_enabled(ctx) &&
+ ctx->Multisample.SampleAlphaToCoverage;
+
+ pb.AlphaTestEnable = color->AlphaEnabled;
+ }
+
+ /* Used for implementing the following bit of GL_EXT_texture_integer:
+ * "Per-fragment operations that require floating-point color
+ * components, including multisample alpha operations, alpha test,
+ * blending, and dithering, have no effect when the corresponding
+ * colors are written to an integer color buffer."
+ *
+ * The OpenGL specification 3.3 (page 196), section 4.1.3 says:
+ * "If drawbuffer zero is not NONE and the buffer it references has an
+ * integer format, the SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_ALPHA_TO_ONE
+ * operations are skipped."
+ */
+ if (rb && !buffer0_is_integer && (color->BlendEnabled & 1)) {
+ GLenum eqRGB = color->Blend[0].EquationRGB;
+ GLenum eqA = color->Blend[0].EquationA;
+ GLenum srcRGB = color->Blend[0].SrcRGB;
+ GLenum dstRGB = color->Blend[0].DstRGB;
+ GLenum srcA = color->Blend[0].SrcA;
+ GLenum dstA = 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;
+
+ /* Due to hardware limitations, the destination may have information
+ * in an alpha channel even when the format specifies no alpha
+ * channel. In order to avoid getting any incorrect blending due to
+ * that alpha channel, coerce the blend factors to values that will
+ * not read the alpha channel, but will instead use the correct
+ * implicit value for alpha.
+ */
+ if (!_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);
+ }
+
+ pb.ColorBufferBlendEnable = true;
+ pb.SourceAlphaBlendFactor = brw_translate_blend_factor(srcA);
+ pb.DestinationAlphaBlendFactor = brw_translate_blend_factor(dstA);
+ pb.SourceBlendFactor = brw_translate_blend_factor(srcRGB);
+ pb.DestinationBlendFactor = brw_translate_blend_factor(dstRGB);
+
+ pb.IndependentAlphaBlendEnable =
+ srcA != srcRGB || dstA != dstRGB || eqA != eqRGB;
+ }
+ }
+}
+
+static const struct brw_tracked_state genX(ps_blend) = {
+ .dirty = {
+ .mesa = _NEW_BUFFERS |
+ _NEW_COLOR |
+ _NEW_MULTISAMPLE,
+ .brw = BRW_NEW_BLORP |
+ BRW_NEW_CONTEXT |
+ BRW_NEW_FRAGMENT_PROGRAM,
+ },
+ .emit = genX(upload_ps_blend)
+};
#endif
/* ---------------------------------------------------------------------- */
@@ -2373,7 +2681,7 @@ genX(init_atoms)(struct brw_context *brw)
&gen6_viewport_state, /* must do after *_vp stages */
&gen6_urb,
- &gen6_blend_state, /* must do before cc unit */
+ &genX(blend_state), /* must do before cc unit */
&gen6_color_calc_state, /* must do before cc unit */
&gen6_depth_stencil_state, /* must do before cc unit */
@@ -2438,7 +2746,7 @@ genX(init_atoms)(struct brw_context *brw)
&gen7_l3_state,
&gen7_push_constant_space,
&gen7_urb,
- &gen6_blend_state, /* must do before cc unit */
+ &genX(blend_state), /* must do before cc unit */
&gen6_color_calc_state, /* must do before cc unit */
&genX(depth_stencil_state), /* must do before cc unit */
@@ -2526,7 +2834,7 @@ genX(init_atoms)(struct brw_context *brw)
&gen7_l3_state,
&gen7_push_constant_space,
&gen7_urb,
- &gen8_blend_state,
+ &genX(blend_state),
&gen6_color_calc_state,
&brw_vs_image_surfaces, /* Before vs push/pull constants and binding table */
@@ -2585,7 +2893,7 @@ genX(init_atoms)(struct brw_context *brw)
&genX(raster_state),
&genX(sbe_state),
&genX(sf_state),
- &gen8_ps_blend,
+ &genX(ps_blend),
&genX(ps_extra),
&genX(ps_state),
&genX(depth_stencil_state),