mesa: change ctx->Color.ColorMask into a 32-bit bitmask
[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)
116 {
117 GLbitfield repl_mask0 =
118 _mesa_replicate_colormask(GET_COLORMASK(ctx->Color.ColorMask, 0),
119 ctx->Const.MaxDrawBuffers);
120
121 return ctx->Color.ColorMask != repl_mask0;
122 }
123
124 /**
125 * Figure out if blend enables/state are different per rt.
126 */
127 static GLboolean
128 blend_per_rt(const struct gl_context *ctx)
129 {
130 if (ctx->Color.BlendEnabled &&
131 (ctx->Color.BlendEnabled != ((1U << ctx->Const.MaxDrawBuffers) - 1))) {
132 /* This can only happen if GL_EXT_draw_buffers2 is enabled */
133 return GL_TRUE;
134 }
135 if (ctx->Color._BlendFuncPerBuffer || ctx->Color._BlendEquationPerBuffer) {
136 /* this can only happen if GL_ARB_draw_buffers_blend is enabled */
137 return GL_TRUE;
138 }
139 return GL_FALSE;
140 }
141
142 void
143 st_update_blend( struct st_context *st )
144 {
145 struct pipe_blend_state *blend = &st->state.blend;
146 const struct gl_context *ctx = st->ctx;
147 unsigned num_state = 1;
148 unsigned i, j;
149
150 memset(blend, 0, sizeof(*blend));
151
152 if (blend_per_rt(ctx) || colormask_per_rt(ctx)) {
153 num_state = ctx->Const.MaxDrawBuffers;
154 blend->independent_blend_enable = 1;
155 }
156 if (ctx->Color.ColorLogicOpEnabled) {
157 /* logicop enabled */
158 blend->logicop_enable = 1;
159 blend->logicop_func = ctx->Color._LogicOp;
160 }
161 else if (ctx->Color.BlendEnabled && !ctx->Color._AdvancedBlendMode) {
162 /* blending enabled */
163 for (i = 0, j = 0; i < num_state; i++) {
164
165 blend->rt[i].blend_enable = (ctx->Color.BlendEnabled >> i) & 0x1;
166
167 if (ctx->Extensions.ARB_draw_buffers_blend)
168 j = i;
169
170 blend->rt[i].rgb_func =
171 translate_blend(ctx->Color.Blend[j].EquationRGB);
172
173 if (ctx->Color.Blend[i].EquationRGB == GL_MIN ||
174 ctx->Color.Blend[i].EquationRGB == GL_MAX) {
175 /* Min/max are special */
176 blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
177 blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
178 }
179 else {
180 blend->rt[i].rgb_src_factor =
181 translate_blend(ctx->Color.Blend[j].SrcRGB);
182 blend->rt[i].rgb_dst_factor =
183 translate_blend(ctx->Color.Blend[j].DstRGB);
184 }
185
186 blend->rt[i].alpha_func =
187 translate_blend(ctx->Color.Blend[j].EquationA);
188
189 if (ctx->Color.Blend[i].EquationA == GL_MIN ||
190 ctx->Color.Blend[i].EquationA == GL_MAX) {
191 /* Min/max are special */
192 blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
193 blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
194 }
195 else {
196 blend->rt[i].alpha_src_factor =
197 translate_blend(ctx->Color.Blend[j].SrcA);
198 blend->rt[i].alpha_dst_factor =
199 translate_blend(ctx->Color.Blend[j].DstA);
200 }
201 }
202 }
203 else {
204 /* no blending / logicop */
205 }
206
207 for (i = 0; i < num_state; i++)
208 blend->rt[i].colormask = GET_COLORMASK(ctx->Color.ColorMask, i);
209
210 blend->dither = ctx->Color.DitherFlag;
211
212 if (_mesa_is_multisample_enabled(ctx) &&
213 !(ctx->DrawBuffer->_IntegerBuffers & 0x1)) {
214 /* Unlike in gallium/d3d10 these operations are only performed
215 * if both msaa is enabled and we have a multisample buffer.
216 */
217 blend->alpha_to_coverage = ctx->Multisample.SampleAlphaToCoverage;
218 blend->alpha_to_one = ctx->Multisample.SampleAlphaToOne;
219 }
220
221 cso_set_blend(st->cso_context, blend);
222 }
223
224 void
225 st_update_blend_color(struct st_context *st)
226 {
227 struct pipe_blend_color bc;
228
229 COPY_4FV(bc.color, st->ctx->Color.BlendColorUnclamped);
230 cso_set_blend_color(st->cso_context, &bc);
231 }