Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/* $Id: blend.c,v 1.1 2003-02-28 11:41:58 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  4.1
6
 *
7
 * Copyright (C) 1999-2002  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
#include "glheader.h"
29
#include "blend.h"
30
#include "colormac.h"
31
#include "context.h"
32
#include "enums.h"
33
#include "macros.h"
34
#include "mtypes.h"
35
 
36
 
37
void
38
_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
39
{
40
 
41
   GET_CURRENT_CONTEXT(ctx);
42
   ASSERT_OUTSIDE_BEGIN_END(ctx);
43
 
44
   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
45
      _mesa_debug(ctx, "glBlendFunc %s %s\n",
46
                  _mesa_lookup_enum_by_nr(sfactor),
47
                  _mesa_lookup_enum_by_nr(dfactor));
48
 
49
   switch (sfactor) {
50
      case GL_SRC_COLOR:
51
      case GL_ONE_MINUS_SRC_COLOR:
52
         if (!ctx->Extensions.NV_blend_square) {
53
            _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
54
            return;
55
         }
56
         /* fall-through */
57
      case GL_ZERO:
58
      case GL_ONE:
59
      case GL_DST_COLOR:
60
      case GL_ONE_MINUS_DST_COLOR:
61
      case GL_SRC_ALPHA:
62
      case GL_ONE_MINUS_SRC_ALPHA:
63
      case GL_DST_ALPHA:
64
      case GL_ONE_MINUS_DST_ALPHA:
65
      case GL_SRC_ALPHA_SATURATE:
66
      case GL_CONSTANT_COLOR:
67
      case GL_ONE_MINUS_CONSTANT_COLOR:
68
      case GL_CONSTANT_ALPHA:
69
      case GL_ONE_MINUS_CONSTANT_ALPHA:
70
         break;
71
      default:
72
         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
73
         return;
74
   }
75
 
76
   switch (dfactor) {
77
      case GL_DST_COLOR:
78
      case GL_ONE_MINUS_DST_COLOR:
79
         if (!ctx->Extensions.NV_blend_square) {
80
            _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
81
            return;
82
         }
83
         /* fall-through */
84
      case GL_ZERO:
85
      case GL_ONE:
86
      case GL_SRC_COLOR:
87
      case GL_ONE_MINUS_SRC_COLOR:
88
      case GL_SRC_ALPHA:
89
      case GL_ONE_MINUS_SRC_ALPHA:
90
      case GL_DST_ALPHA:
91
      case GL_ONE_MINUS_DST_ALPHA:
92
      case GL_CONSTANT_COLOR:
93
      case GL_ONE_MINUS_CONSTANT_COLOR:
94
      case GL_CONSTANT_ALPHA:
95
      case GL_ONE_MINUS_CONSTANT_ALPHA:
96
         break;
97
      default:
98
         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
99
         return;
100
   }
101
 
102
   if (ctx->Color.BlendDstRGB == dfactor &&
103
       ctx->Color.BlendSrcRGB == sfactor &&
104
       ctx->Color.BlendDstA == dfactor &&
105
       ctx->Color.BlendSrcA == sfactor)
106
      return;
107
 
108
   FLUSH_VERTICES(ctx, _NEW_COLOR);
109
   ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor;
110
   ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor;
111
 
112
   if (ctx->Driver.BlendFunc)
113
      ctx->Driver.BlendFunc( ctx, sfactor, dfactor );
114
}
115
 
116
 
117
/* GL_EXT_blend_func_separate */
118
void
119
_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
120
                            GLenum sfactorA, GLenum dfactorA )
121
{
122
   GET_CURRENT_CONTEXT(ctx);
123
   ASSERT_OUTSIDE_BEGIN_END(ctx);
124
 
125
   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
126
      _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
127
                  _mesa_lookup_enum_by_nr(sfactorRGB),
128
                  _mesa_lookup_enum_by_nr(dfactorRGB),
129
                  _mesa_lookup_enum_by_nr(sfactorA),
130
                  _mesa_lookup_enum_by_nr(dfactorA));
