Name

    EXT_multiview_draw_buffers

Name Strings

    GL_EXT_multiview_draw_buffers

Contributors

    Acorn Pooley, NVIDIA
    Greg Roth, NVIDIA
    Maurice Ribble, Qualcomm

Contact

    Greg Roth (groth 'at' nvidia.com)

Version

    Version 3, Sept 03, 2011

Number

    OpenGL ES Extension #125

Status
    
    Complete

Dependencies

    Written against the OpenGL ES 2.0 Specification

    NV_draw_buffers affects the definition of this extension.

    OpenGL ES 3.0 affects the definition of this extension.

Overview

    This extension allows selecting among draw buffers as the
    rendering target. This may be among multiple primary buffers
    pertaining to platform-specific stereoscopic or multiview displays
    or among offscreen framebuffer object color attachments.

    To remove any artificial limitations imposed on the number of
    possible buffers, draw buffers are identified not as individual
    enums, but as pairs of values consisting of an enum representing
    buffer locations such as COLOR_ATTACHMENT_EXT or MULTIVIEW_EXT,
    and an integer representing an identifying index of buffers of this
    location. These (location, index) pairs are used to specify draw
    buffer targets using a new DrawBuffersIndexedEXT call.

    Rendering to buffers of location MULTIVIEW_EXT associated with the
    context allows rendering to multiview buffers created by EGL using
    EGL_EXT_multiview_window for stereoscopic displays.

    Rendering to COLOR_ATTACHMENT_EXT buffers allows implementations to
    increase the number of potential color attachments indefinitely to
    renderbuffers and textures.

    This extension allows the traditional quad buffer stereoscopic
    rendering method that has proven effective by indicating a left or
    right draw buffer and rendering to each accordingly, but is also
    dynamic enough to handle an arbitrary number of color buffer targets
    all using the same shader. This grants the user maximum flexibility
    as well as a familiar interface.

New Procedures and Functions

    void ReadBufferIndexedEXT(enum src, int index);
    void DrawBuffersIndexedEXT(int n, const enum *location,
                               const int *indices);
    void GetIntegeri_vEXT(enum target, uint index, int *data);

New Tokens

    Accepted by the <location> parameter of DrawBuffersIndexedEXT:

        COLOR_ATTACHMENT_EXT                0x90F0
        MULTIVIEW_EXT                       0x90F1

    Accepted by the <target> parameter of GetIntegeri_EXT:

        DRAW_BUFFER_EXT                     0x0C01
        READ_BUFFER_EXT                     0x0C02

    Accepted by the <target> parameter of GetInteger:

        MAX_MULTIVIEW_BUFFERS_EXT           0x90F2


