st/mesa: Disable blending for integer formats.
[mesa.git] / src / mesa / state_tracker / st_atom_blend.c
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/macros.h"
45
46 /**
47 * Convert GLenum blend tokens to pipe tokens.
48 * Both blend factors and blend funcs are accepted.
49 */
50 static GLuint
51 translate_blend(GLenum blend)
52 {
53 switch (blend) {
54 /* blend functions */
55 case GL_FUNC_ADD:
56 return PIPE_BLEND_ADD;
57 case GL_FUNC_SUBTRACT:
58 return PIPE_BLEND_SUBTRACT;
59 case GL_FUNC_REVERSE_SUBTRACT:
60 return PIPE_BLEND_REVERSE_SUBTRACT;
61 case GL_MIN:
62 return PIPE_BLEND_MIN;
63 case GL_MAX:
64 return PIPE_BLEND_MAX;
65
66 /* blend factors */
67 case GL_ONE:
68 return PIPE_BLENDFACTOR_ONE;
69 case GL_SRC_COLOR:
70 return PIPE_BLENDFACTOR_SRC_COLOR;
71 case GL_SRC_ALPHA:
72 return PIPE_BLENDFACTOR_SRC_ALPHA;
73 case GL_DST_ALPHA:
74 return PIPE_BLENDFACTOR_DST_ALPHA;
75 case GL_DST_COLOR:
76 return PIPE_BLENDFACTOR_DST_COLOR;
77 case GL_SRC_ALPHA_SATURATE:
78 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
79 case GL_CONSTANT_COLOR:
80 return PIPE_BLENDFACTOR_CONST_COLOR;
81 case GL_CONSTANT_ALPHA:
82 return PIPE_BLENDFACTOR_CONST_ALPHA;
83 case GL_SRC1_COLOR:
84 return PIPE_BLENDFACTOR_SRC1_COLOR;
85 case GL_SRC1_ALPHA:
86 return PIPE_BLENDFACTOR_SRC1_ALPHA;
87 case GL_ZERO:
88 return PIPE_BLENDFACTOR_ZERO;
89 case GL_ONE_MINUS_SRC_COLOR:
90 return PIPE_BLENDFACTOR_INV_SRC_COLOR;
91 case GL_ONE_MINUS_SRC_ALPHA:
92 return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
93 case GL_ONE_MINUS_DST_COLOR:
94 return PIPE_BLENDFACTOR_INV_DST_COLOR;
95 case GL_ONE_MINUS_DST_ALPHA:
96 return PIPE_BLENDFACTOR_INV_DST_ALPHA;
97 case GL_ONE_MINUS_CONSTANT_COLOR:
98 return PIPE_BLENDFACTOR_INV_CONST_COLOR;
99 case GL_ONE_MINUS_CONSTANT_ALPHA:
100 return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
101 case GL_ONE_MINUS_SRC1_COLOR:
102 return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
103 case GL_ONE_MINUS_SRC1_ALPHA:
104 return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
105 default:
106 assert("invalid GL token in translate_blend()" == NULL);
107 return 0;
108 }
109 }
110
111 /**
112 * Figure out if colormasks are different per rt.
113 */
114 static GLboolean
115 colormask_per_rt(const struct gl_context *ctx, unsigned num_cb)
116 {
117 GLbitfield full_mask = _mesa_replicate_colormask(0xf, num_cb);
118 GLbitfield repl_mask0 =
119 _mesa_replicate_colormask(GET_COLORMASK(ctx->Color.ColorMask, 0),
120 num_cb);
121
122 return (ctx->Color.ColorMask & full_mask) != repl_mask0;
123 }
124
125 /**
126 * Figure out if blend enables/state are different per rt.
127 */
128 static GLboolean
129 blend_per_rt(const struct gl_context *ctx, unsigned num_cb)
130 {
131 GLbitfield cb_mask = u_bit_consecutive(0, num_cb);
132 GLbitfield blend_enabled = ctx->Color.BlendEnabled & cb_mask;
133
134 if (blend_enabled && blend_enabled != cb_mask) {
135 /* This can only happen if GL_EXT_draw_buffers2 is enabled */
136 return GL_TRUE;
137 }
138 if (ctx->Color._BlendFuncPerBuffer || ctx->Color._BlendEquationPerBuffer) {
139 /* this can only happen if GL_ARB_draw_buffers_blend is enabled */
140 return GL_TRUE;
141 }
142 return GL_FALSE;
143 }
144
145 void
146 st_update_blend( struct st_context *st )
147 {
148 struct pipe_blend_state *blend = &st->state.blend;
149 const struct gl_context *ctx = st->ctx;
150 unsigned num_cb = st->state.fb_num_cb;
151 unsigned num_state = 1;
152 unsigned i, j;
153
154 memset(blend, 0, sizeof(*blend));
155
156 if (num_cb > 1 &&
157 (blend_per_rt(ctx, num_cb) || colormask_per_rt(ctx, num_cb))) {
158 num_state = num_cb;
159 blend->independent_blend_enable = 1;
160 }
161
162 for (i = 0; i < num_state; i++)
163 blend->rt[i].colormask = GET_COLORMASK(ctx->Color.ColorMask, i);
164
165 if (ctx->Color.ColorLogicOpEnabled) {
166 /* logicop enabled */
167 blend->logicop_enable = 1;
168 blend->logicop_func = ctx->Color._LogicOp;
169 }
170 else if (ctx->Color.BlendEnabled && !ctx->Color._AdvancedBlendMode) {
171 /* blending enabled */
172 for (i = 0, j = 0; i < num_state; i++) {
173 if (!(ctx->Color.BlendEnabled & (1 << i)) ||
174 (ctx->DrawBuffer->_IntegerBuffers & (1 << i)) ||
175 !blend->rt[i].colormask)
176 continue;
177
178 if (ctx->Extensions.ARB_draw_buffers_blend)
179 j = i;
180
181 blend->rt[i].blend_enable = 1;
182 blend->rt[i].rgb_func =
183 translate_blend(ctx->Color.Blend[j].EquationRGB);
184
185 if (ctx->Color.Blend[i].EquationRGB == GL_MIN ||
186 ctx->Color.Blend[i].EquationRGB == GL_MAX) {
187 /* Min/max are special */
188 blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
189 blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
190 }
191 else {
192 blend->rt[i].rgb_src_factor =
193 translate_blend(ctx->Color.Blend[j].SrcRGB);
194 blend->rt[i].rgb_dst_factor =
195 translate_blend(ctx->Color.Blend[j].DstRGB);
196 }
197
198 blend->rt[i].alpha_func =
199 translate_blend(ctx->Color.Blend[j].EquationA);
200
201 if (ctx->Color.Blend[i].EquationA == GL_MIN ||
202 ctx->Color.Blend[i].EquationA == GL_MAX) {
203 /* Min/max are special */
204 blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
205 blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
206 }
207 else {
208 blend->rt[i].alpha_src_factor =
209 translate_blend(ctx->Color.Blend[j].SrcA);
210 blend->rt[i].alpha_dst_factor =
211 translate_blend(ctx->Color.Blend[j].DstA);
212 }
213 }
214 }
215 else {
216 /* no blending / logicop */
217 }
218
219 blend->dither = ctx->Color.DitherFlag;
220
221 if (_mesa_is_multisample_enabled(ctx) &&
222 !(ctx->DrawBuffer->_IntegerBuffers & 0x1)) {
223 /* Unlike in gallium/d3d10 these operations are only performed
224 * if both msaa is enabled and we have a multisample buffer.
225 */
226 blend->alpha_to_coverage = ctx->Multisample.SampleAlphaToCoverage;
227 blend->alpha_to_one = ctx->Multisample.SampleAlphaToOne;
228 }
229
230 cso_set_blend(st->cso_context, blend);
231 }
232
233 void
234 st_update_blend_color(struct st_context *st)
235 {
236 struct pipe_blend_color bc;
237
238 COPY_4FV(bc.color, st->ctx->Color.BlendColorUnclamped);
239 cso_set_blend_color(st->cso_context, &bc);
240 }