fix for gl_ztrick bug (Ove Kaaven)
[mesa.git] / src / mesa / main / blend.c
1 /* $Id: blend.c,v 1.31 2001/03/12 00:48:37 gareth Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "blend.h"
33 #include "context.h"
34 #include "enums.h"
35 #include "macros.h"
36 #include "mtypes.h"
37 #endif
38
39
40 void
41 _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
42 {
43
44 GET_CURRENT_CONTEXT(ctx);
45 ASSERT_OUTSIDE_BEGIN_END(ctx);
46
47 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
48 fprintf(stderr, "glBlendFunc %s %s\n",
49 _mesa_lookup_enum_by_nr(sfactor),
50 _mesa_lookup_enum_by_nr(dfactor));
51
52 switch (sfactor) {
53 case GL_SRC_COLOR:
54 case GL_ONE_MINUS_SRC_COLOR:
55 if (!ctx->Extensions.NV_blend_square) {
56 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
57 return;
58 }
59 /* fall-through */
60 case GL_ZERO:
61 case GL_ONE:
62 case GL_DST_COLOR:
63 case GL_ONE_MINUS_DST_COLOR:
64 case GL_SRC_ALPHA:
65 case GL_ONE_MINUS_SRC_ALPHA:
66 case GL_DST_ALPHA:
67 case GL_ONE_MINUS_DST_ALPHA:
68 case GL_SRC_ALPHA_SATURATE:
69 case GL_CONSTANT_COLOR:
70 case GL_ONE_MINUS_CONSTANT_COLOR:
71 case GL_CONSTANT_ALPHA:
72 case GL_ONE_MINUS_CONSTANT_ALPHA:
73 break;
74 default:
75 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
76 return;
77 }
78
79 switch (dfactor) {
80 case GL_DST_COLOR:
81 case GL_ONE_MINUS_DST_COLOR:
82 if (!ctx->Extensions.NV_blend_square) {
83 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
84 return;
85 }
86 /* fall-through */
87 case GL_ZERO:
88 case GL_ONE:
89 case GL_SRC_COLOR:
90 case GL_ONE_MINUS_SRC_COLOR:
91 case GL_SRC_ALPHA:
92 case GL_ONE_MINUS_SRC_ALPHA:
93 case GL_DST_ALPHA:
94 case GL_ONE_MINUS_DST_ALPHA:
95 case GL_CONSTANT_COLOR:
96 case GL_ONE_MINUS_CONSTANT_COLOR:
97 case GL_CONSTANT_ALPHA:
98 case GL_ONE_MINUS_CONSTANT_ALPHA:
99 break;
100 default:
101 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
102 return;
103 }
104
105 if (ctx->Color.BlendDstRGB == dfactor &&
106 ctx->Color.BlendSrcRGB == sfactor &&
107 ctx->Color.BlendDstA == dfactor &&
108 ctx->Color.BlendSrcA == sfactor)
109 return;
110
111 FLUSH_VERTICES(ctx, _NEW_COLOR);
112 ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor;
113 ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor;
114
115 if (ctx->Driver.BlendFunc)
116 ctx->Driver.BlendFunc( ctx, sfactor, dfactor );
117 }
118
119
120 /* GL_EXT_blend_func_separate */
121 void
122 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
123 GLenum sfactorA, GLenum dfactorA )
124 {
125 GET_CURRENT_CONTEXT(ctx);
126 ASSERT_OUTSIDE_BEGIN_END(ctx);
127
128 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
129 fprintf(stderr, "glBlendFuncSeperate %s %s %s %s\n",
130 _mesa_lookup_enum_by_nr(sfactorRGB),
131 _mesa_lookup_enum_by_nr(dfactorRGB),
132 _mesa_lookup_enum_by_nr(sfactorA),
133 _mesa_lookup_enum_by_nr(dfactorA));
134
135 switch (sfactorRGB) {
136 case GL_SRC_COLOR:
137 case GL_ONE_MINUS_SRC_COLOR:
138 if (!ctx->Extensions.NV_blend_square) {
139 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
140 return;
141 }
142 /* fall-through */
143 case GL_ZERO:
144 case GL_ONE:
145 case GL_DST_COLOR:
146 case GL_ONE_MINUS_DST_COLOR:
147 case GL_SRC_ALPHA:
148 case GL_ONE_MINUS_SRC_ALPHA:
149 case GL_DST_ALPHA:
150 case GL_ONE_MINUS_DST_ALPHA:
151 case GL_SRC_ALPHA_SATURATE:
152 case GL_CONSTANT_COLOR:
153 case GL_ONE_MINUS_CONSTANT_COLOR:
154 case GL_CONSTANT_ALPHA:
155 case GL_ONE_MINUS_CONSTANT_ALPHA:
156 break;
157 default:
158 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
159 return;
160 }
161
162 switch (dfactorRGB) {
163 case GL_DST_COLOR:
164 case GL_ONE_MINUS_DST_COLOR:
165 if (!ctx->Extensions.NV_blend_square) {
166 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
167 return;
168 }
169 /* fall-through */
170 case GL_ZERO:
171 case GL_ONE:
172 case GL_SRC_COLOR:
173 case GL_ONE_MINUS_SRC_COLOR:
174 case GL_SRC_ALPHA:
175 case GL_ONE_MINUS_SRC_ALPHA:
176 case GL_DST_ALPHA:
177 case GL_ONE_MINUS_DST_ALPHA:
178 case GL_CONSTANT_COLOR:
179 case GL_ONE_MINUS_CONSTANT_COLOR:
180 case GL_CONSTANT_ALPHA:
181 case GL_ONE_MINUS_CONSTANT_ALPHA:
182 break;
183 default:
184 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
185 return;
186 }
187
188 switch (sfactorA) {
189 case GL_SRC_COLOR:
190 case GL_ONE_MINUS_SRC_COLOR:
191 if (!ctx->Extensions.NV_blend_square) {
192 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
193 return;
194 }
195 /* fall-through */
196 case GL_ZERO:
197 case GL_ONE:
198 case GL_DST_COLOR:
199 case GL_ONE_MINUS_DST_COLOR:
200 case GL_SRC_ALPHA:
201 case GL_ONE_MINUS_SRC_ALPHA:
202 case GL_DST_ALPHA:
203 case GL_ONE_MINUS_DST_ALPHA:
204 case GL_SRC_ALPHA_SATURATE:
205 case GL_CONSTANT_COLOR:
206 case GL_ONE_MINUS_CONSTANT_COLOR:
207 case GL_CONSTANT_ALPHA:
208 case GL_ONE_MINUS_CONSTANT_ALPHA:
209 break;
210 default:
211 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
212 return;
213 }
214
215 switch (dfactorA) {
216 case GL_DST_COLOR:
217 case GL_ONE_MINUS_DST_COLOR:
218 if (!ctx->Extensions.NV_blend_square) {
219 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)");
220 return;
221 }
222 /* fall-through */
223 case GL_ZERO:
224 case GL_ONE:
225 case GL_SRC_COLOR:
226 case GL_ONE_MINUS_SRC_COLOR:
227 case GL_SRC_ALPHA:
228 case GL_ONE_MINUS_SRC_ALPHA:
229 case GL_DST_ALPHA:
230 case GL_ONE_MINUS_DST_ALPHA:
231 case GL_CONSTANT_COLOR:
232 case GL_ONE_MINUS_CONSTANT_COLOR:
233 case GL_CONSTANT_ALPHA:
234 case GL_ONE_MINUS_CONSTANT_ALPHA:
235 break;
236 default:
237 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
238 return;
239 }
240
241 if (ctx->Color.BlendSrcRGB == sfactorRGB &&
242 ctx->Color.BlendDstRGB == dfactorRGB &&
243 ctx->Color.BlendSrcA == sfactorA &&
244 ctx->Color.BlendDstA == dfactorA)
245 return;
246
247 FLUSH_VERTICES(ctx, _NEW_COLOR);
248
249 ctx->Color.BlendSrcRGB = sfactorRGB;
250 ctx->Color.BlendDstRGB = dfactorRGB;
251 ctx->Color.BlendSrcA = sfactorA;
252 ctx->Color.BlendDstA = dfactorA;
253
254 if (ctx->Driver.BlendFuncSeparate) {
255 (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
256 sfactorA, dfactorA );
257 }
258 }
259
260
261
262 /* This is really an extension function! */
263 void
264 _mesa_BlendEquation( GLenum mode )
265 {
266 GET_CURRENT_CONTEXT(ctx);
267 ASSERT_OUTSIDE_BEGIN_END(ctx);
268
269 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
270 fprintf(stderr, "glBlendEquation %s\n",
271 _mesa_lookup_enum_by_nr(mode));
272
273 switch (mode) {
274 case GL_FUNC_ADD_EXT:
275 break;
276 case GL_MIN_EXT:
277 case GL_MAX_EXT:
278 if (!ctx->Extensions.EXT_blend_minmax &&
279 !ctx->Extensions.ARB_imaging) {
280 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
281 return;
282 }
283 break;
284 case GL_LOGIC_OP:
285 if (!ctx->Extensions.EXT_blend_logic_op) {
286 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
287 return;
288 }
289 break;
290 case GL_FUNC_SUBTRACT_EXT:
291 case GL_FUNC_REVERSE_SUBTRACT_EXT:
292 if (!ctx->Extensions.EXT_blend_subtract &&
293 !ctx->Extensions.ARB_imaging) {
294 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
295 return;
296 }
297 break;
298 default:
299 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
300 return;
301 }
302
303 if (ctx->Color.BlendEquation == mode)
304 return;
305
306 FLUSH_VERTICES(ctx, _NEW_COLOR);
307 ctx->Color.BlendEquation = mode;
308
309 /* This is needed to support 1.1's RGB logic ops AND
310 * 1.0's blending logicops.
311 */
312 ctx->Color.ColorLogicOpEnabled = (mode==GL_LOGIC_OP &&
313 ctx->Color.BlendEnabled);
314
315 if (ctx->Driver.BlendEquation)
316 (*ctx->Driver.BlendEquation)( ctx, mode );
317 }
318
319
320
321 void
322 _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
323 {
324 GLfloat tmp[4];
325 GET_CURRENT_CONTEXT(ctx);
326 ASSERT_OUTSIDE_BEGIN_END(ctx);
327
328 tmp[0] = CLAMP( red, 0.0, 1.0 );
329 tmp[1] = CLAMP( green, 0.0, 1.0 );
330 tmp[2] = CLAMP( blue, 0.0, 1.0 );
331 tmp[3] = CLAMP( alpha, 0.0, 1.0 );
332
333 if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
334 return;
335
336 FLUSH_VERTICES(ctx, _NEW_COLOR);
337 COPY_4FV( ctx->Color.BlendColor, tmp );
338
339 if (ctx->Driver.BlendColor)
340 (*ctx->Driver.BlendColor)(ctx, tmp);
341 }