1bf215546Sopenharmony_ci/** 2bf215546Sopenharmony_ci * \file blend.c 3bf215546Sopenharmony_ci * Blending operations. 4bf215546Sopenharmony_ci */ 5bf215546Sopenharmony_ci 6bf215546Sopenharmony_ci/* 7bf215546Sopenharmony_ci * Mesa 3-D graphics library 8bf215546Sopenharmony_ci * 9bf215546Sopenharmony_ci * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 12bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 13bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 14bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 16bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 19bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 20bf215546Sopenharmony_ci * 21bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 28bf215546Sopenharmony_ci */ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "glheader.h" 33bf215546Sopenharmony_ci#include "blend.h" 34bf215546Sopenharmony_ci#include "context.h" 35bf215546Sopenharmony_ci#include "draw_validate.h" 36bf215546Sopenharmony_ci#include "enums.h" 37bf215546Sopenharmony_ci#include "macros.h" 38bf215546Sopenharmony_ci#include "mtypes.h" 39bf215546Sopenharmony_ci#include "state.h" 40bf215546Sopenharmony_ci#include "api_exec_decl.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci/** 45bf215546Sopenharmony_ci * Check if given blend source factor is legal. 46bf215546Sopenharmony_ci * \return GL_TRUE if legal, GL_FALSE otherwise. 47bf215546Sopenharmony_ci */ 48bf215546Sopenharmony_cistatic GLboolean 49bf215546Sopenharmony_cilegal_src_factor(const struct gl_context *ctx, GLenum factor) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci switch (factor) { 52bf215546Sopenharmony_ci case GL_SRC_COLOR: 53bf215546Sopenharmony_ci case GL_ONE_MINUS_SRC_COLOR: 54bf215546Sopenharmony_ci case GL_ZERO: 55bf215546Sopenharmony_ci case GL_ONE: 56bf215546Sopenharmony_ci case GL_DST_COLOR: 57bf215546Sopenharmony_ci case GL_ONE_MINUS_DST_COLOR: 58bf215546Sopenharmony_ci case GL_SRC_ALPHA: 59bf215546Sopenharmony_ci case GL_ONE_MINUS_SRC_ALPHA: 60bf215546Sopenharmony_ci case GL_DST_ALPHA: 61bf215546Sopenharmony_ci case GL_ONE_MINUS_DST_ALPHA: 62bf215546Sopenharmony_ci case GL_SRC_ALPHA_SATURATE: 63bf215546Sopenharmony_ci return GL_TRUE; 64bf215546Sopenharmony_ci case GL_CONSTANT_COLOR: 65bf215546Sopenharmony_ci case GL_ONE_MINUS_CONSTANT_COLOR: 66bf215546Sopenharmony_ci case GL_CONSTANT_ALPHA: 67bf215546Sopenharmony_ci case GL_ONE_MINUS_CONSTANT_ALPHA: 68bf215546Sopenharmony_ci return _mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES2; 69bf215546Sopenharmony_ci case GL_SRC1_COLOR: 70bf215546Sopenharmony_ci case GL_SRC1_ALPHA: 71bf215546Sopenharmony_ci case GL_ONE_MINUS_SRC1_COLOR: 72bf215546Sopenharmony_ci case GL_ONE_MINUS_SRC1_ALPHA: 73bf215546Sopenharmony_ci return ctx->API != API_OPENGLES 74bf215546Sopenharmony_ci && ctx->Extensions.ARB_blend_func_extended; 75bf215546Sopenharmony_ci default: 76bf215546Sopenharmony_ci return GL_FALSE; 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci} 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci/** 82bf215546Sopenharmony_ci * Check if given blend destination factor is legal. 83bf215546Sopenharmony_ci * \return GL_TRUE if legal, GL_FALSE otherwise. 84bf215546Sopenharmony_ci */ 85bf215546Sopenharmony_cistatic GLboolean 86bf215546Sopenharmony_cilegal_dst_factor(const struct gl_context *ctx, GLenum factor) 87bf215546Sopenharmony_ci{ 88bf215546Sopenharmony_ci switch (factor) { 89bf215546Sopenharmony_ci case GL_DST_COLOR: 90bf215546Sopenharmony_ci case GL_ONE_MINUS_DST_COLOR: 91bf215546Sopenharmony_ci case GL_ZERO: 92bf215546Sopenharmony_ci case GL_ONE: 93bf215546Sopenharmony_ci case GL_SRC_COLOR: 94bf215546Sopenharmony_ci case GL_ONE_MINUS_SRC_COLOR: 95bf215546Sopenharmony_ci case GL_SRC_ALPHA: 96bf215546Sopenharmony_ci case GL_ONE_MINUS_SRC_ALPHA: 97bf215546Sopenharmony_ci case GL_DST_ALPHA: 98bf215546Sopenharmony_ci case GL_ONE_MINUS_DST_ALPHA: 99bf215546Sopenharmony_ci return GL_TRUE; 100bf215546Sopenharmony_ci case GL_CONSTANT_COLOR: 101bf215546Sopenharmony_ci case GL_ONE_MINUS_CONSTANT_COLOR: 102bf215546Sopenharmony_ci case GL_CONSTANT_ALPHA: 103bf215546Sopenharmony_ci case GL_ONE_MINUS_CONSTANT_ALPHA: 104bf215546Sopenharmony_ci return _mesa_is_desktop_gl(ctx) || ctx->API == API_OPENGLES2; 105bf215546Sopenharmony_ci case GL_SRC_ALPHA_SATURATE: 106bf215546Sopenharmony_ci return (ctx->API != API_OPENGLES 107bf215546Sopenharmony_ci && ctx->Extensions.ARB_blend_func_extended) 108bf215546Sopenharmony_ci || _mesa_is_gles3(ctx); 109bf215546Sopenharmony_ci case GL_SRC1_COLOR: 110bf215546Sopenharmony_ci case GL_SRC1_ALPHA: 111bf215546Sopenharmony_ci case GL_ONE_MINUS_SRC1_COLOR: 112bf215546Sopenharmony_ci case GL_ONE_MINUS_SRC1_ALPHA: 113bf215546Sopenharmony_ci return ctx->API != API_OPENGLES 114bf215546Sopenharmony_ci && ctx->Extensions.ARB_blend_func_extended; 115bf215546Sopenharmony_ci default: 116bf215546Sopenharmony_ci return GL_FALSE; 117bf215546Sopenharmony_ci } 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci/** 122bf215546Sopenharmony_ci * Check if src/dest RGB/A blend factors are legal. If not generate 123bf215546Sopenharmony_ci * a GL error. 124bf215546Sopenharmony_ci * \return GL_TRUE if factors are legal, GL_FALSE otherwise. 125bf215546Sopenharmony_ci */ 126bf215546Sopenharmony_cistatic GLboolean 127bf215546Sopenharmony_civalidate_blend_factors(struct gl_context *ctx, const char *func, 128bf215546Sopenharmony_ci GLenum sfactorRGB, GLenum dfactorRGB, 129bf215546Sopenharmony_ci GLenum sfactorA, GLenum dfactorA) 130bf215546Sopenharmony_ci{ 131bf215546Sopenharmony_ci if (!legal_src_factor(ctx, sfactorRGB)) { 132bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, 133bf215546Sopenharmony_ci "%s(sfactorRGB = %s)", func, 134bf215546Sopenharmony_ci _mesa_enum_to_string(sfactorRGB)); 135bf215546Sopenharmony_ci return GL_FALSE; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci if (!legal_dst_factor(ctx, dfactorRGB)) { 139bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, 140bf215546Sopenharmony_ci "%s(dfactorRGB = %s)", func, 141bf215546Sopenharmony_ci _mesa_enum_to_string(dfactorRGB)); 142bf215546Sopenharmony_ci return GL_FALSE; 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) { 146bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, 147bf215546Sopenharmony_ci "%s(sfactorA = %s)", func, 148bf215546Sopenharmony_ci _mesa_enum_to_string(sfactorA)); 149bf215546Sopenharmony_ci return GL_FALSE; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) { 153bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, 154bf215546Sopenharmony_ci "%s(dfactorA = %s)", func, 155bf215546Sopenharmony_ci _mesa_enum_to_string(dfactorA)); 156bf215546Sopenharmony_ci return GL_FALSE; 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci return GL_TRUE; 160bf215546Sopenharmony_ci} 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_cistatic GLboolean 164bf215546Sopenharmony_ciblend_factor_is_dual_src(GLenum factor) 165bf215546Sopenharmony_ci{ 166bf215546Sopenharmony_ci return (factor == GL_SRC1_COLOR || 167bf215546Sopenharmony_ci factor == GL_SRC1_ALPHA || 168bf215546Sopenharmony_ci factor == GL_ONE_MINUS_SRC1_COLOR || 169bf215546Sopenharmony_ci factor == GL_ONE_MINUS_SRC1_ALPHA); 170bf215546Sopenharmony_ci} 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_cistatic bool 173bf215546Sopenharmony_ciupdate_uses_dual_src(struct gl_context *ctx, int buf) 174bf215546Sopenharmony_ci{ 175bf215546Sopenharmony_ci bool uses_dual_src = 176bf215546Sopenharmony_ci (blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcRGB) || 177bf215546Sopenharmony_ci blend_factor_is_dual_src(ctx->Color.Blend[buf].DstRGB) || 178bf215546Sopenharmony_ci blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcA) || 179bf215546Sopenharmony_ci blend_factor_is_dual_src(ctx->Color.Blend[buf].DstA)); 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci if (((ctx->Color._BlendUsesDualSrc >> buf) & 0x1) != uses_dual_src) { 182bf215546Sopenharmony_ci if (uses_dual_src) 183bf215546Sopenharmony_ci ctx->Color._BlendUsesDualSrc |= 1 << buf; 184bf215546Sopenharmony_ci else 185bf215546Sopenharmony_ci ctx->Color._BlendUsesDualSrc &= ~(1 << buf); 186bf215546Sopenharmony_ci return true; /* changed state */ 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci return false; /* no change */ 189bf215546Sopenharmony_ci} 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci/** 193bf215546Sopenharmony_ci * Return the number of per-buffer blend states to update in 194bf215546Sopenharmony_ci * glBlendFunc, glBlendFuncSeparate, glBlendEquation, etc. 195bf215546Sopenharmony_ci */ 196bf215546Sopenharmony_cistatic inline unsigned 197bf215546Sopenharmony_cinum_buffers(const struct gl_context *ctx) 198bf215546Sopenharmony_ci{ 199bf215546Sopenharmony_ci return ctx->Extensions.ARB_draw_buffers_blend 200bf215546Sopenharmony_ci ? ctx->Const.MaxDrawBuffers : 1; 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci/* Returns true if there was no change */ 205bf215546Sopenharmony_cistatic bool 206bf215546Sopenharmony_ciskip_blend_state_update(const struct gl_context *ctx, 207bf215546Sopenharmony_ci GLenum sfactorRGB, GLenum dfactorRGB, 208bf215546Sopenharmony_ci GLenum sfactorA, GLenum dfactorA) 209bf215546Sopenharmony_ci{ 210bf215546Sopenharmony_ci /* Check if we're really changing any state. If not, return early. */ 211bf215546Sopenharmony_ci if (ctx->Color._BlendFuncPerBuffer) { 212bf215546Sopenharmony_ci const unsigned numBuffers = num_buffers(ctx); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci /* Check all per-buffer states */ 215bf215546Sopenharmony_ci for (unsigned buf = 0; buf < numBuffers; buf++) { 216bf215546Sopenharmony_ci if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB || 217bf215546Sopenharmony_ci ctx->Color.Blend[buf].DstRGB != dfactorRGB || 218bf215546Sopenharmony_ci ctx->Color.Blend[buf].SrcA != sfactorA || 219bf215546Sopenharmony_ci ctx->Color.Blend[buf].DstA != dfactorA) { 220bf215546Sopenharmony_ci return false; 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci else { 225bf215546Sopenharmony_ci /* only need to check 0th per-buffer state */ 226bf215546Sopenharmony_ci if (ctx->Color.Blend[0].SrcRGB != sfactorRGB || 227bf215546Sopenharmony_ci ctx->Color.Blend[0].DstRGB != dfactorRGB || 228bf215546Sopenharmony_ci ctx->Color.Blend[0].SrcA != sfactorA || 229bf215546Sopenharmony_ci ctx->Color.Blend[0].DstA != dfactorA) { 230bf215546Sopenharmony_ci return false; 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci return true; 235bf215546Sopenharmony_ci} 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_cistatic void 239bf215546Sopenharmony_ciblend_func_separate(struct gl_context *ctx, 240bf215546Sopenharmony_ci GLenum sfactorRGB, GLenum dfactorRGB, 241bf215546Sopenharmony_ci GLenum sfactorA, GLenum dfactorA) 242bf215546Sopenharmony_ci{ 243bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT); 244bf215546Sopenharmony_ci ctx->NewDriverState |= ST_NEW_BLEND; 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci const unsigned numBuffers = num_buffers(ctx); 247bf215546Sopenharmony_ci for (unsigned buf = 0; buf < numBuffers; buf++) { 248bf215546Sopenharmony_ci ctx->Color.Blend[buf].SrcRGB = sfactorRGB; 249bf215546Sopenharmony_ci ctx->Color.Blend[buf].DstRGB = dfactorRGB; 250bf215546Sopenharmony_ci ctx->Color.Blend[buf].SrcA = sfactorA; 251bf215546Sopenharmony_ci ctx->Color.Blend[buf].DstA = dfactorA; 252bf215546Sopenharmony_ci } 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci GLbitfield old_blend_uses_dual_src = ctx->Color._BlendUsesDualSrc; 255bf215546Sopenharmony_ci update_uses_dual_src(ctx, 0); 256bf215546Sopenharmony_ci /* We have to replicate the bit to all color buffers. */ 257bf215546Sopenharmony_ci if (ctx->Color._BlendUsesDualSrc & 0x1) 258bf215546Sopenharmony_ci ctx->Color._BlendUsesDualSrc |= BITFIELD_RANGE(1, numBuffers - 1); 259bf215546Sopenharmony_ci else 260bf215546Sopenharmony_ci ctx->Color._BlendUsesDualSrc = 0; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci if (ctx->Color._BlendUsesDualSrc != old_blend_uses_dual_src) 263bf215546Sopenharmony_ci _mesa_update_valid_to_render_state(ctx); 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci ctx->Color._BlendFuncPerBuffer = GL_FALSE; 266bf215546Sopenharmony_ci} 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci/** 270bf215546Sopenharmony_ci * Specify the blending operation. 271bf215546Sopenharmony_ci * 272bf215546Sopenharmony_ci * \param sfactor source factor operator. 273bf215546Sopenharmony_ci * \param dfactor destination factor operator. 274bf215546Sopenharmony_ci * 275bf215546Sopenharmony_ci * \sa glBlendFunc, glBlendFuncSeparateEXT 276bf215546Sopenharmony_ci */ 277bf215546Sopenharmony_civoid GLAPIENTRY 278bf215546Sopenharmony_ci_mesa_BlendFunc( GLenum sfactor, GLenum dfactor ) 279bf215546Sopenharmony_ci{ 280bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci if (skip_blend_state_update(ctx, sfactor, dfactor, sfactor, dfactor)) 283bf215546Sopenharmony_ci return; 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (!validate_blend_factors(ctx, "glBlendFunc", 286bf215546Sopenharmony_ci sfactor, dfactor, sfactor, dfactor)) { 287bf215546Sopenharmony_ci return; 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci blend_func_separate(ctx, sfactor, dfactor, sfactor, dfactor); 291bf215546Sopenharmony_ci} 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_civoid GLAPIENTRY 295bf215546Sopenharmony_ci_mesa_BlendFunc_no_error(GLenum sfactor, GLenum dfactor) 296bf215546Sopenharmony_ci{ 297bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci if (skip_blend_state_update(ctx, sfactor, dfactor, sfactor, dfactor)) 300bf215546Sopenharmony_ci return; 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci blend_func_separate(ctx, sfactor, dfactor, sfactor, dfactor); 303bf215546Sopenharmony_ci} 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci/** 307bf215546Sopenharmony_ci * Set the separate blend source/dest factors for all draw buffers. 308bf215546Sopenharmony_ci * 309bf215546Sopenharmony_ci * \param sfactorRGB RGB source factor operator. 310bf215546Sopenharmony_ci * \param dfactorRGB RGB destination factor operator. 311bf215546Sopenharmony_ci * \param sfactorA alpha source factor operator. 312bf215546Sopenharmony_ci * \param dfactorA alpha destination factor operator. 313bf215546Sopenharmony_ci */ 314bf215546Sopenharmony_civoid GLAPIENTRY 315bf215546Sopenharmony_ci_mesa_BlendFuncSeparate( GLenum sfactorRGB, GLenum dfactorRGB, 316bf215546Sopenharmony_ci GLenum sfactorA, GLenum dfactorA ) 317bf215546Sopenharmony_ci{ 318bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 321bf215546Sopenharmony_ci _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n", 322bf215546Sopenharmony_ci _mesa_enum_to_string(sfactorRGB), 323bf215546Sopenharmony_ci _mesa_enum_to_string(dfactorRGB), 324bf215546Sopenharmony_ci _mesa_enum_to_string(sfactorA), 325bf215546Sopenharmony_ci _mesa_enum_to_string(dfactorA)); 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci if (skip_blend_state_update(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA)) 330bf215546Sopenharmony_ci return; 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci if (!validate_blend_factors(ctx, "glBlendFuncSeparate", 333bf215546Sopenharmony_ci sfactorRGB, dfactorRGB, 334bf215546Sopenharmony_ci sfactorA, dfactorA)) { 335bf215546Sopenharmony_ci return; 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci blend_func_separate(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA); 339bf215546Sopenharmony_ci} 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_civoid GLAPIENTRY 343bf215546Sopenharmony_ci_mesa_BlendFuncSeparate_no_error(GLenum sfactorRGB, GLenum dfactorRGB, 344bf215546Sopenharmony_ci GLenum sfactorA, GLenum dfactorA) 345bf215546Sopenharmony_ci{ 346bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci if (skip_blend_state_update(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA)) 349bf215546Sopenharmony_ci return; 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci blend_func_separate(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA); 352bf215546Sopenharmony_ci} 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_civoid GLAPIENTRY 356bf215546Sopenharmony_ci_mesa_BlendFunciARB_no_error(GLuint buf, GLenum sfactor, GLenum dfactor) 357bf215546Sopenharmony_ci{ 358bf215546Sopenharmony_ci _mesa_BlendFuncSeparateiARB_no_error(buf, sfactor, dfactor, sfactor, 359bf215546Sopenharmony_ci dfactor); 360bf215546Sopenharmony_ci} 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci/** 364bf215546Sopenharmony_ci * Set blend source/dest factors for one color buffer/target. 365bf215546Sopenharmony_ci */ 366bf215546Sopenharmony_civoid GLAPIENTRY 367bf215546Sopenharmony_ci_mesa_BlendFunciARB(GLuint buf, GLenum sfactor, GLenum dfactor) 368bf215546Sopenharmony_ci{ 369bf215546Sopenharmony_ci _mesa_BlendFuncSeparateiARB(buf, sfactor, dfactor, sfactor, dfactor); 370bf215546Sopenharmony_ci} 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_cistatic ALWAYS_INLINE void 374bf215546Sopenharmony_ciblend_func_separatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB, 375bf215546Sopenharmony_ci GLenum sfactorA, GLenum dfactorA, bool no_error) 376bf215546Sopenharmony_ci{ 377bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci if (!no_error) { 380bf215546Sopenharmony_ci if (!ctx->Extensions.ARB_draw_buffers_blend) { 381bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()"); 382bf215546Sopenharmony_ci return; 383bf215546Sopenharmony_ci } 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci if (buf >= ctx->Const.MaxDrawBuffers) { 386bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)", 387bf215546Sopenharmony_ci buf); 388bf215546Sopenharmony_ci return; 389bf215546Sopenharmony_ci } 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB && 393bf215546Sopenharmony_ci ctx->Color.Blend[buf].DstRGB == dfactorRGB && 394bf215546Sopenharmony_ci ctx->Color.Blend[buf].SrcA == sfactorA && 395bf215546Sopenharmony_ci ctx->Color.Blend[buf].DstA == dfactorA) 396bf215546Sopenharmony_ci return; /* no change */ 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci if (!no_error && !validate_blend_factors(ctx, "glBlendFuncSeparatei", 399bf215546Sopenharmony_ci sfactorRGB, dfactorRGB, 400bf215546Sopenharmony_ci sfactorA, dfactorA)) { 401bf215546Sopenharmony_ci return; 402bf215546Sopenharmony_ci } 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT); 405bf215546Sopenharmony_ci ctx->NewDriverState |= ST_NEW_BLEND; 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci ctx->Color.Blend[buf].SrcRGB = sfactorRGB; 408bf215546Sopenharmony_ci ctx->Color.Blend[buf].DstRGB = dfactorRGB; 409bf215546Sopenharmony_ci ctx->Color.Blend[buf].SrcA = sfactorA; 410bf215546Sopenharmony_ci ctx->Color.Blend[buf].DstA = dfactorA; 411bf215546Sopenharmony_ci if (update_uses_dual_src(ctx, buf)) 412bf215546Sopenharmony_ci _mesa_update_valid_to_render_state(ctx); 413bf215546Sopenharmony_ci ctx->Color._BlendFuncPerBuffer = GL_TRUE; 414bf215546Sopenharmony_ci} 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_civoid GLAPIENTRY 418bf215546Sopenharmony_ci_mesa_BlendFuncSeparateiARB_no_error(GLuint buf, GLenum sfactorRGB, 419bf215546Sopenharmony_ci GLenum dfactorRGB, GLenum sfactorA, 420bf215546Sopenharmony_ci GLenum dfactorA) 421bf215546Sopenharmony_ci{ 422bf215546Sopenharmony_ci blend_func_separatei(buf, sfactorRGB, dfactorRGB, sfactorA, dfactorA, 423bf215546Sopenharmony_ci true); 424bf215546Sopenharmony_ci} 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci/** 428bf215546Sopenharmony_ci * Set separate blend source/dest factors for one color buffer/target. 429bf215546Sopenharmony_ci */ 430bf215546Sopenharmony_civoid GLAPIENTRY 431bf215546Sopenharmony_ci_mesa_BlendFuncSeparateiARB(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB, 432bf215546Sopenharmony_ci GLenum sfactorA, GLenum dfactorA) 433bf215546Sopenharmony_ci{ 434bf215546Sopenharmony_ci blend_func_separatei(buf, sfactorRGB, dfactorRGB, sfactorA, dfactorA, 435bf215546Sopenharmony_ci false); 436bf215546Sopenharmony_ci} 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci/** 440bf215546Sopenharmony_ci * Return true if \p mode is a legal blending equation, excluding 441bf215546Sopenharmony_ci * GL_KHR_blend_equation_advanced modes. 442bf215546Sopenharmony_ci */ 443bf215546Sopenharmony_cistatic bool 444bf215546Sopenharmony_cilegal_simple_blend_equation(const struct gl_context *ctx, GLenum mode) 445bf215546Sopenharmony_ci{ 446bf215546Sopenharmony_ci switch (mode) { 447bf215546Sopenharmony_ci case GL_FUNC_ADD: 448bf215546Sopenharmony_ci case GL_FUNC_SUBTRACT: 449bf215546Sopenharmony_ci case GL_FUNC_REVERSE_SUBTRACT: 450bf215546Sopenharmony_ci case GL_MIN: 451bf215546Sopenharmony_ci case GL_MAX: 452bf215546Sopenharmony_ci return GL_TRUE; 453bf215546Sopenharmony_ci default: 454bf215546Sopenharmony_ci return GL_FALSE; 455bf215546Sopenharmony_ci } 456bf215546Sopenharmony_ci} 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_cistatic enum gl_advanced_blend_mode 459bf215546Sopenharmony_ciadvanced_blend_mode_from_gl_enum(GLenum mode) 460bf215546Sopenharmony_ci{ 461bf215546Sopenharmony_ci switch (mode) { 462bf215546Sopenharmony_ci case GL_MULTIPLY_KHR: 463bf215546Sopenharmony_ci return BLEND_MULTIPLY; 464bf215546Sopenharmony_ci case GL_SCREEN_KHR: 465bf215546Sopenharmony_ci return BLEND_SCREEN; 466bf215546Sopenharmony_ci case GL_OVERLAY_KHR: 467bf215546Sopenharmony_ci return BLEND_OVERLAY; 468bf215546Sopenharmony_ci case GL_DARKEN_KHR: 469bf215546Sopenharmony_ci return BLEND_DARKEN; 470bf215546Sopenharmony_ci case GL_LIGHTEN_KHR: 471bf215546Sopenharmony_ci return BLEND_LIGHTEN; 472bf215546Sopenharmony_ci case GL_COLORDODGE_KHR: 473bf215546Sopenharmony_ci return BLEND_COLORDODGE; 474bf215546Sopenharmony_ci case GL_COLORBURN_KHR: 475bf215546Sopenharmony_ci return BLEND_COLORBURN; 476bf215546Sopenharmony_ci case GL_HARDLIGHT_KHR: 477bf215546Sopenharmony_ci return BLEND_HARDLIGHT; 478bf215546Sopenharmony_ci case GL_SOFTLIGHT_KHR: 479bf215546Sopenharmony_ci return BLEND_SOFTLIGHT; 480bf215546Sopenharmony_ci case GL_DIFFERENCE_KHR: 481bf215546Sopenharmony_ci return BLEND_DIFFERENCE; 482bf215546Sopenharmony_ci case GL_EXCLUSION_KHR: 483bf215546Sopenharmony_ci return BLEND_EXCLUSION; 484bf215546Sopenharmony_ci case GL_HSL_HUE_KHR: 485bf215546Sopenharmony_ci return BLEND_HSL_HUE; 486bf215546Sopenharmony_ci case GL_HSL_SATURATION_KHR: 487bf215546Sopenharmony_ci return BLEND_HSL_SATURATION; 488bf215546Sopenharmony_ci case GL_HSL_COLOR_KHR: 489bf215546Sopenharmony_ci return BLEND_HSL_COLOR; 490bf215546Sopenharmony_ci case GL_HSL_LUMINOSITY_KHR: 491bf215546Sopenharmony_ci return BLEND_HSL_LUMINOSITY; 492bf215546Sopenharmony_ci default: 493bf215546Sopenharmony_ci return BLEND_NONE; 494bf215546Sopenharmony_ci } 495bf215546Sopenharmony_ci} 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci/** 498bf215546Sopenharmony_ci * If \p mode is one of the advanced blending equations defined by 499bf215546Sopenharmony_ci * GL_KHR_blend_equation_advanced (and the extension is supported), 500bf215546Sopenharmony_ci * return the corresponding BLEND_* enum. Otherwise, return BLEND_NONE 501bf215546Sopenharmony_ci * (which can also be treated as false). 502bf215546Sopenharmony_ci */ 503bf215546Sopenharmony_cistatic enum gl_advanced_blend_mode 504bf215546Sopenharmony_ciadvanced_blend_mode(const struct gl_context *ctx, GLenum mode) 505bf215546Sopenharmony_ci{ 506bf215546Sopenharmony_ci return _mesa_has_KHR_blend_equation_advanced(ctx) ? 507bf215546Sopenharmony_ci advanced_blend_mode_from_gl_enum(mode) : BLEND_NONE; 508bf215546Sopenharmony_ci} 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_cistatic void 511bf215546Sopenharmony_ciset_advanced_blend_mode(struct gl_context *ctx, 512bf215546Sopenharmony_ci enum gl_advanced_blend_mode advanced_mode) 513bf215546Sopenharmony_ci{ 514bf215546Sopenharmony_ci if (ctx->Color._AdvancedBlendMode != advanced_mode) { 515bf215546Sopenharmony_ci ctx->Color._AdvancedBlendMode = advanced_mode; 516bf215546Sopenharmony_ci _mesa_update_valid_to_render_state(ctx); 517bf215546Sopenharmony_ci } 518bf215546Sopenharmony_ci} 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci/* This is really an extension function! */ 521bf215546Sopenharmony_civoid GLAPIENTRY 522bf215546Sopenharmony_ci_mesa_BlendEquation( GLenum mode ) 523bf215546Sopenharmony_ci{ 524bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 525bf215546Sopenharmony_ci const unsigned numBuffers = num_buffers(ctx); 526bf215546Sopenharmony_ci unsigned buf; 527bf215546Sopenharmony_ci bool changed = false; 528bf215546Sopenharmony_ci enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode); 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 531bf215546Sopenharmony_ci _mesa_debug(ctx, "glBlendEquation(%s)\n", 532bf215546Sopenharmony_ci _mesa_enum_to_string(mode)); 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci if (ctx->Color._BlendEquationPerBuffer) { 535bf215546Sopenharmony_ci /* Check all per-buffer states */ 536bf215546Sopenharmony_ci for (buf = 0; buf < numBuffers; buf++) { 537bf215546Sopenharmony_ci if (ctx->Color.Blend[buf].EquationRGB != mode || 538bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationA != mode) { 539bf215546Sopenharmony_ci changed = true; 540bf215546Sopenharmony_ci break; 541bf215546Sopenharmony_ci } 542bf215546Sopenharmony_ci } 543bf215546Sopenharmony_ci } 544bf215546Sopenharmony_ci else { 545bf215546Sopenharmony_ci /* only need to check 0th per-buffer state */ 546bf215546Sopenharmony_ci if (ctx->Color.Blend[0].EquationRGB != mode || 547bf215546Sopenharmony_ci ctx->Color.Blend[0].EquationA != mode) { 548bf215546Sopenharmony_ci changed = true; 549bf215546Sopenharmony_ci } 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci if (!changed) 553bf215546Sopenharmony_ci return; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci if (!legal_simple_blend_equation(ctx, mode) && !advanced_mode) { 557bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); 558bf215546Sopenharmony_ci return; 559bf215546Sopenharmony_ci } 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci _mesa_flush_vertices_for_blend_adv(ctx, ctx->Color.BlendEnabled, 562bf215546Sopenharmony_ci advanced_mode); 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci for (buf = 0; buf < numBuffers; buf++) { 565bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationRGB = mode; 566bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationA = mode; 567bf215546Sopenharmony_ci } 568bf215546Sopenharmony_ci ctx->Color._BlendEquationPerBuffer = GL_FALSE; 569bf215546Sopenharmony_ci set_advanced_blend_mode(ctx, advanced_mode); 570bf215546Sopenharmony_ci} 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_ci/** 574bf215546Sopenharmony_ci * Set blend equation for one color buffer/target. 575bf215546Sopenharmony_ci */ 576bf215546Sopenharmony_cistatic void 577bf215546Sopenharmony_ciblend_equationi(struct gl_context *ctx, GLuint buf, GLenum mode, 578bf215546Sopenharmony_ci enum gl_advanced_blend_mode advanced_mode) 579bf215546Sopenharmony_ci{ 580bf215546Sopenharmony_ci if (ctx->Color.Blend[buf].EquationRGB == mode && 581bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationA == mode) 582bf215546Sopenharmony_ci return; /* no change */ 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci _mesa_flush_vertices_for_blend_adv(ctx, ctx->Color.BlendEnabled, 585bf215546Sopenharmony_ci advanced_mode); 586bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationRGB = mode; 587bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationA = mode; 588bf215546Sopenharmony_ci ctx->Color._BlendEquationPerBuffer = GL_TRUE; 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci if (buf == 0) 591bf215546Sopenharmony_ci set_advanced_blend_mode(ctx, advanced_mode); 592bf215546Sopenharmony_ci} 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_civoid GLAPIENTRY 596bf215546Sopenharmony_ci_mesa_BlendEquationiARB_no_error(GLuint buf, GLenum mode) 597bf215546Sopenharmony_ci{ 598bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode); 601bf215546Sopenharmony_ci blend_equationi(ctx, buf, mode, advanced_mode); 602bf215546Sopenharmony_ci} 603bf215546Sopenharmony_ci 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_civoid GLAPIENTRY 606bf215546Sopenharmony_ci_mesa_BlendEquationiARB(GLuint buf, GLenum mode) 607bf215546Sopenharmony_ci{ 608bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 609bf215546Sopenharmony_ci enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode); 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 612bf215546Sopenharmony_ci _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n", 613bf215546Sopenharmony_ci buf, _mesa_enum_to_string(mode)); 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci if (buf >= ctx->Const.MaxDrawBuffers) { 616bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationi(buffer=%u)", 617bf215546Sopenharmony_ci buf); 618bf215546Sopenharmony_ci return; 619bf215546Sopenharmony_ci } 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci if (!legal_simple_blend_equation(ctx, mode) && !advanced_mode) { 622bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi"); 623bf215546Sopenharmony_ci return; 624bf215546Sopenharmony_ci } 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci blend_equationi(ctx, buf, mode, advanced_mode); 627bf215546Sopenharmony_ci} 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_cistatic void 631bf215546Sopenharmony_ciblend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA, 632bf215546Sopenharmony_ci bool no_error) 633bf215546Sopenharmony_ci{ 634bf215546Sopenharmony_ci const unsigned numBuffers = num_buffers(ctx); 635bf215546Sopenharmony_ci unsigned buf; 636bf215546Sopenharmony_ci bool changed = false; 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci if (ctx->Color._BlendEquationPerBuffer) { 639bf215546Sopenharmony_ci /* Check all per-buffer states */ 640bf215546Sopenharmony_ci for (buf = 0; buf < numBuffers; buf++) { 641bf215546Sopenharmony_ci if (ctx->Color.Blend[buf].EquationRGB != modeRGB || 642bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationA != modeA) { 643bf215546Sopenharmony_ci changed = true; 644bf215546Sopenharmony_ci break; 645bf215546Sopenharmony_ci } 646bf215546Sopenharmony_ci } 647bf215546Sopenharmony_ci } else { 648bf215546Sopenharmony_ci /* only need to check 0th per-buffer state */ 649bf215546Sopenharmony_ci if (ctx->Color.Blend[0].EquationRGB != modeRGB || 650bf215546Sopenharmony_ci ctx->Color.Blend[0].EquationA != modeA) { 651bf215546Sopenharmony_ci changed = true; 652bf215546Sopenharmony_ci } 653bf215546Sopenharmony_ci } 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_ci if (!changed) 656bf215546Sopenharmony_ci return; 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_ci if (!no_error) { 659bf215546Sopenharmony_ci if ((modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate) { 660bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, 661bf215546Sopenharmony_ci "glBlendEquationSeparateEXT not supported by driver"); 662bf215546Sopenharmony_ci return; 663bf215546Sopenharmony_ci } 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_ci /* Only allow simple blending equations. 666bf215546Sopenharmony_ci * The GL_KHR_blend_equation_advanced spec says: 667bf215546Sopenharmony_ci * 668bf215546Sopenharmony_ci * "NOTE: These enums are not accepted by the <modeRGB> or <modeAlpha> 669bf215546Sopenharmony_ci * parameters of BlendEquationSeparate or BlendEquationSeparatei." 670bf215546Sopenharmony_ci */ 671bf215546Sopenharmony_ci if (!legal_simple_blend_equation(ctx, modeRGB)) { 672bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, 673bf215546Sopenharmony_ci "glBlendEquationSeparateEXT(modeRGB)"); 674bf215546Sopenharmony_ci return; 675bf215546Sopenharmony_ci } 676bf215546Sopenharmony_ci 677bf215546Sopenharmony_ci if (!legal_simple_blend_equation(ctx, modeA)) { 678bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)"); 679bf215546Sopenharmony_ci return; 680bf215546Sopenharmony_ci } 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci _mesa_flush_vertices_for_blend_state(ctx); 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci for (buf = 0; buf < numBuffers; buf++) { 686bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationRGB = modeRGB; 687bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationA = modeA; 688bf215546Sopenharmony_ci } 689bf215546Sopenharmony_ci ctx->Color._BlendEquationPerBuffer = GL_FALSE; 690bf215546Sopenharmony_ci set_advanced_blend_mode(ctx, BLEND_NONE); 691bf215546Sopenharmony_ci} 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_civoid GLAPIENTRY 695bf215546Sopenharmony_ci_mesa_BlendEquationSeparate_no_error(GLenum modeRGB, GLenum modeA) 696bf215546Sopenharmony_ci{ 697bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 698bf215546Sopenharmony_ci blend_equation_separate(ctx, modeRGB, modeA, true); 699bf215546Sopenharmony_ci} 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci 702bf215546Sopenharmony_civoid GLAPIENTRY 703bf215546Sopenharmony_ci_mesa_BlendEquationSeparate(GLenum modeRGB, GLenum modeA) 704bf215546Sopenharmony_ci{ 705bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 708bf215546Sopenharmony_ci _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n", 709bf215546Sopenharmony_ci _mesa_enum_to_string(modeRGB), 710bf215546Sopenharmony_ci _mesa_enum_to_string(modeA)); 711bf215546Sopenharmony_ci 712bf215546Sopenharmony_ci blend_equation_separate(ctx, modeRGB, modeA, false); 713bf215546Sopenharmony_ci} 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_cistatic ALWAYS_INLINE void 717bf215546Sopenharmony_ciblend_equation_separatei(struct gl_context *ctx, GLuint buf, GLenum modeRGB, 718bf215546Sopenharmony_ci GLenum modeA, bool no_error) 719bf215546Sopenharmony_ci{ 720bf215546Sopenharmony_ci if (ctx->Color.Blend[buf].EquationRGB == modeRGB && 721bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationA == modeA) 722bf215546Sopenharmony_ci return; /* no change */ 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci if (!no_error) { 725bf215546Sopenharmony_ci /* Only allow simple blending equations. 726bf215546Sopenharmony_ci * The GL_KHR_blend_equation_advanced spec says: 727bf215546Sopenharmony_ci * 728bf215546Sopenharmony_ci * "NOTE: These enums are not accepted by the <modeRGB> or <modeAlpha> 729bf215546Sopenharmony_ci * parameters of BlendEquationSeparate or BlendEquationSeparatei." 730bf215546Sopenharmony_ci */ 731bf215546Sopenharmony_ci if (!legal_simple_blend_equation(ctx, modeRGB)) { 732bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)"); 733bf215546Sopenharmony_ci return; 734bf215546Sopenharmony_ci } 735bf215546Sopenharmony_ci 736bf215546Sopenharmony_ci if (!legal_simple_blend_equation(ctx, modeA)) { 737bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)"); 738bf215546Sopenharmony_ci return; 739bf215546Sopenharmony_ci } 740bf215546Sopenharmony_ci } 741bf215546Sopenharmony_ci 742bf215546Sopenharmony_ci _mesa_flush_vertices_for_blend_state(ctx); 743bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationRGB = modeRGB; 744bf215546Sopenharmony_ci ctx->Color.Blend[buf].EquationA = modeA; 745bf215546Sopenharmony_ci ctx->Color._BlendEquationPerBuffer = GL_TRUE; 746bf215546Sopenharmony_ci set_advanced_blend_mode(ctx, BLEND_NONE); 747bf215546Sopenharmony_ci} 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_civoid GLAPIENTRY 751bf215546Sopenharmony_ci_mesa_BlendEquationSeparateiARB_no_error(GLuint buf, GLenum modeRGB, 752bf215546Sopenharmony_ci GLenum modeA) 753bf215546Sopenharmony_ci{ 754bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 755bf215546Sopenharmony_ci blend_equation_separatei(ctx, buf, modeRGB, modeA, true); 756bf215546Sopenharmony_ci} 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ci 759bf215546Sopenharmony_ci/** 760bf215546Sopenharmony_ci * Set separate blend equations for one color buffer/target. 761bf215546Sopenharmony_ci */ 762bf215546Sopenharmony_civoid GLAPIENTRY 763bf215546Sopenharmony_ci_mesa_BlendEquationSeparateiARB(GLuint buf, GLenum modeRGB, GLenum modeA) 764bf215546Sopenharmony_ci{ 765bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 768bf215546Sopenharmony_ci _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf, 769bf215546Sopenharmony_ci _mesa_enum_to_string(modeRGB), 770bf215546Sopenharmony_ci _mesa_enum_to_string(modeA)); 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci if (buf >= ctx->Const.MaxDrawBuffers) { 773bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)", 774bf215546Sopenharmony_ci buf); 775bf215546Sopenharmony_ci return; 776bf215546Sopenharmony_ci } 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci blend_equation_separatei(ctx, buf, modeRGB, modeA, false); 779bf215546Sopenharmony_ci} 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci 782bf215546Sopenharmony_ci/** 783bf215546Sopenharmony_ci * Set the blending color. 784bf215546Sopenharmony_ci * 785bf215546Sopenharmony_ci * \param red red color component. 786bf215546Sopenharmony_ci * \param green green color component. 787bf215546Sopenharmony_ci * \param blue blue color component. 788bf215546Sopenharmony_ci * \param alpha alpha color component. 789bf215546Sopenharmony_ci * 790bf215546Sopenharmony_ci * \sa glBlendColor(). 791bf215546Sopenharmony_ci * 792bf215546Sopenharmony_ci * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a 793bf215546Sopenharmony_ci * change, flushes the vertices and notifies the driver via 794bf215546Sopenharmony_ci * dd_function_table::BlendColor callback. 795bf215546Sopenharmony_ci */ 796bf215546Sopenharmony_civoid GLAPIENTRY 797bf215546Sopenharmony_ci_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 798bf215546Sopenharmony_ci{ 799bf215546Sopenharmony_ci GLfloat tmp[4]; 800bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci tmp[0] = red; 803bf215546Sopenharmony_ci tmp[1] = green; 804bf215546Sopenharmony_ci tmp[2] = blue; 805bf215546Sopenharmony_ci tmp[3] = alpha; 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped)) 808bf215546Sopenharmony_ci return; 809bf215546Sopenharmony_ci 810bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT); 811bf215546Sopenharmony_ci ctx->NewDriverState |= ST_NEW_BLEND_COLOR; 812bf215546Sopenharmony_ci COPY_4FV( ctx->Color.BlendColorUnclamped, tmp ); 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_ci ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F); 815bf215546Sopenharmony_ci ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F); 816bf215546Sopenharmony_ci ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F); 817bf215546Sopenharmony_ci ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F); 818bf215546Sopenharmony_ci} 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci 821bf215546Sopenharmony_ci/** 822bf215546Sopenharmony_ci * Specify the alpha test function. 823bf215546Sopenharmony_ci * 824bf215546Sopenharmony_ci * \param func alpha comparison function. 825bf215546Sopenharmony_ci * \param ref reference value. 826bf215546Sopenharmony_ci * 827bf215546Sopenharmony_ci * Verifies the parameters and updates gl_colorbuffer_attrib. 828bf215546Sopenharmony_ci * On a change, flushes the vertices and notifies the driver via 829bf215546Sopenharmony_ci * dd_function_table::AlphaFunc callback. 830bf215546Sopenharmony_ci */ 831bf215546Sopenharmony_civoid GLAPIENTRY 832bf215546Sopenharmony_ci_mesa_AlphaFunc( GLenum func, GLclampf ref ) 833bf215546Sopenharmony_ci{ 834bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 835bf215546Sopenharmony_ci 836bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 837bf215546Sopenharmony_ci _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n", 838bf215546Sopenharmony_ci _mesa_enum_to_string(func), ref); 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref) 841bf215546Sopenharmony_ci return; /* no change */ 842bf215546Sopenharmony_ci 843bf215546Sopenharmony_ci switch (func) { 844bf215546Sopenharmony_ci case GL_NEVER: 845bf215546Sopenharmony_ci case GL_LESS: 846bf215546Sopenharmony_ci case GL_EQUAL: 847bf215546Sopenharmony_ci case GL_LEQUAL: 848bf215546Sopenharmony_ci case GL_GREATER: 849bf215546Sopenharmony_ci case GL_NOTEQUAL: 850bf215546Sopenharmony_ci case GL_GEQUAL: 851bf215546Sopenharmony_ci case GL_ALWAYS: 852bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT); 853bf215546Sopenharmony_ci ctx->NewDriverState |= ctx->DriverFlags.NewAlphaTest; 854bf215546Sopenharmony_ci ctx->Color.AlphaFunc = func; 855bf215546Sopenharmony_ci ctx->Color.AlphaRefUnclamped = ref; 856bf215546Sopenharmony_ci ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F); 857bf215546Sopenharmony_ci return; 858bf215546Sopenharmony_ci 859bf215546Sopenharmony_ci default: 860bf215546Sopenharmony_ci _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" ); 861bf215546Sopenharmony_ci return; 862bf215546Sopenharmony_ci } 863bf215546Sopenharmony_ci} 864bf215546Sopenharmony_ci 865bf215546Sopenharmony_cistatic const enum gl_logicop_mode color_logicop_mapping[16] = { 866bf215546Sopenharmony_ci COLOR_LOGICOP_CLEAR, 867bf215546Sopenharmony_ci COLOR_LOGICOP_AND, 868bf215546Sopenharmony_ci COLOR_LOGICOP_AND_REVERSE, 869bf215546Sopenharmony_ci COLOR_LOGICOP_COPY, 870bf215546Sopenharmony_ci COLOR_LOGICOP_AND_INVERTED, 871bf215546Sopenharmony_ci COLOR_LOGICOP_NOOP, 872bf215546Sopenharmony_ci COLOR_LOGICOP_XOR, 873bf215546Sopenharmony_ci COLOR_LOGICOP_OR, 874bf215546Sopenharmony_ci COLOR_LOGICOP_NOR, 875bf215546Sopenharmony_ci COLOR_LOGICOP_EQUIV, 876bf215546Sopenharmony_ci COLOR_LOGICOP_INVERT, 877bf215546Sopenharmony_ci COLOR_LOGICOP_OR_REVERSE, 878bf215546Sopenharmony_ci COLOR_LOGICOP_COPY_INVERTED, 879bf215546Sopenharmony_ci COLOR_LOGICOP_OR_INVERTED, 880bf215546Sopenharmony_ci COLOR_LOGICOP_NAND, 881bf215546Sopenharmony_ci COLOR_LOGICOP_SET 882bf215546Sopenharmony_ci}; 883bf215546Sopenharmony_ci 884bf215546Sopenharmony_cistatic ALWAYS_INLINE void 885bf215546Sopenharmony_cilogic_op(struct gl_context *ctx, GLenum opcode, bool no_error) 886bf215546Sopenharmony_ci{ 887bf215546Sopenharmony_ci if (ctx->Color.LogicOp == opcode) 888bf215546Sopenharmony_ci return; 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci if (!no_error) { 891bf215546Sopenharmony_ci switch (opcode) { 892bf215546Sopenharmony_ci case GL_CLEAR: 893bf215546Sopenharmony_ci case GL_SET: 894bf215546Sopenharmony_ci case GL_COPY: 895bf215546Sopenharmony_ci case GL_COPY_INVERTED: 896bf215546Sopenharmony_ci case GL_NOOP: 897bf215546Sopenharmony_ci case GL_INVERT: 898bf215546Sopenharmony_ci case GL_AND: 899bf215546Sopenharmony_ci case GL_NAND: 900bf215546Sopenharmony_ci case GL_OR: 901bf215546Sopenharmony_ci case GL_NOR: 902bf215546Sopenharmony_ci case GL_XOR: 903bf215546Sopenharmony_ci case GL_EQUIV: 904bf215546Sopenharmony_ci case GL_AND_REVERSE: 905bf215546Sopenharmony_ci case GL_AND_INVERTED: 906bf215546Sopenharmony_ci case GL_OR_REVERSE: 907bf215546Sopenharmony_ci case GL_OR_INVERTED: 908bf215546Sopenharmony_ci break; 909bf215546Sopenharmony_ci default: 910bf215546Sopenharmony_ci _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" ); 911bf215546Sopenharmony_ci return; 912bf215546Sopenharmony_ci } 913bf215546Sopenharmony_ci } 914bf215546Sopenharmony_ci 915bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT); 916bf215546Sopenharmony_ci ctx->NewDriverState |= ST_NEW_BLEND; 917bf215546Sopenharmony_ci ctx->Color.LogicOp = opcode; 918bf215546Sopenharmony_ci ctx->Color._LogicOp = color_logicop_mapping[opcode & 0x0f]; 919bf215546Sopenharmony_ci _mesa_update_allow_draw_out_of_order(ctx); 920bf215546Sopenharmony_ci} 921bf215546Sopenharmony_ci 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_ci/** 924bf215546Sopenharmony_ci * Specify a logic pixel operation for color index rendering. 925bf215546Sopenharmony_ci * 926bf215546Sopenharmony_ci * \param opcode operation. 927bf215546Sopenharmony_ci * 928bf215546Sopenharmony_ci * Verifies that \p opcode is a valid enum and updates 929bf215546Sopenharmony_ci * gl_colorbuffer_attrib::LogicOp. 930bf215546Sopenharmony_ci * On a change, flushes the vertices and notifies the driver via the 931bf215546Sopenharmony_ci * dd_function_table::LogicOpcode callback. 932bf215546Sopenharmony_ci */ 933bf215546Sopenharmony_civoid GLAPIENTRY 934bf215546Sopenharmony_ci_mesa_LogicOp( GLenum opcode ) 935bf215546Sopenharmony_ci{ 936bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 939bf215546Sopenharmony_ci _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_enum_to_string(opcode)); 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci logic_op(ctx, opcode, false); 942bf215546Sopenharmony_ci} 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci 945bf215546Sopenharmony_civoid GLAPIENTRY 946bf215546Sopenharmony_ci_mesa_LogicOp_no_error(GLenum opcode) 947bf215546Sopenharmony_ci{ 948bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 949bf215546Sopenharmony_ci logic_op(ctx, opcode, true); 950bf215546Sopenharmony_ci} 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_civoid GLAPIENTRY 954bf215546Sopenharmony_ci_mesa_IndexMask( GLuint mask ) 955bf215546Sopenharmony_ci{ 956bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 957bf215546Sopenharmony_ci 958bf215546Sopenharmony_ci if (ctx->Color.IndexMask == mask) 959bf215546Sopenharmony_ci return; 960bf215546Sopenharmony_ci 961bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT); 962bf215546Sopenharmony_ci ctx->NewDriverState |= ST_NEW_BLEND; 963bf215546Sopenharmony_ci ctx->Color.IndexMask = mask; 964bf215546Sopenharmony_ci} 965bf215546Sopenharmony_ci 966bf215546Sopenharmony_ci 967bf215546Sopenharmony_ci/** 968bf215546Sopenharmony_ci * Enable or disable writing of frame buffer color components. 969bf215546Sopenharmony_ci * 970bf215546Sopenharmony_ci * \param red whether to mask writing of the red color component. 971bf215546Sopenharmony_ci * \param green whether to mask writing of the green color component. 972bf215546Sopenharmony_ci * \param blue whether to mask writing of the blue color component. 973bf215546Sopenharmony_ci * \param alpha whether to mask writing of the alpha color component. 974bf215546Sopenharmony_ci * 975bf215546Sopenharmony_ci * \sa glColorMask(). 976bf215546Sopenharmony_ci * 977bf215546Sopenharmony_ci * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a 978bf215546Sopenharmony_ci * change, flushes the vertices and notifies the driver via the 979bf215546Sopenharmony_ci * dd_function_table::ColorMask callback. 980bf215546Sopenharmony_ci */ 981bf215546Sopenharmony_civoid GLAPIENTRY 982bf215546Sopenharmony_ci_mesa_ColorMask( GLboolean red, GLboolean green, 983bf215546Sopenharmony_ci GLboolean blue, GLboolean alpha ) 984bf215546Sopenharmony_ci{ 985bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 986bf215546Sopenharmony_ci 987bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 988bf215546Sopenharmony_ci _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n", 989bf215546Sopenharmony_ci red, green, blue, alpha); 990bf215546Sopenharmony_ci 991bf215546Sopenharmony_ci GLbitfield mask = (!!red) | 992bf215546Sopenharmony_ci ((!!green) << 1) | 993bf215546Sopenharmony_ci ((!!blue) << 2) | 994bf215546Sopenharmony_ci ((!!alpha) << 3); 995bf215546Sopenharmony_ci mask = _mesa_replicate_colormask(mask, ctx->Const.MaxDrawBuffers); 996bf215546Sopenharmony_ci 997bf215546Sopenharmony_ci if (ctx->Color.ColorMask == mask) 998bf215546Sopenharmony_ci return; 999bf215546Sopenharmony_ci 1000bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT); 1001bf215546Sopenharmony_ci ctx->NewDriverState |= ST_NEW_BLEND; 1002bf215546Sopenharmony_ci ctx->Color.ColorMask = mask; 1003bf215546Sopenharmony_ci _mesa_update_allow_draw_out_of_order(ctx); 1004bf215546Sopenharmony_ci} 1005bf215546Sopenharmony_ci 1006bf215546Sopenharmony_ci 1007bf215546Sopenharmony_ci/** 1008bf215546Sopenharmony_ci * For GL_EXT_draw_buffers2 and GL3 1009bf215546Sopenharmony_ci */ 1010bf215546Sopenharmony_civoid GLAPIENTRY 1011bf215546Sopenharmony_ci_mesa_ColorMaski(GLuint buf, GLboolean red, GLboolean green, 1012bf215546Sopenharmony_ci GLboolean blue, GLboolean alpha) 1013bf215546Sopenharmony_ci{ 1014bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci if (MESA_VERBOSE & VERBOSE_API) 1017bf215546Sopenharmony_ci _mesa_debug(ctx, "glColorMaski %u %d %d %d %d\n", 1018bf215546Sopenharmony_ci buf, red, green, blue, alpha); 1019bf215546Sopenharmony_ci 1020bf215546Sopenharmony_ci if (buf >= ctx->Const.MaxDrawBuffers) { 1021bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaski(buf=%u)", buf); 1022bf215546Sopenharmony_ci return; 1023bf215546Sopenharmony_ci } 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_ci GLbitfield mask = (!!red) | 1026bf215546Sopenharmony_ci ((!!green) << 1) | 1027bf215546Sopenharmony_ci ((!!blue) << 2) | 1028bf215546Sopenharmony_ci ((!!alpha) << 3); 1029bf215546Sopenharmony_ci 1030bf215546Sopenharmony_ci if (GET_COLORMASK(ctx->Color.ColorMask, buf) == mask) 1031bf215546Sopenharmony_ci return; 1032bf215546Sopenharmony_ci 1033bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT); 1034bf215546Sopenharmony_ci ctx->NewDriverState |= ST_NEW_BLEND; 1035bf215546Sopenharmony_ci ctx->Color.ColorMask &= ~(0xf << (4 * buf)); 1036bf215546Sopenharmony_ci ctx->Color.ColorMask |= mask << (4 * buf); 1037bf215546Sopenharmony_ci _mesa_update_allow_draw_out_of_order(ctx); 1038bf215546Sopenharmony_ci} 1039bf215546Sopenharmony_ci 1040bf215546Sopenharmony_ci 1041bf215546Sopenharmony_civoid GLAPIENTRY 1042bf215546Sopenharmony_ci_mesa_ClampColor(GLenum target, GLenum clamp) 1043bf215546Sopenharmony_ci{ 1044bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 1045bf215546Sopenharmony_ci 1046bf215546Sopenharmony_ci /* Check for both the extension and the GL version, since the Intel driver 1047bf215546Sopenharmony_ci * does not advertise the extension in core profiles. 1048bf215546Sopenharmony_ci */ 1049bf215546Sopenharmony_ci if (ctx->Version <= 30 && !ctx->Extensions.ARB_color_buffer_float) { 1050bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, "glClampColor()"); 1051bf215546Sopenharmony_ci return; 1052bf215546Sopenharmony_ci } 1053bf215546Sopenharmony_ci 1054bf215546Sopenharmony_ci if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) { 1055bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)"); 1056bf215546Sopenharmony_ci return; 1057bf215546Sopenharmony_ci } 1058bf215546Sopenharmony_ci 1059bf215546Sopenharmony_ci switch (target) { 1060bf215546Sopenharmony_ci case GL_CLAMP_VERTEX_COLOR_ARB: 1061bf215546Sopenharmony_ci if (ctx->API == API_OPENGL_CORE) 1062bf215546Sopenharmony_ci goto invalid_enum; 1063bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, _NEW_LIGHT_STATE, GL_LIGHTING_BIT | GL_ENABLE_BIT); 1064bf215546Sopenharmony_ci ctx->Light.ClampVertexColor = clamp; 1065bf215546Sopenharmony_ci _mesa_update_clamp_vertex_color(ctx, ctx->DrawBuffer); 1066bf215546Sopenharmony_ci break; 1067bf215546Sopenharmony_ci case GL_CLAMP_FRAGMENT_COLOR_ARB: 1068bf215546Sopenharmony_ci if (ctx->API == API_OPENGL_CORE) 1069bf215546Sopenharmony_ci goto invalid_enum; 1070bf215546Sopenharmony_ci if (ctx->Color.ClampFragmentColor != clamp) { 1071bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT); 1072bf215546Sopenharmony_ci ctx->Color.ClampFragmentColor = clamp; 1073bf215546Sopenharmony_ci _mesa_update_clamp_fragment_color(ctx, ctx->DrawBuffer); 1074bf215546Sopenharmony_ci } 1075bf215546Sopenharmony_ci break; 1076bf215546Sopenharmony_ci case GL_CLAMP_READ_COLOR_ARB: 1077bf215546Sopenharmony_ci ctx->Color.ClampReadColor = clamp; 1078bf215546Sopenharmony_ci ctx->PopAttribState |= GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT; 1079bf215546Sopenharmony_ci break; 1080bf215546Sopenharmony_ci default: 1081bf215546Sopenharmony_ci goto invalid_enum; 1082bf215546Sopenharmony_ci } 1083bf215546Sopenharmony_ci return; 1084bf215546Sopenharmony_ci 1085bf215546Sopenharmony_ciinvalid_enum: 1086bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glClampColor(%s)", 1087bf215546Sopenharmony_ci _mesa_enum_to_string(target)); 1088bf215546Sopenharmony_ci} 1089bf215546Sopenharmony_ci 1090bf215546Sopenharmony_cistatic GLboolean 1091bf215546Sopenharmony_ciget_clamp_color(const struct gl_framebuffer *fb, GLenum clamp) 1092bf215546Sopenharmony_ci{ 1093bf215546Sopenharmony_ci if (clamp == GL_TRUE || clamp == GL_FALSE) 1094bf215546Sopenharmony_ci return clamp; 1095bf215546Sopenharmony_ci 1096bf215546Sopenharmony_ci assert(clamp == GL_FIXED_ONLY); 1097bf215546Sopenharmony_ci if (!fb) 1098bf215546Sopenharmony_ci return GL_TRUE; 1099bf215546Sopenharmony_ci 1100bf215546Sopenharmony_ci return fb->_AllColorBuffersFixedPoint; 1101bf215546Sopenharmony_ci} 1102bf215546Sopenharmony_ci 1103bf215546Sopenharmony_ciGLboolean 1104bf215546Sopenharmony_ci_mesa_get_clamp_fragment_color(const struct gl_context *ctx, 1105bf215546Sopenharmony_ci const struct gl_framebuffer *drawFb) 1106bf215546Sopenharmony_ci{ 1107bf215546Sopenharmony_ci return get_clamp_color(drawFb, ctx->Color.ClampFragmentColor); 1108bf215546Sopenharmony_ci} 1109bf215546Sopenharmony_ci 1110bf215546Sopenharmony_ciGLboolean 1111bf215546Sopenharmony_ci_mesa_get_clamp_vertex_color(const struct gl_context *ctx, 1112bf215546Sopenharmony_ci const struct gl_framebuffer *drawFb) 1113bf215546Sopenharmony_ci{ 1114bf215546Sopenharmony_ci return get_clamp_color(drawFb, ctx->Light.ClampVertexColor); 1115bf215546Sopenharmony_ci} 1116bf215546Sopenharmony_ci 1117bf215546Sopenharmony_ciGLboolean 1118bf215546Sopenharmony_ci_mesa_get_clamp_read_color(const struct gl_context *ctx, 1119bf215546Sopenharmony_ci const struct gl_framebuffer *readFb) 1120bf215546Sopenharmony_ci{ 1121bf215546Sopenharmony_ci return get_clamp_color(readFb, ctx->Color.ClampReadColor); 1122bf215546Sopenharmony_ci} 1123bf215546Sopenharmony_ci 1124bf215546Sopenharmony_ci/** 1125bf215546Sopenharmony_ci * Update the ctx->Color._ClampFragmentColor field 1126bf215546Sopenharmony_ci */ 1127bf215546Sopenharmony_civoid 1128bf215546Sopenharmony_ci_mesa_update_clamp_fragment_color(struct gl_context *ctx, 1129bf215546Sopenharmony_ci const struct gl_framebuffer *drawFb) 1130bf215546Sopenharmony_ci{ 1131bf215546Sopenharmony_ci GLboolean clamp; 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci /* Don't clamp if: 1134bf215546Sopenharmony_ci * - there is no colorbuffer 1135bf215546Sopenharmony_ci * - all colorbuffers are unsigned normalized, so clamping has no effect 1136bf215546Sopenharmony_ci * - there is an integer colorbuffer 1137bf215546Sopenharmony_ci */ 1138bf215546Sopenharmony_ci if (!drawFb || !drawFb->_HasSNormOrFloatColorBuffer || 1139bf215546Sopenharmony_ci drawFb->_IntegerBuffers) 1140bf215546Sopenharmony_ci clamp = GL_FALSE; 1141bf215546Sopenharmony_ci else 1142bf215546Sopenharmony_ci clamp = _mesa_get_clamp_fragment_color(ctx, drawFb); 1143bf215546Sopenharmony_ci 1144bf215546Sopenharmony_ci if (ctx->Color._ClampFragmentColor == clamp) 1145bf215546Sopenharmony_ci return; 1146bf215546Sopenharmony_ci 1147bf215546Sopenharmony_ci ctx->NewState |= _NEW_FRAG_CLAMP; /* for state constants */ 1148bf215546Sopenharmony_ci ctx->NewDriverState |= ctx->DriverFlags.NewFragClamp; 1149bf215546Sopenharmony_ci ctx->Color._ClampFragmentColor = clamp; 1150bf215546Sopenharmony_ci} 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci/** 1153bf215546Sopenharmony_ci * Update the ctx->Color._ClampVertexColor field 1154bf215546Sopenharmony_ci */ 1155bf215546Sopenharmony_civoid 1156bf215546Sopenharmony_ci_mesa_update_clamp_vertex_color(struct gl_context *ctx, 1157bf215546Sopenharmony_ci const struct gl_framebuffer *drawFb) 1158bf215546Sopenharmony_ci{ 1159bf215546Sopenharmony_ci ctx->Light._ClampVertexColor = 1160bf215546Sopenharmony_ci _mesa_get_clamp_vertex_color(ctx, drawFb); 1161bf215546Sopenharmony_ci} 1162bf215546Sopenharmony_ci 1163bf215546Sopenharmony_ci/**********************************************************************/ 1164bf215546Sopenharmony_ci/** \name Initialization */ 1165bf215546Sopenharmony_ci/*@{*/ 1166bf215546Sopenharmony_ci 1167bf215546Sopenharmony_ci/** 1168bf215546Sopenharmony_ci * Initialization of the context's Color attribute group. 1169bf215546Sopenharmony_ci * 1170bf215546Sopenharmony_ci * \param ctx GL context. 1171bf215546Sopenharmony_ci * 1172bf215546Sopenharmony_ci * Initializes the related fields in the context color attribute group, 1173bf215546Sopenharmony_ci * __struct gl_contextRec::Color. 1174bf215546Sopenharmony_ci */ 1175bf215546Sopenharmony_civoid _mesa_init_color( struct gl_context * ctx ) 1176bf215546Sopenharmony_ci{ 1177bf215546Sopenharmony_ci GLuint i; 1178bf215546Sopenharmony_ci 1179bf215546Sopenharmony_ci /* Color buffer group */ 1180bf215546Sopenharmony_ci ctx->Color.IndexMask = ~0u; 1181bf215546Sopenharmony_ci ctx->Color.ColorMask = 0xffffffff; 1182bf215546Sopenharmony_ci ctx->Color.ClearIndex = 0; 1183bf215546Sopenharmony_ci ASSIGN_4V( ctx->Color.ClearColor.f, 0, 0, 0, 0 ); 1184bf215546Sopenharmony_ci ctx->Color.AlphaEnabled = GL_FALSE; 1185bf215546Sopenharmony_ci ctx->Color.AlphaFunc = GL_ALWAYS; 1186bf215546Sopenharmony_ci ctx->Color.AlphaRef = 0; 1187bf215546Sopenharmony_ci ctx->Color.BlendEnabled = 0x0; 1188bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ctx->Color.Blend); i++) { 1189bf215546Sopenharmony_ci ctx->Color.Blend[i].SrcRGB = GL_ONE; 1190bf215546Sopenharmony_ci ctx->Color.Blend[i].DstRGB = GL_ZERO; 1191bf215546Sopenharmony_ci ctx->Color.Blend[i].SrcA = GL_ONE; 1192bf215546Sopenharmony_ci ctx->Color.Blend[i].DstA = GL_ZERO; 1193bf215546Sopenharmony_ci ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD; 1194bf215546Sopenharmony_ci ctx->Color.Blend[i].EquationA = GL_FUNC_ADD; 1195bf215546Sopenharmony_ci } 1196bf215546Sopenharmony_ci ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 ); 1197bf215546Sopenharmony_ci ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 ); 1198bf215546Sopenharmony_ci ctx->Color.IndexLogicOpEnabled = GL_FALSE; 1199bf215546Sopenharmony_ci ctx->Color.ColorLogicOpEnabled = GL_FALSE; 1200bf215546Sopenharmony_ci ctx->Color.LogicOp = GL_COPY; 1201bf215546Sopenharmony_ci ctx->Color._LogicOp = COLOR_LOGICOP_COPY; 1202bf215546Sopenharmony_ci ctx->Color.DitherFlag = GL_TRUE; 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_ci /* GL_FRONT is not possible on GLES. Instead GL_BACK will render to either 1205bf215546Sopenharmony_ci * the front or the back buffer depending on the config */ 1206bf215546Sopenharmony_ci if (ctx->Visual.doubleBufferMode || _mesa_is_gles(ctx)) { 1207bf215546Sopenharmony_ci ctx->Color.DrawBuffer[0] = GL_BACK; 1208bf215546Sopenharmony_ci } 1209bf215546Sopenharmony_ci else { 1210bf215546Sopenharmony_ci ctx->Color.DrawBuffer[0] = GL_FRONT; 1211bf215546Sopenharmony_ci } 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci ctx->Color.ClampFragmentColor = ctx->API == API_OPENGL_COMPAT ? 1214bf215546Sopenharmony_ci GL_FIXED_ONLY_ARB : GL_FALSE; 1215bf215546Sopenharmony_ci ctx->Color._ClampFragmentColor = GL_FALSE; 1216bf215546Sopenharmony_ci ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB; 1217bf215546Sopenharmony_ci 1218bf215546Sopenharmony_ci /* GLES 1/2/3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled 1219bf215546Sopenharmony_ci * if EGL_KHR_gl_colorspace has been used to request sRGB. 1220bf215546Sopenharmony_ci */ 1221bf215546Sopenharmony_ci ctx->Color.sRGBEnabled = _mesa_is_gles(ctx); 1222bf215546Sopenharmony_ci 1223bf215546Sopenharmony_ci ctx->Color.BlendCoherent = true; 1224bf215546Sopenharmony_ci} 1225bf215546Sopenharmony_ci 1226bf215546Sopenharmony_ci/*@}*/ 1227