131
 
132
   switch (sfactorRGB) {
133
      case GL_SRC_COLOR:
134
      case GL_ONE_MINUS_SRC_COLOR:
135
         if (!ctx->Extensions.NV_blend_square) {
136
            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
137
            return;
138
         }
139
         /* fall-through */
140
      case GL_ZERO:
141
      case GL_ONE:
142
      case GL_DST_COLOR:
143
      case GL_ONE_MINUS_DST_COLOR:
144
      case GL_SRC_ALPHA:
145
      case GL_ONE_MINUS_SRC_ALPHA:
146
      case GL_DST_ALPHA:
147
      case GL_ONE_MINUS_DST_ALPHA:
148
      case GL_SRC_ALPHA_SATURATE:
149
      case GL_CONSTANT_COLOR:
150
      case GL_ONE_MINUS_CONSTANT_COLOR:
151
      case GL_CONSTANT_ALPHA:
152
      case GL_ONE_MINUS_CONSTANT_ALPHA:
153
         break;
154
      default:
155
         _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
156
         return;
157
   }
158
 
159
   switch (dfactorRGB) {
160
      case GL_DST_COLOR:
161
      case GL_ONE_MINUS_DST_COLOR:
162
         if (!ctx->Extensions.NV_blend_square) {
163
            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
164
            return;
165
         }
166
         /* fall-through */
167
      case GL_ZERO:
168
      case GL_ONE:
169
      case GL_SRC_COLOR:
170
      case GL_ONE_MINUS_SRC_COLOR:
171
      case GL_SRC_ALPHA:
172
      case GL_ONE_MINUS_SRC_ALPHA:
173
      case GL_DST_ALPHA:
174
      case GL_ONE_MINUS_DST_ALPHA:
175
      case GL_CONSTANT_COLOR:
176
      case GL_ONE_MINUS_CONSTANT_COLOR:
177
      case GL_CONSTANT_ALPHA:
178
      case GL_ONE_MINUS_CONSTANT_ALPHA:
179
         break;
180
      default:
181
         _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
182
         return;
183
   }
184
 
185
   switch (sfactorA) {
186
      case GL_SRC_COLOR:
187
      case GL_ONE_MINUS_SRC_COLOR:
188
         if (!ctx->Extensions.NV_blend_square) {
189
            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
190
            return;
191
         }
192
         /* fall-through */
193
      case GL_ZERO:
194
      case GL_ONE:
195
      case GL_DST_COLOR:
196
      case GL_ONE_MINUS_DST_COLOR:
197
      case GL_SRC_ALPHA:
198
      case GL_ONE_MINUS_SRC_ALPHA:
199
      case GL_DST_ALPHA:
200
      case GL_ONE_MINUS_DST_ALPHA:
201
      case GL_SRC_ALPHA_SATURATE:
202
      case GL_CONSTANT_COLOR:
203
      case GL_ONE_MINUS_CONSTANT_COLOR:
204
      case GL_CONSTANT_ALPHA:
205
      case GL_ONE_MINUS_CONSTANT_ALPHA:
206
         break;
207
      default:
208
         _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
209
         return;
210
   }
211
 
212
   switch (dfactorA) {
213
      case GL_DST_COLOR:
214
      case GL_ONE_MINUS_DST_COLOR:
215
         if (!ctx->Extensions.NV_blend_square) {
216
            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)");
217
            return;
218
         }
219
         /* fall-through */
220
      case GL_ZERO:
221
      case GL_ONE:
222
      case GL_SRC_COLOR:
223
      case GL_ONE_MINUS_SRC_COLOR:
224
      case GL_SRC_ALPHA:
225
      case GL_ONE_MINUS_SRC_ALPHA:
226
      case GL_DST_ALPHA:
227
      case GL_ONE_MINUS_DST_ALPHA:
228
      case GL_CONSTANT_COLOR:
229
      case GL_ONE_MINUS_CONSTANT_COLOR:
230
      case GL_CONSTANT_ALPHA:
