1/************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Authors: 30 * Keith Whitwell <keithw@vmware.com> 31 * Brian Paul 32 */ 33 34 35#include "st_context.h" 36#include "st_atom.h" 37 38#include "pipe/p_context.h" 39#include "pipe/p_defines.h" 40#include "cso_cache/cso_context.h" 41 42#include "framebuffer.h" 43#include "main/blend.h" 44#include "main/glformats.h" 45#include "main/macros.h" 46 47/** 48 * Convert GLenum blend tokens to pipe tokens. 49 * Both blend factors and blend funcs are accepted. 50 */ 51static GLuint 52translate_blend(GLenum blend) 53{ 54 switch (blend) { 55 /* blend functions */ 56 case GL_FUNC_ADD: 57 return PIPE_BLEND_ADD; 58 case GL_FUNC_SUBTRACT: 59 return PIPE_BLEND_SUBTRACT; 60 case GL_FUNC_REVERSE_SUBTRACT: 61 return PIPE_BLEND_REVERSE_SUBTRACT; 62 case GL_MIN: 63 return PIPE_BLEND_MIN; 64 case GL_MAX: 65 return PIPE_BLEND_MAX; 66 67 /* blend factors */ 68 case GL_ONE: 69 return PIPE_BLENDFACTOR_ONE; 70 case GL_SRC_COLOR: 71 return PIPE_BLENDFACTOR_SRC_COLOR; 72 case GL_SRC_ALPHA: 73 return PIPE_BLENDFACTOR_SRC_ALPHA; 74 case GL_DST_ALPHA: 75 return PIPE_BLENDFACTOR_DST_ALPHA; 76 case GL_DST_COLOR: 77 return PIPE_BLENDFACTOR_DST_COLOR; 78 case GL_SRC_ALPHA_SATURATE: 79 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 80 case GL_CONSTANT_COLOR: 81 return PIPE_BLENDFACTOR_CONST_COLOR; 82 case GL_CONSTANT_ALPHA: 83 return PIPE_BLENDFACTOR_CONST_ALPHA; 84 case GL_SRC1_COLOR: 85 return PIPE_BLENDFACTOR_SRC1_COLOR; 86 case GL_SRC1_ALPHA: 87 return PIPE_BLENDFACTOR_SRC1_ALPHA; 88 case GL_ZERO: 89 return PIPE_BLENDFACTOR_ZERO; 90 case GL_ONE_MINUS_SRC_COLOR: 91 return PIPE_BLENDFACTOR_INV_SRC_COLOR; 92 case GL_ONE_MINUS_SRC_ALPHA: 93 return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 94 case GL_ONE_MINUS_DST_COLOR: 95 return PIPE_BLENDFACTOR_INV_DST_COLOR; 96 case GL_ONE_MINUS_DST_ALPHA: 97 return PIPE_BLENDFACTOR_INV_DST_ALPHA; 98 case GL_ONE_MINUS_CONSTANT_COLOR: 99 return PIPE_BLENDFACTOR_INV_CONST_COLOR; 100 case GL_ONE_MINUS_CONSTANT_ALPHA: 101 return PIPE_BLENDFACTOR_INV_CONST_ALPHA; 102 case GL_ONE_MINUS_SRC1_COLOR: 103 return PIPE_BLENDFACTOR_INV_SRC1_COLOR; 104 case GL_ONE_MINUS_SRC1_ALPHA: 105 return PIPE_BLENDFACTOR_INV_SRC1_ALPHA; 106 default: 107 assert("invalid GL token in translate_blend()" == NULL); 108 return 0; 109 } 110} 111 112/** 113 * Figure out if colormasks are different per rt. 114 */ 115static GLboolean 116colormask_per_rt(const struct gl_context *ctx, unsigned num_cb) 117{ 118 GLbitfield full_mask = _mesa_replicate_colormask(0xf, num_cb); 119 GLbitfield repl_mask0 = 120 _mesa_replicate_colormask(GET_COLORMASK(ctx->Color.ColorMask, 0), 121 num_cb); 122 123 return (ctx->Color.ColorMask & full_mask) != repl_mask0; 124} 125 126/** 127 * Figure out if blend enables/state are different per rt. 128 */ 129static GLboolean 130blend_per_rt(const struct st_context *st, unsigned num_cb) 131{ 132 const struct gl_context *ctx = st->ctx; 133 GLbitfield cb_mask = u_bit_consecutive(0, num_cb); 134 GLbitfield blend_enabled = ctx->Color.BlendEnabled & cb_mask; 135 136 if (blend_enabled && blend_enabled != cb_mask) { 137 /* This can only happen if GL_EXT_draw_buffers2 is enabled */ 138 return GL_TRUE; 139 } 140 if (ctx->Color._BlendFuncPerBuffer || ctx->Color._BlendEquationPerBuffer) { 141 /* this can only happen if GL_ARB_draw_buffers_blend is enabled */ 142 return GL_TRUE; 143 } 144 if (ctx->DrawBuffer->_IntegerBuffers && 145 (ctx->DrawBuffer->_IntegerBuffers != cb_mask)) { 146 /* If there is a mix of integer/non-integer buffers then blending 147 * must be handled on a per buffer basis. */ 148 return GL_TRUE; 149 } 150 151 if (ctx->DrawBuffer->_BlendForceAlphaToOne) { 152 /* Overriding requires independent blend functions (not just enables), 153 * require drivers exposing PIPE_CAP_RGB_OVERRIDE_DST_ALPHA_BLEND to 154 * also expose PIPE_CAP_INDEP_BLEND_FUNC. 155 */ 156 assert(st->has_indep_blend_func); 157 158 /* If some of the buffers are RGB or emulated L/I, we may need to override blend 159 * factors that reference destination-alpha to constants. We may 160 * need different blend factor overrides per buffer (say one uses 161 * a DST_ALPHA factor and another uses INV_DST_ALPHA), so we flip 162 * on independent blending. This may not be required in all cases, 163 * but burning the CPU to figure it out is probably not worthwhile. 164 */ 165 return GL_TRUE; 166 } 167 168 return GL_FALSE; 169} 170 171/** 172 * Modify blend function to force destination alpha to 1.0 173 * 174 * If \c function specifies a blend function that uses destination alpha, 175 * replace it with a function that hard-wires destination alpha to 1.0. 176 * This is useful when emulating a GL RGB format with an RGBA pipe_format. 177 */ 178static enum pipe_blendfactor 179fix_xrgb_alpha(enum pipe_blendfactor factor) 180{ 181 switch (factor) { 182 case PIPE_BLENDFACTOR_DST_ALPHA: 183 return PIPE_BLENDFACTOR_ONE; 184 185 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 186 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 187 return PIPE_BLENDFACTOR_ZERO; 188 default: 189 return factor; 190 } 191} 192 193void 194st_update_blend( struct st_context *st ) 195{ 196 struct pipe_blend_state *blend = &st->state.blend; 197 const struct gl_context *ctx = st->ctx; 198 unsigned num_cb = st->state.fb_num_cb; 199 unsigned num_state = 1; 200 unsigned i, j; 201 202 memset(blend, 0, sizeof(*blend)); 203 204 blend->max_rt = MAX2(1, num_cb) - 1; 205 206 if (num_cb > 1 && 207 (blend_per_rt(st, num_cb) || colormask_per_rt(ctx, num_cb))) { 208 num_state = num_cb; 209 blend->independent_blend_enable = 1; 210 } 211 212 for (i = 0; i < num_state; i++) 213 blend->rt[i].colormask = GET_COLORMASK(ctx->Color.ColorMask, i); 214 215 if (ctx->Color.ColorLogicOpEnabled) { 216 /* logicop enabled */ 217 blend->logicop_enable = 1; 218 blend->logicop_func = ctx->Color._LogicOp; 219 } 220 else if (ctx->Color.BlendEnabled && 221 ctx->Color._AdvancedBlendMode != BLEND_NONE) { 222 blend->advanced_blend_func = ctx->Color._AdvancedBlendMode; 223 } 224 else if (ctx->Color.BlendEnabled && 225 ctx->Color._AdvancedBlendMode == BLEND_NONE) { 226 /* blending enabled */ 227 for (i = 0, j = 0; i < num_state; i++) { 228 if (!(ctx->Color.BlendEnabled & (1 << i)) || 229 (ctx->DrawBuffer->_IntegerBuffers & (1 << i)) || 230 !blend->rt[i].colormask) 231 continue; 232 233 if (ctx->Extensions.ARB_draw_buffers_blend) 234 j = i; 235 236 blend->rt[i].blend_enable = 1; 237 blend->rt[i].rgb_func = 238 translate_blend(ctx->Color.Blend[j].EquationRGB); 239 240 if (ctx->Color.Blend[i].EquationRGB == GL_MIN || 241 ctx->Color.Blend[i].EquationRGB == GL_MAX) { 242 /* Min/max are special */ 243 blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 244 blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 245 } 246 else { 247 blend->rt[i].rgb_src_factor = 248 translate_blend(ctx->Color.Blend[j].SrcRGB); 249 blend->rt[i].rgb_dst_factor = 250 translate_blend(ctx->Color.Blend[j].DstRGB); 251 } 252 253 blend->rt[i].alpha_func = 254 translate_blend(ctx->Color.Blend[j].EquationA); 255 256 if (ctx->Color.Blend[i].EquationA == GL_MIN || 257 ctx->Color.Blend[i].EquationA == GL_MAX) { 258 /* Min/max are special */ 259 blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 260 blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 261 } 262 else { 263 blend->rt[i].alpha_src_factor = 264 translate_blend(ctx->Color.Blend[j].SrcA); 265 blend->rt[i].alpha_dst_factor = 266 translate_blend(ctx->Color.Blend[j].DstA); 267 } 268 269 const struct gl_renderbuffer *rb = 270 ctx->DrawBuffer->_ColorDrawBuffers[i]; 271 272 if (rb && (ctx->DrawBuffer->_BlendForceAlphaToOne & (1 << i))) { 273 struct pipe_rt_blend_state *rt = &blend->rt[i]; 274 rt->rgb_src_factor = fix_xrgb_alpha(rt->rgb_src_factor); 275 rt->rgb_dst_factor = fix_xrgb_alpha(rt->rgb_dst_factor); 276 rt->alpha_src_factor = fix_xrgb_alpha(rt->alpha_src_factor); 277 rt->alpha_dst_factor = fix_xrgb_alpha(rt->alpha_dst_factor); 278 } 279 } 280 } 281 else { 282 /* no blending / logicop */ 283 } 284 285 if (st->can_dither) 286 blend->dither = ctx->Color.DitherFlag; 287 288 if (_mesa_is_multisample_enabled(ctx) && 289 !(ctx->DrawBuffer->_IntegerBuffers & 0x1)) { 290 /* Unlike in gallium/d3d10 these operations are only performed 291 * if both msaa is enabled and we have a multisample buffer. 292 */ 293 blend->alpha_to_coverage = ctx->Multisample.SampleAlphaToCoverage; 294 blend->alpha_to_one = ctx->Multisample.SampleAlphaToOne; 295 blend->alpha_to_coverage_dither = 296 ctx->Multisample.SampleAlphaToCoverageDitherControl != 297 GL_ALPHA_TO_COVERAGE_DITHER_DISABLE_NV; 298 } 299 300 cso_set_blend(st->cso_context, blend); 301} 302 303void 304st_update_blend_color(struct st_context *st) 305{ 306 struct pipe_context *pipe = st->pipe; 307 struct pipe_blend_color *bc = 308 (struct pipe_blend_color *)st->ctx->Color.BlendColorUnclamped; 309 310 pipe->set_blend_color(pipe, bc); 311} 312