1848b8605Smrg/** 2848b8605Smrg * \file blend.c 3848b8605Smrg * Blending operations. 4848b8605Smrg */ 5848b8605Smrg 6848b8605Smrg/* 7848b8605Smrg * Mesa 3-D graphics library 8848b8605Smrg * 9848b8605Smrg * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 10848b8605Smrg * 11848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 12848b8605Smrg * copy of this software and associated documentation files (the "Software"), 13848b8605Smrg * to deal in the Software without restriction, including without limitation 14848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 16848b8605Smrg * Software is furnished to do so, subject to the following conditions: 17848b8605Smrg * 18848b8605Smrg * The above copyright notice and this permission notice shall be included 19848b8605Smrg * in all copies or substantial portions of the Software. 20848b8605Smrg * 21848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 28848b8605Smrg */ 29848b8605Smrg 30848b8605Smrg 31848b8605Smrg 32848b8605Smrg#include "glheader.h" 33848b8605Smrg#include "blend.h" 34848b8605Smrg#include "context.h" 35848b8605Smrg#include "enums.h" 36848b8605Smrg#include "macros.h" 37848b8605Smrg#include "mtypes.h" 38848b8605Smrg 39848b8605Smrg 40848b8605Smrg 41848b8605Smrg/** 42848b8605Smrg * Check if given blend source factor is legal. 43848b8605Smrg * \return GL_TRUE if legal, GL_FALSE otherwise. 44848b8605Smrg */ 45848b8605Smrgstatic GLboolean 46848b8605Smrglegal_src_factor(const struct gl_context *ctx, GLenum factor) 47848b8605Smrg{ 48848b8605Smrg switch (factor) { 49848b8605Smrg case GL_SRC_COLOR: 50848b8605Smrg case GL_ONE_MINUS_SRC_COLOR: 51848b8605Smrg case GL_ZERO: 52848b8605Smrg case GL_ONE: 53848b8605Smrg case GL_DST_COLOR: 54848b8605Smrg case GL_ONE_MINUS_DST_COLOR: 55848b8605Smrg case GL_SRC_ALPHA: 56848b8605Smrg case GL_ONE_MINUS_SRC_ALPHA: 57848b8605Smrg case GL_DST_ALPHA: 58848b8605Smrg case GL_ONE_MINUS_DST_ALPHA: 59848b8605Smrg case GL_SRC_ALPHA_SATURATE: 60848b8605Smrg return GL_TRUE; 61848b8605Smrg case GL_CONSTANT_COLOR: 62848b8605Smrg case GL_ONE_MINUS_CONSTANT_COLOR: 63848b8605Smrg case GL_CONSTANT_ALPHA: 64848b8605Smrg case GL_ONE_MINUS_CONSTANT_ALPHA: 65848b8605Smrg return _mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES2; 66848b8605Smrg case GL_SRC1_COLOR: 67848b8605Smrg case GL_SRC1_ALPHA: 68848b8605Smrg case GL_ONE_MINUS_SRC1_COLOR: 69848b8605Smrg case GL_ONE_MINUS_SRC1_ALPHA: 70b8e80941Smrg return ctx->API != API_OPENGLES 71848b8605Smrg && ctx->Extensions.ARB_blend_func_extended; 72848b8605Smrg default: 73848b8605Smrg return GL_FALSE; 74848b8605Smrg } 75848b8605Smrg} 76848b8605Smrg 77848b8605Smrg 78848b8605Smrg/** 79848b8605Smrg * Check if given blend destination factor is legal. 80848b8605Smrg * \return GL_TRUE if legal, GL_FALSE otherwise. 81848b8605Smrg */ 82848b8605Smrgstatic GLboolean 83848b8605Smrglegal_dst_factor(const struct gl_context *ctx, GLenum factor) 84848b8605Smrg{ 85848b8605Smrg switch (factor) { 86848b8605Smrg case GL_DST_COLOR: 87848b8605Smrg case GL_ONE_MINUS_DST_COLOR: 88848b8605Smrg case GL_ZERO: 89848b8605Smrg case GL_ONE: 90848b8605Smrg case GL_SRC_COLOR: 91848b8605Smrg case GL_ONE_MINUS_SRC_COLOR: 92848b8605Smrg case GL_SRC_ALPHA: 93848b8605Smrg case GL_ONE_MINUS_SRC_ALPHA: 94848b8605Smrg case GL_DST_ALPHA: 95848b8605Smrg case GL_ONE_MINUS_DST_ALPHA: 96848b8605Smrg return GL_TRUE; 97848b8605Smrg case GL_CONSTANT_COLOR: 98848b8605Smrg case GL_ONE_MINUS_CONSTANT_COLOR: 99848b8605Smrg case GL_CONSTANT_ALPHA: 100848b8605Smrg case GL_ONE_MINUS_CONSTANT_ALPHA: 101848b8605Smrg return _mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES2; 102848b8605Smrg case GL_SRC_ALPHA_SATURATE: 103b8e80941Smrg return (ctx->API != API_OPENGLES 104848b8605Smrg && ctx->Extensions.ARB_blend_func_extended) 105848b8605Smrg || _mesa_is_gles3(ctx); 106848b8605Smrg case GL_SRC1_COLOR: 107848b8605Smrg case GL_SRC1_ALPHA: 108848b8605Smrg case GL_ONE_MINUS_SRC1_COLOR: 109848b8605Smrg case GL_ONE_MINUS_SRC1_ALPHA: 110b8e80941Smrg return ctx->API != API_OPENGLES 111848b8605Smrg && ctx->Extensions.ARB_blend_func_extended; 112848b8605Smrg default: 113848b8605Smrg return GL_FALSE; 114848b8605Smrg } 115848b8605Smrg} 116848b8605Smrg 117848b8605Smrg 118848b8605Smrg/** 119848b8605Smrg * Check if src/dest RGB/A blend factors are legal. If not generate 120848b8605Smrg * a GL error. 121848b8605Smrg * \return GL_TRUE if factors are legal, GL_FALSE otherwise. 122848b8605Smrg */ 123848b8605Smrgstatic GLboolean 124848b8605Smrgvalidate_blend_factors(struct gl_context *ctx, const char *func, 125848b8605Smrg GLenum sfactorRGB, GLenum dfactorRGB, 126848b8605Smrg GLenum sfactorA, GLenum dfactorA) 127848b8605Smrg{ 128848b8605Smrg if (!legal_src_factor(ctx, sfactorRGB)) { 129848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, 130848b8605Smrg "%s(sfactorRGB = %s)", func, 131b8e80941Smrg _mesa_enum_to_string(sfactorRGB)); 132848b8605Smrg return GL_FALSE; 133848b8605Smrg } 134848b8605Smrg 135848b8605Smrg if (!legal_dst_factor(ctx, dfactorRGB)) { 136848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, 137848b8605Smrg "%s(dfactorRGB = %s)", func, 138b8e80941Smrg _mesa_enum_to_string(dfactorRGB)); 139848b8605Smrg return GL_FALSE; 140848b8605Smrg } 141848b8605Smrg 142848b8605Smrg if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) { 143848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, 144848b8605Smrg "%s(sfactorA = %s)", func, 145b8e80941Smrg _mesa_enum_to_string(sfactorA)); 146848b8605Smrg return GL_FALSE; 147848b8605Smrg } 148848b8605Smrg 149848b8605Smrg if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) { 150848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, 151848b8605Smrg "%s(dfactorA = %s)", func, 152b8e80941Smrg _mesa_enum_to_string(dfactorA)); 153848b8605Smrg return GL_FALSE; 154848b8605Smrg } 155848b8605Smrg 156848b8605Smrg return GL_TRUE; 157848b8605Smrg} 158848b8605Smrg 159848b8605Smrg 160848b8605Smrgstatic GLboolean 161848b8605Smrgblend_factor_is_dual_src(GLenum factor) 162848b8605Smrg{ 163848b8605Smrg return (factor == GL_SRC1_COLOR || 164848b8605Smrg factor == GL_SRC1_ALPHA || 165848b8605Smrg factor == GL_ONE_MINUS_SRC1_COLOR || 166848b8605Smrg factor == GL_ONE_MINUS_SRC1_ALPHA); 167848b8605Smrg} 168848b8605Smrg 169848b8605Smrgstatic void 170848b8605Smrgupdate_uses_dual_src(struct gl_context *ctx, int buf) 171848b8605Smrg{ 172848b8605Smrg ctx->Color.Blend[buf]._UsesDualSrc = 173848b8605Smrg (blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcRGB) || 174848b8605Smrg blend_factor_is_dual_src(ctx->Color.Blend[buf].DstRGB) || 175848b8605Smrg blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcA) || 176848b8605Smrg blend_factor_is_dual_src(ctx->Color.Blend[buf].DstA)); 177848b8605Smrg} 178848b8605Smrg 179b8e80941Smrg 180b8e80941Smrg/** 181b8e80941Smrg * Return the number of per-buffer blend states to update in 182b8e80941Smrg * glBlendFunc, glBlendFuncSeparate, glBlendEquation, etc. 183b8e80941Smrg */ 184b8e80941Smrgstatic inline unsigned 185b8e80941Smrgnum_buffers(const struct gl_context *ctx) 186b8e80941Smrg{ 187b8e80941Smrg return ctx->Extensions.ARB_draw_buffers_blend 188b8e80941Smrg ? ctx->Const.MaxDrawBuffers : 1; 189b8e80941Smrg} 190b8e80941Smrg 191b8e80941Smrg 192b8e80941Smrg/* Returns true if there was no change */ 193b8e80941Smrgstatic bool 194b8e80941Smrgskip_blend_state_update(const struct gl_context *ctx, 195b8e80941Smrg GLenum sfactorRGB, GLenum dfactorRGB, 196b8e80941Smrg GLenum sfactorA, GLenum dfactorA) 197b8e80941Smrg{ 198b8e80941Smrg /* Check if we're really changing any state. If not, return early. */ 199b8e80941Smrg if (ctx->Color._BlendFuncPerBuffer) { 200b8e80941Smrg const unsigned numBuffers = num_buffers(ctx); 201b8e80941Smrg 202b8e80941Smrg /* Check all per-buffer states */ 203b8e80941Smrg for (unsigned buf = 0; buf < numBuffers; buf++) { 204b8e80941Smrg if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB || 205b8e80941Smrg ctx->Color.Blend[buf].DstRGB != dfactorRGB || 206b8e80941Smrg ctx->Color.Blend[buf].SrcA != sfactorA || 207b8e80941Smrg ctx->Color.Blend[buf].DstA != dfactorA) { 208b8e80941Smrg return false; 209b8e80941Smrg } 210b8e80941Smrg } 211b8e80941Smrg } 212b8e80941Smrg else { 213b8e80941Smrg /* only need to check 0th per-buffer state */ 214b8e80941Smrg if (ctx->Color.Blend[0].SrcRGB != sfactorRGB || 215b8e80941Smrg ctx->Color.Blend[0].DstRGB != dfactorRGB || 216b8e80941Smrg ctx->Color.Blend[0].SrcA != sfactorA || 217b8e80941Smrg ctx->Color.Blend[0].DstA != dfactorA) { 218b8e80941Smrg return false; 219b8e80941Smrg } 220b8e80941Smrg } 221b8e80941Smrg 222b8e80941Smrg return true; 223b8e80941Smrg} 224b8e80941Smrg 225b8e80941Smrg 226b8e80941Smrgstatic void 227b8e80941Smrgblend_func_separate(struct gl_context *ctx, 228b8e80941Smrg GLenum sfactorRGB, GLenum dfactorRGB, 229b8e80941Smrg GLenum sfactorA, GLenum dfactorA) 230b8e80941Smrg{ 231b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewBlend ? 0 : _NEW_COLOR); 232b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewBlend; 233b8e80941Smrg 234b8e80941Smrg const unsigned numBuffers = num_buffers(ctx); 235b8e80941Smrg for (unsigned buf = 0; buf < numBuffers; buf++) { 236b8e80941Smrg ctx->Color.Blend[buf].SrcRGB = sfactorRGB; 237b8e80941Smrg ctx->Color.Blend[buf].DstRGB = dfactorRGB; 238b8e80941Smrg ctx->Color.Blend[buf].SrcA = sfactorA; 239b8e80941Smrg ctx->Color.Blend[buf].DstA = dfactorA; 240b8e80941Smrg } 241b8e80941Smrg 242b8e80941Smrg update_uses_dual_src(ctx, 0); 243b8e80941Smrg for (unsigned buf = 1; buf < numBuffers; buf++) { 244b8e80941Smrg ctx->Color.Blend[buf]._UsesDualSrc = ctx->Color.Blend[0]._UsesDualSrc; 245b8e80941Smrg } 246b8e80941Smrg 247b8e80941Smrg ctx->Color._BlendFuncPerBuffer = GL_FALSE; 248b8e80941Smrg 249b8e80941Smrg if (ctx->Driver.BlendFuncSeparate) { 250b8e80941Smrg ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB, 251b8e80941Smrg sfactorA, dfactorA); 252b8e80941Smrg } 253b8e80941Smrg} 254b8e80941Smrg 255b8e80941Smrg 256b8e80941Smrg/** 257b8e80941Smrg * Specify the blending operation. 258b8e80941Smrg * 259b8e80941Smrg * \param sfactor source factor operator. 260b8e80941Smrg * \param dfactor destination factor operator. 261b8e80941Smrg * 262b8e80941Smrg * \sa glBlendFunc, glBlendFuncSeparateEXT 263b8e80941Smrg */ 264b8e80941Smrgvoid GLAPIENTRY 265b8e80941Smrg_mesa_BlendFunc( GLenum sfactor, GLenum dfactor ) 266b8e80941Smrg{ 267b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 268b8e80941Smrg 269b8e80941Smrg if (skip_blend_state_update(ctx, sfactor, dfactor, sfactor, dfactor)) 270b8e80941Smrg return; 271b8e80941Smrg 272b8e80941Smrg if (!validate_blend_factors(ctx, "glBlendFunc", 273b8e80941Smrg sfactor, dfactor, sfactor, dfactor)) { 274b8e80941Smrg return; 275b8e80941Smrg } 276b8e80941Smrg 277b8e80941Smrg blend_func_separate(ctx, sfactor, dfactor, sfactor, dfactor); 278b8e80941Smrg} 279b8e80941Smrg 280b8e80941Smrg 281b8e80941Smrgvoid GLAPIENTRY 282b8e80941Smrg_mesa_BlendFunc_no_error(GLenum sfactor, GLenum dfactor) 283b8e80941Smrg{ 284b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 285b8e80941Smrg 286b8e80941Smrg if (skip_blend_state_update(ctx, sfactor, dfactor, sfactor, dfactor)) 287b8e80941Smrg return; 288b8e80941Smrg 289b8e80941Smrg blend_func_separate(ctx, sfactor, dfactor, sfactor, dfactor); 290b8e80941Smrg} 291b8e80941Smrg 292b8e80941Smrg 293848b8605Smrg/** 294848b8605Smrg * Set the separate blend source/dest factors for all draw buffers. 295848b8605Smrg * 296848b8605Smrg * \param sfactorRGB RGB source factor operator. 297848b8605Smrg * \param dfactorRGB RGB destination factor operator. 298848b8605Smrg * \param sfactorA alpha source factor operator. 299848b8605Smrg * \param dfactorA alpha destination factor operator. 300848b8605Smrg */ 301848b8605Smrgvoid GLAPIENTRY 302848b8605Smrg_mesa_BlendFuncSeparate( GLenum sfactorRGB, GLenum dfactorRGB, 303848b8605Smrg GLenum sfactorA, GLenum dfactorA ) 304848b8605Smrg{ 305848b8605Smrg GET_CURRENT_CONTEXT(ctx); 306848b8605Smrg 307848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 308848b8605Smrg _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n", 309b8e80941Smrg _mesa_enum_to_string(sfactorRGB), 310b8e80941Smrg _mesa_enum_to_string(dfactorRGB), 311b8e80941Smrg _mesa_enum_to_string(sfactorA), 312b8e80941Smrg _mesa_enum_to_string(dfactorA)); 313b8e80941Smrg 314b8e80941Smrg 315b8e80941Smrg 316b8e80941Smrg if (skip_blend_state_update(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA)) 317b8e80941Smrg return; 318848b8605Smrg 319848b8605Smrg if (!validate_blend_factors(ctx, "glBlendFuncSeparate", 320848b8605Smrg sfactorRGB, dfactorRGB, 321848b8605Smrg sfactorA, dfactorA)) { 322848b8605Smrg return; 323848b8605Smrg } 324848b8605Smrg 325b8e80941Smrg blend_func_separate(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA); 326b8e80941Smrg} 327848b8605Smrg 328b8e80941Smrg 329b8e80941Smrgvoid GLAPIENTRY 330b8e80941Smrg_mesa_BlendFuncSeparate_no_error(GLenum sfactorRGB, GLenum dfactorRGB, 331b8e80941Smrg GLenum sfactorA, GLenum dfactorA) 332b8e80941Smrg{ 333b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 334b8e80941Smrg 335b8e80941Smrg if (skip_blend_state_update(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA)) 336848b8605Smrg return; 337848b8605Smrg 338b8e80941Smrg blend_func_separate(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA); 339b8e80941Smrg} 340848b8605Smrg 341848b8605Smrg 342b8e80941Smrgvoid GLAPIENTRY 343b8e80941Smrg_mesa_BlendFunciARB_no_error(GLuint buf, GLenum sfactor, GLenum dfactor) 344b8e80941Smrg{ 345b8e80941Smrg _mesa_BlendFuncSeparateiARB_no_error(buf, sfactor, dfactor, sfactor, 346b8e80941Smrg dfactor); 347848b8605Smrg} 348848b8605Smrg 349848b8605Smrg 350848b8605Smrg/** 351848b8605Smrg * Set blend source/dest factors for one color buffer/target. 352848b8605Smrg */ 353848b8605Smrgvoid GLAPIENTRY 354848b8605Smrg_mesa_BlendFunciARB(GLuint buf, GLenum sfactor, GLenum dfactor) 355848b8605Smrg{ 356848b8605Smrg _mesa_BlendFuncSeparateiARB(buf, sfactor, dfactor, sfactor, dfactor); 357848b8605Smrg} 358848b8605Smrg 359848b8605Smrg 360b8e80941Smrgstatic ALWAYS_INLINE void 361b8e80941Smrgblend_func_separatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB, 362b8e80941Smrg GLenum sfactorA, GLenum dfactorA, bool no_error) 363848b8605Smrg{ 364848b8605Smrg GET_CURRENT_CONTEXT(ctx); 365848b8605Smrg 366b8e80941Smrg if (!no_error) { 367b8e80941Smrg if (!ctx->Extensions.ARB_draw_buffers_blend) { 368b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()"); 369b8e80941Smrg return; 370b8e80941Smrg } 371848b8605Smrg 372b8e80941Smrg if (buf >= ctx->Const.MaxDrawBuffers) { 373b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)", 374b8e80941Smrg buf); 375b8e80941Smrg return; 376b8e80941Smrg } 377848b8605Smrg } 378848b8605Smrg 379848b8605Smrg if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB && 380848b8605Smrg ctx->Color.Blend[buf].DstRGB == dfactorRGB && 381848b8605Smrg ctx->Color.Blend[buf].SrcA == sfactorA && 382848b8605Smrg ctx->Color.Blend[buf].DstA == dfactorA) 383848b8605Smrg return; /* no change */ 384848b8605Smrg 385b8e80941Smrg if (!no_error && !validate_blend_factors(ctx, "glBlendFuncSeparatei", 386b8e80941Smrg sfactorRGB, dfactorRGB, 387b8e80941Smrg sfactorA, dfactorA)) { 388b8e80941Smrg return; 389b8e80941Smrg } 390b8e80941Smrg 391b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewBlend ? 0 : _NEW_COLOR); 392b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewBlend; 393848b8605Smrg 394848b8605Smrg ctx->Color.Blend[buf].SrcRGB = sfactorRGB; 395848b8605Smrg ctx->Color.Blend[buf].DstRGB = dfactorRGB; 396848b8605Smrg ctx->Color.Blend[buf].SrcA = sfactorA; 397848b8605Smrg ctx->Color.Blend[buf].DstA = dfactorA; 398848b8605Smrg update_uses_dual_src(ctx, buf); 399848b8605Smrg ctx->Color._BlendFuncPerBuffer = GL_TRUE; 400b8e80941Smrg} 401848b8605Smrg 402b8e80941Smrg 403b8e80941Smrgvoid GLAPIENTRY 404b8e80941Smrg_mesa_BlendFuncSeparateiARB_no_error(GLuint buf, GLenum sfactorRGB, 405b8e80941Smrg GLenum dfactorRGB, GLenum sfactorA, 406b8e80941Smrg GLenum dfactorA) 407b8e80941Smrg{ 408b8e80941Smrg blend_func_separatei(buf, sfactorRGB, dfactorRGB, sfactorA, dfactorA, 409b8e80941Smrg true); 410848b8605Smrg} 411848b8605Smrg 412848b8605Smrg 413848b8605Smrg/** 414b8e80941Smrg * Set separate blend source/dest factors for one color buffer/target. 415848b8605Smrg */ 416b8e80941Smrgvoid GLAPIENTRY 417b8e80941Smrg_mesa_BlendFuncSeparateiARB(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB, 418b8e80941Smrg GLenum sfactorA, GLenum dfactorA) 419b8e80941Smrg{ 420b8e80941Smrg blend_func_separatei(buf, sfactorRGB, dfactorRGB, sfactorA, dfactorA, 421b8e80941Smrg false); 422b8e80941Smrg} 423b8e80941Smrg 424b8e80941Smrg 425b8e80941Smrg/** 426b8e80941Smrg * Return true if \p mode is a legal blending equation, excluding 427b8e80941Smrg * GL_KHR_blend_equation_advanced modes. 428b8e80941Smrg */ 429b8e80941Smrgstatic bool 430b8e80941Smrglegal_simple_blend_equation(const struct gl_context *ctx, GLenum mode) 431848b8605Smrg{ 432848b8605Smrg switch (mode) { 433848b8605Smrg case GL_FUNC_ADD: 434848b8605Smrg case GL_FUNC_SUBTRACT: 435848b8605Smrg case GL_FUNC_REVERSE_SUBTRACT: 436848b8605Smrg return GL_TRUE; 437848b8605Smrg case GL_MIN: 438848b8605Smrg case GL_MAX: 439848b8605Smrg return ctx->Extensions.EXT_blend_minmax; 440848b8605Smrg default: 441848b8605Smrg return GL_FALSE; 442848b8605Smrg } 443848b8605Smrg} 444848b8605Smrg 445b8e80941Smrgstatic enum gl_advanced_blend_mode 446b8e80941Smrgadvanced_blend_mode_from_gl_enum(GLenum mode) 447b8e80941Smrg{ 448b8e80941Smrg switch (mode) { 449b8e80941Smrg case GL_MULTIPLY_KHR: 450b8e80941Smrg return BLEND_MULTIPLY; 451b8e80941Smrg case GL_SCREEN_KHR: 452b8e80941Smrg return BLEND_SCREEN; 453b8e80941Smrg case GL_OVERLAY_KHR: 454b8e80941Smrg return BLEND_OVERLAY; 455b8e80941Smrg case GL_DARKEN_KHR: 456b8e80941Smrg return BLEND_DARKEN; 457b8e80941Smrg case GL_LIGHTEN_KHR: 458b8e80941Smrg return BLEND_LIGHTEN; 459b8e80941Smrg case GL_COLORDODGE_KHR: 460b8e80941Smrg return BLEND_COLORDODGE; 461b8e80941Smrg case GL_COLORBURN_KHR: 462b8e80941Smrg return BLEND_COLORBURN; 463b8e80941Smrg case GL_HARDLIGHT_KHR: 464b8e80941Smrg return BLEND_HARDLIGHT; 465b8e80941Smrg case GL_SOFTLIGHT_KHR: 466b8e80941Smrg return BLEND_SOFTLIGHT; 467b8e80941Smrg case GL_DIFFERENCE_KHR: 468b8e80941Smrg return BLEND_DIFFERENCE; 469b8e80941Smrg case GL_EXCLUSION_KHR: 470b8e80941Smrg return BLEND_EXCLUSION; 471b8e80941Smrg case GL_HSL_HUE_KHR: 472b8e80941Smrg return BLEND_HSL_HUE; 473b8e80941Smrg case GL_HSL_SATURATION_KHR: 474b8e80941Smrg return BLEND_HSL_SATURATION; 475b8e80941Smrg case GL_HSL_COLOR_KHR: 476b8e80941Smrg return BLEND_HSL_COLOR; 477b8e80941Smrg case GL_HSL_LUMINOSITY_KHR: 478b8e80941Smrg return BLEND_HSL_LUMINOSITY; 479b8e80941Smrg default: 480b8e80941Smrg return BLEND_NONE; 481b8e80941Smrg } 482b8e80941Smrg} 483b8e80941Smrg 484b8e80941Smrg/** 485b8e80941Smrg * If \p mode is one of the advanced blending equations defined by 486b8e80941Smrg * GL_KHR_blend_equation_advanced (and the extension is supported), 487b8e80941Smrg * return the corresponding BLEND_* enum. Otherwise, return BLEND_NONE 488b8e80941Smrg * (which can also be treated as false). 489b8e80941Smrg */ 490b8e80941Smrgstatic enum gl_advanced_blend_mode 491b8e80941Smrgadvanced_blend_mode(const struct gl_context *ctx, GLenum mode) 492b8e80941Smrg{ 493b8e80941Smrg return _mesa_has_KHR_blend_equation_advanced(ctx) ? 494b8e80941Smrg advanced_blend_mode_from_gl_enum(mode) : BLEND_NONE; 495b8e80941Smrg} 496848b8605Smrg 497848b8605Smrg/* This is really an extension function! */ 498848b8605Smrgvoid GLAPIENTRY 499848b8605Smrg_mesa_BlendEquation( GLenum mode ) 500848b8605Smrg{ 501848b8605Smrg GET_CURRENT_CONTEXT(ctx); 502b8e80941Smrg const unsigned numBuffers = num_buffers(ctx); 503b8e80941Smrg unsigned buf; 504b8e80941Smrg bool changed = false; 505b8e80941Smrg enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode); 506848b8605Smrg 507848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 508848b8605Smrg _mesa_debug(ctx, "glBlendEquation(%s)\n", 509b8e80941Smrg _mesa_enum_to_string(mode)); 510b8e80941Smrg 511b8e80941Smrg if (ctx->Color._BlendEquationPerBuffer) { 512b8e80941Smrg /* Check all per-buffer states */ 513b8e80941Smrg for (buf = 0; buf < numBuffers; buf++) { 514b8e80941Smrg if (ctx->Color.Blend[buf].EquationRGB != mode || 515b8e80941Smrg ctx->Color.Blend[buf].EquationA != mode) { 516b8e80941Smrg changed = true; 517b8e80941Smrg break; 518b8e80941Smrg } 519b8e80941Smrg } 520848b8605Smrg } 521b8e80941Smrg else { 522b8e80941Smrg /* only need to check 0th per-buffer state */ 523b8e80941Smrg if (ctx->Color.Blend[0].EquationRGB != mode || 524b8e80941Smrg ctx->Color.Blend[0].EquationA != mode) { 525b8e80941Smrg changed = true; 526848b8605Smrg } 527848b8605Smrg } 528b8e80941Smrg 529848b8605Smrg if (!changed) 530848b8605Smrg return; 531848b8605Smrg 532b8e80941Smrg 533b8e80941Smrg if (!legal_simple_blend_equation(ctx, mode) && !advanced_mode) { 534b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); 535b8e80941Smrg return; 536b8e80941Smrg } 537b8e80941Smrg 538b8e80941Smrg _mesa_flush_vertices_for_blend_adv(ctx, ctx->Color.BlendEnabled, 539b8e80941Smrg advanced_mode); 540b8e80941Smrg 541848b8605Smrg for (buf = 0; buf < numBuffers; buf++) { 542848b8605Smrg ctx->Color.Blend[buf].EquationRGB = mode; 543848b8605Smrg ctx->Color.Blend[buf].EquationA = mode; 544848b8605Smrg } 545848b8605Smrg ctx->Color._BlendEquationPerBuffer = GL_FALSE; 546b8e80941Smrg ctx->Color._AdvancedBlendMode = advanced_mode; 547848b8605Smrg 548848b8605Smrg if (ctx->Driver.BlendEquationSeparate) 549b8e80941Smrg ctx->Driver.BlendEquationSeparate(ctx, mode, mode); 550848b8605Smrg} 551848b8605Smrg 552848b8605Smrg 553848b8605Smrg/** 554848b8605Smrg * Set blend equation for one color buffer/target. 555848b8605Smrg */ 556b8e80941Smrgstatic void 557b8e80941Smrgblend_equationi(struct gl_context *ctx, GLuint buf, GLenum mode, 558b8e80941Smrg enum gl_advanced_blend_mode advanced_mode) 559848b8605Smrg{ 560848b8605Smrg if (ctx->Color.Blend[buf].EquationRGB == mode && 561848b8605Smrg ctx->Color.Blend[buf].EquationA == mode) 562848b8605Smrg return; /* no change */ 563848b8605Smrg 564b8e80941Smrg _mesa_flush_vertices_for_blend_adv(ctx, ctx->Color.BlendEnabled, 565b8e80941Smrg advanced_mode); 566848b8605Smrg ctx->Color.Blend[buf].EquationRGB = mode; 567848b8605Smrg ctx->Color.Blend[buf].EquationA = mode; 568848b8605Smrg ctx->Color._BlendEquationPerBuffer = GL_TRUE; 569848b8605Smrg 570b8e80941Smrg if (buf == 0) 571b8e80941Smrg ctx->Color._AdvancedBlendMode = advanced_mode; 572b8e80941Smrg} 573b8e80941Smrg 574b8e80941Smrg 575b8e80941Smrgvoid GLAPIENTRY 576b8e80941Smrg_mesa_BlendEquationiARB_no_error(GLuint buf, GLenum mode) 577b8e80941Smrg{ 578b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 579b8e80941Smrg 580b8e80941Smrg enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode); 581b8e80941Smrg blend_equationi(ctx, buf, mode, advanced_mode); 582848b8605Smrg} 583848b8605Smrg 584848b8605Smrg 585848b8605Smrgvoid GLAPIENTRY 586b8e80941Smrg_mesa_BlendEquationiARB(GLuint buf, GLenum mode) 587848b8605Smrg{ 588848b8605Smrg GET_CURRENT_CONTEXT(ctx); 589b8e80941Smrg enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode); 590848b8605Smrg 591848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 592b8e80941Smrg _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n", 593b8e80941Smrg buf, _mesa_enum_to_string(mode)); 594848b8605Smrg 595b8e80941Smrg if (buf >= ctx->Const.MaxDrawBuffers) { 596b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationi(buffer=%u)", 597b8e80941Smrg buf); 598848b8605Smrg return; 599848b8605Smrg } 600848b8605Smrg 601b8e80941Smrg if (!legal_simple_blend_equation(ctx, mode) && !advanced_mode) { 602b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi"); 603848b8605Smrg return; 604848b8605Smrg } 605848b8605Smrg 606b8e80941Smrg blend_equationi(ctx, buf, mode, advanced_mode); 607b8e80941Smrg} 608848b8605Smrg 609848b8605Smrg 610b8e80941Smrgstatic void 611b8e80941Smrgblend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA, 612b8e80941Smrg bool no_error) 613b8e80941Smrg{ 614b8e80941Smrg const unsigned numBuffers = num_buffers(ctx); 615b8e80941Smrg unsigned buf; 616b8e80941Smrg bool changed = false; 617b8e80941Smrg 618b8e80941Smrg if (ctx->Color._BlendEquationPerBuffer) { 619b8e80941Smrg /* Check all per-buffer states */ 620b8e80941Smrg for (buf = 0; buf < numBuffers; buf++) { 621b8e80941Smrg if (ctx->Color.Blend[buf].EquationRGB != modeRGB || 622b8e80941Smrg ctx->Color.Blend[buf].EquationA != modeA) { 623b8e80941Smrg changed = true; 624b8e80941Smrg break; 625b8e80941Smrg } 626b8e80941Smrg } 627b8e80941Smrg } else { 628b8e80941Smrg /* only need to check 0th per-buffer state */ 629b8e80941Smrg if (ctx->Color.Blend[0].EquationRGB != modeRGB || 630b8e80941Smrg ctx->Color.Blend[0].EquationA != modeA) { 631b8e80941Smrg changed = true; 632848b8605Smrg } 633848b8605Smrg } 634b8e80941Smrg 635848b8605Smrg if (!changed) 636848b8605Smrg return; 637848b8605Smrg 638b8e80941Smrg if (!no_error) { 639b8e80941Smrg if ((modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate) { 640b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 641b8e80941Smrg "glBlendEquationSeparateEXT not supported by driver"); 642b8e80941Smrg return; 643b8e80941Smrg } 644b8e80941Smrg 645b8e80941Smrg /* Only allow simple blending equations. 646b8e80941Smrg * The GL_KHR_blend_equation_advanced spec says: 647b8e80941Smrg * 648b8e80941Smrg * "NOTE: These enums are not accepted by the <modeRGB> or <modeAlpha> 649b8e80941Smrg * parameters of BlendEquationSeparate or BlendEquationSeparatei." 650b8e80941Smrg */ 651b8e80941Smrg if (!legal_simple_blend_equation(ctx, modeRGB)) { 652b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, 653b8e80941Smrg "glBlendEquationSeparateEXT(modeRGB)"); 654b8e80941Smrg return; 655b8e80941Smrg } 656b8e80941Smrg 657b8e80941Smrg if (!legal_simple_blend_equation(ctx, modeA)) { 658b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)"); 659b8e80941Smrg return; 660b8e80941Smrg } 661b8e80941Smrg } 662b8e80941Smrg 663b8e80941Smrg _mesa_flush_vertices_for_blend_state(ctx); 664b8e80941Smrg 665848b8605Smrg for (buf = 0; buf < numBuffers; buf++) { 666848b8605Smrg ctx->Color.Blend[buf].EquationRGB = modeRGB; 667848b8605Smrg ctx->Color.Blend[buf].EquationA = modeA; 668848b8605Smrg } 669848b8605Smrg ctx->Color._BlendEquationPerBuffer = GL_FALSE; 670b8e80941Smrg ctx->Color._AdvancedBlendMode = BLEND_NONE; 671848b8605Smrg 672848b8605Smrg if (ctx->Driver.BlendEquationSeparate) 673848b8605Smrg ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA); 674848b8605Smrg} 675848b8605Smrg 676848b8605Smrg 677b8e80941Smrgvoid GLAPIENTRY 678b8e80941Smrg_mesa_BlendEquationSeparate_no_error(GLenum modeRGB, GLenum modeA) 679b8e80941Smrg{ 680b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 681b8e80941Smrg blend_equation_separate(ctx, modeRGB, modeA, true); 682b8e80941Smrg} 683b8e80941Smrg 684b8e80941Smrg 685b8e80941Smrgvoid GLAPIENTRY 686b8e80941Smrg_mesa_BlendEquationSeparate(GLenum modeRGB, GLenum modeA) 687b8e80941Smrg{ 688b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 689b8e80941Smrg 690b8e80941Smrg if (MESA_VERBOSE & VERBOSE_API) 691b8e80941Smrg _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n", 692b8e80941Smrg _mesa_enum_to_string(modeRGB), 693b8e80941Smrg _mesa_enum_to_string(modeA)); 694b8e80941Smrg 695b8e80941Smrg blend_equation_separate(ctx, modeRGB, modeA, false); 696b8e80941Smrg} 697b8e80941Smrg 698b8e80941Smrg 699b8e80941Smrgstatic ALWAYS_INLINE void 700b8e80941Smrgblend_equation_separatei(struct gl_context *ctx, GLuint buf, GLenum modeRGB, 701b8e80941Smrg GLenum modeA, bool no_error) 702b8e80941Smrg{ 703b8e80941Smrg if (ctx->Color.Blend[buf].EquationRGB == modeRGB && 704b8e80941Smrg ctx->Color.Blend[buf].EquationA == modeA) 705b8e80941Smrg return; /* no change */ 706b8e80941Smrg 707b8e80941Smrg if (!no_error) { 708b8e80941Smrg /* Only allow simple blending equations. 709b8e80941Smrg * The GL_KHR_blend_equation_advanced spec says: 710b8e80941Smrg * 711b8e80941Smrg * "NOTE: These enums are not accepted by the <modeRGB> or <modeAlpha> 712b8e80941Smrg * parameters of BlendEquationSeparate or BlendEquationSeparatei." 713b8e80941Smrg */ 714b8e80941Smrg if (!legal_simple_blend_equation(ctx, modeRGB)) { 715b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)"); 716b8e80941Smrg return; 717b8e80941Smrg } 718b8e80941Smrg 719b8e80941Smrg if (!legal_simple_blend_equation(ctx, modeA)) { 720b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)"); 721b8e80941Smrg return; 722b8e80941Smrg } 723b8e80941Smrg } 724b8e80941Smrg 725b8e80941Smrg _mesa_flush_vertices_for_blend_state(ctx); 726b8e80941Smrg ctx->Color.Blend[buf].EquationRGB = modeRGB; 727b8e80941Smrg ctx->Color.Blend[buf].EquationA = modeA; 728b8e80941Smrg ctx->Color._BlendEquationPerBuffer = GL_TRUE; 729b8e80941Smrg ctx->Color._AdvancedBlendMode = BLEND_NONE; 730b8e80941Smrg} 731b8e80941Smrg 732b8e80941Smrg 733b8e80941Smrgvoid GLAPIENTRY 734b8e80941Smrg_mesa_BlendEquationSeparateiARB_no_error(GLuint buf, GLenum modeRGB, 735b8e80941Smrg GLenum modeA) 736b8e80941Smrg{ 737b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 738b8e80941Smrg blend_equation_separatei(ctx, buf, modeRGB, modeA, true); 739b8e80941Smrg} 740b8e80941Smrg 741b8e80941Smrg 742848b8605Smrg/** 743848b8605Smrg * Set separate blend equations for one color buffer/target. 744848b8605Smrg */ 745848b8605Smrgvoid GLAPIENTRY 746848b8605Smrg_mesa_BlendEquationSeparateiARB(GLuint buf, GLenum modeRGB, GLenum modeA) 747848b8605Smrg{ 748848b8605Smrg GET_CURRENT_CONTEXT(ctx); 749848b8605Smrg 750848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 751848b8605Smrg _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf, 752b8e80941Smrg _mesa_enum_to_string(modeRGB), 753b8e80941Smrg _mesa_enum_to_string(modeA)); 754848b8605Smrg 755848b8605Smrg if (buf >= ctx->Const.MaxDrawBuffers) { 756848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)", 757848b8605Smrg buf); 758848b8605Smrg return; 759848b8605Smrg } 760848b8605Smrg 761b8e80941Smrg blend_equation_separatei(ctx, buf, modeRGB, modeA, false); 762848b8605Smrg} 763848b8605Smrg 764848b8605Smrg 765848b8605Smrg/** 766848b8605Smrg * Set the blending color. 767848b8605Smrg * 768848b8605Smrg * \param red red color component. 769848b8605Smrg * \param green green color component. 770848b8605Smrg * \param blue blue color component. 771848b8605Smrg * \param alpha alpha color component. 772848b8605Smrg * 773848b8605Smrg * \sa glBlendColor(). 774848b8605Smrg * 775848b8605Smrg * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a 776848b8605Smrg * change, flushes the vertices and notifies the driver via 777848b8605Smrg * dd_function_table::BlendColor callback. 778848b8605Smrg */ 779848b8605Smrgvoid GLAPIENTRY 780848b8605Smrg_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 781848b8605Smrg{ 782848b8605Smrg GLfloat tmp[4]; 783848b8605Smrg GET_CURRENT_CONTEXT(ctx); 784848b8605Smrg 785848b8605Smrg tmp[0] = red; 786848b8605Smrg tmp[1] = green; 787848b8605Smrg tmp[2] = blue; 788848b8605Smrg tmp[3] = alpha; 789848b8605Smrg 790848b8605Smrg if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped)) 791848b8605Smrg return; 792848b8605Smrg 793b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewBlendColor ? 0 : _NEW_COLOR); 794b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewBlendColor; 795848b8605Smrg COPY_4FV( ctx->Color.BlendColorUnclamped, tmp ); 796848b8605Smrg 797848b8605Smrg ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F); 798848b8605Smrg ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F); 799848b8605Smrg ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F); 800848b8605Smrg ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F); 801848b8605Smrg 802848b8605Smrg if (ctx->Driver.BlendColor) 803b8e80941Smrg ctx->Driver.BlendColor(ctx, ctx->Color.BlendColor); 804848b8605Smrg} 805848b8605Smrg 806848b8605Smrg 807848b8605Smrg/** 808848b8605Smrg * Specify the alpha test function. 809848b8605Smrg * 810848b8605Smrg * \param func alpha comparison function. 811848b8605Smrg * \param ref reference value. 812848b8605Smrg * 813848b8605Smrg * Verifies the parameters and updates gl_colorbuffer_attrib. 814848b8605Smrg * On a change, flushes the vertices and notifies the driver via 815848b8605Smrg * dd_function_table::AlphaFunc callback. 816848b8605Smrg */ 817848b8605Smrgvoid GLAPIENTRY 818848b8605Smrg_mesa_AlphaFunc( GLenum func, GLclampf ref ) 819848b8605Smrg{ 820848b8605Smrg GET_CURRENT_CONTEXT(ctx); 821848b8605Smrg 822848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 823848b8605Smrg _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n", 824b8e80941Smrg _mesa_enum_to_string(func), ref); 825b8e80941Smrg 826b8e80941Smrg if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref) 827b8e80941Smrg return; /* no change */ 828848b8605Smrg 829848b8605Smrg switch (func) { 830848b8605Smrg case GL_NEVER: 831848b8605Smrg case GL_LESS: 832848b8605Smrg case GL_EQUAL: 833848b8605Smrg case GL_LEQUAL: 834848b8605Smrg case GL_GREATER: 835848b8605Smrg case GL_NOTEQUAL: 836848b8605Smrg case GL_GEQUAL: 837848b8605Smrg case GL_ALWAYS: 838b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewAlphaTest ? 0 : _NEW_COLOR); 839b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewAlphaTest; 840848b8605Smrg ctx->Color.AlphaFunc = func; 841848b8605Smrg ctx->Color.AlphaRefUnclamped = ref; 842848b8605Smrg ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F); 843848b8605Smrg 844848b8605Smrg if (ctx->Driver.AlphaFunc) 845848b8605Smrg ctx->Driver.AlphaFunc(ctx, func, ctx->Color.AlphaRef); 846848b8605Smrg return; 847848b8605Smrg 848848b8605Smrg default: 849848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" ); 850848b8605Smrg return; 851848b8605Smrg } 852848b8605Smrg} 853848b8605Smrg 854b8e80941Smrgstatic const enum gl_logicop_mode color_logicop_mapping[16] = { 855b8e80941Smrg COLOR_LOGICOP_CLEAR, 856b8e80941Smrg COLOR_LOGICOP_AND, 857b8e80941Smrg COLOR_LOGICOP_AND_REVERSE, 858b8e80941Smrg COLOR_LOGICOP_COPY, 859b8e80941Smrg COLOR_LOGICOP_AND_INVERTED, 860b8e80941Smrg COLOR_LOGICOP_NOOP, 861b8e80941Smrg COLOR_LOGICOP_XOR, 862b8e80941Smrg COLOR_LOGICOP_OR, 863b8e80941Smrg COLOR_LOGICOP_NOR, 864b8e80941Smrg COLOR_LOGICOP_EQUIV, 865b8e80941Smrg COLOR_LOGICOP_INVERT, 866b8e80941Smrg COLOR_LOGICOP_OR_REVERSE, 867b8e80941Smrg COLOR_LOGICOP_COPY_INVERTED, 868b8e80941Smrg COLOR_LOGICOP_OR_INVERTED, 869b8e80941Smrg COLOR_LOGICOP_NAND, 870b8e80941Smrg COLOR_LOGICOP_SET 871b8e80941Smrg}; 872b8e80941Smrg 873b8e80941Smrgstatic ALWAYS_INLINE void 874b8e80941Smrglogic_op(struct gl_context *ctx, GLenum opcode, bool no_error) 875b8e80941Smrg{ 876b8e80941Smrg if (ctx->Color.LogicOp == opcode) 877b8e80941Smrg return; 878b8e80941Smrg 879b8e80941Smrg if (!no_error) { 880b8e80941Smrg switch (opcode) { 881b8e80941Smrg case GL_CLEAR: 882b8e80941Smrg case GL_SET: 883b8e80941Smrg case GL_COPY: 884b8e80941Smrg case GL_COPY_INVERTED: 885b8e80941Smrg case GL_NOOP: 886b8e80941Smrg case GL_INVERT: 887b8e80941Smrg case GL_AND: 888b8e80941Smrg case GL_NAND: 889b8e80941Smrg case GL_OR: 890b8e80941Smrg case GL_NOR: 891b8e80941Smrg case GL_XOR: 892b8e80941Smrg case GL_EQUIV: 893b8e80941Smrg case GL_AND_REVERSE: 894b8e80941Smrg case GL_AND_INVERTED: 895b8e80941Smrg case GL_OR_REVERSE: 896b8e80941Smrg case GL_OR_INVERTED: 897b8e80941Smrg break; 898b8e80941Smrg default: 899b8e80941Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" ); 900b8e80941Smrg return; 901b8e80941Smrg } 902b8e80941Smrg } 903b8e80941Smrg 904b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewLogicOp ? 0 : _NEW_COLOR); 905b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewLogicOp; 906b8e80941Smrg ctx->Color.LogicOp = opcode; 907b8e80941Smrg ctx->Color._LogicOp = color_logicop_mapping[opcode & 0x0f]; 908b8e80941Smrg 909b8e80941Smrg if (ctx->Driver.LogicOpcode) 910b8e80941Smrg ctx->Driver.LogicOpcode(ctx, ctx->Color._LogicOp); 911b8e80941Smrg} 912b8e80941Smrg 913848b8605Smrg 914848b8605Smrg/** 915848b8605Smrg * Specify a logic pixel operation for color index rendering. 916848b8605Smrg * 917848b8605Smrg * \param opcode operation. 918848b8605Smrg * 919848b8605Smrg * Verifies that \p opcode is a valid enum and updates 920b8e80941Smrg * gl_colorbuffer_attrib::LogicOp. 921848b8605Smrg * On a change, flushes the vertices and notifies the driver via the 922848b8605Smrg * dd_function_table::LogicOpcode callback. 923848b8605Smrg */ 924848b8605Smrgvoid GLAPIENTRY 925848b8605Smrg_mesa_LogicOp( GLenum opcode ) 926848b8605Smrg{ 927848b8605Smrg GET_CURRENT_CONTEXT(ctx); 928848b8605Smrg 929848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 930b8e80941Smrg _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_enum_to_string(opcode)); 931848b8605Smrg 932b8e80941Smrg logic_op(ctx, opcode, false); 933b8e80941Smrg} 934848b8605Smrg 935848b8605Smrg 936b8e80941Smrgvoid GLAPIENTRY 937b8e80941Smrg_mesa_LogicOp_no_error(GLenum opcode) 938b8e80941Smrg{ 939b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 940b8e80941Smrg logic_op(ctx, opcode, true); 941848b8605Smrg} 942848b8605Smrg 943848b8605Smrg 944848b8605Smrgvoid GLAPIENTRY 945848b8605Smrg_mesa_IndexMask( GLuint mask ) 946848b8605Smrg{ 947848b8605Smrg GET_CURRENT_CONTEXT(ctx); 948848b8605Smrg 949848b8605Smrg if (ctx->Color.IndexMask == mask) 950848b8605Smrg return; 951848b8605Smrg 952b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR); 953b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewColorMask; 954848b8605Smrg ctx->Color.IndexMask = mask; 955848b8605Smrg} 956848b8605Smrg 957848b8605Smrg 958848b8605Smrg/** 959848b8605Smrg * Enable or disable writing of frame buffer color components. 960848b8605Smrg * 961848b8605Smrg * \param red whether to mask writing of the red color component. 962848b8605Smrg * \param green whether to mask writing of the green color component. 963848b8605Smrg * \param blue whether to mask writing of the blue color component. 964848b8605Smrg * \param alpha whether to mask writing of the alpha color component. 965848b8605Smrg * 966848b8605Smrg * \sa glColorMask(). 967848b8605Smrg * 968848b8605Smrg * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a 969848b8605Smrg * change, flushes the vertices and notifies the driver via the 970848b8605Smrg * dd_function_table::ColorMask callback. 971848b8605Smrg */ 972848b8605Smrgvoid GLAPIENTRY 973848b8605Smrg_mesa_ColorMask( GLboolean red, GLboolean green, 974848b8605Smrg GLboolean blue, GLboolean alpha ) 975848b8605Smrg{ 976848b8605Smrg GET_CURRENT_CONTEXT(ctx); 977848b8605Smrg 978848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 979848b8605Smrg _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n", 980848b8605Smrg red, green, blue, alpha); 981848b8605Smrg 982b8e80941Smrg GLbitfield mask = (!!red) | 983b8e80941Smrg ((!!green) << 1) | 984b8e80941Smrg ((!!blue) << 2) | 985b8e80941Smrg ((!!alpha) << 3); 986b8e80941Smrg mask = _mesa_replicate_colormask(mask, ctx->Const.MaxDrawBuffers); 987b8e80941Smrg 988b8e80941Smrg if (ctx->Color.ColorMask == mask) 989b8e80941Smrg return; 990b8e80941Smrg 991b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR); 992b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewColorMask; 993b8e80941Smrg ctx->Color.ColorMask = mask; 994848b8605Smrg 995848b8605Smrg if (ctx->Driver.ColorMask) 996848b8605Smrg ctx->Driver.ColorMask( ctx, red, green, blue, alpha ); 997848b8605Smrg} 998848b8605Smrg 999848b8605Smrg 1000848b8605Smrg/** 1001848b8605Smrg * For GL_EXT_draw_buffers2 and GL3 1002848b8605Smrg */ 1003848b8605Smrgvoid GLAPIENTRY 1004b8e80941Smrg_mesa_ColorMaski(GLuint buf, GLboolean red, GLboolean green, 1005b8e80941Smrg GLboolean blue, GLboolean alpha) 1006848b8605Smrg{ 1007848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1008848b8605Smrg 1009848b8605Smrg if (MESA_VERBOSE & VERBOSE_API) 1010b8e80941Smrg _mesa_debug(ctx, "glColorMaski %u %d %d %d %d\n", 1011848b8605Smrg buf, red, green, blue, alpha); 1012848b8605Smrg 1013848b8605Smrg if (buf >= ctx->Const.MaxDrawBuffers) { 1014b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaski(buf=%u)", buf); 1015848b8605Smrg return; 1016848b8605Smrg } 1017848b8605Smrg 1018b8e80941Smrg GLbitfield mask = (!!red) | 1019b8e80941Smrg ((!!green) << 1) | 1020b8e80941Smrg ((!!blue) << 2) | 1021b8e80941Smrg ((!!alpha) << 3); 1022848b8605Smrg 1023b8e80941Smrg if (GET_COLORMASK(ctx->Color.ColorMask, buf) == mask) 1024848b8605Smrg return; 1025848b8605Smrg 1026b8e80941Smrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewColorMask ? 0 : _NEW_COLOR); 1027b8e80941Smrg ctx->NewDriverState |= ctx->DriverFlags.NewColorMask; 1028b8e80941Smrg ctx->Color.ColorMask &= ~(0xf << (4 * buf)); 1029b8e80941Smrg ctx->Color.ColorMask |= mask << (4 * buf); 1030848b8605Smrg} 1031848b8605Smrg 1032848b8605Smrg 1033848b8605Smrgvoid GLAPIENTRY 1034848b8605Smrg_mesa_ClampColor(GLenum target, GLenum clamp) 1035848b8605Smrg{ 1036848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1037848b8605Smrg 1038b8e80941Smrg /* Check for both the extension and the GL version, since the Intel driver 1039b8e80941Smrg * does not advertise the extension in core profiles. 1040b8e80941Smrg */ 1041b8e80941Smrg if (ctx->Version <= 30 && !ctx->Extensions.ARB_color_buffer_float) { 1042b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "glClampColor()"); 1043b8e80941Smrg return; 1044b8e80941Smrg } 1045b8e80941Smrg 1046848b8605Smrg if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) { 1047848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)"); 1048848b8605Smrg return; 1049848b8605Smrg } 1050848b8605Smrg 1051848b8605Smrg switch (target) { 1052848b8605Smrg case GL_CLAMP_VERTEX_COLOR_ARB: 1053b8e80941Smrg if (ctx->API == API_OPENGL_CORE) 1054848b8605Smrg goto invalid_enum; 1055848b8605Smrg FLUSH_VERTICES(ctx, _NEW_LIGHT); 1056848b8605Smrg ctx->Light.ClampVertexColor = clamp; 1057b8e80941Smrg _mesa_update_clamp_vertex_color(ctx, ctx->DrawBuffer); 1058848b8605Smrg break; 1059848b8605Smrg case GL_CLAMP_FRAGMENT_COLOR_ARB: 1060b8e80941Smrg if (ctx->API == API_OPENGL_CORE) 1061848b8605Smrg goto invalid_enum; 1062848b8605Smrg FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP); 1063848b8605Smrg ctx->Color.ClampFragmentColor = clamp; 1064b8e80941Smrg _mesa_update_clamp_fragment_color(ctx, ctx->DrawBuffer); 1065848b8605Smrg break; 1066848b8605Smrg case GL_CLAMP_READ_COLOR_ARB: 1067848b8605Smrg ctx->Color.ClampReadColor = clamp; 1068848b8605Smrg break; 1069848b8605Smrg default: 1070848b8605Smrg goto invalid_enum; 1071848b8605Smrg } 1072848b8605Smrg return; 1073848b8605Smrg 1074848b8605Smrginvalid_enum: 1075848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, "glClampColor(%s)", 1076b8e80941Smrg _mesa_enum_to_string(target)); 1077848b8605Smrg} 1078848b8605Smrg 1079848b8605Smrgstatic GLboolean 1080848b8605Smrgget_clamp_color(const struct gl_framebuffer *fb, GLenum clamp) 1081848b8605Smrg{ 1082848b8605Smrg if (clamp == GL_TRUE || clamp == GL_FALSE) 1083848b8605Smrg return clamp; 1084848b8605Smrg 1085b8e80941Smrg assert(clamp == GL_FIXED_ONLY); 1086848b8605Smrg if (!fb) 1087848b8605Smrg return GL_TRUE; 1088848b8605Smrg 1089848b8605Smrg return fb->_AllColorBuffersFixedPoint; 1090848b8605Smrg} 1091848b8605Smrg 1092848b8605SmrgGLboolean 1093b8e80941Smrg_mesa_get_clamp_fragment_color(const struct gl_context *ctx, 1094b8e80941Smrg const struct gl_framebuffer *drawFb) 1095848b8605Smrg{ 1096b8e80941Smrg return get_clamp_color(drawFb, ctx->Color.ClampFragmentColor); 1097848b8605Smrg} 1098848b8605Smrg 1099848b8605SmrgGLboolean 1100b8e80941Smrg_mesa_get_clamp_vertex_color(const struct gl_context *ctx, 1101b8e80941Smrg const struct gl_framebuffer *drawFb) 1102848b8605Smrg{ 1103b8e80941Smrg return get_clamp_color(drawFb, ctx->Light.ClampVertexColor); 1104848b8605Smrg} 1105848b8605Smrg 1106848b8605SmrgGLboolean 1107b8e80941Smrg_mesa_get_clamp_read_color(const struct gl_context *ctx, 1108b8e80941Smrg const struct gl_framebuffer *readFb) 1109848b8605Smrg{ 1110b8e80941Smrg return get_clamp_color(readFb, ctx->Color.ClampReadColor); 1111848b8605Smrg} 1112848b8605Smrg 1113848b8605Smrg/** 1114848b8605Smrg * Update the ctx->Color._ClampFragmentColor field 1115848b8605Smrg */ 1116848b8605Smrgvoid 1117b8e80941Smrg_mesa_update_clamp_fragment_color(struct gl_context *ctx, 1118b8e80941Smrg const struct gl_framebuffer *drawFb) 1119848b8605Smrg{ 1120848b8605Smrg /* Don't clamp if: 1121848b8605Smrg * - there is no colorbuffer 1122848b8605Smrg * - all colorbuffers are unsigned normalized, so clamping has no effect 1123848b8605Smrg * - there is an integer colorbuffer 1124848b8605Smrg */ 1125b8e80941Smrg if (!drawFb || !drawFb->_HasSNormOrFloatColorBuffer || 1126b8e80941Smrg drawFb->_IntegerBuffers) 1127848b8605Smrg ctx->Color._ClampFragmentColor = GL_FALSE; 1128848b8605Smrg else 1129b8e80941Smrg ctx->Color._ClampFragmentColor = 1130b8e80941Smrg _mesa_get_clamp_fragment_color(ctx, drawFb); 1131848b8605Smrg} 1132848b8605Smrg 1133848b8605Smrg/** 1134848b8605Smrg * Update the ctx->Color._ClampVertexColor field 1135848b8605Smrg */ 1136848b8605Smrgvoid 1137b8e80941Smrg_mesa_update_clamp_vertex_color(struct gl_context *ctx, 1138b8e80941Smrg const struct gl_framebuffer *drawFb) 1139848b8605Smrg{ 1140b8e80941Smrg ctx->Light._ClampVertexColor = 1141b8e80941Smrg _mesa_get_clamp_vertex_color(ctx, drawFb); 1142848b8605Smrg} 1143848b8605Smrg 1144848b8605Smrg/** 1145848b8605Smrg * Returns an appropriate mesa_format for color rendering based on the 1146848b8605Smrg * GL_FRAMEBUFFER_SRGB state. 1147848b8605Smrg * 1148848b8605Smrg * Some drivers implement GL_FRAMEBUFFER_SRGB using a flag on the blend state 1149848b8605Smrg * (which GL_FRAMEBUFFER_SRGB maps to reasonably), but some have to do so by 1150848b8605Smrg * overriding the format of the surface. This is a helper for doing the 1151848b8605Smrg * surface format override variant. 1152848b8605Smrg */ 1153848b8605Smrgmesa_format 1154848b8605Smrg_mesa_get_render_format(const struct gl_context *ctx, mesa_format format) 1155848b8605Smrg{ 1156848b8605Smrg if (ctx->Color.sRGBEnabled) 1157848b8605Smrg return format; 1158848b8605Smrg else 1159848b8605Smrg return _mesa_get_srgb_format_linear(format); 1160848b8605Smrg} 1161848b8605Smrg 1162848b8605Smrg/**********************************************************************/ 1163848b8605Smrg/** \name Initialization */ 1164848b8605Smrg/*@{*/ 1165848b8605Smrg 1166848b8605Smrg/** 1167848b8605Smrg * Initialization of the context's Color attribute group. 1168848b8605Smrg * 1169848b8605Smrg * \param ctx GL context. 1170848b8605Smrg * 1171848b8605Smrg * Initializes the related fields in the context color attribute group, 1172848b8605Smrg * __struct gl_contextRec::Color. 1173848b8605Smrg */ 1174848b8605Smrgvoid _mesa_init_color( struct gl_context * ctx ) 1175848b8605Smrg{ 1176848b8605Smrg GLuint i; 1177848b8605Smrg 1178848b8605Smrg /* Color buffer group */ 1179848b8605Smrg ctx->Color.IndexMask = ~0u; 1180b8e80941Smrg ctx->Color.ColorMask = 0xffffffff; 1181848b8605Smrg ctx->Color.ClearIndex = 0; 1182848b8605Smrg ASSIGN_4V( ctx->Color.ClearColor.f, 0, 0, 0, 0 ); 1183848b8605Smrg ctx->Color.AlphaEnabled = GL_FALSE; 1184848b8605Smrg ctx->Color.AlphaFunc = GL_ALWAYS; 1185848b8605Smrg ctx->Color.AlphaRef = 0; 1186848b8605Smrg ctx->Color.BlendEnabled = 0x0; 1187b8e80941Smrg for (i = 0; i < ARRAY_SIZE(ctx->Color.Blend); i++) { 1188848b8605Smrg ctx->Color.Blend[i].SrcRGB = GL_ONE; 1189848b8605Smrg ctx->Color.Blend[i].DstRGB = GL_ZERO; 1190848b8605Smrg ctx->Color.Blend[i].SrcA = GL_ONE; 1191848b8605Smrg ctx->Color.Blend[i].DstA = GL_ZERO; 1192848b8605Smrg ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD; 1193848b8605Smrg ctx->Color.Blend[i].EquationA = GL_FUNC_ADD; 1194848b8605Smrg } 1195848b8605Smrg ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 ); 1196848b8605Smrg ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 ); 1197848b8605Smrg ctx->Color.IndexLogicOpEnabled = GL_FALSE; 1198848b8605Smrg ctx->Color.ColorLogicOpEnabled = GL_FALSE; 1199848b8605Smrg ctx->Color.LogicOp = GL_COPY; 1200b8e80941Smrg ctx->Color._LogicOp = COLOR_LOGICOP_COPY; 1201848b8605Smrg ctx->Color.DitherFlag = GL_TRUE; 1202848b8605Smrg 1203848b8605Smrg /* GL_FRONT is not possible on GLES. Instead GL_BACK will render to either 1204848b8605Smrg * the front or the back buffer depending on the config */ 1205848b8605Smrg if (ctx->Visual.doubleBufferMode || _mesa_is_gles(ctx)) { 1206848b8605Smrg ctx->Color.DrawBuffer[0] = GL_BACK; 1207848b8605Smrg } 1208848b8605Smrg else { 1209848b8605Smrg ctx->Color.DrawBuffer[0] = GL_FRONT; 1210848b8605Smrg } 1211848b8605Smrg 1212848b8605Smrg ctx->Color.ClampFragmentColor = ctx->API == API_OPENGL_COMPAT ? 1213848b8605Smrg GL_FIXED_ONLY_ARB : GL_FALSE; 1214848b8605Smrg ctx->Color._ClampFragmentColor = GL_FALSE; 1215848b8605Smrg ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB; 1216848b8605Smrg 1217b8e80941Smrg /* GLES 1/2/3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled 1218b8e80941Smrg * if EGL_KHR_gl_colorspace has been used to request sRGB. 1219b8e80941Smrg */ 1220b8e80941Smrg ctx->Color.sRGBEnabled = _mesa_is_gles(ctx); 1221b8e80941Smrg 1222b8e80941Smrg ctx->Color.BlendCoherent = true; 1223848b8605Smrg} 1224848b8605Smrg 1225848b8605Smrg/*@}*/ 1226