Changes to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
Operations and the Frame Buffer)

    Modify section 4.2.1, "Selecting a Buffer for Writing"

    Change first paragraph to:

    By default, color values are written into the front buffer for
    single buffered contexts or into the back buffer for back buffered
    contexts as determined when creating the GL context. To control
    the color buffer into which each of the fragment color values is
    written, DrawBuffersNV or DrawBuffersIndexedEXT is used.

    Add to the end of 4.2.1:

    The command

        void DrawBuffersIndexedEXT(sizei n, const enum *locations,
                                   const int *indices);

    defines the draw buffers to which all fragment colors are written.
    <n> specifies the number of values in <locations> and <indices>.
    <locations> is a pointer to an array of symbolic constants
    specifying the location of the draw buffer. <indices> is a pointer
    to an array of integer values specifying the index of the draw
    buffer. Together <locations> and <indices> specify the draw buffer
    to which each fragment color is written.

    Each constant in <locations> must be MULTIVIEW_EXT, COLOR_-
    ATTACHMENT_EXT, or NONE. Otherwise, an INVALID_ENUM error is
    generated. Further, acceptable values for the constants in
    <locations> depend on whether the GL is using the default
    framebuffer (i.e. DRAW_FRAMEBUFFER_BINDING is non-zero). For more
    information about framebuffer objects, see section 4.4.
    
    If the GL is bound to the default framebuffer, then each of the
    location constants must be MULTIVIEW_EXT or NONE.
    
    If the GL is bound to a framebuffer object, then each of the
    location constants must be COLOR_ATTACHMENT_EXT or NONE.

    Where the constant in <locations> is MULTIVIEW_EXT, the
    corresponding value in <indices> must be a value from 0 through
    MAX_MULTIVIEW_BUFFERS_EXT. Where the constant in <locations> is
    COLOR_ATTACHMENT_EXT, the value in <indices> must be a value from 0
    through MAX_COLOR_ATTACHMENTS_NV. Otherwise, an INVALID_OPERATION
    error is generated. Where the constant in <locations> is NONE, the
    value in <indices> is ignored.

    For monoscopic rendering, the only available view is index 0. For
    stereoscopic rendering, view index 0 corresponds to the left buffer
    and view index 1 corresponds to the right buffer.

    The draw buffers being defined correspond, in order, to the
    respective fragment colors. The draw buffer for fragment colors
    beyond <n> is set to NONE.

    Except for where the constant in <locations> is NONE, a buffer may
    not be specified more than once by the arrays pointed to by
    <locations> and <indices>. Specifying a buffer more than once will
    result in the error INVALID_OPERATION.

    If a fragment shader writes to "gl_FragColor", DrawBuffersIndexedEXT
    specifies a set of draw buffers into which the color written to
    "gl_FragColor" is written. If a fragment shader writes to
    gl_FragData, DrawBuffersIndexedEXT specifies a set of draw buffers
    into which each of the multiple output colors defined by these
    variables are separately written. If a fragment shader writes to
    neither gl_FragColor nor gl_FragData, the values of the fragment
    colors following shader execution are undefined, and may differ
    for each fragment color.
    
    Indicating a buffer or buffers using DrawBuffersIndexedEXT causes
    subsequent pixel color value writes to affect the indicated
    buffers.  If more than one color buffer is selected for drawing,
    blending is computed and applied independently for each buffer.

    Specifying NONE in the <locations> array for an fragment color will
    inhibit that fragment color from being written to any buffer.

    Monoscopic surfaces include only left buffers, while stereoscopic
    surfaces include a left and a right buffer, and multiview surfaces
    include more than 1 buffer (a stereoscopic surface is a multiview
    surface with 2 buffers).  The type of surface is selected at EGL
    surface initialization.

    The state required to handle color buffer selection is two integers
    for each supported fragment color for each framebuffer or
    framebuffer object. For the default framebuffer, the initial state
    of the draw buffer location for fragment color zero is MULTIVIEW_EXT
    and the index is 0. For framebuffer objects, the initial state of
    the draw buffer location for fragment color zero is COLOR_-
    ATTACHMENT_EXT and the index is 0. The initial state of draw buffers
    for fragment colors other than zero is NONE.
    
    The color buffer location and index to which fragment colors are
    written for an output color index <i> can be queried by calling
    GetIntegeri_vEXT with <target> DRAW_BUFFER_EXT and index
    <i>. This returns a pair of values representing the draw buffer
    location and index. The number of multiview buffers available to a
    GL context can be queried by calling GetIntegerv with <target>
    MAX_MULTIVIEW_BUFFERS_EXT.

    Section 4.3.1 (Reading Pixels), subsection "Obtaining Pixels from
    the Framebuffer" add:

    For color formats, the read buffer from which values are obtained is
    one of the color buffers; the selection of color buffer is
    controlled with ReadBufferIndexedEXT.

    The command

        void ReadBufferIndexedEXT(enum location, int index);

    takes a symbolic constant and integer pair to select the color
    buffer from which color values are obtained. <location> must be one
    of MULTIVIEW_EXT, COLOR_ATTACHMENT_EXT, or NONE. Otherwise, an
    INVALID_ENUM error is generated. If <location> is MULTIVIEW_EXT,
    <index> must be a value from 0 through MAX_MULTIVIEW_BUFFERS_EXT.
    If <location> is COLOR_ATTACHMENT_EXT, <index> must be a value from
    0 through MAX_COLOR_ATTACHMENTS_NV. Otherwise, an INVALID_OPERATION
    error is generated. If <location> is NONE, <index> is ignored.

    The acceptable values for <location> depend on whether the GL is
    using the default framebuffer (i.e. FRAMEBUFFER_BINDING is zero), or
    a framebuffer object (i.e. FRAMEBUFFER_BINDING is non-zero). For
    more information about framebuffer objects, see section 4.4.

    If the object bound to FRAMEBUFFER_BINDING is not framebuffer
    complete (as defined in section 4.4.5), then ReadPixels generates
    the error INVALID_FRAMEBUFFER_OPERATION. If <location> is a constant
    that is neither legal for the default framebuffer, nor legal for a
    framebuffer object, then the error INVALID_ENUM results.

    When FRAMEBUFFER_BINDING is zero, i.e. the default framebuffer,
    <location> must be MULTIVIEW_EXT or NONE. If the buffer indicated by
    <index> is missing, the error INVALID_OPERATION is generated. For
    the default framebuffer, the initial setting for READ_BUFFER_EXT is
    <location> of MULTIVIEW_EXT and <index> of zero.

    When the GL is using a framebuffer object, <location> must be NONE
    or COLOR_ATTACHMENT_EXT. Specifying COLOR_ATTACHMENT_EXT enables
    reading from the image attached to the framebuffer at COLOR_-
    ATTACHMENT<index>_NV. For framebuffer objects, the initial setting
    for READ_BUFFER_EXT is <location> of COLOR_ATTACHMENT_EXT and
    <index> of zero.

    ReadPixels generates an INVALID_OPERATION error if it attempts to
    select a color buffer while READ_BUFFER_EXT is none.

