Name

    ARB_blend_func_extended

Name Strings

    GL_ARB_blend_func_extended

Contributors

    Graham Sellers, AMD
    Mark Young, AMD
    Nick Haemel, AMD
    Pierre Boudier, AMD
    Mais Alnasser, AMD
    Jeff Bolz, NVIDIA
    Pat Brown, NVIDIA
    Ian Stewart, NVIDIA
    Mark Kilgard, NVIDIA

Contact

    Graham Sellers, AMD (graham.sellers 'at' amd.com)

Notice

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

Status

    Complete. Approved by the ARB at the 2010/01/22 F2F meeting.
    Approved by the Khronos Board of Promoters on March 10, 2010.

Version

    Last Modified Date:         05/22/2015
    Author Revision:            13

Number

    ARB Extension #78

Dependencies

    OpenGL 1.0 is required.

    The ARB_fragment_shader extension is required.

    The EXT_gpu_shader4 extension is required.

    The EXT_blend_func_separate extension interacts with this extension.

    The ARB_draw_buffers extension trivially affects the definition of this
    extension.

    The ARB_draw_buffers_blend extension affects the definition of this
    extension.

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

Overview

    Traditional OpenGL includes fixed-function blending that combines source
    colors with the existing content of a render buffer in a variety of ways.
    A number of extensions have enhanced this functionality by adding further
    sources of blending weights and methods to combine them. However, the inputs
    to the fixed-function blending units are constrained to a source color (as
    output from fragment shading), destination color (as the current content
    of the frame buffer) or constants that may be used in their place.

    This extension adds new blending functions whereby a fragment shader may
    output two colors, one of which is treated as the source color, and the
    other used as a blending factor for either source or destination colors.
    Furthermore, this extension increases orthogonality by allowing the
    SRC_ALPHA_SATURATE function to be used as the destination weight.

IP Status

    No known IP claims.

New Procedures and Functions

    void BindFragDataLocationIndexed(uint program, uint colorNumber,
                                        uint index, const char * name);

    int GetFragDataIndex(uint program, const char * name);

New Tokens

    Accepted by the <src> and <dst> parameters of BlendFunc and
    BlendFunci, and by the <srcRGB>, <dstRGB>, <srcAlpha> and <dstAlpha>
    parameters of BlendFuncSeparate and BlendFuncSeparatei:

        SRC1_COLOR                                      0x88F9
        SRC1_ALPHA
        ONE_MINUS_SRC1_COLOR                            0x88FA
        ONE_MINUS_SRC1_ALPHA                            0x88FB

    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv
    and GetDoublev:

        MAX_DUAL_SOURCE_DRAW_BUFFERS                    0x88FC

Additions to Chapter 2 of the OpenGL 3.2 Specification (Compatibility Profile) (OpenGL Operation)

    None.

Additions to Chapter 3 of the OpenGL 3.2 Specification (Compatibility Profile) (Rasterization)

    Modify the "Shader Outputs" subsection of Section 3.12.2, Shader Execution

    Modify the text on p.297 beginning "The binding of a user-defined varying
    out variable to a fragment..."

    The binding of a user-defined varying out variable to a fragment color number
    can be specified explicitly. The command

        void BindFragDataLocationIndexed(uint program, uint colorNumber, uint index, const char * name);

    specifies that the varying out variable name in <program> should be bound to
    fragment color <colorNumber> when the program is next linked. <index> may be
    zero or one to specify that the color be used as either the first or second
    color input to the blend equation, respectively, as described in Section 4.1.8. 

    If <name> was bound previously, its assigned binding is replaced with
    colorNumber. <name> must be a null-terminated string. The error INVALID_VALUE
    is generated if <colorNumber> is equal or greater than MAX_DRAW_BUFFERS and
    <index> is zero, or if <colorNumber> is equal or greater than
    MAX_DUAL_SOURCE_DRAW_BUFFERS and <index> is greater than or equal to one.
    The command

        void BindFragDataLocation(uint program, uint colorNumber, const char * name)

    is equivalent to calling BindFragDataLocationIndexed with the same values
    for <program>, <colorNumber> and <name>, and with <index> set to zero.

    When a program is linked, any varying out variables without a binding
    specified through BindFragDataLocationIndexed or BindFragDataLocation will
    automatically be bound to fragment colors and indices by the GL.  All such
    assignments will use color indices of zero.  Such bindings can be queried
    using the commands GetFragDataLocation and GetFragDataIndex.  Output
    binding assignments will cause LinkProgram to fail:

      * if the number of active outputs is greater than the value of
        MAX_DRAW_BUFFERS;

      * if the program has an active output assigned to a location greater
        than or equal to the value of MAX_DUAL_SOURCE_DRAW_BUFFERS and has an
        active output assigned an index greater than or equal to one;

      * if more than one varying out variable is bound to the same number and
        index; or

      * if the explicit binding assignments do not leave enough space for the
        linker to automatically assign a location for a varying out array,
        which requires multiple contiguous locations.

    BindFragDataLocationIndexed may be issued before any shader objects are
    attached to a program object. Hence it is allowed to bind any name (except a
    name starting with gl_) to a color number and index, including a name that
    is never used as a varying out variable in any fragment shader object.
    Assigned bindings for variables that do not exist are ignored.

    Add to the last paragraph on p.279

    The command

        int GetFragDataIndex(uint program, const char * name);

    returns the index of the fragment color to which the variable <name> was bound
    when the program object <program> was last linked. If program has not been
    successfully linked, the error INVALID_OPERATION is generated. If name is not
    a varying out variable, or if an error occurs, -1 will be returned.

