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