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 (at) 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/macros.h" 44 45 /** 46 * Convert GLenum blend tokens to pipe tokens. 47 * Both blend factors and blend funcs are accepted. 48 */ 49 static GLuint 50 translate_blend(GLenum blend) 51 { 52 switch (blend) { 53 /* blend functions */ 54 case GL_FUNC_ADD: 55 return PIPE_BLEND_ADD; 56 case GL_FUNC_SUBTRACT: 57 return PIPE_BLEND_SUBTRACT; 58 case GL_FUNC_REVERSE_SUBTRACT: 59 return PIPE_BLEND_REVERSE_SUBTRACT; 60 case GL_MIN: 61 return PIPE_BLEND_MIN; 62 case GL_MAX: 63 return PIPE_BLEND_MAX; 64 65 /* blend factors */ 66 case GL_ONE: 67 return PIPE_BLENDFACTOR_ONE; 68 case GL_SRC_COLOR: 69 return PIPE_BLENDFACTOR_SRC_COLOR; 70 case GL_SRC_ALPHA: 71 return PIPE_BLENDFACTOR_SRC_ALPHA; 72 case GL_DST_ALPHA: 73 return PIPE_BLENDFACTOR_DST_ALPHA; 74 case GL_DST_COLOR: 75 return PIPE_BLENDFACTOR_DST_COLOR; 76 case GL_SRC_ALPHA_SATURATE: 77 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 78 case GL_CONSTANT_COLOR: 79 return PIPE_BLENDFACTOR_CONST_COLOR; 80 case GL_CONSTANT_ALPHA: 81 return PIPE_BLENDFACTOR_CONST_ALPHA; 82 case GL_SRC1_COLOR: 83 return PIPE_BLENDFACTOR_SRC1_COLOR; 84 case GL_SRC1_ALPHA: 85 return PIPE_BLENDFACTOR_SRC1_ALPHA; 86 case GL_ZERO: 87 return PIPE_BLENDFACTOR_ZERO; 88 case GL_ONE_MINUS_SRC_COLOR: 89 return PIPE_BLENDFACTOR_INV_SRC_COLOR; 90 case GL_ONE_MINUS_SRC_ALPHA: 91 return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 92 case GL_ONE_MINUS_DST_COLOR: 93 return PIPE_BLENDFACTOR_INV_DST_COLOR; 94 case GL_ONE_MINUS_DST_ALPHA: 95 return PIPE_BLENDFACTOR_INV_DST_ALPHA; 96 case GL_ONE_MINUS_CONSTANT_COLOR: 97 return PIPE_BLENDFACTOR_INV_CONST_COLOR; 98 case GL_ONE_MINUS_CONSTANT_ALPHA: 99 return PIPE_BLENDFACTOR_INV_CONST_ALPHA; 100 case GL_ONE_MINUS_SRC1_COLOR: 101 return PIPE_BLENDFACTOR_INV_SRC1_COLOR; 102 case GL_ONE_MINUS_SRC1_ALPHA: 103 return PIPE_BLENDFACTOR_INV_SRC1_ALPHA; 104 default: 105 assert("invalid GL token in translate_blend()" == NULL); 106 return 0; 107 } 108 } 109 110 111 /** 112 * Convert GLenum logicop tokens to pipe tokens. 113 */ 114 static GLuint 115 translate_logicop(GLenum logicop) 116 { 117 switch (logicop) { 118 case GL_CLEAR: 119 return PIPE_LOGICOP_CLEAR; 120 case GL_NOR: 121 return PIPE_LOGICOP_NOR; 122 case GL_AND_INVERTED: 123 return PIPE_LOGICOP_AND_INVERTED; 124 case GL_COPY_INVERTED: 125 return PIPE_LOGICOP_COPY_INVERTED; 126 case GL_AND_REVERSE: 127 return PIPE_LOGICOP_AND_REVERSE; 128 case GL_INVERT: 129 return PIPE_LOGICOP_INVERT; 130 case GL_XOR: 131 return PIPE_LOGICOP_XOR; 132 case GL_NAND: 133 return PIPE_LOGICOP_NAND; 134 case GL_AND: 135 return PIPE_LOGICOP_AND; 136 case GL_EQUIV: 137 return PIPE_LOGICOP_EQUIV; 138 case GL_NOOP: 139 return PIPE_LOGICOP_NOOP; 140 case GL_OR_INVERTED: 141 return PIPE_LOGICOP_OR_INVERTED; 142 case GL_COPY: 143 return PIPE_LOGICOP_COPY; 144 case GL_OR_REVERSE: 145 return PIPE_LOGICOP_OR_REVERSE; 146 case GL_OR: 147 return PIPE_LOGICOP_OR; 148 case GL_SET: 149 return PIPE_LOGICOP_SET; 150 default: 151 assert("invalid GL token in translate_logicop()" == NULL); 152 return 0; 153 } 154 } 155 156 /** 157 * Figure out if colormasks are different per rt. 158 */ 159 static GLboolean 160 colormask_per_rt(const struct gl_context *ctx) 161 { 162 /* a bit suboptimal have to compare lots of values */ 163 unsigned i; 164 for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) { 165 if (memcmp(ctx->Color.ColorMask[0], ctx->Color.ColorMask[i], 4)) { 166 return GL_TRUE; 167 } 168 } 169 return GL_FALSE; 170 } 171 172 /** 173 * Figure out if blend enables/state are different per rt. 174 */ 175 static GLboolean 176 blend_per_rt(const struct gl_context *ctx) 177 { 178 if (ctx->Color.BlendEnabled && 179 (ctx->Color.BlendEnabled != ((1U << ctx->Const.MaxDrawBuffers) - 1))) { 180 /* This can only happen if GL_EXT_draw_buffers2 is enabled */ 181 return GL_TRUE; 182 } 183 if (ctx->Color._BlendFuncPerBuffer || ctx->Color._BlendEquationPerBuffer) { 184 /* this can only happen if GL_ARB_draw_buffers_blend is enabled */ 185 return GL_TRUE; 186 } 187 return GL_FALSE; 188 } 189 190 void 191 st_update_blend( struct st_context *st ) 192 { 193 struct pipe_blend_state *blend = &st->state.blend; 194 const struct gl_context *ctx = st->ctx; 195 unsigned num_state = 1; 196 unsigned i, j; 197 198 memset(blend, 0, sizeof(*blend)); 199 200 if (blend_per_rt(ctx) || colormask_per_rt(ctx)) { 201 num_state = ctx->Const.MaxDrawBuffers; 202 blend->independent_blend_enable = 1; 203 } 204 if (ctx->Color.ColorLogicOpEnabled) { 205 /* logicop enabled */ 206 blend->logicop_enable = 1; 207 blend->logicop_func = translate_logicop(ctx->Color.LogicOp); 208 } 209 else if (ctx->Color.BlendEnabled && !ctx->Color._AdvancedBlendMode) { 210 /* blending enabled */ 211 for (i = 0, j = 0; i < num_state; i++) { 212 213 blend->rt[i].blend_enable = (ctx->Color.BlendEnabled >> i) & 0x1; 214 215 if (ctx->Extensions.ARB_draw_buffers_blend) 216 j = i; 217 218 blend->rt[i].rgb_func = 219 translate_blend(ctx->Color.Blend[j].EquationRGB); 220 221 if (ctx->Color.Blend[i].EquationRGB == GL_MIN || 222 ctx->Color.Blend[i].EquationRGB == GL_MAX) { 223 /* Min/max are special */ 224 blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 225 blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 226 } 227 else { 228 blend->rt[i].rgb_src_factor = 229 translate_blend(ctx->Color.Blend[j].SrcRGB); 230 blend->rt[i].rgb_dst_factor = 231 translate_blend(ctx->Color.Blend[j].DstRGB); 232 } 233 234 blend->rt[i].alpha_func = 235 translate_blend(ctx->Color.Blend[j].EquationA); 236 237 if (ctx->Color.Blend[i].EquationA == GL_MIN || 238 ctx->Color.Blend[i].EquationA == GL_MAX) { 239 /* Min/max are special */ 240 blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 241 blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 242 } 243 else { 244 blend->rt[i].alpha_src_factor = 245 translate_blend(ctx->Color.Blend[j].SrcA); 246 blend->rt[i].alpha_dst_factor = 247 translate_blend(ctx->Color.Blend[j].DstA); 248 } 249 } 250 } 251 else { 252 /* no blending / logicop */ 253 } 254 255 /* Colormask - maybe reverse these bits? */ 256 for (i = 0; i < num_state; i++) { 257 if (ctx->Color.ColorMask[i][0]) 258 blend->rt[i].colormask |= PIPE_MASK_R; 259 if (ctx->Color.ColorMask[i][1]) 260 blend->rt[i].colormask |= PIPE_MASK_G; 261 if (ctx->Color.ColorMask[i][2]) 262 blend->rt[i].colormask |= PIPE_MASK_B; 263 if (ctx->Color.ColorMask[i][3]) 264 blend->rt[i].colormask |= PIPE_MASK_A; 265 } 266 267 blend->dither = ctx->Color.DitherFlag; 268 269 if (_mesa_is_multisample_enabled(ctx) && 270 !(ctx->DrawBuffer->_IntegerBuffers & 0x1)) { 271 /* Unlike in gallium/d3d10 these operations are only performed 272 * if both msaa is enabled and we have a multisample buffer. 273 */ 274 blend->alpha_to_coverage = ctx->Multisample.SampleAlphaToCoverage; 275 blend->alpha_to_one = ctx->Multisample.SampleAlphaToOne; 276 } 277 278 cso_set_blend(st->cso_context, blend); 279 } 280 281 void 282 st_update_blend_color(struct st_context *st) 283 { 284 struct pipe_blend_color bc; 285 286 COPY_4FV(bc.color, st->ctx->Color.BlendColorUnclamped); 287 cso_set_blend_color(st->cso_context, &bc); 288 } 289