mesa: Change "BRIAN PAUL" to "THE AUTHORS" in license text.
[mesa.git] / src / mesa / main / blend.c
index 09acdf5c588a7ff3b92e92a9b4f66ff8d25a4e4f..b78dc32d54fb046c4a7315d2a3a2ab7f2f6e82b5 100644 (file)
@@ -22,7 +22,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
@@ -58,11 +58,18 @@ legal_src_factor(const struct gl_context *ctx, GLenum factor)
    case GL_DST_ALPHA:
    case GL_ONE_MINUS_DST_ALPHA:
    case GL_SRC_ALPHA_SATURATE:
+      return GL_TRUE;
    case GL_CONSTANT_COLOR:
    case GL_ONE_MINUS_CONSTANT_COLOR:
    case GL_CONSTANT_ALPHA:
    case GL_ONE_MINUS_CONSTANT_ALPHA:
-      return GL_TRUE;
+      return _mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES2;
+   case GL_SRC1_COLOR:
+   case GL_SRC1_ALPHA:
+   case GL_ONE_MINUS_SRC1_COLOR:
+   case GL_ONE_MINUS_SRC1_ALPHA:
+      return _mesa_is_desktop_gl(ctx)
+         && ctx->Extensions.ARB_blend_func_extended;
    default:
       return GL_FALSE;
    }
@@ -88,11 +95,22 @@ legal_dst_factor(const struct gl_context *ctx, GLenum factor)
    case GL_ONE_MINUS_SRC_ALPHA:
    case GL_DST_ALPHA:
    case GL_ONE_MINUS_DST_ALPHA:
+      return GL_TRUE;
    case GL_CONSTANT_COLOR:
    case GL_ONE_MINUS_CONSTANT_COLOR:
    case GL_CONSTANT_ALPHA:
    case GL_ONE_MINUS_CONSTANT_ALPHA:
-      return GL_TRUE;
+      return _mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES2;
+   case GL_SRC_ALPHA_SATURATE:
+      return (_mesa_is_desktop_gl(ctx)
+              && ctx->Extensions.ARB_blend_func_extended)
+         || _mesa_is_gles3(ctx);
+   case GL_SRC1_COLOR:
+   case GL_SRC1_ALPHA:
+   case GL_ONE_MINUS_SRC1_COLOR:
+   case GL_ONE_MINUS_SRC1_ALPHA:
+      return _mesa_is_desktop_gl(ctx)
+         && ctx->Extensions.ARB_blend_func_extended;
    default:
       return GL_FALSE;
    }
@@ -152,9 +170,27 @@ validate_blend_factors(struct gl_context *ctx, const char *func,
 void GLAPIENTRY
 _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
 {
-   _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
+   _mesa_BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
 }
 
+static GLboolean
+blend_factor_is_dual_src(GLenum factor)
+{
+   return (factor == GL_SRC1_COLOR ||
+          factor == GL_SRC1_ALPHA ||
+          factor == GL_ONE_MINUS_SRC1_COLOR ||
+          factor == GL_ONE_MINUS_SRC1_ALPHA);
+}
+
+static void
+update_uses_dual_src(struct gl_context *ctx, int buf)
+{
+   ctx->Color.Blend[buf]._UsesDualSrc =
+      (blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcRGB) ||
+       blend_factor_is_dual_src(ctx->Color.Blend[buf].DstRGB) ||
+       blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcA) ||
+       blend_factor_is_dual_src(ctx->Color.Blend[buf].DstA));
+}
 
 /**
  * Set the separate blend source/dest factors for all draw buffers.
@@ -165,13 +201,12 @@ _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
  * \param dfactorA alpha destination factor operator.
  */
 void GLAPIENTRY
-_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
+_mesa_BlendFuncSeparate( GLenum sfactorRGB, GLenum dfactorRGB,
                             GLenum sfactorA, GLenum dfactorA )
 {
    GLuint buf, numBuffers;
    GLboolean changed;
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
@@ -209,6 +244,7 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
       ctx->Color.Blend[buf].DstRGB = dfactorRGB;
       ctx->Color.Blend[buf].SrcA = sfactorA;
       ctx->Color.Blend[buf].DstA = dfactorA;
+      update_uses_dual_src(ctx, buf);
    }
    ctx->Color._BlendFuncPerBuffer = GL_FALSE;
 
@@ -219,16 +255,13 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
 }
 
 
