Name

    KHR_stream_fifo

Name Strings

    EGL_KHR_stream_fifo

Contributors

    Acorn Pooley

Contacts

    Acorn Pooley, NVIDIA  (apooley 'at' nvidia.com)

Notice

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

Status

    Complete.
    Approved by the Khronos Board of Promoters on December 2, 2011.

Version

    Version 6, October 12, 2011

Number

    EGL Extension #36

Dependencies

    Requires EGL 1.2.
    Requires the EGL_KHR_stream extension.

    This extension is written based on the wording of the EGL 1.2
    specification.

    The EGL_KHR_stream_producer_eglsurface and
    EGL_NV_stream_producer_eglsurface extensions affect the wording of
    this extension.

    The EGL_KHR_stream_producer_aldatalocator and
    EGL_NV_stream_producer_aldatalocator extensions affect the wording
    of this extension.

    The EGL_KHR_stream_consumer_gltexture and
    EGL_NV_stream_consumer_gltexture extensions affect the wording
    of this extension.

Overview

    This extension allows an EGLStream to operate as a fifo rather
    than as a mailbox.

    The EGL_KHR_stream extension defines the EGLStream object.
    The EGLStream object works like a 1 entry mailbox, allowing the
    consumer to consume the frame that the producer most recently
    inserted.  If the consumer requests image frames faster than the
    producer creates them then it gets the most recent one over and
    over until a new one is inserted.  If the producer inserts frames
    faster than the consumer can consume them then the extra frames
    are discarded.  The producer is never stalled.

    This extension allows an EGLStream to be placed into fifo mode.
    In fifo mode no images are discarded.  If the producer attempts to
    insert a frame and the fifo is full then the producer will stall
    until there is room in the fifo.  When the consumer retrieves an
    image frame from the EGLStream it will see the image frame that
    immediately follows the image frame that it last retrieved (unless
    no such frame has been inserted yet in which case it retrieves the
    same image frame that it retrieved last time).

    Timing of the EGLStream in mailbox mode, as described by the
    EGL_KHR_stream extension, is the responsibility of the
    producer (with help from the consumer in the form of the
    EGL_CONSUMER_LATENCY_USEC_KHR hint).

    In contrast, timing of an EGLStream in fifo mode is the
    responsibility of the consumer.  Each image frame in the fifo has
    an associated timestamp set by the producer.  The consumer can use
    this timestamp to determine when the image frame is intended to be
    displayed to the user.


New Types

    This type represents an absolute time in nanoseconds.

    typedef khronos_utime_nanoseconds_t EGLTimeKHR

New functions

    EGLBoolean eglQueryStreamTimeKHR(
        EGLDisplay   dpy,
        EGLStreamKHR stream,
        EGLenum      attribute,
        EGLTimeKHR  *value);

New Tokens

    Accepted as an attribute in the <attrib_list> parameter of
    eglCreateStreamKHR and as the <attribute> parameter of
    eglQueryStreamKHR.

    EGL_STREAM_FIFO_LENGTH_KHR                  0x31FC

    These enums are accepted the <attribute> parameter of
    eglQueryStreamTimeKHR.

    EGL_STREAM_TIME_NOW_KHR                     0x31FD
    EGL_STREAM_TIME_CONSUMER_KHR                0x31FE
    EGL_STREAM_TIME_PRODUCER_KHR                0x31FF

Add 4 new entries to "Table 3.10.4.4 EGLStream Attributes" in the
EGL_KHR_stream extension spec:

        Attribute                   Read/Write   Type        Section
        --------------------------  ----------   ----------  --------
        EGL_STREAM_FIFO_LENGTH_KHR      io       EGLint      3.10.4.xx
        EGL_STREAM_TIME_NOW_KHR         ro       EGLTimeKHR  3.10.4.xx
        EGL_STREAM_TIME_CONSUMER_KHR    ro       EGLTimeKHR  3.10.4.xx
        EGL_STREAM_TIME_PRODUCER_KHR    ro       EGLTimeKHR  3.10.4.xx

