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