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