Name

    KHR_blend_equation_advanced

Name Strings

    GL_KHR_blend_equation_advanced
    GL_KHR_blend_equation_advanced_coherent

Contact

    Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com)

Notice

    Copyright (c) 2012-2015 The Khronos Group Inc. Copyright terms at
        http://www.khronos.org/registry/speccopyright.html

Contributors

    OpenGL ES Working Group in Khronos
    Jeff Bolz, NVIDIA Corporation
    Mathias Heyer, NVIDIA Corporation
    Mark Kilgard, NVIDIA Corporation
    Daniel Koch, NVIDIA Corporation
    Rik Cabanier, Adobe
    Slawek Grajewski, Intel

Status

    Complete.
    Ratified by the Khronos Board of Promoters on 2014/03/14.

Version

    Last Modified Date:         April 16, 2016
    Revision:                   16

Number

    ARB Extension #174
    OpenGL ES Extension #168

Dependencies

    This extension is written against the OpenGL 4.1 Specification
    (Compatibility Profile).

    This extension is written against the OpenGL Shading Language
    Specification, Version 4.10 (Revision 6).

    OpenGL 2.0 is required (for Desktop).

    OpenGL ES 2.0 is required (for mobile).

    EXT_blend_minmax is required (for mobile).

    This extension interacts with OpenGL 4.0.

    This extension interacts with OpenGL 4.1 (Core Profile).

    This extension interacts with OpenGL 4.3 or later.

    This extension interacts with OpenGL ES 2.0.

    This extension interacts with OpenGL ES 3.0.

    This extension interacts with NV_path_rendering.

Overview

    This extension adds a number of "advanced" blending equations that can be
    used to perform new color blending operations, many of which are more
    complex than the standard blend modes provided by unextended OpenGL.  This
    extension provides two different extension string entries:

    - KHR_blend_equation_advanced:  Provides the new blending equations, but
      guarantees defined results only if each sample is touched no more than
      once in any single rendering pass.  The command BlendBarrierKHR() is
      provided to indicate a boundary between passes.

    - KHR_blend_equation_advanced_coherent:  Provides the new blending
      equations, and guarantees that blending is done coherently and in API
      primitive order.  An enable is provided to allow implementations to opt
      out of fully coherent blending and instead behave as though only
      KHR_blend_equation_advanced were supported.

    Some implementations may support KHR_blend_equation_advanced without
    supporting KHR_blend_equation_advanced_coherent.

    In unextended OpenGL, the set of blending equations is limited, and can be
    expressed very simply.  The MIN and MAX blend equations simply compute
    component-wise minimums or maximums of source and destination color
    components.  The FUNC_ADD, FUNC_SUBTRACT, and FUNC_REVERSE_SUBTRACT
    multiply the source and destination colors by source and destination
    factors and either add the two products together or subtract one from the
    other.  This limited set of operations supports many common blending
    operations but precludes the use of more sophisticated transparency and
    blending operations commonly available in many dedicated imaging APIs.

    This extension provides a number of new "advanced" blending equations.
    Unlike traditional blending operations using the FUNC_ADD equation, these
    blending equations do not use source and destination factors specified by
    BlendFunc.  Instead, each blend equation specifies a complete equation
    based on the source and destination colors.  These new blend equations are
    used for both RGB and alpha components; they may not be used to perform
    separate RGB and alpha blending (via functions like
    BlendEquationSeparate).

    These blending operations are performed using premultiplied source and
    destination colors, where RGB colors produced by the fragment shader and
    stored in the framebuffer are considered to be multiplied by alpha
    (coverage).  Many of these advanced blending equations are formulated
    where the result of blending source and destination colors with partial
    coverage have three separate contributions:  from the portions covered by
    both the source and the destination, from the portion covered only by the
    source, and from the portion covered only by the destination.  Such
    equations are defined assuming that the source and destination coverage
    have no spatial correlation within the pixel.

    In addition to the coherency issues on implementations not supporting
    KHR_blend_equation_advanced_coherent, this extension has several
    limitations worth noting.  First, the new blend equations are not
    supported while rendering to more than one color buffer at once; an
    INVALID_OPERATION will be generated if an application attempts to render
    any primitives in this unsupported configuration.  Additionally, blending
    precision may be limited to 16-bit floating-point, which could result in a
    loss of precision and dynamic range for framebuffer formats with 32-bit
    floating-point components, and in a loss of precision for formats with 12-
    and 16-bit signed or unsigned normalized integer components.

New Procedures and Functions

    void BlendBarrierKHR(void);

New Tokens

    Accepted by the <cap> parameter of Disable, Enable, and IsEnabled, and by
    the <pname> parameter of GetIntegerv, GetBooleanv, GetFloatv, GetDoublev
    and GetInteger64v:

        BLEND_ADVANCED_COHERENT_KHR                     0x9285

    Note:  The BLEND_ADVANCED_COHERENT_KHR enable is provided if and only if
    the KHR_blend_equation_advanced_coherent extension is supported.  On
    implementations supporting only KHR_blend_equation_advanced, this enable
    is considered not to exist.

    Accepted by the <mode> parameter of BlendEquation and BlendEquationi:

        MULTIPLY_KHR                                    0x9294
        SCREEN_KHR                                      0x9295
        OVERLAY_KHR                                     0x9296
        DARKEN_KHR                                      0x9297
        LIGHTEN_KHR                                     0x9298
        COLORDODGE_KHR                                  0x9299
        COLORBURN_KHR                                   0x929A
        HARDLIGHT_KHR                                   0x929B
        SOFTLIGHT_KHR                                   0x929C
        DIFFERENCE_KHR                                  0x929E
        EXCLUSION_KHR                                   0x92A0

        HSL_HUE_KHR                                     0x92AD
        HSL_SATURATION_KHR                              0x92AE
        HSL_COLOR_KHR                                   0x92AF
        HSL_LUMINOSITY_KHR                              0x92B0

    NOTE:  These enums are not accepted by the <modeRGB> or <modeAlpha>
    parameters of BlendEquationSeparate or BlendEquationSeparatei.