Additions to Chapter 4 of the OpenGL 3.2 Specification (Compatibility Profile) (Per-Fragment Operations
and the Framebuffer)

    Modify the first paragraph of the Blending Functions subsection of Section
    4.1.8 Blending (p. 292) as follows:

    The weighting factors used by the blend equation are determined by the blend
    functions. There are four possible sources for weighting factors. These are
    the constant color (Rc, Gc, Bc, Ac) (see BlendColor, p. 211), the first
    source color (Rs0, Gs0, Bs0, As0), the second source color
    (Rs1, Gs1, Bs1, As1), and the destination color (the existing content of the
    draw buffer). Additionally the special constants ZERO and ONE are
    available as weighting factors. Blend functions are specified ...

    Modify Table 4.2 (p. 213) as follows

                                                            RGB Blend Factors                   Alpha Blend Factors
        Value                                               (Sr, Sg, Sb) or (Dr, Dg, Db)        Sa or Da
        -----                                               ----------------------------        -------------------
        ZERO                                                (0, 0, 0)                           0
        ONE                                                 (1, 1, 1)                           1
        SRC_COLOR                                           (Rs0, Gs0, Bs0)                     As0
        ONE_MINUS_SRC_COLOR                                 (1, 1, 1) - (Rs0, Gs0, Bs0)         1 - As0
        DST_COLOR                                           (Rd, Gd, Bd)                        Ad
        ONE_MINUS_DST_COLOR                                 (1, 1, 1) - (Rd, Gd, Bd)            1 - Ad
        SRC_ALPHA                                           (As0, As0, As0)                     As0
        ONE_MINUS_SRC_ALPHA                                 (1, 1, 1) - (As0, As0, As0)         1 - As0
        DST_ALPHA                                           (Ad, Ad, Ad)                        Ad
        ONE_MINUS_DST_ALPHA                                 (1, 1, 1) - (Ad, Ad, Ad)            1 - Ad
        CONSTANT_COLOR                                      (Rc, Gc, Bc)                        Ac
        ONE_MINUS_CONSTANT_COLOR                            (1, 1, 1) - (Rc, Gc, Bc)            1 - Ac
        CONSTANT_ALPHA                                      (Ac, Ac, Ac)                        Ac
        ONE_MINUS_CONSTANT_ALPHA                            (1, 1, 1) - (Ac, Ac, Ac)            1 - Ac
        SRC_ALPHA_SATURATE                                  (f, f, f)                           1                       (Now allowed for dst)
        SRC1_COLOR                                          (Rs1, Gs1, Bs1)                     As1                     New
        ONE_MINUS_SRC1_COLOR                                (1, 1, 1) - (Rs1, Gs1, Bs1)         1 - As1                 New
        SRC1_ALPHA                                          (As1, As1, As1)                     As1                     New
        ONE_MINUS_SRC1_ALPHA                                (1, 1, 1) - (As1, As1, As1)         1 - As1                 New

    Remove Footnote 1 from Table 4.2.

    Add the following subsections to Section 4.1.8 Blending, at the end of the
    description of Blend Function (p. 294)

    Dual Source Blending and Multiple Draw Buffers

    Blend functions that require the second color input, <Rs1, Gs1, Bs1, As1>
    (SRC1_COLOR, SRC1_ALPHA, ONE_MINUS_SRC1_COLOR, or
    ONE_MINUS_SRC1_ALPHA) may consume hardware resources that could
    otherwise be used for rendering to multiple draw buffers. Therefore, the
    number of draw buffers that can be attached to a frame buffer may be lower
    when using dual-source blending.

    The maximum number of draw buffers that may be attached to a single frame
    buffer when using dual-source blending functions is implementation dependent
    and can be queried by calling GetIntegerv with the symbolic constant 
    MAX_DUAL_SOURCE_DRAW_BUFFERS. When
    using dual-source blending, MAX_DUAL_SOURCE_DRAW_BUFFERS should be used
    in place of MAX_DRAW_BUFFERS to determine the maximum number of draw
    buffers that may be attached to a single frame buffer. The value of
    MAX_DUAL_SOURCE_DRAW_BUFFERS must be at least 1. If the value of
    MAX_DUAL_SOURCE_DRAW_BUFFERS is 1, then dual-source blending and
    multiple draw buffers cannot be used simultaneously.

    If either blend function is set to one of the second source factors
    (SRC1_COLOR, SRC1_ALPHA, ONE_MINUS_SRC1_COLOR, or
    ONE_MINUS_SRC1_ALPHA) for any draw buffer and any draw buffers equal to
    or greater than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS have values other than NONE,
    the error INVALID_OPERATION is generated by Begin, or any procedure that
    implicitly calls Begin.

    Generation of Second Color Source for Blending

    There is no way to generate the second source color using the fixed-function
    fragment pipeline. Rendering using any of the blend functions that consume
    the second input color (SRC1_COLOR, ONE_MINUS_SRC1_COLOR,
    SRC1_ALPHA or ONE_MINUS_SRC1_ALPHA) using fixed function will produce
    undefined results.  To produce input for the second source color, a shader
    must be used.

    When using a GLSL fragment shader with dual-source blending functions,
    the color output varyings are bound to the first and second inputs of a
    draw buffer using BindFragDataLocationIndexed as described in the "Shader
    Outputs" subsection of Section 3.12.2. Data written to the first of these outputs
    becomes the first source color input to the blender (corresponding to
    SRC_COLOR and SRC_ALPHA). Data written to the second of these outputs
    generates the second source color input to the blender (corresponding to
    SRC1_COLOR and SRC1_ALPHA).

    If the second color input to the blender is not written in the shader, or if
    no output is bound to the second input of a blender, the result of the blending
    operation is not defined.

    Other shading languages may define similar methods for producing the first
    and second color inputs to blending equations.

