Major rework of tnl module
[mesa.git] / src / mesa / main / blend.c
1 /* $Id: blend.c,v 1.27 2000/12/26 05:09:27 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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
29 #ifdef PC_HEADER
30 #include "all.h"
31 #else
32 #include "glheader.h"
33 #include "blend.h"
34 #include "context.h"
35 #include "enums.h"
36 #include "macros.h"
37 #include "mtypes.h"
38 #endif
39
40
41 void
42 _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
43 {
44
45 GET_CURRENT_CONTEXT(ctx);
46 ASSERT_OUTSIDE_BEGIN_END(ctx);
47
48 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
49 fprintf(stderr, "glBlendFunc %s %s\n",
50 gl_lookup_enum_by_nr(sfactor),
51 gl_lookup_enum_by_nr(dfactor));
52
53 switch (sfactor) {
54 case GL_SRC_COLOR:
55 case GL_ONE_MINUS_SRC_COLOR:
56 if (!ctx->Extensions.NV_blend_square) {
57 gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
58 return;
59 }
60 /* fall-through */
61 case GL_ZERO:
62 case GL_ONE:
63 case GL_DST_COLOR:
64 case GL_ONE_MINUS_DST_COLOR:
65 case GL_SRC_ALPHA:
66 case GL_ONE_MINUS_SRC_ALPHA:
67 case GL_DST_ALPHA:
68 case GL_ONE_MINUS_DST_ALPHA:
69 case GL_SRC_ALPHA_SATURATE:
70 case GL_CONSTANT_COLOR:
71 case GL_ONE_MINUS_CONSTANT_COLOR:
72 case GL_CONSTANT_ALPHA:
73 case GL_ONE_MINUS_CONSTANT_ALPHA:
74 break;
75 default:
76 gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
77 return;
78 }
79
80 switch (dfactor) {
81 case GL_DST_COLOR:
82 case GL_ONE_MINUS_DST_COLOR:
83 if (!ctx->Extensions.NV_blend_square) {
84 gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
85 return;
86 }
87 /* fall-through */
88 case GL_ZERO:
89 case GL_ONE:
90 case GL_SRC_COLOR:
91 case GL_ONE_MINUS_SRC_COLOR:
92 case GL_SRC_ALPHA:
93 case GL_ONE_MINUS_SRC_ALPHA:
94 case GL_DST_ALPHA:
95 case GL_ONE_MINUS_DST_ALPHA:
96 case GL_CONSTANT_COLOR:
97 case GL_ONE_MINUS_CONSTANT_COLOR:
98 case GL_CONSTANT_ALPHA:
99 case GL_ONE_MINUS_CONSTANT_ALPHA:
100 break;
101 default:
102 gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
103 return;
104 }
105
106 if (ctx->Color.BlendDstRGB == dfactor &&
107 ctx->Color.BlendSrcRGB == sfactor &&
108 ctx->Color.BlendDstA == dfactor &&
109 ctx->Color.BlendSrcA == sfactor)
110 return;
111
112 FLUSH_VERTICES(ctx, _NEW_COLOR);
113 ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor;
114 ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor;
115
116 if (ctx->Driver.BlendFunc)
117 ctx->Driver.BlendFunc( ctx, sfactor, dfactor );
118 }
119
120
121 /* GL_EXT_blend_func_separate */
122 void
123 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
124 GLenum sfactorA, GLenum dfactorA )
125 {
126 GET_CURRENT_CONTEXT(ctx);
127 ASSERT_OUTSIDE_BEGIN_END(ctx);
128
129 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
130 fprintf(stderr, "glBlendFuncSeperate %s %s %s %s\n",
131 gl_lookup_enum_by_nr(sfactorRGB),
132 gl_lookup_enum_by_nr(dfactorRGB),
133 gl_lookup_enum_by_nr(sfactorA),
134 gl_lookup_enum_by_nr(dfactorA));
135
136 switch (sfactorRGB) {
137 case GL_SRC_COLOR:
138 case GL_ONE_MINUS_SRC_COLOR:
139 if (!ctx->Extensions.NV_blend_square) {
140 gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
141 return;
142 }
143 /* fall-through */
144 case GL_ZERO:
145 case GL_ONE:
146 case GL_DST_COLOR:
147 case GL_ONE_MINUS_DST_COLOR:
148 case GL_SRC_ALPHA:
149 case GL_ONE_MINUS_SRC_ALPHA:
150 case GL_DST_ALPHA:
151 case GL_ONE_MINUS_DST_ALPHA:
152 case GL_SRC_ALPHA_SATURATE:
153 case GL_CONSTANT_COLOR:
154 case GL_ONE_MINUS_CONSTANT_COLOR:
155 case GL_CONSTANT_ALPHA:
156 case GL_ONE_MINUS_CONSTANT_ALPHA:
157 break;
158 default:
159 gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
160 return;
161 }
162
163 switch (dfactorRGB) {
164 case GL_DST_COLOR:
165 case GL_ONE_MINUS_DST_COLOR:
166 if (!ctx->Extensions.NV_blend_square) {
167 gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
168 return;
169 }
170 /* fall-through */
171 case GL_ZERO:
172 case GL_ONE:
173 case GL_SRC_COLOR:
174 case GL_ONE_MINUS_SRC_COLOR:
175 case GL_SRC_ALPHA:
176 case GL_ONE_MINUS_SRC_ALPHA:
177 case GL_DST_ALPHA:
178 case GL_ONE_MINUS_DST_ALPHA:
179 case GL_CONSTANT_COLOR:
180 case GL_ONE_MINUS_CONSTANT_COLOR:
181 case GL_CONSTANT_ALPHA:
182 case GL_ONE_MINUS_CONSTANT_ALPHA:
183 break;
184 default:
185 gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
186 return;
187 }
188
189 switch (sfactorA) {
190 case GL_SRC_COLOR:
191 case GL_ONE_MINUS_SRC_COLOR:
192 if (!ctx->Extensions.NV_blend_square) {
193 gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
194 return;
195 }
196 /* fall-through */
197 case GL_ZERO:
198 case GL_ONE:
199 case GL_DST_COLOR:
200 case GL_ONE_MINUS_DST_COLOR:
201 case GL_SRC_ALPHA:
202 case GL_ONE_MINUS_SRC_ALPHA:
203 case GL_DST_ALPHA:
204 case GL_ONE_MINUS_DST_ALPHA:
205 case GL_SRC_ALPHA_SATURATE:
206 case GL_CONSTANT_COLOR:
207 case GL_ONE_MINUS_CONSTANT_COLOR:
208 case GL_CONSTANT_ALPHA:
209 case GL_ONE_MINUS_CONSTANT_ALPHA:
210 break;
211 default:
212 gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
213 return;
214 }
215
216 switch (dfactorA) {
217 case GL_DST_COLOR:
218 case GL_ONE_MINUS_DST_COLOR:
219 if (!ctx->Extensions.NV_blend_square) {
220 gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)");
221 return;
222 }
223 /* fall-through */
224 case GL_ZERO:
225 case GL_ONE:
226 case GL_SRC_COLOR:
227 case GL_ONE_MINUS_SRC_COLOR:
228 case GL_SRC_ALPHA:
229 case GL_ONE_MINUS_SRC_ALPHA:
230 case GL_DST_ALPHA:
231 case GL_ONE_MINUS_DST_ALPHA:
232 case GL_CONSTANT_COLOR:
233 case GL_ONE_MINUS_CONSTANT_COLOR:
234 case GL_CONSTANT_ALPHA:
235 case GL_ONE_MINUS_CONSTANT_ALPHA:
236 break;
237 default:
238 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
239 return;
240 }
241
242 if (ctx->Color.BlendSrcRGB == sfactorRGB &&
243 ctx->Color.BlendDstRGB == dfactorRGB &&
244 ctx->Color.BlendSrcA == sfactorA &&
245 ctx->Color.BlendDstA == dfactorA)
246 return;
247
248 FLUSH_VERTICES(ctx, _NEW_COLOR);
249
250 ctx->Color.BlendSrcRGB = sfactorRGB;
251 ctx->Color.BlendDstRGB = dfactorRGB;
252 ctx->Color.BlendSrcA = sfactorA;
253 ctx->Color.BlendDstA = dfactorA;
254
255 if (ctx->Driver.BlendFuncSeparate) {
256 (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
257 sfactorA, dfactorA );
258 }
259 }
260
261
262
263 /* This is really an extension function! */
264 void
265 _mesa_BlendEquation( GLenum mode )
266 {
267 GET_CURRENT_CONTEXT(ctx);
268 ASSERT_OUTSIDE_BEGIN_END(ctx);
269
270 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
271 fprintf(stderr, "glBlendEquation %s\n",
272 gl_lookup_enum_by_nr(mode));
273
274 switch (mode) {
275 case GL_MIN_EXT:
276 case GL_MAX_EXT:
277 case GL_FUNC_ADD_EXT:
278 if (!ctx->Extensions.EXT_blend_minmax) {
279 gl_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
280 return;
281 }
282 case GL_LOGIC_OP:
283 break;
284 case GL_FUNC_SUBTRACT_EXT:
285 case GL_FUNC_REVERSE_SUBTRACT_EXT:
286 if (!ctx->Extensions.EXT_blend_subtract) {
287 gl_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
288 return;
289 }
290 break;
291 default:
292 gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
293 return;
294 }
295
296 if (ctx->Color.BlendEquation == mode)
297 return;
298
299 FLUSH_VERTICES(ctx, _NEW_COLOR);
300 ctx->Color.BlendEquation = mode;
301
302 /* This is needed to support 1.1's RGB logic ops AND
303 * 1.0's blending logicops.
304 */
305 ctx->Color.ColorLogicOpEnabled = (mode==GL_LOGIC_OP &&
306 ctx->Color.BlendEnabled);
307
308 if (ctx->Driver.BlendEquation)
309 ctx->Driver.BlendEquation( ctx, mode );
310 }
311
312
313
314 void
315 _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
316 {
317 GLfloat tmp[4];
318 GET_CURRENT_CONTEXT(ctx);
319 ASSERT_OUTSIDE_BEGIN_END(ctx);
320
321 tmp[0] = CLAMP( red, 0.0, 1.0 );
322 tmp[1] = CLAMP( green, 0.0, 1.0 );
323 tmp[2] = CLAMP( blue, 0.0, 1.0 );
324 tmp[3] = CLAMP( alpha, 0.0, 1.0 );
325
326 if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
327 return;
328
329 FLUSH_VERTICES(ctx, _NEW_COLOR);
330 COPY_4FV( ctx->Color.BlendColor, tmp );
331 }
332