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 (st->needs_rgb_dst_alpha_override && ctx->DrawBuffer->_RGBBuffers) { 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, 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 if (num_cb > 1 && 205 (blend_per_rt(st, num_cb) || colormask_per_rt(ctx, num_cb))) { 206 num_state = num_cb; 207 blend->independent_blend_enable = 1; 208 } 209 210 for (i = 0; i < num_state; i++) 211 blend->rt[i].colormask = GET_COLORMASK(ctx->Color.ColorMask, i); 212 213 if (ctx->Color.ColorLogicOpEnabled) { 214 /* logicop enabled */ 215 blend->logicop_enable = 1; 216 blend->logicop_func = ctx->Color._LogicOp; 217 } 218 else if (ctx->Color.BlendEnabled && !ctx->Color._AdvancedBlendMode) { 219 /* blending enabled */ 220 for (i = 0, j = 0; i < num_state; i++) { 221 if (!(ctx->Color.BlendEnabled & (1 << i)) || 222 (ctx->DrawBuffer->_IntegerBuffers & (1 << i)) || 223 !blend->rt[i].colormask) 224 continue; 225 226 if (ctx->Extensions.ARB_draw_buffers_blend) 227 j = i; 228 229 blend->rt[i].blend_enable = 1; 230 blend->rt[i].rgb_func = 231 translate_blend(ctx->Color.Blend[j].EquationRGB); 232 233 if (ctx->Color.Blend[i].EquationRGB == GL_MIN || 234 ctx->Color.Blend[i].EquationRGB == GL_MAX) { 235 /* Min/max are special */ 236 blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 237 blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 238 } 239 else { 240 blend->rt[i].rgb_src_factor = 241 translate_blend(ctx->Color.Blend[j].SrcRGB); 242 blend->rt[i].rgb_dst_factor = 243 translate_blend(ctx->Color.Blend[j].DstRGB); 244 } 245 246 blend->rt[i].alpha_func = 247 translate_blend(ctx->Color.Blend[j].EquationA); 248 249 if (ctx->Color.Blend[i].EquationA == GL_MIN || 250 ctx->Color.Blend[i].EquationA == GL_MAX) { 251 /* Min/max are special */ 252 blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 253 blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 254 } 255 else { 256 blend->rt[i].alpha_src_factor = 257 translate_blend(ctx->Color.Blend[j].SrcA); 258 blend->rt[i].alpha_dst_factor = 259 translate_blend(ctx->Color.Blend[j].DstA); 260 } 261 262 const struct gl_renderbuffer *rb = 263 ctx->DrawBuffer->_ColorDrawBuffers[i]; 264 265 if (st->needs_rgb_dst_alpha_override && rb && 266 (ctx->DrawBuffer->_RGBBuffers & (1 << i))) { 267 struct pipe_rt_blend_state *rt = &blend->rt[i]; 268 rt->rgb_src_factor = fix_xrgb_alpha(rt->rgb_src_factor); 269 rt->rgb_dst_factor = fix_xrgb_alpha(rt->rgb_dst_factor); 270 rt->alpha_src_factor = fix_xrgb_alpha(rt->alpha_src_factor); 271 rt->alpha_dst_factor = fix_xrgb_alpha(rt->alpha_dst_factor); 272 } 273 } 274 } 275 else { 276 /* no blending / logicop */ 277 } 278 279 blend->dither = ctx->Color.DitherFlag; 280 281 if (_mesa_is_multisample_enabled(ctx) && 282 !(ctx->DrawBuffer->_IntegerBuffers & 0x1)) { 283 /* Unlike in gallium/d3d10 these operations are only performed 284 * if both msaa is enabled and we have a multisample buffer. 285 */ 286 blend->alpha_to_coverage = ctx->Multisample.SampleAlphaToCoverage; 287 blend->alpha_to_one = ctx->Multisample.SampleAlphaToOne; 288 } 289 290 cso_set_blend(st->cso_context, blend); 291} 292 293void 294st_update_blend_color(struct st_context *st) 295{ 296 struct pipe_blend_color bc; 297 298 COPY_4FV(bc.color, st->ctx->Color.BlendColorUnclamped); 299 cso_set_blend_color(st->cso_context, &bc); 300} 301