Add a new paragraph to the end of section "3.10.4.2 Querying EGLStream
Attributes" in the EGL_KHR_stream extension.

    Call

        EGLBoolean eglQueryStreamTimeKHR(
            EGLDisplay   dpy,
            EGLStreamKHR stream,
            EGLenum      attribute,
            EGLTimeKHR  *value);

    to query <attribute> from <stream> for attributes whose type is
    EGLTimeKHR.

    If an error occurs EGL_FALSE is returned and an error is
    generated.

        - EGL_BAD_STREAM_KHR is generated if <stream> is not a valid
          EGLStream created for <dpy>.

        - EGL_BAD_ATTRIBUTE is generated if <attribute> is not a valid
          EGLStream attribute with type EGLTimeKHR.


Add new sections 3.1.4.xx at the end of section "3.10.4 EGLStream
Attributes" in the EGL_KHR_stream extension.

    3.1.4.x EGL_STREAM_FIFO_LENGTH_KHR Attribute

    The EGL_STREAM_FIFO_LENGTH_KHR may be set in the <attrib_list>
    parameter of eglCreateStreamKHR(), but is read-only once the
    stream is created.  It can be queried with eglQueryStreamKHR().
    Its default value is 0.  Setting it to a value less than 0
    generates an EGL_BAD_PARAMETER error.

    When EGL_STREAM_FIFO_LENGTH_KHR is 0 the EGLStream operates in
    mailbox mode as described in section "3.10.5.1 EGLStream operation
    in mailbox mode"

    When EGL_STREAM_FIFO_LENGTH_KHR is greater than 0 then the
    EGLStream operates in fifo mode as described in section "3.10.5.2
    EGLStream operation in fifo mode".

    In fifo mode the EGLStream contains up to N image frames, where N
    is the value of the EGL_STREAM_FIFO_LENGTH_KHR attribute.

    The value of EGL_STREAM_FIFO_LENGTH_KHR is independent from the
    number of internal buffers used by the producer.  The producer may
    require some number of internal buffers, but those are in addition
    to the fifo buffers described by EGL_STREAM_FIFO_LENGTH_KHR.

    3.1.4.x+1 EGL_STREAM_TIME_NOW_KHR Attribute

    This indicates the current time.  It is measured as the number of
    nanoseconds since some arbitrary event (e.g. the last time the
    system rebooted).

    3.1.4.x+2 EGL_STREAM_TIME_CONSUMER_KHR Attribute

    This indicates the timestamp of the image frame that the consumer
    most recently consumed (i.e. frame number EGL_CONSUMER_FRAME_KHR).
    The frame should first be displayed to the user when
    EGL_STREAM_TIME_NOW_KHR matches this value.

    In mailbox mode the timestamp for an image frame is always equal
    to the time that the producer inserted the image frame into the
    EGLStream, minus the value of EGL_CONSUMER_LATENCY_USEC_KHR.

    In fifo mode the timestamp for an image frame is set by the
    producer when it is inserted into the EGLStream.

    The timestamp uses the same time units as EGL_STREAM_TIME_NOW_KHR.

    3.1.4.x+3 EGL_STREAM_TIME_PRODUCER_KHR Attribute

    This indicates the timestamp of the image frame that the producer
    most recently inserted into the EGLStream (i.e. frame number
    EGL_PRODUCER_FRAME_KHR).


Modify the first sentence of section "3.10.5.1 EGLStream operation in
mailbox mode" in the EGL_KHR_stream extension to:

    When the EGL_STREAM_FIFO_LENGTH_KHR attribute is 0
    then the EGLStream conceptually operates as a mailbox.


