1 /**************************************************************************
3 * Copyright 2007 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Keith Whitwell <keithw@vmware.com>
35 #include "st_context.h"
38 #include "pipe/p_context.h"
39 #include "pipe/p_defines.h"
40 #include "cso_cache/cso_context.h"
42 #include "framebuffer.h"
43 #include "main/blend.h"
44 #include "main/glformats.h"
45 #include "main/macros.h"
48 * Convert GLenum blend tokens to pipe tokens.
49 * Both blend factors and blend funcs are accepted.
52 translate_blend(GLenum blend
)
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
;
63 return PIPE_BLEND_MIN
;
65 return PIPE_BLEND_MAX
;
69 return PIPE_BLENDFACTOR_ONE
;
71 return PIPE_BLENDFACTOR_SRC_COLOR
;
73 return PIPE_BLENDFACTOR_SRC_ALPHA
;
75 return PIPE_BLENDFACTOR_DST_ALPHA
;
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
;
85 return PIPE_BLENDFACTOR_SRC1_COLOR
;
87 return PIPE_BLENDFACTOR_SRC1_ALPHA
;
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
;
107 assert("invalid GL token in translate_blend()" == NULL
);
113 * Figure out if colormasks are different per rt.
116 colormask_per_rt(const struct gl_context
*ctx
, unsigned num_cb
)
118 GLbitfield full_mask
= _mesa_replicate_colormask(0xf, num_cb
);
119 GLbitfield repl_mask0
=
120 _mesa_replicate_colormask(GET_COLORMASK(ctx
->Color
.ColorMask
, 0),
123 return (ctx
->Color
.ColorMask
& full_mask
) != repl_mask0
;
127 * Figure out if blend enables/state are different per rt.
130 blend_per_rt(const struct st_context
*st
, unsigned num_cb
)
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
;
136 if (blend_enabled
&& blend_enabled
!= cb_mask
) {
137 /* This can only happen if GL_EXT_draw_buffers2 is enabled */
140 if (ctx
->Color
._BlendFuncPerBuffer
|| ctx
->Color
._BlendEquationPerBuffer
) {
141 /* this can only happen if GL_ARB_draw_buffers_blend is enabled */
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. */
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.
156 assert(st
->has_indep_blend_func
);
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.
172 * Modify blend function to force destination alpha to 1.0
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.
178 static enum pipe_blendfactor
179 fix_xrgb_alpha(enum pipe_blendfactor factor
)
182 case PIPE_BLENDFACTOR_DST_ALPHA
:
183 return PIPE_BLENDFACTOR_ONE
;
185 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
186 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
187 return PIPE_BLENDFACTOR_ZERO
;
194 st_update_blend( struct st_context
*st
)
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;
202 memset(blend
, 0, sizeof(*blend
));
204 blend
->max_rt
= MAX2(1, num_cb
) - 1;
207 (blend_per_rt(st
, num_cb
) || colormask_per_rt(ctx
, num_cb
))) {
209 blend
->independent_blend_enable
= 1;
212 for (i
= 0; i
< num_state
; i
++)
213 blend
->rt
[i
].colormask
= GET_COLORMASK(ctx
->Color
.ColorMask
, i
);
215 if (ctx
->Color
.ColorLogicOpEnabled
) {
216 /* logicop enabled */
217 blend
->logicop_enable
= 1;
218 blend
->logicop_func
= ctx
->Color
._LogicOp
;
220 else if (ctx
->Color
.BlendEnabled
&&
221 ctx
->Color
._AdvancedBlendMode
!= BLEND_NONE
) {
222 blend
->advanced_blend_func
= ctx
->Color
._AdvancedBlendMode
;
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
)
233 if (ctx
->Extensions
.ARB_draw_buffers_blend
)
236 blend
->rt
[i
].blend_enable
= 1;
237 blend
->rt
[i
].rgb_func
=
238 translate_blend(ctx
->Color
.Blend
[j
].EquationRGB
);
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
;
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
);
253 blend
->rt
[i
].alpha_func
=
254 translate_blend(ctx
->Color
.Blend
[j
].EquationA
);
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
;
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
);
269 const struct gl_renderbuffer
*rb
=
270 ctx
->DrawBuffer
->_ColorDrawBuffers
[i
];
272 if (st
->needs_rgb_dst_alpha_override
&& rb
&&
273 (ctx
->DrawBuffer
->_RGBBuffers
& (1 << i
))) {
274 struct pipe_rt_blend_state
*rt
= &blend
->rt
[i
];
275 rt
->rgb_src_factor
= fix_xrgb_alpha(rt
->rgb_src_factor
);
276 rt
->rgb_dst_factor
= fix_xrgb_alpha(rt
->rgb_dst_factor
);
277 rt
->alpha_src_factor
= fix_xrgb_alpha(rt
->alpha_src_factor
);
278 rt
->alpha_dst_factor
= fix_xrgb_alpha(rt
->alpha_dst_factor
);
283 /* no blending / logicop */
286 blend
->dither
= ctx
->Color
.DitherFlag
;
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.
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
;
300 cso_set_blend(st
->cso_context
, blend
);
304 st_update_blend_color(struct st_context
*st
)
306 struct pipe_blend_color bc
;
308 COPY_4FV(bc
.color
, st
->ctx
->Color
.BlendColorUnclamped
);
309 cso_set_blend_color(st
->cso_context
, &bc
);