Additions to Chapter 5 of the OpenGL 3.2 Specification (Compatibility Profile) (Special
Functions)

    None.

Additions to Chapter 6 of the OpenGL 3.2 Specification (Compatibility Profile) (State and
State Requests)

    None.

Dependencies on ARB_fragment_shader

    If ARB_fragment_shader is not supported then references to
    ARB_fragment_shader in section 4.1.8 and elsewhere in this document should
    be removed. In this case, there is no way to generate the second color input
    to the blending equation unless a further extension to another shading
    language is defined and used.

Dependencies on ARB_draw_buffers

    Using dual-source blending functions may consume additional outputs from
    hardware shading units and therefore can reduce the number of draw buffers
    that may be attached to a single frame buffer when dual-source blending
    functions are enabled. In this case, the value of 
    MAX_DUAL_SOURCE_DRAW_BUFFERS may be less than the value of
    MAX_DRAW_BUFFERS. If ARB_draw_buffers is not supported then the value of
    MAX_DUAL_SOURCE_DRAW_BUFFERS will be 1. Furthermore, the discussion
    in the subsection entitled "Dual Source Blending and Multiple Draw Buffers"
    may be discarded.

Dependencies on EXT_blend_func_separate

    If EXT_blend_func_separate is not supported, remove references to
    BlendFuncSeparate. Also, remove any references to BLEND_SRC_ALPHA and
    BLEND_DST_ALPHA, and replace references to BLEND_SRC_RGB and BLEND_DST_RGB
    with BLEND_SRC and BLEND_DST, respectively. In this case, the new blend
    functions may only be enabled via the BlendFunc procedure.

Dependencies on ARB_draw_buffers_blend

    If ARB_draw_buffers_blend is not supported, all references to BlendFunci
    and BlendFuncSeparatei should be removed. In this case, the blend
    functions for all attached draw buffers will be the same.