-#if _HAVE_FULL_GL
-
-
 /**
  * Set blend source/dest factors for one color buffer/target.
  */
 void GLAPIENTRY
-_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
+_mesa_BlendFunciARB(GLuint buf, GLenum sfactor, GLenum dfactor)
 {
-   _mesa_BlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor);
+   _mesa_BlendFuncSeparateiARB(buf, sfactor, dfactor, sfactor, dfactor);
 }
 
 
@@ -236,11 +269,10 @@ _mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
  * Set separate blend source/dest factors for one color buffer/target.
  */
 void GLAPIENTRY
-_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
+_mesa_BlendFuncSeparateiARB(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
                          GLenum sfactorA, GLenum dfactorA)
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (!ctx->Extensions.ARB_draw_buffers_blend) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()");
@@ -271,6 +303,7 @@ _mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
    ctx->Color.Blend[buf].DstRGB = dfactorRGB;
    ctx->Color.Blend[buf].SrcA = sfactorA;
    ctx->Color.Blend[buf].DstA = dfactorA;
+   update_uses_dual_src(ctx, buf);
    ctx->Color._BlendFuncPerBuffer = GL_TRUE;
 
    if (ctx->Driver.BlendFuncSeparatei) {
@@ -308,7 +341,6 @@ _mesa_BlendEquation( GLenum mode )
    GLuint buf, numBuffers;
    GLboolean changed;
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glBlendEquation(%s)\n",
@@ -349,10 +381,9 @@ _mesa_BlendEquation( GLenum mode )
  * Set blend equation for one color buffer/target.
  */
 void GLAPIENTRY
-_mesa_BlendEquationi(GLuint buf, GLenum mode)
+_mesa_BlendEquationiARB(GLuint buf, GLenum mode)
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
@@ -384,12 +415,11 @@ _mesa_BlendEquationi(GLuint buf, GLenum mode)
 
 
 void GLAPIENTRY
-_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
+_mesa_BlendEquationSeparate( GLenum modeRGB, GLenum modeA )
 {
    GLuint buf, numBuffers;
    GLboolean changed;
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n",
@@ -442,10 +472,9 @@ _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
  * Set separate blend equations for one color buffer/target.
  */
 void GLAPIENTRY
-_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
+_mesa_BlendEquationSeparateiARB(GLuint buf, GLenum modeRGB, GLenum modeA)
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf,
@@ -482,10 +511,6 @@ _mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
 }
 
 
-
-#endif /* _HAVE_FULL_GL */
-
-
 /**
  * Set the blending color.
  *
@@ -505,7 +530,6 @@ _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
 {
    GLfloat tmp[4];
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    tmp[0] = red;
    tmp[1] = green;
@@ -542,7 +566,6 @@ void GLAPIENTRY
 _mesa_AlphaFunc( GLenum func, GLclampf ref )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n",
@@ -590,7 +613,6 @@ void GLAPIENTRY
 _mesa_LogicOp( GLenum opcode )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode));
@@ -628,12 +650,11 @@ _mesa_LogicOp( GLenum opcode )
       ctx->Driver.LogicOpcode( ctx, opcode );
 }
 
-#if _HAVE_FULL_GL
+
 void GLAPIENTRY
 _mesa_IndexMask( GLuint mask )
 {
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (ctx->Color.IndexMask == mask)
       return;
@@ -641,7 +662,6 @@ _mesa_IndexMask( GLuint mask )
    FLUSH_VERTICES(ctx, _NEW_COLOR);
    ctx->Color.IndexMask = mask;
 }
-#endif
 
 
 /**
@@ -666,7 +686,6 @@ _mesa_ColorMask( GLboolean red, GLboolean green,
    GLubyte tmp[4];
    GLuint i;
    GLboolean flushed;
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
@@ -700,12 +719,11 @@ _mesa_ColorMask( GLboolean red, GLboolean green,
  * For GL_EXT_draw_buffers2 and GL3
  */
 void GLAPIENTRY
-_mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
+_mesa_ColorMaski( GLuint buf, GLboolean red, GLboolean green,
                         GLboolean blue, GLboolean alpha )
 {
    GLubyte tmp[4];
    GET_CURRENT_CONTEXT(ctx);
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
@@ -736,12 +754,10 @@ _mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
 
 
 void GLAPIENTRY
-_mesa_ClampColorARB(GLenum target, GLenum clamp)
+_mesa_ClampColor(GLenum target, GLenum clamp)
 {
    GET_CURRENT_CONTEXT(ctx);
 
-   ASSERT_OUTSIDE_BEGIN_END(ctx);
-
    if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
       return;
@@ -749,24 +765,95 @@ _mesa_ClampColorARB(GLenum target, GLenum clamp)
 
    switch (target) {
    case GL_CLAMP_VERTEX_COLOR_ARB:
+      if (ctx->API == API_OPENGL_CORE &&
+          !ctx->Extensions.ARB_color_buffer_float) {
+         goto invalid_enum;
+      }
       FLUSH_VERTICES(ctx, _NEW_LIGHT);
       ctx->Light.ClampVertexColor = clamp;
+      _mesa_update_clamp_vertex_color(ctx);
       break;
    case GL_CLAMP_FRAGMENT_COLOR_ARB:
+      if (ctx->API == API_OPENGL_CORE &&
+          !ctx->Extensions.ARB_color_buffer_float) {
+         goto invalid_enum;
+      }
       FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
       ctx->Color.ClampFragmentColor = clamp;
+      _mesa_update_clamp_fragment_color(ctx);
       break;
    case GL_CLAMP_READ_COLOR_ARB:
-      FLUSH_VERTICES(ctx, _NEW_COLOR);
       ctx->Color.ClampReadColor = clamp;
       break;
    default:
-      _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
-      return;
+      goto invalid_enum;
    }
+   return;
+
+invalid_enum:
+   _mesa_error(ctx, GL_INVALID_ENUM, "glClampColor(%s)",
+               _mesa_lookup_enum_by_nr(target));
 }
 
+static GLboolean
+get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp)
+{
+   if (clamp == GL_TRUE || clamp == GL_FALSE)
+      return clamp;
 
+   ASSERT(clamp == GL_FIXED_ONLY);
+   if (!fb)
+      return GL_TRUE;
+
+   return fb->_AllColorBuffersFixedPoint;
+}
+
+GLboolean
+_mesa_get_clamp_fragment_color(const struct gl_context *ctx)
+{
+   return get_clamp_color(ctx->DrawBuffer,
+                                ctx->Color.ClampFragmentColor);
+}
+
+GLboolean
+_mesa_get_clamp_vertex_color(const struct gl_context *ctx)
+{
+   return get_clamp_color(ctx->DrawBuffer, ctx->Light.ClampVertexColor);
+}
+
+GLboolean
+_mesa_get_clamp_read_color(const struct gl_context *ctx)
+{
+   return get_clamp_color(ctx->ReadBuffer, ctx->Color.ClampReadColor);
+}
+
+/**
+ * Update the ctx->Color._ClampFragmentColor field
+ */
+void
+_mesa_update_clamp_fragment_color(struct gl_context *ctx)
+{
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+   /* Don't clamp if:
+    * - there is no colorbuffer
+    * - all colorbuffers are unsigned normalized, so clamping has no effect
+    * - there is an integer colorbuffer
+    */
+   if (!fb || !fb->_HasSNormOrFloatColorBuffer || fb->_IntegerColor)
+      ctx->Color._ClampFragmentColor = GL_FALSE;
+   else
+      ctx->Color._ClampFragmentColor = _mesa_get_clamp_fragment_color(ctx);
+}
+
+/**
+ * Update the ctx->Color._ClampVertexColor field
+ */
+void
+_mesa_update_clamp_vertex_color(struct gl_context *ctx)
+{
+   ctx->Light._ClampVertexColor = _mesa_get_clamp_vertex_color(ctx);
+}
 
 
 /**********************************************************************/
@@ -816,10 +903,17 @@ void _mesa_init_color( struct gl_context * ctx )
       ctx->Color.DrawBuffer[0] = GL_FRONT;
    }
 
-   ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
-   ctx->Color._ClampFragmentColor = GL_TRUE;
+   ctx->Color.ClampFragmentColor = ctx->API == API_OPENGL_COMPAT ?
+                                   GL_FIXED_ONLY_ARB : GL_FALSE;
+   ctx->Color._ClampFragmentColor = GL_FALSE;
    ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
-   ctx->Color._ClampReadColor = GL_TRUE;
+
+   if (ctx->API == API_OPENGLES2) {
+      /* GLES 3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled. */
+      ctx->Color.sRGBEnabled = GL_TRUE;
+   } else {
+      ctx->Color.sRGBEnabled = GL_FALSE;
+   }
 }
 
 /*@}*/