231
      case GL_ONE_MINUS_CONSTANT_ALPHA:
232
         break;
233
      default:
234
         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
235
         return;
236
   }
237
 
238
   if (ctx->Color.BlendSrcRGB == sfactorRGB &&
239
       ctx->Color.BlendDstRGB == dfactorRGB &&
240
       ctx->Color.BlendSrcA == sfactorA &&
241
       ctx->Color.BlendDstA == dfactorA)
242
      return;
243
 
244
   FLUSH_VERTICES(ctx, _NEW_COLOR);
245
 
246
   ctx->Color.BlendSrcRGB = sfactorRGB;
247
   ctx->Color.BlendDstRGB = dfactorRGB;
248
   ctx->Color.BlendSrcA = sfactorA;
249
   ctx->Color.BlendDstA = dfactorA;
250
 
251
   if (ctx->Driver.BlendFuncSeparate) {
252
      (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
253
                                        sfactorA, dfactorA );
254
   }
255
}
256
 
257
 
258
 
259
/* This is really an extension function! */
260
void
261
_mesa_BlendEquation( GLenum mode )
262
{
263
   GET_CURRENT_CONTEXT(ctx);
264
   ASSERT_OUTSIDE_BEGIN_END(ctx);
265
 
266
   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
267
      _mesa_debug(ctx, "glBlendEquation %s\n",
268
                  _mesa_lookup_enum_by_nr(mode));
269
 
270
   switch (mode) {
271
      case GL_FUNC_ADD_EXT:
272
         break;
273
      case GL_MIN_EXT:
274
      case GL_MAX_EXT:
275
         if (!ctx->Extensions.EXT_blend_minmax &&
276
             !ctx->Extensions.ARB_imaging) {
277
            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
278
            return;
279
         }
280
         break;
281
      case GL_LOGIC_OP:
282
         if (!ctx->Extensions.EXT_blend_logic_op) {
283
            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
284
            return;
285
         }
286
         break;
287
      case GL_FUNC_SUBTRACT_EXT:
288
      case GL_FUNC_REVERSE_SUBTRACT_EXT:
289
         if (!ctx->Extensions.EXT_blend_subtract &&
290
             !ctx->Extensions.ARB_imaging) {
291
            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
292
            return;
293
         }
294
         break;
295
      default:
296
         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
297
         return;
298
   }
299
 
300
   if (ctx->Color.BlendEquation == mode)
301
      return;
302
 
303
   FLUSH_VERTICES(ctx, _NEW_COLOR);
304
   ctx->Color.BlendEquation = mode;
305
 
306
   /* This is needed to support 1.1's RGB logic ops AND
307
    * 1.0's blending logicops.
308
    */
309
   ctx->Color.ColorLogicOpEnabled = (mode==GL_LOGIC_OP &&
310
                                     ctx->Color.BlendEnabled);
311
 
312
   if (ctx->Driver.BlendEquation)
313
      (*ctx->Driver.BlendEquation)( ctx, mode );
314
}
315
 
316
 
317
 
318
void
319
_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
320
{
321
   GLfloat tmp[4];
322
   GET_CURRENT_CONTEXT(ctx);
323
   ASSERT_OUTSIDE_BEGIN_END(ctx);
324
 
325
   tmp[0] = CLAMP( red,   0.0F, 1.0F );
326
   tmp[1] = CLAMP( green, 0.0F, 1.0F );
327
   tmp[2] = CLAMP( blue,  0.0F, 1.0F );
328
   tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
329
 
330
   if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
331
      return;
332
 
333
   FLUSH_VERTICES(ctx, _NEW_COLOR);
334
   COPY_4FV( ctx->Color.BlendColor, tmp );
335
 
336
   if (ctx->Driver.BlendColor)
337
      (*ctx->Driver.BlendColor)(ctx, tmp);
338
}
339
 
340
 