Add a new section after section "3.10.5.1 EGLStream operation in
mailbox mode" in the EGL_KHR_stream extension.

    3.10.5.2 EGLStream operation in fifo mode

    When the EGL_STREAM_FIFO_LENGTH_KHR attribute is greater than 0
    then the EGLStream operates in fifo mode.  The length of the fifo
    is the value of the EGL_STREAM_FIFO_LENGTH_KHR attribute.

    In fifo mode the EGLStream conceptually operates as a fifo.

    When the consumer wants to consume a new image frame, behavior
    depends on the state of the EGLStream.  If the state is
    EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR then the fifo is not
    empty and the image frame to consume is removed from the tail of
    the fifo.  If the state is
    EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR then the fifo is empty
    and the consumer consumes the same frame that it most recently
    consumed.  Otherwise there are no image frames available to
    consume (behavior in this case is described in the documentation
    for each type of consumer - see section "3.10.2 Connecting an
    EGLStream to a consumer").

    If the fifo is empty when the consumer is finished consuming an
    image frame then the consumer holds on to the image frame in case
    it needs to be consumed again later (this happens if the consumer
    wants to consume another image frame before the producer has
    inserted a new image frame into the fifo).  In this case the state
    of the EGLStream will be EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR
    until the producer inserts a new image frame (or until the state
    becomes EGL_STREAM_STATE_DISCONNECTED_KHR).

    The producer inserts image frames at the head of the fifo.  If the
    fifo is full (already contains <L> image frames, where <L> is the
    value of the EGL_STREAM_FIFO_LENGTH_KHR attribute) then producer
    is stalled until the fifo is no longer full.  When the fifo is not
    empty the EGLStream state is
    EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR.

    This operation implies:

        - Frames are never discarded until the consumer has examined
          them.

        - If the consumer consumes frames slower than the producer
          inserts frames, then the producer will stall.

        - If the consumer consumes frames faster than the producer
          inserts frames, then the consumer may see some frames more
          than once.

        - The consumer can see each frame exactly once if it always
          waits until the stream is in the
          EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR state before
          retrieving an image from the stream.

    In mailbox mode the producer is responsible for timing.  In fifo
    mode the consumer is responsible for timing.

    In fifo mode the producer marks each image frame with a timestamp.
    The timestamp indicates at what time the image frame should first
    be visible to the user.  Exactly how a producer sets the timestamp
    is described in the documentation for each type of producer.  If
    the value of an image frame's timestamp is T then the producer
    must insert that image frame *before* time
        T - EGL_CONSUMER_LATENCY_USEC_KHR
    Image frames must be inserted in increasing timestamp order.

    The consumer is responsible for presenting each image frame to the
    user at the time indicated by its timestamp.  The consumer should
    indicate its minimum latency to the producer by setting the
    EGL_CONSUMER_LATENCY_USEC_KHR attribute.


If the EGL_KHR_stream_producer_eglsurface or
EGL_NV_stream_producer_eglsurface extension is present then add a
paragraph to the end of section "3.10.3.1 Stream Surface Producer"
from that extension:

    If <stream>'s EGL_STREAM_FIFO_LENGTH_KHR value is nonzero then
    <stream> operates in fifo mode.  Each time the EGLSurface is
    passed to eglSwapBuffers() an image frame is inserted into the
    fifo.  The eglSwapBuffers call sets the timestamp of the image
    frame to the time that eglSwapBuffers was called PLUS the value of
    the EGL_CONSUMER_LATENCY_USEC_KHR attribute.

If the EGL_KHR_stream_producer_eglsurface or
EGL_NV_stream_producer_eglsurface extension is present then add a
paragraph to section "3.9.x Posting to a Stream"
from that extension, between the 2nd paragraph (which begins "If
<surface> is the producer of an EGLStream...") and the 3rd paragraph
(which begins "When eglSwapBuffers returns the contents..."):

    If the value of the EGL_STREAM_FIFO_LENGTH_KHR attribute, <L> is
    greater than zero, and there are already <L> image frames in the
    EGLStream fifo, then the eglSwapBuffers function blocks (does not
    return and does not insert the new image frame) until there is
    room in the EGLStream fifo (i.e. there are less than <L> image
    frames in the fifo).

If the EGL_KHR_stream_producer_aldatalocator or
EGL_NV_stream_producer_aldatalocator extension is present then replace
the 2nd to last paragraph (the one that starts "The OpenMAX AL object
will use the value of...") of section "3.10.3.1 OpenMAX AL Stream
Producer" from that extension with the following 2 paragraphs:

    If <stream>'s EGL_STREAM_FIFO_LENGTH_KHR value is zero then the
    stream operates in mailbox mode.  The OpenMAX AL object will use
    the value of the EGL_CONSUMER_LATENCY_USEC_KHR attribute of
    <stream> to determine when to insert each image frame.  If the
    EGL_CONSUMER_LATENCY_USEC_KHR attribute is modified (by the
    consumer and/or by the application) then then OpenMAX AL object
    will adjust its timing within 500 milliseconds of the change.  If
    an image frame is intended to appear to the user at time T (e.g.
    so that it is synchronized with audio) then the OpenMAX AL object
    must insert the image frame at time
        T - EGL_CONSUMER_LATENCY_USEC_KHR
    and set the image frame's timestamp to T.

    If the <stream>'s EGL_STREAM_FIFO_LENGTH_KHR value is nonzero then
    <stream> operates in fifo mode.  If an image frame is intended to
    appear to the user at time T then the OpenMAX AL object will
    insert the image frame into the fifo before time
        T - EGL_CONSUMER_LATENCY_USEC_KHR
    and set the image frame's timestamp to T.

If the EGL_KHR_stream_consumer_gltexture or
EGL_NV_stream_consumer_gltexture extension is present then replace the
3rd to last paragraph (the one that starts "If the producer has not
inserted any new image frames...") of section "3.10.2.1 GL Texture
External consumer" from that extension with the following 2
paragraphs:

    When <stream>'s EGL_STREAM_FIFO_LENGTH_KHR value is zero then the
    stream operates in mailbox mode.  If the producer has not inserted
    any new image frames since the last call to
    eglStreamConsumerAcquireNV then eglStreamConsumerAcquireNV will
    "latch" the same image frame it latched last time
    eglStreamConsumerAcquireNV was called.  If the producer has
    inserted one new image frame since the last call to
    eglStreamConsumerAcquireNV then the eglStreamConsumerAcquireNV
    will "latch" the newly inserted image frame.  If the producer has
    inserted more than one new image frame since the last call to
    eglStreamConsumerAcquireNV then all but the most recently inserted
    image frames are discarded and the producer will "latch" the most
    recently inserted image frame.

    When <stream>'s EGL_STREAM_FIFO_LENGTH_KHR value is nonzero then
    <stream> operates in fifo mode.  Each call to
    eglStreamConsumerAcquireNV "latches" the next image frame in the
    fifo into the OpenGL texture, removing that image frame from the
    fifo.  If there are no new image frames in the fifo then
    eglStreamConsumerAcquireNV will "latch" the same image frame it
    latched last time eglStreamConsumerAcquireNV was called.


Issues
    1.  Is this extension useful?

        RESOLVED: Yes.  Browser vendors and others have expressed
        interest.

    2.  Why not include this functionality in the base EGL_KHR_stream
        extension?

        RESOLVED: Including it there was confusing.  Several
        developers interested in EGLStream have thought at first that
        they want to use EGLStreams in fifo mode.  Later after
        thinking about it they realize standard mode (non-fifo or
        "mailbox" mode) is more useful.

        Mailbox mode is easier to use and is less confusing for
        aldatalocator-producer, gltexture-consumer usecase which was
        the primary usecase for the extension at the time it was
        devised.

        Trying to describe both mailbox mode and fifo mode in
        the same extension made the extension complicated.  It was
        confusing when the timestamps were useful (only in fifo mode).
        It was confusing how the EGL_CONSUMER_LATENCY_USEC_KHR
        attribute worked in different modes.

        these problems the fifo functionality was split into this
        separate extension.  This also allows existing consumer and
        producer extensions to be defined in terms of mailbox mode,
        simplifying them and making them easier to understand.  Then
        interactions with fifo mode can be described separately.

        Also, the fifo mode is more complicated to use and implement than
        the mailbox mode.  It was thought that there might be problems
        with the fifo mode that could lead to a new extension
        replacing the fifo mode extension.  By keeping the fifo mode
        functionality segregated into its own extension this would be
        easier to accomplish.

Revision History

    #6 (October 12, 2011) Acorn Pooley
        - Clarify fifo mode operation.  (Does not change behavior.)


    #5 (October 11, 2011) Acorn Pooley
        - Resolve issue 1
        - fix typos
        - add issue 2

    #4 (September 27, 2011) Acorn Pooley
        - Assign enum values (bug 8064)

    #3 (July 6, 2011) Acorn Pooley
        - Rename EGL_KHR_image_stream to EGL_KHR_stream

    #2 (version #2 skipped)

    #1  (July 1, 2011) Acorn Pooley
        - Initial draft

# vim:ai:ts=4:sts=4:expandtab:textwidth=70
