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