fixed pointer arithmetic error in glCopyPixels
[mesa.git] / src / mesa / main / blend.c
index ef1ec85c910757e0f285d3f810ab504bb682cbb3..b00e834d4f2ffbf432ebfa46d23b81ee9d0e27b0 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: blend.c,v 1.27 2000/12/26 05:09:27 keithw Exp $ */
+/* $Id: blend.c,v 1.34 2001/09/14 21:36:43 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
  * Version:  3.5
  *
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  */
 
 
-
 #ifdef PC_HEADER
 #include "all.h"
 #else
 #include "glheader.h"
 #include "blend.h"
+#include "colormac.h"
 #include "context.h"
 #include "enums.h"
 #include "macros.h"
 void
 _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
 {
-   
+
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
       fprintf(stderr, "glBlendFunc %s %s\n",
-             gl_lookup_enum_by_nr(sfactor),
-             gl_lookup_enum_by_nr(dfactor));
+             _mesa_lookup_enum_by_nr(sfactor),
+             _mesa_lookup_enum_by_nr(dfactor));
 
    switch (sfactor) {
       case GL_SRC_COLOR:
       case GL_ONE_MINUS_SRC_COLOR:
          if (!ctx->Extensions.NV_blend_square) {
-            gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
+            _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
             return;
          }
          /* fall-through */
@@ -73,7 +73,7 @@ _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
       case GL_ONE_MINUS_CONSTANT_ALPHA:
          break;
       default:
-         gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
          return;
    }
 
@@ -81,7 +81,7 @@ _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
       case GL_DST_COLOR:
       case GL_ONE_MINUS_DST_COLOR:
          if (!ctx->Extensions.NV_blend_square) {
-            gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
+            _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
             return;
          }
          /* fall-through */
@@ -99,7 +99,7 @@ _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
       case GL_ONE_MINUS_CONSTANT_ALPHA:
          break;
       default:
-         gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
          return;
    }
 
@@ -113,7 +113,7 @@ _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
    ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor;
    ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor;
 
-   if (ctx->Driver.BlendFunc) 
+   if (ctx->Driver.BlendFunc)
       ctx->Driver.BlendFunc( ctx, sfactor, dfactor );
 }
 
@@ -127,17 +127,17 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
-      fprintf(stderr, "glBlendFuncSeperate %s %s %s %s\n",
-             gl_lookup_enum_by_nr(sfactorRGB),
-             gl_lookup_enum_by_nr(dfactorRGB),
-             gl_lookup_enum_by_nr(sfactorA),
-             gl_lookup_enum_by_nr(dfactorA));
+      fprintf(stderr, "glBlendFuncSeparate %s %s %s %s\n",
+             _mesa_lookup_enum_by_nr(sfactorRGB),
+             _mesa_lookup_enum_by_nr(dfactorRGB),
+             _mesa_lookup_enum_by_nr(sfactorA),
+             _mesa_lookup_enum_by_nr(dfactorA));
 
    switch (sfactorRGB) {
       case GL_SRC_COLOR:
       case GL_ONE_MINUS_SRC_COLOR:
          if (!ctx->Extensions.NV_blend_square) {
-            gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
+            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
             return;
          }
          /* fall-through */
@@ -156,7 +156,7 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
       case GL_ONE_MINUS_CONSTANT_ALPHA:
          break;
       default:
-         gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
+         _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
          return;
    }
 
@@ -164,7 +164,7 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
       case GL_DST_COLOR:
       case GL_ONE_MINUS_DST_COLOR:
          if (!ctx->Extensions.NV_blend_square) {
-            gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
+            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
             return;
          }
          /* fall-through */
@@ -182,7 +182,7 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
       case GL_ONE_MINUS_CONSTANT_ALPHA:
          break;
       default:
-         gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
+         _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
          return;
    }
 
@@ -190,7 +190,7 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
       case GL_SRC_COLOR:
       case GL_ONE_MINUS_SRC_COLOR:
          if (!ctx->Extensions.NV_blend_square) {
-            gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
+            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
             return;
          }
          /* fall-through */
@@ -209,7 +209,7 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
       case GL_ONE_MINUS_CONSTANT_ALPHA:
          break;
       default:
-         gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
+         _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
          return;
    }
 
@@ -217,7 +217,7 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
       case GL_DST_COLOR:
       case GL_ONE_MINUS_DST_COLOR:
          if (!ctx->Extensions.NV_blend_square) {
-            gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)");
+            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)");
             return;
          }
          /* fall-through */
@@ -235,7 +235,7 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
       case GL_ONE_MINUS_CONSTANT_ALPHA:
          break;
       default:
-         gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
          return;
    }
 
@@ -269,44 +269,52 @@ _mesa_BlendEquation( GLenum mode )
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
       fprintf(stderr, "glBlendEquation %s\n",
-             gl_lookup_enum_by_nr(mode));
+             _mesa_lookup_enum_by_nr(mode));
 
    switch (mode) {
+      case GL_FUNC_ADD_EXT:
+         break;
       case GL_MIN_EXT:
       case GL_MAX_EXT:
-      case GL_FUNC_ADD_EXT:
-         if (!ctx->Extensions.EXT_blend_minmax) {
-            gl_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
+         if (!ctx->Extensions.EXT_blend_minmax &&
+             !ctx->Extensions.ARB_imaging) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
             return;
          }
+         break;
       case GL_LOGIC_OP:
+         if (!ctx->Extensions.EXT_blend_logic_op) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
+            return;
+         }
          break;
       case GL_FUNC_SUBTRACT_EXT:
       case GL_FUNC_REVERSE_SUBTRACT_EXT:
-         if (!ctx->Extensions.EXT_blend_subtract) {
-            gl_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
+         if (!ctx->Extensions.EXT_blend_subtract &&
+             !ctx->Extensions.ARB_imaging) {
+            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
             return;
          }
          break;
       default:
-         gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
+         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
          return;
    }
 
    if (ctx->Color.BlendEquation == mode)
       return;
-   
+
    FLUSH_VERTICES(ctx, _NEW_COLOR);
    ctx->Color.BlendEquation = mode;
 
    /* This is needed to support 1.1's RGB logic ops AND
     * 1.0's blending logicops.
     */
-   ctx->Color.ColorLogicOpEnabled = (mode==GL_LOGIC_OP && 
+   ctx->Color.ColorLogicOpEnabled = (mode==GL_LOGIC_OP &&
                                     ctx->Color.BlendEnabled);
 
    if (ctx->Driver.BlendEquation)
-      ctx->Driver.BlendEquation( ctx, mode );
+      (*ctx->Driver.BlendEquation)( ctx, mode );
 }
 
 
@@ -318,15 +326,141 @@ _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   tmp[0] = CLAMP( red,   0.0, 1.0 );
-   tmp[1] = CLAMP( green, 0.0, 1.0 );
-   tmp[2] = CLAMP( blue,  0.0, 1.0 );
-   tmp[3] = CLAMP( alpha, 0.0, 1.0 );
+   tmp[0] = CLAMP( red,   0.0F, 1.0F );
+   tmp[1] = CLAMP( green, 0.0F, 1.0F );
+   tmp[2] = CLAMP( blue,  0.0F, 1.0F );
+   tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
 
    if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
       return;
 
    FLUSH_VERTICES(ctx, _NEW_COLOR);
    COPY_4FV( ctx->Color.BlendColor, tmp );
+
+   if (ctx->Driver.BlendColor)
+      (*ctx->Driver.BlendColor)(ctx, tmp);
+}
+
+
+void
+_mesa_AlphaFunc( GLenum func, GLclampf ref )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLchan cref;
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   switch (func) {
+   case GL_NEVER:
+   case GL_LESS:
+   case GL_EQUAL:
+   case GL_LEQUAL:
+   case GL_GREATER:
+   case GL_NOTEQUAL:
+   case GL_GEQUAL:
+   case GL_ALWAYS:
+      /* convert float alpha ref to GLchan type */
+      UNCLAMPED_FLOAT_TO_CHAN(cref, ref);
+
+      if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == cref)
+         return;
+
+      FLUSH_VERTICES(ctx, _NEW_COLOR);
+      ctx->Color.AlphaFunc = func;
+      ctx->Color.AlphaRef = cref;
+
+      if (ctx->Driver.AlphaFunc)
+         ctx->Driver.AlphaFunc(ctx, func, cref);
+      return;
+
+   default:
+      _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
+      return;
+   }
+}
+
+
+void
+_mesa_LogicOp( GLenum opcode )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   switch (opcode) {
+      case GL_CLEAR:
+      case GL_SET:
+      case GL_COPY:
+      case GL_COPY_INVERTED:
+      case GL_NOOP:
+      case GL_INVERT:
+      case GL_AND:
+      case GL_NAND:
+      case GL_OR:
+      case GL_NOR:
+      case GL_XOR:
+      case GL_EQUIV:
+      case GL_AND_REVERSE:
+      case GL_AND_INVERTED:
+      case GL_OR_REVERSE:
+      case GL_OR_INVERTED:
+        break;
+      default:
+         _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
+        return;
+   }
+
+   if (ctx->Color.LogicOp == opcode)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   ctx->Color.LogicOp = opcode;
+
+   if (ctx->Driver.LogicOpcode)
+      ctx->Driver.LogicOpcode( ctx, opcode );
 }
 
+
+void
+_mesa_IndexMask( GLuint mask )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (ctx->Color.IndexMask == mask)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   ctx->Color.IndexMask = mask;
+
+   if (ctx->Driver.IndexMask)
+      ctx->Driver.IndexMask( ctx, mask );
+}
+
+
+void
+_mesa_ColorMask( GLboolean red, GLboolean green,
+                 GLboolean blue, GLboolean alpha )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLubyte tmp[4];
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & VERBOSE_API)
+      fprintf(stderr, "glColorMask %d %d %d %d\n", red, green, blue, alpha);
+
+   /* Shouldn't have any information about channel depth in core mesa
+    * -- should probably store these as the native booleans:
+    */
+   tmp[RCOMP] = red    ? 0xff : 0x0;
+   tmp[GCOMP] = green  ? 0xff : 0x0;
+   tmp[BCOMP] = blue   ? 0xff : 0x0;
+   tmp[ACOMP] = alpha  ? 0xff : 0x0;
+
+   if (TEST_EQ_4UBV(tmp, ctx->Color.ColorMask))
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   COPY_4UBV(ctx->Color.ColorMask, tmp);
+
+   if (ctx->Driver.ColorMask)
+      ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
+}