Additions to Chapter 2 of the OpenGL 4.1 Specification (OpenGL Operation)

    None.

Additions to Chapter 3 of the OpenGL 4.1 Specification (Rasterization)

    None.

Additions to Chapter 4 of the OpenGL 4.1 Specification (Per-Fragment
Operations and the Frame Buffer)

    Modify Section 4.1.8, Blending (p. 359).

    (modify the first paragraph, p. 361, allowing for new values in the
    <mode> parameter) ... <modeRGB> and <modeAlpha> must be one of
    FUNC_ADD, FUNC_SUBTRACT, FUNC_REVERSE_SUBTRACT, MIN, or MAX as listed
    in Table 4.1.  <mode> must be one of the mode values in Table 4.1,
    or one of the blend equations listed in tables X.1 and X.2. ...

    (modify the third paragraph, p. 361, specifying minimum precision and
    dynamic range for blend operations) ... Blending computations are treated
    as if carried out in floating-point.  For the equations in table 4.1,
    blending computations will be performed with a precision and dynamic range
    no lower than that used to represent destination components.  For the
    equations in table X.1 and X.2, blending computations will be performed
    with a precision and dynamic range no lower than the smaller of that used
    to represent destination components or that used to represent 16-bit
    floating-point values as described in section 2.1.1.

    (add unnumbered subsection prior to "Dual Source Blending and Multiple
     Draw Buffers", p. 363)

    Advanced Blend Equations

    The advanced blend equations are those listed in tables X.1 and X.2.  When
    using one of these equations, blending is performed according to the
    following equations:

      R = f(Rs',Rd')*p0(As,Ad) + Y*Rs'*p1(As,Ad) + Z*Rd'*p2(As,Ad)
      G = f(Gs',Gd')*p0(As,Ad) + Y*Gs'*p1(As,Ad) + Z*Gd'*p2(As,Ad)
      B = f(Bs',Bd')*p0(As,Ad) + Y*Bs'*p1(As,Ad) + Z*Bd'*p2(As,Ad)
      A =          X*p0(As,Ad) +     Y*p1(As,Ad) +     Z*p2(As,Ad)

    where the function f and terms X, Y, and Z are specified in the table.
    The R, G, and B components of the source color used for blending are
    considered to have been premultiplied by the A component prior to
    blending.  The base source color (Rs',Gs',Bs') is obtained by dividing
    through by the A component:

      (Rs', Gs', Bs') =
        (0, 0, 0),              if As == 0
        (Rs/As, Gs/As, Bs/As),  otherwise

    The destination color components are always considered to have been
    premultiplied by the destination A component and the base destination
    color (Rd', Gd', Bd') is obtained by dividing through by the A component:

      (Rd', Gd', Bd') =
        (0, 0, 0),               if Ad == 0
        (Rd/Ad, Gd/Ad, Bd/Ad),   otherwise

    When blending using advanced blend equations, we expect that the R, G, and
    B components of premultiplied source and destination color inputs be
    stored as the product of non-premultiplied R, G, and B components and the
    A component of the color.  If any R, G, or B component of a premultiplied
    input color is non-zero and the A component is zero, the color is
    considered ill-formed, and the corresponding component of the blend result
    will be undefined.

    The weighting functions p0, p1, and p2 are defined as follows:

      p0(As,Ad) = As*Ad
      p1(As,Ad) = As*(1-Ad)
      p2(As,Ad) = Ad*(1-As)

    In these functions, the A components of the source and destination colors
    are taken to indicate the portion of the pixel covered by the fragment
    (source) and the fragments previously accumulated in the pixel
    (destination).  The functions p0, p1, and p2 approximate the relative
    portion of the pixel covered by the intersection of the source and
    destination, covered only by the source, and covered only by the
    destination, respectively.  The equations defined here assume that there
    is no correlation between the source and destination coverage.


      Mode                      Blend Coefficients
      --------------------      -----------------------------------
      MULTIPLY_KHR              (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = Cs*Cd

      SCREEN_KHR                (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = Cs+Cd-Cs*Cd

      OVERLAY_KHR               (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = 2*Cs*Cd, if Cd <= 0.5
                                           1-2*(1-Cs)*(1-Cd), otherwise

      DARKEN_KHR                (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = min(Cs,Cd)

      LIGHTEN_KHR               (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = max(Cs,Cd)

      COLORDODGE_KHR            (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) =
                                  0, if Cd <= 0
                                  min(1,Cd/(1-Cs)), if Cd > 0 and Cs < 1
                                  1, if Cd > 0 and Cs >= 1

      COLORBURN_KHR             (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) =
                                  1, if Cd >= 1
                                  1 - min(1,(1-Cd)/Cs), if Cd < 1 and Cs > 0
                                  0, if Cd < 1 and Cs <= 0

      HARDLIGHT_KHR             (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = 2*Cs*Cd, if Cs <= 0.5
                                           1-2*(1-Cs)*(1-Cd), otherwise

      SOFTLIGHT_KHR             (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) =
                                  Cd-(1-2*Cs)*Cd*(1-Cd),
                                    if Cs <= 0.5
                                  Cd+(2*Cs-1)*Cd*((16*Cd-12)*Cd+3),
                                    if Cs > 0.5 and Cd <= 0.25
                                  Cd+(2*Cs-1)*(sqrt(Cd)-Cd),
                                    if Cs > 0.5 and Cd > 0.25

      DIFFERENCE_KHR            (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = abs(Cd-Cs)

      EXCLUSION_KHR             (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = Cs+Cd-2*Cs*Cd

      Table X.1, Advanced Blend Equations


    When using one of the HSL blend equations in table X.2 as the blend
    equation, the RGB color components produced by the function f() are
    effectively obtained by converting both the non-premultiplied source and
    destination colors to the HSL (hue, saturation, luminosity) color space,
    generating a new HSL color by selecting H, S, and L components from the
    source or destination according to the blend equation, and then converting
    the result back to RGB.  In the equations below, a blended RGB color is
    produced according to the following pseudocode:

      float minv3(vec3 c) {
        return min(min(c.r, c.g), c.b);
      }
      float maxv3(vec3 c) {
        return max(max(c.r, c.g), c.b);
      }
      float lumv3(vec3 c) {
        return dot(c, vec3(0.30, 0.59, 0.11));
      }
      float satv3(vec3 c) {
        return maxv3(c) - minv3(c);
      }

      // If any color components are outside [0,1], adjust the color to
      // get the components in range.
      vec3 ClipColor(vec3 color) {
        float lum = lumv3(color);
        float mincol = minv3(color);
        float maxcol = maxv3(color);
        if (mincol < 0.0) {
          color = lum + ((color-lum)*lum) / (lum-mincol);
        }
        if (maxcol > 1.0) {
          color = lum + ((color-lum)*lum) / (maxcol-lum);
        }
        return color;
      }

      // Take the base RGB color <cbase> and override its luminosity
      // with that of the RGB color <clum>.
      vec3 SetLum(vec3 cbase, vec3 clum) {
        float lbase = lumv3(cbase);
        float llum = lumv3(clum);
        float ldiff = llum - lbase;
        vec3 color = cbase + vec3(ldiff);
        return ClipColor(color);
      }

      // Take the base RGB color <cbase> and override its saturation with
      // that of the RGB color <csat>.  The override the luminosity of the
      // result with that of the RGB color <clum>.
      vec3 SetLumSat(vec3 cbase, vec3 csat, vec3 clum)
      {
        float minbase = minv3(cbase);
        float sbase = satv3(cbase);
        float ssat = satv3(csat);
        vec3 color;
        if (sbase > 0) {
          // Equivalent (modulo rounding errors) to setting the
          // smallest (R,G,B) component to 0, the largest to <ssat>,
          // and interpolating the "middle" component based on its
          // original value relative to the smallest/largest.
          color = (cbase - minbase) * ssat / sbase;
        } else {
          color = vec3(0.0);
        }
        return SetLum(color, clum);
      }


      Mode                      Result
      --------------------      ----------------------------------------
      HSL_HUE_KHR               (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = SetLumSat(Cs,Cd,Cd);

      HSL_SATURATION_KHR        (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = SetLumSat(Cd,Cs,Cd);

      HSL_COLOR_KHR             (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = SetLum(Cs,Cd);

      HSL_LUMINOSITY_KHR        (X,Y,Z)  = (1,1,1)
                                f(Cs,Cd) = SetLum(Cd,Cs);

      Table X.2, Hue-Saturation-Luminosity Advanced Blend Equations


    Advanced blending equations are supported only when rendering to a single
    color buffer using fragment color zero.  If any non-NONE draw buffer uses
    a blend equation found in table X.1 or X.2, the error INVALID_OPERATION is
    generated by [[Compatibility Profile:  Begin or any operation that
    implicitly calls Begin (such as DrawElements)]] [[Core Profile and OpenGL
    ES:  DrawArrays and the other drawing commands defined in section 2.8.3]]
    if:

      * the draw buffer for color output zero selects multiple color buffers
        (e.g., FRONT_AND_BACK in the default framebuffer); or

      * the draw buffer for any other color output is not NONE.

    [[ The following paragraph applies to KHR_blend_equation_advanced only. ]]

    When using advanced blending equations, applications should split their
    rendering into a collection of blending passes, none of which touch an
    individual sample in the framebuffer more than once.  The results of
    blending are undefined if the sample being blended has been touched
    previously in the same pass.  The command

      void BlendBarrierKHR(void);

    specifies a boundary between passes when using advanced blend equations.
    Any command that causes the value of a sample to be modified using the
    framebuffer is considered to touch the sample, including clears, blended
    or unblended primitives, and BlitFramebuffer copies.

    [[ The following paragraph applies to KHR_blend_equation_advanced_coherent
       only. ]]

    When using advanced blending equations, blending is typically done
    coherently and in primitive order.  When an individual sample is covered
    by multiple primitives, blending for that sample is performed sequentially
    in the order in which the primitives were submitted.  This coherent
    blending is enabled by default, but can be enabled or disabled by calling
    Enable or Disable with the symbolic constant BLEND_ADVANCED_COHERENT_KHR.
    If coherent blending is disabled, applications should split their
    rendering into a collection of blending passes, none of which touch an
    individual sample in the framebuffer more than once.  When coherent
    blending is disabled, the results of blending are undefined if the sample
    being blended has been touched previously in the same pass.  The command

      void BlendBarrierKHR(void);

    specifies a boundary between passes when using advanced blend equations.
    Any command that causes the value of a sample to be modified using the
    framebuffer is considered to touch the sample, including clears, blended
    or unblended primitives, and BlitFramebuffer copies.

    Advanced blending equations require the use of a fragment shader with a
    matching "blend_support" layout qualifier.  If the current blend equation
    is found in table X.1 or X.2, and the active fragment shader does not
    include the layout qualifier matching the blend equation or
    "blend_support_all_equations", the error INVALID_OPERATION is generated by
    [[Compatibility Profile:  Begin or any operation that implicitly calls
    Begin (such as DrawElements)]] [[Core Profile and OpenGL ES:  DrawArrays
    and the other drawing commands defined in section 2.8.3]] The set of
    layout qualifiers supported in fragment shaders is specified in sectino
    4.3.8.2 of the OpenGL Shading Language Specification.


Additions to Chapter 5 of the OpenGL 4.1 Specification (Special Functions)

    None.

Additions to Chapter 6 of the OpenGL 4.1 Specification (State and
State Requests)

    None.

Additions to Appendix A of the OpenGL 4.1 Specification (Invariance)

    None.

Additions to the AGL/GLX/WGL/EGL Specifications

    None.

Additions to the OpenGL Shading Language Specification, Version 4.10

    Including the following line in a shader can be used to control the
    language features described in this extension:

      #extension GL_KHR_blend_equation_advanced : <behavior>

    where <behavior> is as specified in section 3.3.

    A new preprocessor #define is added to the OpenGL Shading Language:

      #define GL_KHR_blend_equation_advanced 1

    Modify Section 4.3.8.2, Output Layout Qualifiers, p. 47

    (add to the end of the section, p. 50)

    Fragment shaders additionally support the following layout qualifiers,
    specifying a set of advanced blend equations supported when the fragment
    shader is used.  These layout qualifiers are only permitted on the
    interface qualifier out, and use the identifiers specified in the "Layout
    Qualifier" column of Table X.3.

    If a layout qualifier in Table X.3 is specified in the fragment shader,
    the fragment shader may be used with the corresponding advanced blend
    equation in the "Blend Equation(s) Supported" column.  Additionally, the
    special qualifier "blend_support_all_equations" indicates that the shader
    may be used with any advanced blending equation supported by the OpenGL
    Specification.  It is not an error to specify more than one of these
    identifiers in any fragment shader.  Specifying more than one qualifier or
    "blend_support_all_equations" means that the fragment shader may be used
    with multiple advanced blend equations.  Additionally, it is not an error
    to specify any single any of these layout qualifiers more than once.

        Layout Qualifier                Blend Equation(s) Supported
        ------------------------        ------------------------------
        blend_support_multiply          MULTIPLY_KHR
        blend_support_screen            SCREEN_KHR
        blend_support_overlay           OVERLAY_KHR
        blend_support_darken            DARKEN_KHR
        blend_support_lighten           LIGHTEN_KHR
        blend_support_colordodge        COLORDODGE_KHR
        blend_support_colorburn         COLORBURN_KHR
        blend_support_hardlight         HARDLIGHT_KHR
        blend_support_softlight         SOFTLIGHT_KHR
        blend_support_difference        DIFFERENCE_KHR
        blend_support_exclusion         EXCLUSION_KHR
        blend_support_hsl_hue           HSL_HUE_KHR
        blend_support_hsl_saturation    HSL_SATURATION_KHR
        blend_support_hsl_color         HSL_COLOR_KHR
        blend_support_hsl_luminosity    HSL_LUMINOSITY_KHR
        blend_support_all_equations     /all blend equations/

      Table X.3, Fragment Shader Output Layout Qualifiers for Blend Support

    A draw-time error will be generated in the OpenGL API if an application
    attempts to render using an advanced blending equation without having a
    matching layout qualifier specified in the active fragment shader.

GLX Protocol

    !!! TBD

Dependencies on OpenGL 4.0

    If OpenGL 4.0 is not supported, references to the BlendEquationi API should
    be removed.

Dependencies on OpenGL 4.1 (Core Profile)

    This extension throws an INVALID_OPERATION when Begin is called if advanced
    blend equations are used in conjunction with multiple draw buffers.  For
    the core profile of OpenGL 4.1 (and other versions of OpenGL), there is no
    Begin command; instead, the error is thrown by other rendering commands
    such as DrawArrays.  The language in this specification documenting the
    error has separate versions for the core and compatibility profiles.

Dependencies on OpenGL 4.3 or later (any Profile)

    References to Chapter 4 are replaced with references to Chapter 17 (Writing
    Fragments and Samples to the Framebuffer).
    References to section 4.1.8 are replaced with references to section 17.3.8.
    References to Table 4.1 are replace with references to Table 17.1.
    References to section 2.1.1 are replaced with references to section 2.3.3.

Dependencies on OpenGL ES 2.0

    If unextended OpenGL ES 2.0 is supported, references to BlendEquationi,
    BlendEquationSeparatei, GetInteger64v, and GetDoublev should be ignored.

    Ignore any references to multiple draw buffers if EXT_draw_buffers or
    NV_draw_buffers is not supported.

Dependencies on EXT_blend_minmax

    Requires EXT_blend_minmax on OpenGL ES 2.0 implementations and references
    to MIN and MAX should be replace by references to MIN_EXT and MAX_EXT as
    introduced by that extension.

Dependencies on OpenGL ES 3.0

    If unextended OpenGL ES 3.0 is supported, references to BlendEquationi,
    BlendEquationSeparatei, and GetDoublev should be ignored.

Dependencies on NV_path_rendering

    When NV_path_rendering is supported, covering geometry generated by the
    commands CoverFillPathNV, CoverFillPathInstancedNV, CoverStrokePathNV, and
    CoverStrokePathInstancedNV will automatically be blended coherently
    relative to previous geometry when using the blend equations in this
    extension.  This guarantee is provided even on implementations supporting
    only NV_blend_equation_advanced.

    Insert the following language after the discussion of the
    BlendBarrierKHR() command for both extensions:

      [[ For KHR_blend_equation_advanced only: ]]

      The commands CoverFillPathNV, CoverFillPathInstancedNV,
      CoverStrokePathNV, and CoverStrokePathInstancedNV are considered to
      start a new blending pass, as though BlendBarrierKHR were called prior
      to the cover operation.  If a cover primitive is followed by subsequent
      non-cover primitives using advanced blend equations and touching the
      same samples, applications must call BlendBarrierKHR after the cover
      primitives to ensure defined blending results.

      [[ For KHR_blend_equation_advanced_coherent, the language immediately
         above should be used, but the first sentence should be prefixed with
         "When coherent blending is disabled, ...". ]]


Errors

    If any non-NONE draw buffer uses a blend equation found in table X.1 or
    X.2, the error INVALID_OPERATION is generated by Begin or any operation
    that implicitly calls Begin (such as DrawElements) if:

      * the draw buffer for color output zero selects multiple color buffers
        (e.g., FRONT_AND_BACK in the default framebuffer); or

      * the draw buffer for any other color output is not NONE.

New State
                                             Initial
    Get Value             Type  Get Command   Value         Description               Sec    Attribute
    --------------------  ----  ------------  ------------  ------------------------  -----  ------------
    BLEND_ADVANCED_        B    IsEnabled     TRUE          are advanced blending     4.1.8  color-buffer
      COHERENT_KHR                                          equations guaranteed to
                                                            be evaluated coherently?

    Note:  The BLEND_ADVANCED_COHERENT_KHR enable is provided if and only if
    the KHR_blend_equation_advanced_coherent extension is supported.  On
    implementations supporting only KHR_blend_equation_advanced, this enable
    is considered not to exist.

New Implementation Dependent State

    None.

Issues

    Note:  These issues apply specifically to the definition of the
    KHR_blend_equation_advanced specification, which was derived from the
    extension NV_blend_equation_advanced.  The issues from the original
    NV_blend_equation_advanced specification have been removed, but can be
    found (as of August 2013) in the OpenGL Registry at:

      http://www.opengl.org/registry/specs/NV/blend_equation_advanced.txt

    (0) How does this extension differ from the NV_blend_equation_advanced
        extension for OpenGL and OpenGL ES?

      RESOLVED:  A number of features have been removed from
      NV_blend_equation_advanced, including:

      * The BlendParameterivNV API has been removed, and with it, the
        BLEND_PREMULTIPLIED_SRC_NV and BLEND_OVERLAP_NV parameters.  The spec
        has been refactored to assume premultipled source colors and
        uncorrelated source and destination coverage.

      * A number of less commonly used blend modes have been removed,
        including:

         - certain "X/Y/Z" blending modes supported by few, if any, standards
           (INVERT, INVERT_RGB_NV, LINEARDODGE_NV, LINEARBURN_NV,
           VIVIDLIGHT_NV, LINEARLIGHT_NV, PINLIGHT_NV, HARDMIX_NV)

         - various versions of additive and subtractive modes (PLUS_NV,
           PLUS_CLAMPED_NV, PLUS_CLAMPED_ALPHA_NV, PLUS_DARKER_NV, MINUS_NV,
           MINUS_CLAMPED_NV)

         - other uncommon miscellaneous modes (CONTRAST_NV, INVERT_OVG_NV,
           RED, GREEN, BLUE)

      Additionally, this extension adds blending support layout qualifiers to
      the fragment shader (qualifying "out").  Each fragment shader can
      specify a set of advanced blend equations that can be used when it is
      active.  For example:

        layout(blend_support_hardlight, blend_support_softlight) out;

      specifies that the HARDLIGHT_KHR and SOFTLIGHT_KHR equations are allowed
      when using the shader.  A draw-time error will be generated if an
      advanced blend equation is enabled in the API and a matching layout
      qualifier is not specified in the active fragment shader.

    (1) What should we do about the BLEND_PREMULTIPLIED_SRC_NV blend parameter
        from NV_blend_equation_advanced?

      RESOLVED:  Remove this parameter for simplicity.  All equations in this
      extension assume that the source and destination colors are both
      premultiplied.

    (2) What should we do about the BLEND_OVERLAP_NV blend parameter from
        NV_blend_equation_advanced?

      RESOLVED:  Remove this parameter for simplicitly.  All equations in this
      extension assume an UNCORRELATED_NV overlap mode.  Blending using the
      UNCORRELATED_NV overlap mode is usually mathematically simpler than
      blending using the DISJOINT_NV or CONJOINT_NV modes.

    (3) What set of "complex" blending equations should we support in this
        extension?

      RESOLVED:  During standardization of this extensions, the set of
      equations provided in this extension has been reduced to a smaller
      subset for simplicitly.  The remaining equations are typically found in
      a wide collection of compositing standards.  In particular, the
      standarization process removed several classes of blend equations from
      the NV_blend_equation_advanced, as described in "differences" issue (0)
      above.

    (4) Should we support the "Porter-Duff" blend equations (e.g.,
        SRC_OVER_NV) from NV_blend_equation_advanced?

      RESOLVED:  All of these blend equations should be supportable in
      unextended OpenGL ES 3.0, and have been removed for simplicity.  The
      primary rationale for this decision is to reduce the number of internal
      paths required by the driver; some implementations may have separate
      paths for traditional OpenGL blending and for the new advanced blending
      equations.  Redirecting "simple" advanced blending equations to
      traditional fixed-function blending hardware may involved more driver
      implementation work and may have different performance characteristics
      than other "complex" blending equations.

      This approach does mean that an application wanting to use both
      Porter-Duff blend equations and advanced blending equations provided by
      this extension will need GL_to program blending somewhat differently
      when using the Porter-Duff equations:

        if (isPorterDuff(equation)) {
          glBlendEquation(GL_FUNC_ADD);        // enable sf*S+df*D blending
          glBlendFunc(srcFactor, dstFactor);   // and program blend factors
        } else {
          glBlendEquation(equation);  // advanced eqs. don't use BlendFunc
        }

    (5) Should we impose any requirements on fragment shaders when used in
        conjunction with advanced blend equations?

      RESOLVED:  Yes.  This extension adds fragment shader layout qualifiers
      allowing individual shaders to specify that they will be used with one
      or multiple advanced blending equations.  When using an advanced
      blending equation from this extension, it is necessary to use a fragment
      shader with a matching layout qualifier.  A draw-time error will be
      generated if the current fragment shader doesn't include a layout
      qualifier matching the current advanced blending mode.

      The rationale for this decision is that some implementations of this
      extension may require special fragment shader code when using advanced
      blending equations, and may perhaps perform the entire blending
      operation in the fragment shader.  Knowing the set of blending equations
      that a fragment shader will be used with at compile time may reduce the
      extent of run-time fragment shader re-compilation when the shader is
      used.

      Note that NV_blend_equation_advanced doesn't include layout qualifiers
      or the draw-time error specified here.

    (6) How do we handle coherency when a fragment is hit multiple times?

      RESOLVED:  In this extension, blending equations will be done coherently
      and in primitive order by default, as is the case with traditional
      blending in OpenGL and OpenGL ES.

      The NVIDIA extension provides two separate extension string entries:

        * NV_blend_equation_advanced
        * NV_blend_equation_advanced_coherent

      Exposing the former without the latter signals that the implementation
      can support blending with these equations, but is unable to ensure that
      fragments are blended in order when the same (x,y) is touched multiple
      times.  To ensure coherent results and proper ordering using the
      non-coherent version of the extension, an application must separate its
      rendering into "passes" that touch each (x,y) at most once, and call
      BlendBarrierNV between passes.  There are important use cases (e.g.,
      many path rendering algorithms) where this limitation isn't too
      restrictive, and NVIDIA chose to expose the non-coherent version to
      allow the functionality to be used on a larger set of GPUs.

      This extension is functionally comparable to an implementation of the
      NVIDIA extension exposing both strings, where coherent behavior is
      enabled by default.  NV_blend_equation_advanced_coherent and this
      extension both provide the ability to opt out of this automatic
      coherence by disabling BLEND_ADVANCED_COHERENT_KHR and using
      BlendBarrierKHR manually.  This could theoretically result in higher
      performance -- see issue (32) of the NVIDIA extension for more
      discussion.

    (7) How should the blend equations COLORDODGE_KHR and COLORBURN_KHR be
        expressed mathematically?

      RESOLVED:  NVIDIA changed the definition of these equations after the
      NV_blend_equation_advanced spec was originally published, as discussed
      below.  These changes add new special cases to the COLORDODGE_KHR and
      COLORBURN_KHR equations that are found in newer compositing standard
      specifications and in a number of implementations of old and new
      standards.  They believe that the omission of the special case in other
      older specifications is a bug.  They have no plans to add new blend
      equation tokens to support "equivalent" modes without the new special
      case.  We are adopting the same approach in this extension.

      Note, however, that older versions of this extension and older NVIDIA
      drivers implementing it will lack these special cases.  A driver update
      may be required to get the new behavior.

      There is some disagreement in different published specifications about
      how these two blend equations should be handled.  At the time the NVIDIA
      extension was initially developed, all specifications they found that
      specified blending equations mathematically (see issue 28 of
      NV_blend_equation_advanced) were written the same way.  Since then, they
      discovered that newer working drafts of the W3C Compositing and Blending
      Level 1 specification (for CSS and SVG) express "color-burn" as follows
      (translated to our nomenclature):

        if (Cd == 1)            // their Cb (backdrop) is our Cd (destination)
          f(Cs,Cd) = 1          // their B() is our f()
        else if (Cs == 0)
          f(Cs,Cd) = 0
        else
          f(Cs,Cd) = 1 - min(1, (1-Cd)/Cs)

      http://www.w3.org/TR/2013/WD-compositing-1-20131010/
        #blendingcolorburn

      Earlier versions of the same W3C specification, an older SVG compositing
      draft specification, the Adobe PDF specification (and the ISO 32000-1
      standard), and the KHR_advanced_blending extension to OpenVG all specify
      the following equation without the initial special case:

        if (Cs == 0)
          f(Cs,Cd) = 0
        else
          f(Cs,Cd) = 1 - min(1, (1-Cd)/Cs)

        http://www.w3.org/TR/2012/WD-compositing-20120816/
          #blendingcolorburn
        http://www.w3.org/TR/2011/WD-SVGCompositing-20110315/
        http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/
          pdfs/pdf_reference_1-7.pdf
        http://www.khronos.org/registry/vg/extensions/KHR/
          advanced_blending.txt

      For the Adobe PDF specification, the corrected blend equations are
      published in an Adobe supplement to ISO 32000-1 and are expected to be
      accepted in a future version of the standard:

        http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/
          devnet/pdf/pdfs/adobe_supplement_iso32000_1.pdf

      The author's understanding is that multiple shipping implementations of
      these blending modes implement the special case for "Cd==1" above,
      including various Adobe products and the open-source Ghostscript
      project.

      We believe that the extra special case in this specification is
      consistent with the physical model of color burning.  Burning is
      described in

        http://en.wikipedia.org/wiki/Dodging_and_burning

      as making a print with normal exposure, and then adding additional
      exposure to darken the overall image.  In the general equation:

        1 - min(1, (1-Cd)/Cs)

      Cs operates as a sort of fudge factor where a value of 1.0 implies no
      additional exposure time and 0.0 implies arbitrarily long additional
      exposure time, where the initial amount of exposure (1-Cd) is multiplied
      by 1/Cs and then clamped to maximum exposure by the min() operation.
      The Cd==1 special case here implies that we get zero exposure in the
      initial print, since 1-Cd==0.  No amount of extra exposure time will
      generate any additional exposure.  This would imply that the final
      result should have zero exposure and thus a final f() value of 1.  This
      matches the initial special case.  Without that special case, we would
      hit the second special case if Cs==0 (infinite exposure time), which
      would yield an incorrect final value of 0 (full exposure).

      A similar issue applies to COLORDODGE_KHR, where some specifications
      include a special case for Cb==0 while others do not.  We have added a
      special case there as well.

    (8) The NV_blend_equation_advanced extension has two variants:
        NV_blend_equation_advanced and NV_blend_equation_advanced_coherent.
        Some implementations of that extension are not capable of performing
        fully coherent blending when samples are touched more than once
        without a barrier, and may expose only the former.  Should we follow
        this pattern here or support only the "coherent" variant?

      RESOLVED:  Yes.  The working group originally decided to support only
      the "coherent" variant (revision 4) for simplicity but later decided to
      support both extension string entries as some implementations on both
      OpenGL and OpenGL ES are unable to support the "coherent" variant.
      Applications not wanting to manage coherency manually should look for
      the KHR_blend_equation_advanced_coherent extension and ignore
      KHR_blend_equation_advanced.

    (9) We don't permit the use of advanced blend equations with multiple draw
        buffers.  Should we produce compile-, link-, or draw-time errors if we
        encounter a shader that includes both (a) one or more layout
        qualifiers indicating that the shader wants to use advanced blending
        and (b) a color output with a location other than zero?

      RESOLVED:  No.

      In the current extension, there is a draw-time error generated if you
      try to use one of the new blend equations with multiple color targets
      (glDrawBuffers with a count > 1).  With this restriction, any "extra"
      fragment shader color outputs could never be successfully blended into
      the framebuffer with one of these equations.

      When only one draw buffer is enabled when using a shader with multiple
      outputs, "extra" outputs will simply be dropped and have no effect on
      the framebuffer.  You can already do this in unextended OpenGL and
      OpenGL ES without generating an error.  We didn't feel that the value of
      such a warning/error justifies the draw-time overhead needed to detect
      and report such a condition.

      Since this extension requires that you declare the intent to use
      advanced blending using layout qualifers, it is possible to identify a
      shader that may want to use "extra" color outputs with advanced blending
      at compile time, with no draw-time overhead.  We decided not to treat
      this condition as an error for several reasons:

       - Advanced blending layout qualifiers don't require that blending
         actually be enabled.  Multiple draw buffers with multiple outputs
         work just fine in that case.

       - If we treated this condition as an error and a future extension
         relaxed the DrawBuffers restriction, it would be necessary to also
         add a GLSL language feature to disable the now-undesirable error.

    (10) What happens when converting a premultiplied color with an alpha of
         zero to a non-premultiplied color?

      RESOLVED:  We specify that a premultiplied color of (0,0,0,0) should
      produce non-premultiplied (R,G,B) values of (0,0,0).  A premultiplied
      color with an alpha of zero and a non-zero R, G, or B component is
      considered to be ill-formed and will produce undefined blending results.

      For a non-premultiplied color (R',G',B',A'), the corresponding
      premultiplied color (R,G,B,A) should satisfy the equation:

        (R,G,B,A) = (R'*A', G'*A', B'*A', A')

      If the alpha of a non-premultiplied color is zero, the corresponding
      premultiplied color (R,G,B,A) should be (0,0,0,0).

      We specify that ill-formed premultiplied colors produce undefined
      blending results to enable certain performance optimizations.  In many
      of these blending equations, the alpha component used as a denominator
      to compute the non-premultiplied color ends up being multiplied by the
      same alpha component in the coverage, resulting in cancellation.  For
      example, implementations may want to substitute a premultiplied
      destination color into the last term of the basic blend equation:

        R = f(Rs',Rd')*p0(As,Ad) + Y*Rs'*p1(As,Ad) + Z*Rd'*p2(As,Ad)
          =                                    ... + Z*Rd'*(Ad*(1-As))
          =                                    ... + Z*(Rd'*Ad)*(1-As)
          =                                    ... + Z* Rd * (1-As)

      This substitution would be invalid for ill-formed premultiplied
      destination colors.  We choose to specify undefined results for invalid
      input colors rather than requiring implementations to skip such
      optimizations or include logic to check for zero alpha values for each
      input.

Revision History

    Revision 16, April 16, 2016 (from a September 30, 2014 edit that wasn't
                                 published)

      Fix incorrectly specified color clamping in the HSL blend modes.

    Revision 15, May 9, 2015

      Renumber as OpenGL ARB extension instead of vendor extension, by
      symmetry with other KHR Khronos-approved extensions. Add copyright
      notice.

    Revision 14, March 14, 2014

      Cast as KHR extension.

    Revisions 12 and 13, March 5, 2014

      For non-coherent blending, clarify that all writes to a sample are
      considered to "touch" that sample and require a BlendBarrierKHR call
      before blending overlapping geometry.  Clears, non-blended geometry, and
      copies by BlitFramebuffer or TexSubImage are all considered to "touch" a
      sample (bug 11738).  Specify that non-premultiplied values corresponding
      to ill-conditioned premultiplied colors such as (1,1,1,0) are undefined
      (bug 11739).  Add issue (10) related to the ill-conditioned
      premultiplied color issue.

    Revision 11, January 30, 2014

      Cast as OES extension.

    Revision 10, January 22, 2014

      Add issue (9), where we decided not to add compile- or link-time errors
      when using both advanced blending and multiple color outputs (bug
      11468).

    Revision 9, January 2, 2014

      Fix typo in issue (0).

    Revision 8, November 6, 2013

      Restore support for non-coherent-only implementations that was removed
      in revision 4.  Fix the language about non-coherent blending to specify
      that results are undefined only if an individual *sample* is touched
      more than once (instead of *pixel*).  Minor language tweaks to use
      "equations" consistently, instead of sometimes using "modes".

    Revision 7, October 21, 2013

      Add a reference to the Adobe supplement to ISO 32000-1, which includes
      the corrected equations for COLORDODGE_NV and COLORBURN_NV.  Move
      "NVIDIA Implementation Details" down a bit in the spec.

    Revision 6, October 16, 2013

      Add new special cases for COLORDODGE_KHR and COLORBURN_KHR, as described
      in issue (7).  Mark issue (7) as resolved.

    Revision 5, October 15, 2013

      Remove Porter-Duff blend equations from the specification (issue 4).
      Add a Draw-time error if an advanced blending equation is used without
      specifying a matching layout qualifier in the fragment shader (issue 5).

      Add issues for the spec issues discussed during standardization in
      Khronos.  Remove OpenGL ES 2.0 and 3.0 interactions dealing with
      handling tokens present in OpenGL but not the core OpenGL ES
      specification, since the relevant equations (ZERO and XOR) have been
      removed.

    Revision 4, September 6, 2013

      Removed support for non-coherent-only implementations.  Implementations
      that could support NV_blend_equation_advanced (app-managed coherency
      only) but not NV_blend_equation_advanced_coherent will be unable to
      support this extension.

    Revision 3, August 19, 2013

      Fixed typos in the OpenGL ES 2.0 and 3.0 interactions section of
      NV_blend_equation_advanced.

    Revision 2, August 13, 2013

      Removed issues from the original NV_blend_equation_advanced
      specification.  Rename "NV" prefixes and suffixes to "XXX" since the
      future status of this extension is unknown.  Remove the
      BlendParameterivNV function and the BLEND_PREMULTIPLIED_SRC_NV and
      BLEND_OVERLAP_NV parameters.  Source colors are assumed to be
      premultiplied.  The source and destination pixel coverage, derived from
      their respective alpha components, is assumed to be uncorrelated.
      Removed the miscellaneous blend modes (PLUS_NV, PLUS_CLAMPED_NV,
      PLUS_CLAMPED_ALPHA_NV, PLUS_DARKER_NV, MINUS_NV, MINUS_CLAMPED_NV,
      CONTRAST_NV, INVERT_OVG_NV, RED, GREEN, BLUE) from Table X.4 of
      NV_blend_equation_advanced.  Removed some of the less common "X/Y/Z"
      blend modes (INVERT, INVERT_RGB_NV, LINEARDODGE_NV, LINEARBURN_NV,
      VIVIDLIGHT_NV, LINEARLIGHT_NV, PINLIGHT_NV, HARDMIX_NV).  Add layout
      qualifiers to the OpenGL Shading Language to indicate the set of
      advanced blend equations are supported with a particular fragment
      shader; using blend equations not identified in the current fragment
      shader result in undefined blending results.

    Revision 1, August 13, 2013

      Forked the original NV_blend_equation_advanced specification.