Changes to chapter 6

    Add to section 6.1.1, "Simple Queries" before description of
    IsEnabled:

    Indexed simple state variables are queried with the command

        void GetIntegeri_vEXT(enum target, uint index, int* data);

    <target> is the name of the indexed state and <index> is the
    index of the particular element being queried. <data> is a
    pointer to a scalar or array of the indicated type in which
    to place the returned data. An INVALID_VALUE error is generated
    if <index> is outside the valid range for the indexed state
    <target>.

Changes to Chapter 3 of the OpenGL Shading Language 1.0 Specification
(Basics)

    Add a new section:

    3.4.1 GL_EXT_multiview_draw_buffers Extension

    To use the GL_EXT_multiview_draw_buffers extension in a shader it
    must be enabled using the #extension directive.

    The shading language preprocessor #define GL_EXT_multiview_draw_-
    buffers will be defined to 1, if the GL_EXT_multiview_draw_buffers
    extension is supported.

Dependencies on NV_draw_buffers:

    If NV_draw_buffers is not supported and OpenGL ES 3 is, add to the
    description of DrawBuffersIndexedEXT:

        The <i>th index listed in <indices> must be <i> or NONE.
        Specifying a buffer out of order will generate the error
        INVALID_OPERATION.

    If neither NV_draw_buffers nor OpenGL ES 3 is supported, all
    references to DrawBuffersNV and color attachments are removed. The
    following is substituted for the above changes to Chapter 4 (Per-
    Fragment Operations and the Frame Buffer):

    Change section 4.2.1, "Selecting a Buffer for Writing"

    Change first paragraph to:

    By default, color values are written into the front buffer for
    single buffered contexts or into the back buffer for back buffered
    contexts as determined when creating the GL context. To control
    the color buffer into which each of the fragment color values is
    written, DrawBuffersIndexedEXT is used.

    Add to the end of 4.2.1:

    The command

        void DrawBuffersIndexedEXT(sizei n, const enum *locations,
                                   const int *indices);

    defines the draw buffers to which all fragment colors are written.
    <n> specifies the number of values in <locations> and <indices>.
    <locations> is a pointer to an array of symbolic constants
    specifying the location of the draw buffer. <indices> is a pointer
    to an array of integer values specifying the index of the draw
    buffer. Together <locations> and <indices> specify the draw buffer
    to which each fragment color is written.

    Each constant in <locations> must be MULTIVIEW_EXT or NONE.
    Otherwise, an INVALID_ENUM error is generated.

    DrawBuffersIndexedEXT generates an INVALID_OPERATION error if the GL
    is bound to a framebuffer object.
    
    Where the constant in <locations> is MULTIVIEW_EXT, the
    corresponding value in <indices> must be a value from 0 through
    MAX_MULTIVIEW_BUFFERS_EXT. Otherwise, an INVALID_OPERATION error is
    generated. Where the constant in <locations> is NONE, the value
    in <indices> is ignored.

    An INVALID_VALUE error is generated if <n> is not 1.

    For monoscopic rendering, the only available view is index 0. For
    stereoscopic rendering, view index 0 is left and view index 1 is
    right.

    If a fragment shader writes to "gl_FragColor" or "gl_FragData[0]",
    DrawBuffersIndexedEXT specifies a set of draw buffers into which the
    output color is written. If a fragment shader writes to neither
    gl_FragColor nor gl_FragData[0], the values of the fragment colors
    following shader execution are undefined, and may differ for each
    fragment color.
    
    Indicating a buffer using DrawBuffersIndexedEXT causes subsequent
    pixel color value writes to affect the indicated buffer.

    Specifying NONE in the <locations> array for an fragment color will
    inhibit that fragment color from being written to any buffer.

    Monoscopic surfaces include only left buffers, while stereoscopic
    surfaces include a left and a right buffer, and multiview surfaces
    include more than 1 buffer (a stereoscopic surface is a multiview
    surface with 2 buffers).  The type of surface is selected at EGL
    surface initialization.

    The state required to handle color buffer selection is two integers
    for the fragment color output for each framebuffer or framebuffer
    object. For the default framebuffer, the initial state of the draw
    buffer location for fragment color zero is MULTIVIEW_EXT and the
    index is 0. For framebuffer objects, the initial state of the draw
    buffer location for fragment color zero is COLOR_ATTACHMENT_EXT and
    the index is 0.

    The color buffer location and index to which fragment colors are
    written can be queried by calling GetIntegeri_vEXT with <target>
    DRAW_BUFFER_EXT and index 0. This returns a pair of values
    representing the draw buffer location and index. The number of
    multiview buffers available to a GL context can be queried by
    calling GetIntegerv with <target> MAX_MULTIVIEW_BUFFERS_EXT.

    The command

        void ReadBufferIndexedEXT(enum location, int index);

    takes a symbolic constant and integer pair to select the color
    buffer from which color values are obtained. <location> must be
    MULTIVIEW_EXT or NONE. Otherwise, an INVALID_ENUM error is
    generated. If <location> is MULTIVIEW_EXT, <index> must be a value
    from 0 through MAX_MULTIVIEW_BUFFERS_EXT. Otherwise, an
    INVALID_OPERATION error is generated. If <location> is NONE, the
    <index> is ignored.

    When FRAMEBUFFER_BINDING is zero, i.e. the default framebuffer,
    <location> must be MULTIVIEW_EXT or NONE. If the buffer indicated by
    <index> is missing, the error INVALID_OPERATION is generated. For
    the default framebuffer, the initial setting for READ_BUFFER_EXT is
    <location> of MULTIVIEW_EXT and <index> of zero.

    ReadBufferIndexedEXT generates an INVALID_OPERATION error if the GL
    is bound to a framebuffer object.

    ReadPixels generates an INVALID_OPERATION error if it attempts to
    select a color buffer while READ_BUFFER_EXT is none.

