1 /* 2 * Copyright 2009 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Eric Anholt <eric (at) anholt.net> 25 * 26 */ 27 28 #include "brw_context.h" 29 #include "brw_state.h" 30 #include "brw_defines.h" 31 #include "brw_util.h" 32 #include "intel_batchbuffer.h" 33 #include "main/macros.h" 34 35 static void 36 gen6_upload_blend_state(struct brw_context *brw) 37 { 38 bool is_buffer_zero_integer_format = false; 39 struct gl_context *ctx = &brw->intel.ctx; 40 struct gen6_blend_state *blend; 41 int b; 42 int nr_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers; 43 int size; 44 45 /* We need at least one BLEND_STATE written, because we might do 46 * thread dispatch even if _NumColorDrawBuffers is 0 (for example 47 * for computed depth or alpha test), which will do an FB write 48 * with render target 0, which will reference BLEND_STATE[0] for 49 * alpha test enable. 50 */ 51 if (nr_draw_buffers == 0 && ctx->Color.AlphaEnabled) 52 nr_draw_buffers = 1; 53 54 size = sizeof(*blend) * nr_draw_buffers; 55 blend = brw_state_batch(brw, AUB_TRACE_BLEND_STATE, 56 size, 64, &brw->cc.blend_state_offset); 57 58 memset(blend, 0, size); 59 60 for (b = 0; b < nr_draw_buffers; b++) { 61 /* _NEW_BUFFERS */ 62 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[b]; 63 GLenum rb_type; 64 bool integer; 65 66 if (rb) 67 rb_type = _mesa_get_format_datatype(rb->Format); 68 else 69 rb_type = GL_UNSIGNED_NORMALIZED; 70 71 /* Used for implementing the following bit of GL_EXT_texture_integer: 72 * "Per-fragment operations that require floating-point color 73 * components, including multisample alpha operations, alpha test, 74 * blending, and dithering, have no effect when the corresponding 75 * colors are written to an integer color buffer." 76 */ 77 integer = (rb_type == GL_INT || rb_type == GL_UNSIGNED_INT); 78 79 if(b == 0 && integer) 80 is_buffer_zero_integer_format = true; 81 82 /* _NEW_COLOR */ 83 if (ctx->Color.ColorLogicOpEnabled) { 84 /* Floating point RTs should have no effect from LogicOp, 85 * except for disabling of blending. 86 * 87 * From the Sandy Bridge PRM, Vol 2 Par 1, Section 8.1.11, "Logic Ops", 88 * 89 * "Logic Ops are only supported on *_UNORM surfaces (excluding 90 * _SRGB variants), otherwise Logic Ops must be DISABLED." 91 */ 92 if (rb_type == GL_UNSIGNED_NORMALIZED) { 93 blend[b].blend1.logic_op_enable = 1; 94 blend[b].blend1.logic_op_func = 95 intel_translate_logic_op(ctx->Color.LogicOp); 96 } 97 } else if (ctx->Color.BlendEnabled & (1 << b) && !integer) { 98 GLenum eqRGB = ctx->Color.Blend[b].EquationRGB; 99 GLenum eqA = ctx->Color.Blend[b].EquationA; 100 GLenum srcRGB = ctx->Color.Blend[b].SrcRGB; 101 GLenum dstRGB = ctx->Color.Blend[b].DstRGB; 102 GLenum srcA = ctx->Color.Blend[b].SrcA; 103 GLenum dstA = ctx->Color.Blend[b].DstA; 104 105 if (eqRGB == GL_MIN || eqRGB == GL_MAX) { 106 srcRGB = dstRGB = GL_ONE; 107 } 108 109 if (eqA == GL_MIN || eqA == GL_MAX) { 110 srcA = dstA = GL_ONE; 111 } 112 113 blend[b].blend0.dest_blend_factor = brw_translate_blend_factor(dstRGB); 114 blend[b].blend0.source_blend_factor = brw_translate_blend_factor(srcRGB); 115 blend[b].blend0.blend_func = brw_translate_blend_equation(eqRGB); 116 117 blend[b].blend0.ia_dest_blend_factor = brw_translate_blend_factor(dstA); 118 blend[b].blend0.ia_source_blend_factor = brw_translate_blend_factor(srcA); 119 blend[b].blend0.ia_blend_func = brw_translate_blend_equation(eqA); 120 121 blend[b].blend0.blend_enable = 1; 122 blend[b].blend0.ia_blend_enable = (srcA != srcRGB || 123 dstA != dstRGB || 124 eqA != eqRGB); 125 } 126 127 /* See section 8.1.6 "Pre-Blend Color Clamping" of the 128 * SandyBridge PRM Volume 2 Part 1 for HW requirements. 129 * 130 * We do our ARB_color_buffer_float CLAMP_FRAGMENT_COLOR 131 * clamping in the fragment shader. For its clamping of 132 * blending, the spec says: 133 * 134 * "RESOLVED: For fixed-point color buffers, the inputs and 135 * the result of the blending equation are clamped. For 136 * floating-point color buffers, no clamping occurs." 137 * 138 * So, generally, we want clamping to the render target's range. 139 * And, good news, the hardware tables for both pre- and 140 * post-blend color clamping are either ignored, or any are 141 * allowed, or clamping is required but RT range clamping is a 142 * valid option. 143 */ 144 blend[b].blend1.pre_blend_clamp_enable = 1; 145 blend[b].blend1.post_blend_clamp_enable = 1; 146 blend[b].blend1.clamp_range = BRW_RENDERTARGET_CLAMPRANGE_FORMAT; 147 148 /* _NEW_COLOR */ 149 if (ctx->Color.AlphaEnabled && !integer) { 150 blend[b].blend1.alpha_test_enable = 1; 151 blend[b].blend1.alpha_test_func = 152 intel_translate_compare_func(ctx->Color.AlphaFunc); 153 154 } 155 156 /* _NEW_COLOR */ 157 if (ctx->Color.DitherFlag && !integer) { 158 blend[b].blend1.dither_enable = 1; 159 blend[b].blend1.y_dither_offset = 0; 160 blend[b].blend1.x_dither_offset = 0; 161 } 162 163 blend[b].blend1.write_disable_r = !ctx->Color.ColorMask[b][0]; 164 blend[b].blend1.write_disable_g = !ctx->Color.ColorMask[b][1]; 165 blend[b].blend1.write_disable_b = !ctx->Color.ColorMask[b][2]; 166 blend[b].blend1.write_disable_a = !ctx->Color.ColorMask[b][3]; 167 168 /* OpenGL specification 3.3 (page 196), section 4.1.3 says: 169 * "If drawbuffer zero is not NONE and the buffer it references has an 170 * integer format, the SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_ALPHA_TO_ONE 171 * operations are skipped." 172 */ 173 if(!is_buffer_zero_integer_format) { 174 /* _NEW_MULTISAMPLE */ 175 blend[b].blend1.alpha_to_coverage = 176 ctx->Multisample._Enabled && ctx->Multisample.SampleAlphaToCoverage; 177 178 /* From SandyBridge PRM, volume 2 Part 1, section 8.2.3, BLEND_STATE: 179 * DWord 1, Bit 30 (AlphaToOne Enable): 180 * "If Dual Source Blending is enabled, this bit must be disabled" 181 */ 182 if (ctx->Color.Blend[b]._UsesDualSrc) 183 blend[b].blend1.alpha_to_one = false; 184 else 185 blend[b].blend1.alpha_to_one = 186 ctx->Multisample._Enabled && ctx->Multisample.SampleAlphaToOne; 187 188 blend[b].blend1.alpha_to_coverage_dither = (brw->intel.gen >= 7); 189 } 190 else { 191 blend[b].blend1.alpha_to_coverage = false; 192 blend[b].blend1.alpha_to_one = false; 193 } 194 } 195 196 brw->state.dirty.cache |= CACHE_NEW_BLEND_STATE; 197 } 198 199 const struct brw_tracked_state gen6_blend_state = { 200 .dirty = { 201 .mesa = (_NEW_COLOR | 202 _NEW_BUFFERS | 203 _NEW_MULTISAMPLE), 204 .brw = BRW_NEW_BATCH, 205 .cache = 0, 206 }, 207 .emit = gen6_upload_blend_state, 208 }; 209 210 static void 211 gen6_upload_color_calc_state(struct brw_context *brw) 212 { 213 struct gl_context *ctx = &brw->intel.ctx; 214 struct gen6_color_calc_state *cc; 215 216 cc = brw_state_batch(brw, AUB_TRACE_CC_STATE, 217 sizeof(*cc), 64, &brw->cc.state_offset); 218 memset(cc, 0, sizeof(*cc)); 219 220 /* _NEW_COLOR */ 221 cc->cc0.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; 222 UNCLAMPED_FLOAT_TO_UBYTE(cc->cc1.alpha_ref_fi.ui, ctx->Color.AlphaRef); 223 224 /* _NEW_STENCIL */ 225 cc->cc0.stencil_ref = ctx->Stencil.Ref[0]; 226 cc->cc0.bf_stencil_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace]; 227 228 /* _NEW_COLOR */ 229 cc->constant_r = ctx->Color.BlendColorUnclamped[0]; 230 cc->constant_g = ctx->Color.BlendColorUnclamped[1]; 231 cc->constant_b = ctx->Color.BlendColorUnclamped[2]; 232 cc->constant_a = ctx->Color.BlendColorUnclamped[3]; 233 234 brw->state.dirty.cache |= CACHE_NEW_COLOR_CALC_STATE; 235 } 236 237 const struct brw_tracked_state gen6_color_calc_state = { 238 .dirty = { 239 .mesa = _NEW_COLOR | _NEW_STENCIL, 240 .brw = BRW_NEW_BATCH, 241 .cache = 0, 242 }, 243 .emit = gen6_upload_color_calc_state, 244 }; 245 246 static void upload_cc_state_pointers(struct brw_context *brw) 247 { 248 struct intel_context *intel = &brw->intel; 249 250 BEGIN_BATCH(4); 251 OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2)); 252 OUT_BATCH(brw->cc.blend_state_offset | 1); 253 OUT_BATCH(brw->cc.depth_stencil_state_offset | 1); 254 OUT_BATCH(brw->cc.state_offset | 1); 255 ADVANCE_BATCH(); 256 } 257 258 const struct brw_tracked_state gen6_cc_state_pointers = { 259 .dirty = { 260 .mesa = 0, 261 .brw = (BRW_NEW_BATCH | 262 BRW_NEW_STATE_BASE_ADDRESS), 263 .cache = (CACHE_NEW_BLEND_STATE | 264 CACHE_NEW_COLOR_CALC_STATE | 265 CACHE_NEW_DEPTH_STENCIL_STATE) 266 }, 267 .emit = upload_cc_state_pointers, 268 }; 269