Interactions with NV_gpu_program5

    If NV_gpu_program5 is supported, fragment result bindings 
    "result.color[n].primary" and "result.color[n].secondary" can be used to
    specify the <n>th color outputs for index 0 and 1, respectively.

Additions to the AGL/GLX/WGL Specifications

    None.

GLX Protocol

    None.

Errors

    The error INVALID_OPERATION is generated by Begin or any procedure that
    implicitly calls Begin if any draw buffer has a blend function requiring the
    second color input (SRC1_COLOR, ONE_MINUS_SRC1_COLOR, SRC1_ALPHA or
    ONE_MINUS_SRC1_ALPHA), and a framebuffer is bound that has more than
    the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active color attachments.

New State

    Table 6.21 (p. 286)

    Get Value                 Type  Get Command   Initial Value   Description          Sec    Attribute
    ------------------------  ----  ------------  -------------   -------------------  -----  ---------
    BLEND_SRC_RGB             Z19   GetIntegerv   ONE             Blending source RGB  4.1.8  color-buffer
                                                                  function
    BLEND_SRC_ALPHA           Z19   GetIntegerv   ONE             Blending source A    4.1.8  color-buffer
                                                                  function
    BLEND_DST_RGB             Z19   GetIntegerv   ZERO            Blending dest. RGB   4.1.8  color-buffer
                                                                  function
    BLEND_DST_ALPHA           Z19   GetIntegerv   ZERO            Blending dest. A     4.1.8  color-buffer
                                                                  function

NOTE: The only change is that Z14 and Z15 change to Z19 for the existing blend
function state. No new state is actually added to the OpenGL Specification.

New Implementation Dependent State

    Get Value                        Type  Get Command     Minimum Value    Description             Sec.     Attribute
    ---------                        ----  -----------     -------------    -------------------     -----    ---------
    MAX_DUAL_SOURCE_DRAW_BUFFERS     Z+    GetIntegerv     1                Maximum number of       4.1.8    -
                                                                            active draw buffers
                                                                            when using dual-source
                                                                            blending

Example Use Cases

    There are several potential uses for this functionality. A first example
    is in the implementation of sub-pixel accurate font rendering algorithms.
    Given a known layout of pixel elements (red, green and blue components),
    coverage may be calculated independently for each element and passed
    to the blender in the second source color as a per-channel opacity. To use
    this mode, use the following blend functions:

        glBlendFunc(GL_SRC1_COLOR, GL_ONE_MINUS_SRC1_COLOR);

    As a second example, consider a partially reflective colored glass window.
    It will attenuate light passing through it, and reflect some of the light
    that strikes it. Using an appropriate combination of functions, this effect
    may be simulated in a single pass using only fixed-function blending
    hardware. In this case, the following blend functions may be used:

        glBlendFunc(GL_SRC_ALPHA, GL_SRC1_COLOR);