New State

    Add the new Table 6.X "Framebuffer (State per framebuffer object)" :

        State                     Type    Get Command      Initial    Description
        ---------------           -----   ---------------  -------    -----------
        DRAW_BUFFER_EXT           nxZ+    GetIntegeri_vEXT See 4.2.1  Multiview draw buffer
                                                                      location and index
                                                                      selected for the
                                                                      specified color output
        READ_BUFFER_EXT           nxZ+    GetInteger       See 4.3.1  Read source buffer
                                                                      location and index

    Add the new Table 6.X "Framebuffer Dependent Values" :

        State                     Type    Get Command     Min Value  Description
        ---------------           -----   --------------- ---------  -----------
        MAX_MULTIVIEW_BUFFERS_EXT Z+      GetIntegerv     1          Number of multiview
                                                                     draw buffers

Issues

    1. What should this extension be called?

    RESOLVED: multiview_draw_buffers. Multiview has come to be the
    standard term to refer to stereoscopic and beyond buffer rendering
    and this approach centers around the traditional usage of
    a drawbuffers call to specify the buffer(s) to render to.

    2. How should draw buffer bindings be queried?

    RESOLVED: A new indexed integer query function called
    glGetIntegeri_vEXT. This extension adds an indexed binding for draw
    buffers so it follows that an indexed query should be used to
    retrieve the state that it sets. The name glGetIntegeri_vEXT is
    chosen as it was in desktop GL to clarify the 'i' suffix
    indicating an indexed call as opposed to 'i' indicating an integer
    variant of a call accepting parameters of various types.

    3. Should the <location> parameter of DrawBuffersIndexedEXT be removed?

    RESOLVED: No. It is useful when draw_buffers is supported.

Revision History
    Version 4, 25 Sept 2012 Clean up overview. Fix a few typographical
                            errors.
    Version 3, 03 Sept 2011 EXTify. Remove ALL broadcast. 
                            Add interactions for ES3 and non-
                            draw_buffers cases
    Version 2, 02 Aug 2011 Responses to feedback.
    Version 1, 14 April 2011 First draft.