341
void
342
_mesa_AlphaFunc( GLenum func, GLclampf ref )
343
{
344
   GET_CURRENT_CONTEXT(ctx);
345
   ASSERT_OUTSIDE_BEGIN_END(ctx);
346
 
347
   switch (func) {
348
   case GL_NEVER:
349
   case GL_LESS:
350
   case GL_EQUAL:
351
   case GL_LEQUAL:
352
   case GL_GREATER:
353
   case GL_NOTEQUAL:
354
   case GL_GEQUAL:
355
   case GL_ALWAYS:
356
      ref = CLAMP(ref, 0.0F, 1.0F);
357
 
358
      if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
359
         return; /* no change */
360
 
361
      FLUSH_VERTICES(ctx, _NEW_COLOR);
362
      ctx->Color.AlphaFunc = func;
363
      ctx->Color.AlphaRef = ref;
364
 
365
      if (ctx->Driver.AlphaFunc)
366
         ctx->Driver.AlphaFunc(ctx, func, ref);
367
      return;
368
 
369
   default:
370
      _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
371
      return;
372
   }
373
}
374
 
375
 
376
void
377
_mesa_LogicOp( GLenum opcode )
378
{
379
   GET_CURRENT_CONTEXT(ctx);
380
   ASSERT_OUTSIDE_BEGIN_END(ctx);
381
 
382
   switch (opcode) {
383
      case GL_CLEAR:
384
      case GL_SET:
385
      case GL_COPY:
386
      case GL_COPY_INVERTED:
387
      case GL_NOOP:
388
      case GL_INVERT:
389
      case GL_AND:
390
      case GL_NAND:
391
      case GL_OR:
392
      case GL_NOR:
393
      case GL_XOR:
394
      case GL_EQUIV:
395
      case GL_AND_REVERSE:
396
      case GL_AND_INVERTED:
397
      case GL_OR_REVERSE:
398
      case GL_OR_INVERTED:
399
         break;
400
      default:
401
         _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
402
         return;
403
   }
404
 
405
   if (ctx->Color.LogicOp == opcode)
406
      return;
407
 
408
   FLUSH_VERTICES(ctx, _NEW_COLOR);
409
   ctx->Color.LogicOp = opcode;
410
 
411
   if (ctx->Driver.LogicOpcode)
412
      ctx->Driver.LogicOpcode( ctx, opcode );
413
}
414
 
415
 
416
void
417
_mesa_IndexMask( GLuint mask )
418
{
419
   GET_CURRENT_CONTEXT(ctx);
420
   ASSERT_OUTSIDE_BEGIN_END(ctx);
421
 
422
   if (ctx->Color.IndexMask == mask)
423
      return;
424
 
425
   FLUSH_VERTICES(ctx, _NEW_COLOR);
426
   ctx->Color.IndexMask = mask;
427
 
428
   if (ctx->Driver.IndexMask)
429
      ctx->Driver.IndexMask( ctx, mask );
430
}
431
 
432
 
433
void
434
_mesa_ColorMask( GLboolean red, GLboolean green,
435
                 GLboolean blue, GLboolean alpha )
436
{
437
   GET_CURRENT_CONTEXT(ctx);
438
   GLubyte tmp[4];
439
   ASSERT_OUTSIDE_BEGIN_END(ctx);
440
 
441
   if (MESA_VERBOSE & VERBOSE_API)
442
      _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
443
 
444
   /* Shouldn't have any information about channel depth in core mesa
445
    * -- should probably store these as the native booleans:
446
    */
447
   tmp[RCOMP] = red    ? 0xff : 0x0;
448
   tmp[GCOMP] = green  ? 0xff : 0x0;
449
   tmp[BCOMP] = blue   ? 0xff : 0x0;
450
   tmp[ACOMP] = alpha  ? 0xff : 0x0;
451
 
452
   if (TEST_EQ_4UBV(tmp, ctx->Color.ColorMask))
453
      return;
454
 
455
   FLUSH_VERTICES(ctx, _NEW_COLOR);
456
   COPY_4UBV(ctx->Color.ColorMask, tmp);
457
 
458
   if (ctx->Driver.ColorMask)
459
      ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
460
}