Issues

    1) Should the new tokens be SRC1_COLOR and SRC2_COLOR (1-based), or
       be SRC0_COLOR and SRC1_COLOR.

       RESOLVED: Indices in OpenGL are generally zero based. These follow
       suit.

    2) What happens when rendering using a dual-source blend function using
       fixed-function?

       RESOLVED: There is no reasonable way to generate the second source color
       for blending using fixed-function fragment processing. However, as it is
       possible to set the blend function and then enable a shader, there isn't
       really a clean way to report an error. Therefore, we allow it, but leave
       the result undefined.

    2a) Can't we use an existing output from fixed function, like back color,
        to make this work?

       DISCUSSION: We could relabel things. For example, make the front color
       be the first input to blending and the back color the second input. This
       kind of thing would come at the cost of lost fixed function capability,
       possible ambiguity and added complexity in the fixed function
       specification. The new functionality in this extension is most useful
       when reading data from multiple textures or other complex sources that
       would just be too complex to express with fixed function processing.
       For these reasons, rendering through dual-source blending functions using
       the fixed function pipeline is not supported and will produce undefined
       results.

    2b) Then why write this against OpenGL 2.1 which includes fixed-function?
        Why not write against OpenGL 3.x that only supports shaders anyway?

       DISCUSSION: Because this extension adds functionality to existing
       extensions and those are written against OpenGL 2.1. Furthermore, the
       functionality described here does not rely on any core feature provided
       by OpenGL 3.x and can be easily built upon and used in implementations of
       OpenGL 2.1 or earlier versions of the OpenGL Specification.

       RESOLVED: Updated to stand against OpenGL 3.2, but kept the fixed function
       issues in the spec.

    3) Why is this not orthogonal and interoperable with ARB_draw_buffers?

       RESOLVED: This is functionality that has existed in hardware for some
       time and been made available via other graphics APIs. In some hardware
       and APIs, the second color input from the shader is actually what would
       have been written to draw buffer 1. This is the functionality that is
       guaranteed to be universally supported. This extension does not preclude
       use with multiple draw buffers except exclusion through implementation
       defined limits. If future hardware supports multiple color outputs
       simultaneously to multiple draw buffers, it can simply advertise higher
       limits.

    4) Can we not add an implementation state query to find out if it's
       available with multiple draw buffers?

       RESOLVED: Done. Query MAX_DUAL_SOURCE_DRAW_BUFFERS. If this returns
       the same value as MAX_DRAW_BUFFERS then the functions are orthogonal.
       If this returns 1, then they cannot be used together. If it returns some
       value between 1 and MAX_DRAW_BUFFERS, then dual-source blending
       may consume some additional hardware routing resources, but can be used
       with multiple draw buffers provided the MAX_DUAL_SOURCE_DRAW_BUFFERS
       limit is not exceeded.

    5) Should there also be a Link error if the fragment shader uses both an
       index=1 output below MAX and an index=0 output greater than or equal to
       MAX? The quoted begin-time error leaves open the possibility of an app
       doing something like BindFragDataLocationIndexed(colorNumber=0, index=0)
       + (colorNumber=0, index=1) + (colorNumber=1, index=0), then rendering
       without using the src1 blend functions. If an implementation aliases
       index=1 onto other index=0 outputs, then it wouldn't be able to handle
       that case.

       DISCUSSION: The begin time error language states '... if any draw buffer
       has a blend function requiring the second color input ...'. This means
       that the outputs can be bound to non-zero indices, but if the blend
       function does not consume that output, no error will be generated. In
       theory, an implementation could ignore output bound to color=0, index=1
       in this case and operate as if it were not there. However, it makes no
       sense for the linker to accept such a configuration of outputs because
       the underlying hardware may not be able to support it. Therefore, we can
       generate a link time error, thus eliminating this begin-time check and
       potentially improving run-time performance.

Revision History

    Rev.    Date      Author    Changes
    ----  --------    --------  -----------------------------------------
    13    05/22/2015  mjk       Fix misspellings
    12    02/05/2010  istewart  Add interactions with NV_gpu_program5.
    11    01/26/2010  pbrown    Assign enum values.
    10    01/14/2010  pbrown    Add spec language allowing for a link error if
                                explicit output bindings don't leave enough 
                                space for array outputs.  Clarify that any 
                                automatic assignments for fragment outputs
                                will use color index zero.
     9    12/10/2009  Jon Leech Fix typos in blending equation table, remove
                                ARB suffixes for core 3.3 inclusion, clean
                                up "GL_TOKEN" vs. "the value of GL_TOKEN".
     8    11/19/2009  gsellers  Remove SRC0_COLOR etc. enums, use old ones
                                instead. Use previously defined value for
                                SRC1_ALPHA. Update text to match.
     7    10/26/2009  gsellers  Change BindFragDataLocationIndexedARB to take a
                                numerical index instead of an enum. Clarify
                                behavior in several places. Add issue 5.
     6    10/20/2009  gsellers  Update to diff to OpenGL 3.2 (Compatibility) spec.
                                Add BindFragDataLocationIndexedARB and
                                GetFragDataIndexARB. Remove idea of making shader
                                outputs arrays. Define Begin time error when
                                blend func is SRC1_* for FBO with >=
                                MAX_DUAL_SOURCE_DRAW_BUFFERS draw buffers.
     5    05/21/2009  gsellers  Clarify meaning of MAX_DUAL_SOURCE_BUFFERS_ARB.
                                Clarify the (lack of) interaction with fixed
                                function fragment processing and further
                                justify lack of support (Issues 2a and 2b).
                                Clarify modification to state.
     4    05/19/2009  gsellers  Allow simultaneous use of ARB_draw_buffers with
                                this extension;
                                add MAX_DUAL_SOURCE_DRAW_BUFFERS_ARB.
                                Document interaction with ARB_draw_buffers_blend.
     3    05/19/2009  gsellers  Remove access via gl_FragData, replace with user
                                defined output varyings.
     2    05/15/2009  gsellers  Minor cleanup. Add usage examples.
     1    05/14/2009  gsellers  Initial draft
