Loading [MathJax]/extensions/tex2jax.js
  • <xmp id="om0om">
  • <table id="om0om"><noscript id="om0om"></noscript></table>
  • NVIDIA DRIVE OS Linux SDK API Reference

    6.0.9 Release
    All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
    EGL_KHR_stream_cross_process_fd
    Name
    
        KHR_stream_cross_process_fd
    
    Name Strings
    
        EGL_KHR_stream_cross_process_fd
    
    Contributors
    
        Acorn Pooley
        Ian Stewart
    
    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 EGL Working Group on June 6, 2012.
        Approved by the Khronos Board of Promoters on July 27, 2012.
    
    Version
    
        Version 8 - June 5, 2012
    
    Number
    
        EGL Extension #41
    
    Dependencies
    
        Requires EGL 1.2.
        Requires EGL_KHR_stream
    
        This extension is written based on the wording of the EGL 1.2
        specification.
    
        This extension interacts with the following extensions if they are
        also present:
            EGL_KHR_stream_producer_eglsurface
            EGL_KHR_stream_consumer_gltexture
            EGL_KHR_stream_producer_aldatalocator
            EGL_KHR_stream_fifo
    
    Overview
    
        This extension allows an EGLStreamKHR object handle to be
        duplicated into another process so that the EGLStream producer can
        be in one process while the EGLStream consumer can be in another
        process.
    
        Duplicating the EGLStreamKHR object handle into another process is
        peformed in 3 steps
    
            1) Get a file descriptor associated with the EGLStream.
            2) Duplicate the file descriptor into another process.
            3) Create an EGLStreamKHR from the duplicated file descriptor in
                the other process.
    
        The file descriptor is obtained by calling
        eglGetStreamFileDescriptorKHR().
    
        Duplicating the file descriptor into another process is outside
        the scope of this extension.  See issue #1 for an example of how
        to do this on a Linux system.
    
        The EGLStreamKHR object handle is created in the second process by
        passing the file descriptor to the
        eglCreateStreamFromFileDescriptorKHR() function.  This must be
        done while the EGLStream is in the EGL_STREAM_STATE_CREATED_KHR
        state.
    
        Once the EGLStreamKHR object handle is created in the second
        process, it refers to the same EGLStream as the EGLStreamKHR
        object handle in the original process.  A consumer can be
        associated with the EGLStream from either process.  A producer can
        be associated with the EGLStream from either process.
    
    New Types
    
        Represents a native OS file descriptor.
    
        typedef int EGLNativeFileDescriptorKHR
    
    New Procedures and Functions
    
        EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
            EGLDisplay dpy,
            EGLStreamKHR stream);
    
        EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
            EGLDisplay dpy,
            EGLNativeFileDescriptorKHR file_descriptor);
    
    New Tokens
    
        Returned from eglGetStreamFileDescriptorKHR on error.
    
        #define EGL_NO_FILE_DESCRIPTOR_KHR  ((EGLNativeFileDescriptorKHR)(-1))
    
    Add a new section just after section "3.10.1 Creating an EGLStream" in
    the EGL_KHR_stream extension
    
        3.10.1.1 Duplicating an EGLStream from a file descriptor
    
        Call
    
            EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
                EGLDisplay dpy,
                EGLStreamKHR stream);
    
        to create a file descriptor that refers to the EGLStream.
        <stream> must be an EGLStream in the EGL_STREAM_STATE_CREATED_KHR
        state.  eglGetStreamFileDescriptorKHR may be called at most once
        for any <stream>.
    
        On success a file descriptor is returned which can be used
        to create a duplicate EGLStreamKHR handle which refers to the same
        underlying EGLStream as <stream>.  This file descriptor and file
        descriptors duplicated from it should only be used in a call to
        eglCreateStreamFromFileDescriptorKHR() and/or a call to close().
        In particular reads, writes, and other operations on the file
        descriptor result in undefined behavior.
    
        On failure the functions returns EGL_NO_FILE_DESCRIPTOR_KHR and
        generates an error
    
            - EGL_BAD_DISPLAY is generated if <dpy> is not a valid
              initialized EGLDisplay
    
            - EGL_BAD_STREAM_KHR is generated if <stream> is not a valid
              EGLStreamKHR handle created for <dpy>.
    
            - EGL_BAD_STATE_KHR is generated if <stream> is not in the
              EGL_STREAM_STATE_CREATED_KHR state or if
              eglGetStreamFileDescriptorKHR() has previously been called
              on this <stream>.
    
            - EGL_BAD_STATE_KHR is generated if <stream> was not created
              by eglCreateStreamKHR (e.g. if it was created by
              eglCreateStreamFromFileDescriptorKHR).
    
        The file descriptor returned by eglGetStreamFileDescriptorKHR can
        be duplicated into a different process address space using system
        specific mechanisms outside the scope of this specification.  (For
        example, on a Linux system it can be sent over a UNIX domain
        socket using sendmsg/recvmsg.)
    
        Call
    
            EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
                EGLDisplay dpy,
                EGLNativeFileDescriptorKHR file_descriptor);
    
        to create an EGLStreamKHR handle.  <file_descriptor> must be a
        file descriptor returned by eglGetStreamFileDescriptorKHR or a
        file descriptor duplicated from such a file descriptor (possibly
        in a different process).  The EGLStream must be in the
        EGL_STREAM_STATE_CREATED_KHR or EGL_STREAM_STATE_CONNECTING_KHR
        state.
    
        On success an EGLStreamKHR handle is returned.  This EGLStreamKHR
        handle refers to the same EGLStream which was used to create the
        <file_descriptor> or the file descriptor from which
        <file_descriptor> was duplicated.
    
        After the file descriptor is passed to
        eglCreateStreamFromFileDescriptorKHR it may no longer be used to
        create a new EGLStream.
    
        On failure EGL_NO_STREAM_KHR is returned and an error is
        generated.
    
            - EGL_BAD_DISPLAY is generated if <dpy> is not a valid
              initialized EGLDisplay
    
            - EGL_BAD_ATTRIBUTE is generated if <file_descriptor> is
              EGL_NO_FILE_DESCRIPTOR_KHR.
    
            - EGL_BAD_ATTRIBUTE is generated if <file_descriptor> is
              not an open file descriptor referring to an EGLStream
              created on the same Native Display as <dpy>.
    
            - EGL_BAD_ATTRIBUTE is generated if <file_descriptor> has
              already been used to create a stream handle via a previous
              call to eglCreateStreamFromFileDescriptorKHR.
    
            - EGL_BAD_STATE_KHR is generated if <stream> is not in the
              EGL_STREAM_STATE_CREATED_KHR or
              EGL_STREAM_STATE_CONNECTING_KHR state.
    
        The application should close the file descriptor and any file
        descriptors duplicated from it once
        eglCreateStreamFromFileDescriptorKHR has returned.  Open file
        descriptors will consume resources until they are closed or until
        all processes that hold them open have terminated.  Closing the
        file descriptors after calling
        eglCreateStreamFromFileDescriptorKHR will not affect the
        associated EGLStream.  If an application calls
        eglGetStreamFileDescriptorKHR and then determines that the file
        descriptor and/or the EGLStream is no longer needed then it may
        (and should) close the file descriptor and destroy the EGLStream
        (this is not considered an error).
    
        If a process which has successfully connected a consumer or
        producer to the EGLStream terminates (normally or abnormally) then
        the EGLStream state becomes EGL_STREAM_STATE_DISCONNECTED_KHR.
    
        If a process has created an EGLStreamKHR handle either with
        eglCreateStreamKHR or eglCreateStreamFromFileDescriptorKHR but has
        not connected a producer or consumer to the stream, and this
        process terminates (normally or abnormally) then this has no
        effect on the EGLStream.
    
    Interactions with the EGL_KHR_stream_producer_eglsurface extension.
    
        The eglCreateStreamProducerSurfaceKHR() function can be called
        from either the process that created the original EGLStreamKHR, or
        from the process which called eglCreateStreamFromFileDescriptorKHR.
    
    Interactions with the EGL_KHR_stream_consumer_gltexture extension.
    
        The eglStreamConsumerGLTextureExternalKHR() function can be called
        from either the process that created the original EGLStreamKHR, or
        from the process which called
        eglCreateStreamFromFileDescriptorKHR.  The
        eglStreamConsumerAcquireKHR() and eglStreamConsumerReleaseKHR()
        functions must be called from the same process that calls
        eglStreamConsumerGLTextureExternalKHR() (or else they will fail
        and generate an EGL_BAD_ACCESS error).
    
    Interactions with the EGL_KHR_stream_producer_aldatalocator extension.
    
        The CreateMediaPlayer() method can be called from either the
        process that created the original EGLStreamKHR, or from the
        process which called eglCreateStreamFromFileDescriptorKHR.
    
    Interactions with the EGL_KHR_stream_fifo extension.
    
        The queries for EGL_STREAM_FIFO_LENGTH_KHR,
        EGL_STREAM_TIME_NOW_KHR, EGL_STREAM_TIME_CONSUMER_KHR, and
        EGL_STREAM_TIME_PRODUCER_KHR can be made from either process.  The
        time values returned by the EGL_STREAM_TIME_NOW_KHR query will be
        consistent between the two processes (i.e. if queried at the same
        time from both processes, the same value (plus or minus some
        margin of error) will be returned).
    
    Interactions with the EGL_NV_stream_cross_process_fd extension.
    
        These extensions may both exist on the same implementation and
        are functionally equivalent. Mixing and matching file descriptors
        from one extension with functions from the other is allowed.
    
    Interactions with the EGL_NV_stream_sync extension.
    
        The eglCreateStreamSyncNV() function may only be called from a
        process which has successfully connected a consumer to the
        EGLStream.  Otherwise eglCreateStreamSyncNV generates a
        EGL_BAD_ACCESS error.
    
    Issues
        1.  How does the application transfer the file descriptor to
            another process?
    
            RESOLVED: This is outside the scope of this extension.  The
            application can use existing operating system mechanisms for
            duplicating the file descriptor into another process.  For
            example on Linux a file descriptor can be sent over a UNIX
            domain socket using the following code (call send_fd() to
            send the file descriptor, and receive_fd() in the other
            process to receive the file descriptor).  (The following code
            is placed into the public domain by its author, Acorn Pooley)
    
                #include <stdio.h>
                #include <stdlib.h>
                #include <unistd.h>
                #include <sys/types.h>
                #include <sys/socket.h>
                #include <sys/un.h>
    
                #define FATAL_ERROR() exit(1)
                #define SOCKET_NAME "/tmp/example_socket"
    
                /* Send <fd_to_send> (a file descriptor) to another process */
                /* over a unix domain socket named <socket_name>.           */
                /* <socket_name> can be any nonexistant filename.           */
                void send_fd(const char *socket_name, int fd_to_send)
                {
                    int sock_fd;
                    struct sockaddr_un sock_addr;
                    struct msghdr msg;
                    struct iovec iov[1];
                    char ctrl_buf[CMSG_SPACE(sizeof(int))];
                    struct cmsghdr *cmsg = NULL;
    
                    sock_fd = socket(PF_UNIX, SOCK_STREAM, 0);
                    if (sock_fd < 0) FATAL_ERROR();
    
                    memset(&sock_addr, 0, sizeof(struct sockaddr_un));
                    sock_addr.sun_family = AF_UNIX;
                    strncpy(sock_addr.sun_path,
                            socket_name,
                            sizeof(sock_addr.sun_path)-1);
    
                    while (connect(sock_fd,
                                (const struct sockaddr*)&sock_addr,
                                sizeof(struct sockaddr_un))) {
                        printf("Waiting for reciever\n");
                        sleep(1);
                    }
    
                    memset(&msg, 0, sizeof(msg));
    
                    iov[0].iov_len  = 1;    // must send at least 1 byte
                    iov[0].iov_base = "x";  // any byte value (value ignored)
                    msg.msg_iov = iov;
                    msg.msg_iovlen = 1;
    
                    memset(ctrl_buf, 0, sizeof(ctrl_buf));
                    msg.msg_control = ctrl_buf;
                    msg.msg_controllen = sizeof(ctrl_buf);
    
                    cmsg = CMSG_FIRSTHDR(&msg);
                    cmsg->cmsg_level = SOL_SOCKET;
                    cmsg->cmsg_type = SCM_RIGHTS;
                    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
                    *((int *) CMSG_DATA(cmsg)) = fd_to_send;
    
                    msg.msg_controllen = cmsg->cmsg_len;
    
                    if (sendmsg(sock_fd, &msg, 0) <= 0) FATAL_ERROR();
    
                    close(sock_fd);
                }
    
                /* Listen on a unix domain socket named <socket_name> and  */
                /* receive a file descriptor from another process.         */
                /* Returns the file descriptor.  Note: the integer value   */
                /* of the file descriptor may be different from the        */
                /* integer value in the other process, but the file        */
                /* descriptors in each process will refer to the same file */
                /* object in the kernel.                                   */
                int receive_fd(const char *socket_name)
                {
                    int listen_fd;
                    struct sockaddr_un sock_addr;
                    int connect_fd;
                    struct sockaddr_un connect_addr;
                    socklen_t connect_addr_len = 0;
                    struct msghdr msg;
                    struct iovec iov[1];
                    char msg_buf[1];
                    char ctrl_buf[CMSG_SPACE(sizeof(int))];
                    struct cmsghdr *cmsg;
    
                    listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
                    if (listen_fd < 0) FATAL_ERROR();
    
                    unlink(socket_name);
    
                    memset(&sock_addr, 0, sizeof(struct sockaddr_un));
                    sock_addr.sun_family = AF_UNIX;
                    strncpy(sock_addr.sun_path,
                            socket_name,
                            sizeof(sock_addr.sun_path)-1);
    
                    if (bind(listen_fd,
                             (const struct sockaddr*)&sock_addr,
                             sizeof(struct sockaddr_un)))
                        FATAL_ERROR();
    
                    if (listen(listen_fd, 1)) FATAL_ERROR();
    
                    connect_fd = accept(
                                    listen_fd,
                                    (struct sockaddr *)&connect_addr,
                                    &connect_addr_len);
                    close(listen_fd);
                    unlink(socket_name);
                    if (connect_fd < 0) FATAL_ERROR();
    
                    memset(&msg, 0, sizeof(msg));
    
                    iov[0].iov_base = msg_buf;
                    iov[0].iov_len  = sizeof(msg_buf);
                    msg.msg_iov = iov;
                    msg.msg_iovlen = 1;
    
                    msg.msg_control = ctrl_buf;
                    msg.msg_controllen = sizeof(ctrl_buf);
    
                    if (recvmsg(connect_fd, &msg, 0) <= 0) FATAL_ERROR();
    
                    cmsg = CMSG_FIRSTHDR(&msg);
                    if (!cmsg) FATAL_ERROR();
                    if (cmsg->cmsg_level != SOL_SOCKET) FATAL_ERROR();
                    if (cmsg->cmsg_type != SCM_RIGHTS) FATAL_ERROR();
    
                    return *(int *) CMSG_DATA(cmsg);
                }
    
        2.  Does this extension work with all consumers and all producers?
    
            RESOLVED: This extension is compatible with
                EGL_KHR_stream_producer_eglsurface
                EGL_KHR_stream_consumer_gltexture
                EGL_KHR_stream_producer_aldatalocator
                EGL_KHR_stream_fifo
            as described in the Interactions sections.  Whether an
            EGLStream that has been duplicated into another process will
            work with other types of consumers and producers should be
            mentioned in the description of those consumers and producers.
    
        3.  Does EGL create a file descriptor for every EGLStream when the
            EGLStream is created, or is the file descriptor be created
            when eglGetStreamFileDescriptorKHR is called?
    
            RESOLVED: This is implementation dependent.  However,
            recommended behavior is to create the file descriptor when
            eglGetStreamFileDescriptorKHR is called.  This avoids
            polluting the file descriptor namespace (which may have a
            limited size on some systems) with descriptors for EGLStreams
            which will only be used inside a single process.  The
            eglGetStreamFileDescriptorKHR function will fail and generate
            an EGL_BAD_ALLOC error if it is unable to allocate a file
            descriptor for the EGLStream.
    
        4.  Should the EGLStream be created from the file descriptor with
            the existing eglCreateStreamKHR function or with a new
            function dedicated to that purpose?
    
            The advantage of creating a new function is that a new
            parameter can be added with a specific type.  This is not
            really necessary for this extension since a file descriptor is
            a small integer which can fit into the EGLint in the
            eglCreateStreamKHR attrib_list.  However, other similar
            extensions may be invented that use other types of handles
            (not file descriptors) which may not fit into an EGLint.
            Creating a dedicated function allows these other extensions to
            use a similar function.
    
            RESOLVED: Use a different function.
    
        5.  How does this extension interact with the
            EGL_NV_stream_cross_process_fd extension?
    
            RESOLVED: These extensions may both exist on the same
            implementation and are functionally equivalent. Mixing and
            matching file descriptors from one extension with functions
            from the other is allowed.
    
        6.  Who should close the file descriptors and when?
    
            There is no way for the EGL implementation to safely close all
            the file descriptors associated with an EGLStream because some
            of them may have been created using OS specific duping
            mechanisms.  Also, the app may need to close a descriptor if
            it runs into an error before it is able to call
            eglCreateStreamFromFileDescriptorKHR.  Therefore the
            application will need to close at least some of the created
            file descriptors.  To make things simple and clear it is
            therefore left up to the app to close all the file
            descriptors.  The app is not *required* to do this, but not
            doing so will "leak" file descriptors which will consume
            resources until the process terminates.
    
            Allowing the app to close all file descriptors as soon as
            eglCreateStreamFromFileDescriptorKHR returns simplifies the
            app (no need to keep track of open file descriptors).
    
            RESOLVED: Application is responsible for closing all file
            descriptors.  They can be safely closed as soon as
            eglCreateStreamFromFileDescriptorKHR returns.
    
        7.  What happens when an invalid file descriptor is passed to
            eglCreateStreamFromFileDescriptorKHR()?
    
            RESOLVED: The implementation must detect this and generate an
            error.  If the file descriptor refers to a file then the
            implementation may not modify the file, change the seek
            location, or otherwise modify the file descriptor.
    
        8.  What happens if one process hangs or crashes?
    
            RESOLVED: If either the consumer's or producer's process
            terminates (normally or abnormally) the EGL implementation
            must notice this and place the EGLStream in
            EGL_STREAM_STATE_DISCONNECTED_KHR state.  If the consumer is
            blocked in a eglStreamConsumerAcquireKHR() call, the call will
            generate an EGL_BAD_STATE_KHR message and return EGL_FALSE.
            If the consumer process has created a reusable sync object with
            eglCreateStreamSyncNV() and is blocking in a
            eglClientWaitSyncKHR() call, the call will block until the
            timeout runs out.
    
            If the producer process "hangs" (e.g. enters an infinite loop,
            blocks in a kernel call, etc) then the consumer process will
            continue to function.  The consumer will continue to use the
            last frame that the producer produced.  If the producer has
            not yet produced a frame then the EGLStream will be in
            EGL_STREAM_STATE_EMPTY_KHR state and no frame will be
            available.  The consumer process can block in some situations:
                - If a EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR is set then
                    eglStreamConsumerAcquireKHR() will block until the
                    timeout runs out (or indefinitely if timeout is
                    negative).
                - eglClientWaitSyncKHR() will block until the timeout runs
                    out.
    
            If the consumer process "hangs" then the producer process will
            continue to function.  If the EGLStream has had
            EGL_STREAM_FIFO_LENGTH_KHR set to a nonzero value then the
            producer will block indefinitely when it fills the fifo and
            tries to insert another frame.  Otherwise the producer will
            not block (as new frames are inserted into the EGLStream old
            ones will be discarded).
    
    Revision History
    
        #8  (June 5, 2012) Acorn Pooley
            - rename from XXX to KHR
    
        #7  (June 5, 2012) Acorn Pooley
            - Add issue 8.
            - Better define EGLStream behavior when a process terminates.
            - Add Interactions with the EGL_NV_stream_sync extension.
    
        #6  (April 20, 2012) Ian Stewart
            - Fix extension/function names in interactions
            - Removed references to NV_stream_sync.
            - Changed interactions with NV_stream_cross_process_fd such
              that they are interchangeable.
    
        #5  (April 18, 2012) Acorn Pooley
            - Add issue 7
            - define errors generated when passing invalid file descriptors
    
        #4  (January 29, 2012) Acorn Pooley
            - Fork EGL_XXX_stream_cross_process_fd.txt from
              EGL_NV_stream_cross_process_fd.txt to make changes suggested
              by working group.
            - add issues 4, 5, and 6.
    
        #3  (January 6, 2012) Acorn Pooley
            - fix typos (EGLImage -> EGLStream)
    
        #2  (December 7, 2011) Acorn Pooley
            - Upload to Khronos for review
    
        #1  (September 27, 2011) Acorn Pooley
            - Initial draft
    
    # vim:ai:ts=4:sts=4:expandtab:textwidth=70
    
    人人超碰97caoporen国产