Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /************************************************************************** |
2 | * |
||
3 | * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. |
||
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 TUNGSTEN GRAPHICS 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 |
||
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 "main/macros.h" |
||
43 | |||
44 | /** |
||
45 | * Convert GLenum blend tokens to pipe tokens. |
||
46 | * Both blend factors and blend funcs are accepted. |
||
47 | */ |
||
48 | static GLuint |
||
49 | translate_blend(GLenum blend) |
||
50 | { |
||
51 | switch (blend) { |
||
52 | /* blend functions */ |
||
53 | case GL_FUNC_ADD: |
||
54 | return PIPE_BLEND_ADD; |
||
55 | case GL_FUNC_SUBTRACT: |
||
56 | return PIPE_BLEND_SUBTRACT; |
||
57 | case GL_FUNC_REVERSE_SUBTRACT: |
||
58 | return PIPE_BLEND_REVERSE_SUBTRACT; |
||
59 | case GL_MIN: |
||
60 | return PIPE_BLEND_MIN; |
||
61 | case GL_MAX: |
||
62 | return PIPE_BLEND_MAX; |
||
63 | |||
64 | /* blend factors */ |
||
65 | case GL_ONE: |
||
66 | return PIPE_BLENDFACTOR_ONE; |
||
67 | case GL_SRC_COLOR: |
||
68 | return PIPE_BLENDFACTOR_SRC_COLOR; |
||
69 | case GL_SRC_ALPHA: |
||
70 | return PIPE_BLENDFACTOR_SRC_ALPHA; |
||
71 | case GL_DST_ALPHA: |
||
72 | return PIPE_BLENDFACTOR_DST_ALPHA; |
||
73 | case GL_DST_COLOR: |
||
74 | return PIPE_BLENDFACTOR_DST_COLOR; |
||
75 | case GL_SRC_ALPHA_SATURATE: |
||
76 | return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; |
||
77 | case GL_CONSTANT_COLOR: |
||
78 | return PIPE_BLENDFACTOR_CONST_COLOR; |
||
79 | case GL_CONSTANT_ALPHA: |
||
80 | return PIPE_BLENDFACTOR_CONST_ALPHA; |
||
81 | /* |
||
82 | return PIPE_BLENDFACTOR_SRC1_COLOR; |
||
83 | return PIPE_BLENDFACTOR_SRC1_ALPHA; |
||
84 | */ |
||
85 | case GL_ZERO: |
||
86 | return PIPE_BLENDFACTOR_ZERO; |
||
87 | case GL_ONE_MINUS_SRC_COLOR: |
||
88 | return PIPE_BLENDFACTOR_INV_SRC_COLOR; |
||
89 | case GL_ONE_MINUS_SRC_ALPHA: |
||
90 | return PIPE_BLENDFACTOR_INV_SRC_ALPHA; |
||
91 | case GL_ONE_MINUS_DST_COLOR: |
||
92 | return PIPE_BLENDFACTOR_INV_DST_COLOR; |
||
93 | case GL_ONE_MINUS_DST_ALPHA: |
||
94 | return PIPE_BLENDFACTOR_INV_DST_ALPHA; |
||
95 | case GL_ONE_MINUS_CONSTANT_COLOR: |
||
96 | return PIPE_BLENDFACTOR_INV_CONST_COLOR; |
||
97 | case GL_ONE_MINUS_CONSTANT_ALPHA: |
||
98 | return PIPE_BLENDFACTOR_INV_CONST_ALPHA; |
||
99 | /* |
||
100 | return PIPE_BLENDFACTOR_INV_SRC1_COLOR; |
||
101 | return PIPE_BLENDFACTOR_INV_SRC1_ALPHA; |
||
102 | */ |
||
103 | default: |
||
104 | assert("invalid GL token in translate_blend()" == NULL); |
||
105 | return 0; |
||
106 | } |
||
107 | } |
||
108 | |||
109 | |||
110 | /** |
||
111 | * Convert GLenum logicop tokens to pipe tokens. |
||
112 | */ |
||
113 | static GLuint |
||
114 | translate_logicop(GLenum logicop) |
||
115 | { |
||
116 | switch (logicop) { |
||
117 | case GL_CLEAR: |
||
118 | return PIPE_LOGICOP_CLEAR; |
||
119 | case GL_NOR: |
||
120 | return PIPE_LOGICOP_NOR; |
||
121 | case GL_AND_INVERTED: |
||
122 | return PIPE_LOGICOP_AND_INVERTED; |
||
123 | case GL_COPY_INVERTED: |
||
124 | return PIPE_LOGICOP_COPY_INVERTED; |
||
125 | case GL_AND_REVERSE: |
||
126 | return PIPE_LOGICOP_AND_REVERSE; |
||
127 | case GL_INVERT: |
||
128 | return PIPE_LOGICOP_INVERT; |
||
129 | case GL_XOR: |
||
130 | return PIPE_LOGICOP_XOR; |
||
131 | case GL_NAND: |
||
132 | return PIPE_LOGICOP_NAND; |
||
133 | case GL_AND: |
||
134 | return PIPE_LOGICOP_AND; |
||
135 | case GL_EQUIV: |
||
136 | return PIPE_LOGICOP_EQUIV; |
||
137 | case GL_NOOP: |
||
138 | return PIPE_LOGICOP_NOOP; |
||
139 | case GL_OR_INVERTED: |
||
140 | return PIPE_LOGICOP_OR_INVERTED; |
||
141 | case GL_COPY: |
||
142 | return PIPE_LOGICOP_COPY; |
||
143 | case GL_OR_REVERSE: |
||
144 | return PIPE_LOGICOP_OR_REVERSE; |
||
145 | case GL_OR: |
||
146 | return PIPE_LOGICOP_OR; |
||
147 | case GL_SET: |
||
148 | return PIPE_LOGICOP_SET; |
||
149 | default: |
||
150 | assert("invalid GL token in translate_logicop()" == NULL); |
||
151 | return 0; |
||
152 | } |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Figure out if colormasks are different per rt. |
||
157 | */ |
||
158 | static GLboolean |
||
159 | colormask_per_rt(struct gl_context *ctx) |
||
160 | { |
||
161 | /* a bit suboptimal have to compare lots of values */ |
||
162 | unsigned i; |
||
163 | for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) { |
||
164 | if (memcmp(ctx->Color.ColorMask[0], ctx->Color.ColorMask[i], 4)) { |
||
165 | return GL_TRUE; |
||
166 | } |
||
167 | } |
||
168 | return GL_FALSE; |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Figure out if blend enables are different per rt. |
||
173 | */ |
||
174 | static GLboolean |
||
175 | blend_per_rt(struct gl_context *ctx) |
||
176 | { |
||
177 | if (ctx->Color.BlendEnabled && |
||
178 | (ctx->Color.BlendEnabled != ((1 << ctx->Const.MaxDrawBuffers) - 1))) { |
||
179 | return GL_TRUE; |
||
180 | } |
||
181 | return GL_FALSE; |
||
182 | } |
||
183 | |||
184 | static void |
||
185 | update_blend( struct st_context *st ) |
||
186 | { |
||
187 | struct pipe_blend_state *blend = &st->state.blend; |
||
188 | unsigned num_state = 1; |
||
189 | unsigned i; |
||
190 | |||
191 | memset(blend, 0, sizeof(*blend)); |
||
192 | |||
193 | if (blend_per_rt(st->ctx) || colormask_per_rt(st->ctx)) { |
||
194 | num_state = st->ctx->Const.MaxDrawBuffers; |
||
195 | blend->independent_blend_enable = 1; |
||
196 | } |
||
197 | /* Note it is impossible to correctly deal with EXT_blend_logic_op and |
||
198 | EXT_draw_buffers2/EXT_blend_equation_separate at the same time. |
||
199 | These combinations would require support for per-rt logicop enables |
||
200 | and separate alpha/rgb logicop/blend support respectively. Neither |
||
201 | possible in gallium nor most hardware. Assume these combinations |
||
202 | don't happen. */ |
||
203 | if (st->ctx->Color.ColorLogicOpEnabled || |
||
204 | (st->ctx->Color.BlendEnabled && |
||
205 | st->ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) { |
||
206 | /* logicop enabled */ |
||
207 | blend->logicop_enable = 1; |
||
208 | blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp); |
||
209 | } |
||
210 | else if (st->ctx->Color.BlendEnabled) { |
||
211 | /* blending enabled */ |
||
212 | for (i = 0; i < num_state; i++) { |
||
213 | |||
214 | blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1; |
||
215 | |||
216 | blend->rt[i].rgb_func = translate_blend(st->ctx->Color.BlendEquationRGB); |
||
217 | if (st->ctx->Color.BlendEquationRGB == GL_MIN || |
||
218 | st->ctx->Color.BlendEquationRGB == GL_MAX) { |
||
219 | /* Min/max are special */ |
||
220 | blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE; |
||
221 | blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; |
||
222 | } |
||
223 | else { |
||
224 | blend->rt[i].rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB); |
||
225 | blend->rt[i].rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB); |
||
226 | } |
||
227 | |||
228 | blend->rt[i].alpha_func = translate_blend(st->ctx->Color.BlendEquationA); |
||
229 | if (st->ctx->Color.BlendEquationA == GL_MIN || |
||
230 | st->ctx->Color.BlendEquationA == GL_MAX) { |
||
231 | /* Min/max are special */ |
||
232 | blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE; |
||
233 | blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; |
||
234 | } |
||
235 | else { |
||
236 | blend->rt[i].alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA); |
||
237 | blend->rt[i].alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA); |
||
238 | } |
||
239 | } |
||
240 | } |
||
241 | else { |
||
242 | /* no blending / logicop */ |
||
243 | } |
||
244 | |||
245 | /* Colormask - maybe reverse these bits? */ |
||
246 | for (i = 0; i < num_state; i++) { |
||
247 | if (st->ctx->Color.ColorMask[i][0]) |
||
248 | blend->rt[i].colormask |= PIPE_MASK_R; |
||
249 | if (st->ctx->Color.ColorMask[i][1]) |
||
250 | blend->rt[i].colormask |= PIPE_MASK_G; |
||
251 | if (st->ctx->Color.ColorMask[i][2]) |
||
252 | blend->rt[i].colormask |= PIPE_MASK_B; |
||
253 | if (st->ctx->Color.ColorMask[i][3]) |
||
254 | blend->rt[i].colormask |= PIPE_MASK_A; |
||
255 | } |
||
256 | |||
257 | if (st->ctx->Color.DitherFlag) |
||
258 | blend->dither = 1; |
||
259 | |||
260 | if (st->ctx->Multisample.Enabled) { |
||
261 | /* unlike in gallium/d3d10 these operations are only performed |
||
262 | if msaa is enabled */ |
||
263 | if (st->ctx->Multisample.SampleAlphaToCoverage) |
||
264 | blend->alpha_to_coverage = 1; |
||
265 | if (st->ctx->Multisample.SampleAlphaToOne) |
||
266 | blend->alpha_to_one = 1; |
||
267 | } |
||
268 | |||
269 | cso_set_blend(st->cso_context, blend); |
||
270 | |||
271 | { |
||
272 | struct pipe_blend_color bc; |
||
273 | COPY_4FV(bc.color, st->ctx->Color.BlendColor); |
||
274 | cso_set_blend_color(st->cso_context, &bc); |
||
275 | } |
||
276 | } |
||
277 | |||
278 | |||
279 | const struct st_tracked_state st_update_blend = { |
||
280 | "st_update_blend", /* name */ |
||
281 | { /* dirty */ |
||
282 | (_NEW_COLOR | _NEW_MULTISAMPLE), /* XXX _NEW_BLEND someday? */ /* mesa */ |
||
283 | 0, /* st */ |
||
284 | }, |
||
285 | update_blend, /* update */ |
||
286 | };>>><>> |