Blame src/wayland-eglstream-server.c

Packit Service f6fdc3
/*
Packit Service f6fdc3
 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
Packit Service f6fdc3
 *
Packit Service f6fdc3
 * Permission is hereby granted, free of charge, to any person obtaining a
Packit Service f6fdc3
 * copy of this software and associated documentation files (the "Software"),
Packit Service f6fdc3
 * to deal in the Software without restriction, including without limitation
Packit Service f6fdc3
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
Packit Service f6fdc3
 * and/or sell copies of the Software, and to permit persons to whom the
Packit Service f6fdc3
 * Software is furnished to do so, subject to the following conditions:
Packit Service f6fdc3
 *
Packit Service f6fdc3
 * The above copyright notice and this permission notice shall be included in
Packit Service f6fdc3
 * all copies or substantial portions of the Software.
Packit Service f6fdc3
 *
Packit Service f6fdc3
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service f6fdc3
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service f6fdc3
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
Packit Service f6fdc3
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service f6fdc3
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service f6fdc3
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Packit Service f6fdc3
 * DEALINGS IN THE SOFTWARE.
Packit Service f6fdc3
 */
Packit Service f6fdc3
Packit Service f6fdc3
#include <stdio.h>
Packit Service f6fdc3
#include <stdlib.h>
Packit Service f6fdc3
#include <string.h>
Packit Service f6fdc3
#include <stddef.h>
Packit Service f6fdc3
#include <unistd.h>
Packit Service f6fdc3
#include <assert.h>
Packit Service f6fdc3
#include <sys/socket.h>
Packit Service f6fdc3
#include <sys/types.h>
Packit Service f6fdc3
#include <netinet/in.h>
Packit Service f6fdc3
#include <netdb.h>
Packit Service f6fdc3
Packit Service f6fdc3
#include <wayland-server.h>
Packit Service f6fdc3
#include <EGL/egl.h>
Packit Service f6fdc3
#include <EGL/eglext.h>
Packit Service f6fdc3
Packit Service f6fdc3
#include "wayland-eglstream-server.h"
Packit Service f6fdc3
#include "wayland-eglstream-server-protocol.h"
Packit Service f6fdc3
#include "wayland-eglstream.h"
Packit Service f6fdc3
#include "wayland-eglswap.h"
Packit Service f6fdc3
#include "wayland-eglutils.h"
Packit Service 68ab9c
#include "wayland-thread.h"
Packit Service f6fdc3
Packit Service f6fdc3
#define MASK(_VAL_) (1 << (_VAL_))
Packit Service f6fdc3
Packit Service f6fdc3
static struct wl_list wlStreamDpyList = WL_LIST_INIT(&wlStreamDpyList);
Packit Service f6fdc3
Packit Service f6fdc3
static void
Packit Service f6fdc3
destroy_wl_eglstream_resource(struct wl_resource *resource)
Packit Service f6fdc3
{
Packit Service f6fdc3
    struct wl_eglstream *wlStream = wl_resource_get_user_data(resource);
Packit Service f6fdc3
Packit Service f6fdc3
    if (wlStream->handle >= 0) {
Packit Service f6fdc3
        close(wlStream->handle);
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    free(wlStream);
Packit Service f6fdc3
}
Packit Service f6fdc3
Packit Service f6fdc3
static void
Packit Service f6fdc3
destroy_wl_eglstream(struct wl_client *client, struct wl_resource *resource)
Packit Service f6fdc3
{
Packit Service f6fdc3
    (void) client;
Packit Service f6fdc3
    wl_resource_destroy(resource);
Packit Service f6fdc3
}
Packit Service f6fdc3
Packit Service f6fdc3
static void
Packit Service f6fdc3
handle_create_stream(struct wl_client *client,
Packit Service f6fdc3
                     struct wl_resource *resource, uint32_t id,
Packit Service f6fdc3
                     int32_t width, int32_t height,
Packit Service f6fdc3
                     int handle, int handle_type,
Packit Service f6fdc3
                     struct wl_array *attribs)
Packit Service f6fdc3
{
Packit Service f6fdc3
    struct wl_eglstream_display *wlStreamDpy =
Packit Service f6fdc3
        wl_resource_get_user_data(resource);
Packit Service f6fdc3
    struct wl_eglstream *wlStream;
Packit Service f6fdc3
    struct sockaddr_in sockAddr;
Packit Service f6fdc3
    char sockAddrStr[NI_MAXHOST];
Packit Service f6fdc3
    intptr_t *attr;
Packit Service f6fdc3
    int mask = 0;
Packit Service f6fdc3
    enum wl_eglstream_error err;
Packit Service f6fdc3
Packit Service f6fdc3
    wlStream = calloc(1, sizeof *wlStream);
Packit Service f6fdc3
    if (wlStream == NULL) {
Packit Service f6fdc3
        err = WL_EGLSTREAM_ERROR_BAD_ALLOC;
Packit Service f6fdc3
        goto error_create_stream;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    wlStream->wlStreamDpy = wlStreamDpy;
Packit Service f6fdc3
    wlStream->eglStream = EGL_NO_STREAM_KHR;
Packit Service f6fdc3
    wlStream->width = width;
Packit Service f6fdc3
    wlStream->height = height;
Packit Service f6fdc3
    wlStream->handle = -1;
Packit Service f6fdc3
    wlStream->yInverted = EGL_FALSE;
Packit Service f6fdc3
Packit Service f6fdc3
    memset(&sockAddr, 0, sizeof(sockAddr));
Packit Service f6fdc3
Packit Service f6fdc3
    switch (handle_type) {
Packit Service f6fdc3
        case WL_EGLSTREAM_HANDLE_TYPE_FD:
Packit Service f6fdc3
            wlStream->handle = handle;
Packit Service f6fdc3
            wlStream->fromFd = EGL_TRUE;
Packit Service f6fdc3
            break;
Packit Service f6fdc3
Packit Service f6fdc3
        case WL_EGLSTREAM_HANDLE_TYPE_INET:
Packit Service f6fdc3
            sockAddr.sin_family = AF_INET;
Packit Service f6fdc3
            wlStream->isInet    = EGL_TRUE;
Packit Service f6fdc3
            /* Close the given dummy fd */
Packit Service f6fdc3
            close(handle);
Packit Service f6fdc3
            break;
Packit Service f6fdc3
Packit Service f6fdc3
        case WL_EGLSTREAM_HANDLE_TYPE_SOCKET:
Packit Service f6fdc3
            wlStream->handle = handle;
Packit Service f6fdc3
            break;
Packit Service f6fdc3
Packit Service f6fdc3
        default:
Packit Service f6fdc3
            err = WL_EGLSTREAM_ERROR_BAD_HANDLE;
Packit Service f6fdc3
            goto error_create_stream;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    wl_array_for_each(attr, attribs) {
Packit Service f6fdc3
        switch (attr[0]) {
Packit Service f6fdc3
            case WL_EGLSTREAM_ATTRIB_INET_ADDR:
Packit Service f6fdc3
                /* INET_ADDR should only be set once */
Packit Service f6fdc3
                if (mask & MASK(WL_EGLSTREAM_ATTRIB_INET_ADDR)) {
Packit Service f6fdc3
                    err = WL_EGLSTREAM_ERROR_BAD_ATTRIBS;
Packit Service f6fdc3
                    goto error_create_stream;
Packit Service f6fdc3
                }
Packit Service f6fdc3
                sockAddr.sin_addr.s_addr = htonl((int)attr[1]);
Packit Service f6fdc3
                mask |= MASK(WL_EGLSTREAM_ATTRIB_INET_ADDR);
Packit Service f6fdc3
                break;
Packit Service f6fdc3
Packit Service f6fdc3
            case WL_EGLSTREAM_ATTRIB_INET_PORT:
Packit Service f6fdc3
                /* INET_PORT should only be set once */
Packit Service f6fdc3
                if (mask & MASK(WL_EGLSTREAM_ATTRIB_INET_PORT)) {
Packit Service f6fdc3
                    err = WL_EGLSTREAM_ERROR_BAD_ATTRIBS;
Packit Service f6fdc3
                    goto error_create_stream;
Packit Service f6fdc3
                }
Packit Service f6fdc3
                sockAddr.sin_port = htons((int)attr[1]);
Packit Service f6fdc3
                mask |= MASK(WL_EGLSTREAM_ATTRIB_INET_PORT);
Packit Service f6fdc3
                break;
Packit Service f6fdc3
Packit Service f6fdc3
            case WL_EGLSTREAM_ATTRIB_Y_INVERTED:
Packit Service f6fdc3
                /* Y_INVERTED should only be set once */
Packit Service f6fdc3
                if (mask & MASK(WL_EGLSTREAM_ATTRIB_Y_INVERTED)) {
Packit Service f6fdc3
                    err = WL_EGLSTREAM_ERROR_BAD_ATTRIBS;
Packit Service f6fdc3
                    goto error_create_stream;
Packit Service f6fdc3
                }
Packit Service f6fdc3
                wlStream->yInverted = (EGLBoolean)attr[1];
Packit Service f6fdc3
                mask |= MASK(WL_EGLSTREAM_ATTRIB_Y_INVERTED);
Packit Service f6fdc3
                break;
Packit Service f6fdc3
Packit Service f6fdc3
            default:
Packit Service f6fdc3
                assert(!"Unknown attribute");
Packit Service f6fdc3
                break;
Packit Service f6fdc3
        }
Packit Service f6fdc3
Packit Service f6fdc3
        /* Attribs processed in pairs */
Packit Service f6fdc3
        attr++;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    if (wlStream->isInet) {
Packit Service f6fdc3
        /* Both address and port should have been set */
Packit Service f6fdc3
        if (mask != (MASK(WL_EGLSTREAM_ATTRIB_INET_ADDR) |
Packit Service f6fdc3
                     MASK(WL_EGLSTREAM_ATTRIB_INET_PORT))) {
Packit Service f6fdc3
            err = WL_EGLSTREAM_ERROR_BAD_ATTRIBS;
Packit Service f6fdc3
            goto error_create_stream;
Packit Service f6fdc3
        }
Packit Service f6fdc3
Packit Service f6fdc3
        wlStream->handle = socket(AF_INET, SOCK_STREAM, 0);
Packit Service f6fdc3
        if (wlStream->handle == -1) {
Packit Service f6fdc3
            err = WL_EGLSTREAM_ERROR_BAD_ALLOC;
Packit Service f6fdc3
            goto error_create_stream;
Packit Service f6fdc3
        }
Packit Service f6fdc3
Packit Service f6fdc3
        if (connect(wlStream->handle,
Packit Service f6fdc3
                    (struct sockaddr *)&sockAddr,
Packit Service f6fdc3
                    sizeof(sockAddr)) < 0) {
Packit Service f6fdc3
            err = WL_EGLSTREAM_ERROR_BAD_ADDRESS;
Packit Service f6fdc3
            goto error_create_stream;
Packit Service f6fdc3
        }
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    wlStream->resource =
Packit Service f6fdc3
        wl_resource_create(client, &wl_buffer_interface, 1, id);
Packit Service f6fdc3
    if (!wlStream->resource) {
Packit Service f6fdc3
        err = WL_EGLSTREAM_ERROR_BAD_ALLOC;
Packit Service f6fdc3
        goto error_create_stream;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    wl_resource_set_implementation(
Packit Service f6fdc3
                        wlStream->resource,
Packit Service f6fdc3
                        (void (**)(void))&wlStreamDpy->wl_eglstream_interface,
Packit Service f6fdc3
                        wlStream,
Packit Service f6fdc3
                        destroy_wl_eglstream_resource);
Packit Service f6fdc3
    return;
Packit Service f6fdc3
Packit Service f6fdc3
error_create_stream:
Packit Service f6fdc3
    switch (err) {
Packit Service f6fdc3
        case WL_EGLSTREAM_ERROR_BAD_ALLOC:
Packit Service f6fdc3
            wl_resource_post_no_memory(resource);
Packit Service f6fdc3
            break;
Packit Service f6fdc3
        case WL_EGLSTREAM_ERROR_BAD_HANDLE:
Packit Service f6fdc3
            wl_resource_post_error(resource, err, "Invalid or unknown handle");
Packit Service f6fdc3
            break;
Packit Service f6fdc3
        case WL_EGLSTREAM_ERROR_BAD_ATTRIBS:
Packit Service f6fdc3
            wl_resource_post_error(resource, err, "Malformed attributes list");
Packit Service f6fdc3
            break;
Packit Service f6fdc3
        case WL_EGLSTREAM_ERROR_BAD_ADDRESS:
Packit Service f6fdc3
            wl_resource_post_error(resource, err, "Unable to connect to %s:%d.",
Packit Service f6fdc3
                                   (getnameinfo((struct sockaddr *)&sockAddr,
Packit Service f6fdc3
                                                sizeof(sockAddr),
Packit Service f6fdc3
                                                sockAddrStr, NI_MAXHOST,
Packit Service f6fdc3
                                                NULL, 0,
Packit Service f6fdc3
                                                NI_NUMERICHOST) ?
Packit Service f6fdc3
                                    "<invalid IP>" : sockAddrStr),
Packit Service f6fdc3
                                   ntohs(sockAddr.sin_port));
Packit Service f6fdc3
            break;
Packit Service f6fdc3
        default:
Packit Service f6fdc3
            assert(!"Unknown error code");
Packit Service f6fdc3
            break;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    if (wlStream) {
Packit Service f6fdc3
        if (wlStream->isInet && wlStream->handle >= 0) {
Packit Service f6fdc3
            close(wlStream->handle);
Packit Service f6fdc3
        }
Packit Service f6fdc3
        free(wlStream);
Packit Service f6fdc3
    }
Packit Service f6fdc3
}
Packit Service f6fdc3
Packit Service f6fdc3
static void
Packit Service f6fdc3
handle_swap_interval(struct wl_client *client,
Packit Service f6fdc3
                     struct wl_resource *displayResource,
Packit Service f6fdc3
                     struct wl_resource *streamResource,
Packit Service f6fdc3
                     int interval)
Packit Service f6fdc3
{
Packit Service f6fdc3
    struct wl_eglstream_display *wlStreamDpy =
Packit Service f6fdc3
        wl_resource_get_user_data(displayResource);
Packit Service f6fdc3
    struct wl_eglstream *wlStream =
Packit Service f6fdc3
        wl_eglstream_display_get_stream(wlStreamDpy, streamResource);
Packit Service f6fdc3
    (void) client;
Packit Service f6fdc3
Packit Service f6fdc3
    if (wlEglStreamSwapIntervalCallback(wlStreamDpy->data,
Packit Service f6fdc3
                                        wlStream->eglStream,
Packit Service f6fdc3
                                        &interval) == EGL_BAD_MATCH) {
Packit Service f6fdc3
        wl_eglstream_display_send_swapinterval_override(displayResource,
Packit Service f6fdc3
                                                        interval,
Packit Service f6fdc3
                                                        streamResource);
Packit Service f6fdc3
    }
Packit Service f6fdc3
}
Packit Service f6fdc3
Packit Service f6fdc3
static const struct wl_eglstream_display_interface
Packit Service f6fdc3
wl_eglstream_display_interface_impl = {
Packit Service f6fdc3
    handle_create_stream,
Packit Service f6fdc3
    handle_swap_interval,
Packit Service f6fdc3
};
Packit Service f6fdc3
Packit Service f6fdc3
static void
Packit Service f6fdc3
wl_eglstream_display_global_bind(struct wl_client *client,
Packit Service f6fdc3
                                 void *data,
Packit Service f6fdc3
                                 uint32_t version,
Packit Service f6fdc3
                                 uint32_t id)
Packit Service f6fdc3
{
Packit Service f6fdc3
    struct wl_eglstream_display *wlStreamDpy  = NULL;
Packit Service f6fdc3
    struct wl_resource          *resource     = NULL;
Packit Service f6fdc3
Packit Service f6fdc3
    wlStreamDpy = (struct wl_eglstream_display *)data;
Packit Service f6fdc3
    resource    = wl_resource_create(client,
Packit Service f6fdc3
                                     &wl_eglstream_display_interface,
Packit Service f6fdc3
                                     version,
Packit Service f6fdc3
                                     id);
Packit Service f6fdc3
    if (!resource) {
Packit Service f6fdc3
        wl_client_post_no_memory(client);
Packit Service f6fdc3
        return;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    wl_resource_set_implementation(resource,
Packit Service f6fdc3
                                   &wl_eglstream_display_interface_impl,
Packit Service f6fdc3
                                   data,
Packit Service f6fdc3
                                   NULL);
Packit Service f6fdc3
Packit Service f6fdc3
Packit Service f6fdc3
    wl_eglstream_display_send_caps(resource, wlStreamDpy->supported_caps);
Packit Service f6fdc3
}
Packit Service f6fdc3
Packit Service f6fdc3
EGLBoolean
Packit Service f6fdc3
wl_eglstream_display_bind(WlEglPlatformData *data,
Packit Service f6fdc3
                          struct wl_display *wlDisplay,
Packit Service f6fdc3
                          EGLDisplay eglDisplay)
Packit Service f6fdc3
{
Packit Service f6fdc3
    struct wl_eglstream_display *wlStreamDpy = NULL;
Packit Service f6fdc3
    const char                  *exts        = NULL;
Packit Service f6fdc3
    char                        *env         = NULL;
Packit Service f6fdc3
Packit Service f6fdc3
    /* Check whether there's an EGLDisplay already bound to the given
Packit Service f6fdc3
     * wl_display */
Packit Service f6fdc3
    if (wl_eglstream_display_get(eglDisplay) != NULL) {
Packit Service f6fdc3
        return EGL_FALSE;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    wlStreamDpy = calloc(1, sizeof(*wlStreamDpy));
Packit Service f6fdc3
    if (!wlStreamDpy) {
Packit Service f6fdc3
        return EGL_FALSE;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    wlStreamDpy->data          = data;
Packit Service f6fdc3
    wlStreamDpy->wlDisplay     = wlDisplay;
Packit Service f6fdc3
    wlStreamDpy->eglDisplay    = eglDisplay;
Packit Service f6fdc3
    wlStreamDpy->caps_override = 0;
Packit Service f6fdc3
Packit Service 4e1167
    wlExternalApiUnlock();
Packit Service f6fdc3
    exts = data->egl.queryString(eglDisplay, EGL_EXTENSIONS);
Packit Service 4e1167
    wlExternalApiLock();
Packit Service f6fdc3
Packit Service f6fdc3
#define CACHE_EXT(_PREFIX_, _NAME_)                                      \
Packit Service f6fdc3
        wlStreamDpy->exts._NAME_ =                                       \
Packit Service f6fdc3
            !!wlEglFindExtension("EGL_" #_PREFIX_ "_" #_NAME_, exts)
Packit Service f6fdc3
Packit Service f6fdc3
    CACHE_EXT(NV,  stream_attrib);
Packit Service f6fdc3
    CACHE_EXT(KHR, stream_cross_process_fd);
Packit Service f6fdc3
    CACHE_EXT(NV,  stream_remote);
Packit Service f6fdc3
    CACHE_EXT(NV,  stream_socket);
Packit Service f6fdc3
    CACHE_EXT(NV,  stream_socket_inet);
Packit Service f6fdc3
    CACHE_EXT(NV,  stream_socket_unix);
Packit Service f6fdc3
    CACHE_EXT(NV,  stream_origin);
Packit Service f6fdc3
Packit Service f6fdc3
#undef CACHE_EXT
Packit Service f6fdc3
Packit Service f6fdc3
    /* Advertise server capabilities */
Packit Service f6fdc3
    if (wlStreamDpy->exts.stream_cross_process_fd) {
Packit Service f6fdc3
        wlStreamDpy->supported_caps |= WL_EGLSTREAM_DISPLAY_CAP_STREAM_FD;
Packit Service f6fdc3
    }
Packit Service f6fdc3
    if (wlStreamDpy->exts.stream_attrib &&
Packit Service f6fdc3
        wlStreamDpy->exts.stream_remote &&
Packit Service f6fdc3
        wlStreamDpy->exts.stream_socket) {
Packit Service f6fdc3
        if (wlStreamDpy->exts.stream_socket_inet) {
Packit Service f6fdc3
            wlStreamDpy->supported_caps |= WL_EGLSTREAM_DISPLAY_CAP_STREAM_INET;
Packit Service f6fdc3
        }
Packit Service f6fdc3
        if (wlStreamDpy->exts.stream_socket_unix) {
Packit Service f6fdc3
            wlStreamDpy->supported_caps |= WL_EGLSTREAM_DISPLAY_CAP_STREAM_SOCKET;
Packit Service f6fdc3
        }
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    env = getenv("WL_EGLSTREAM_CAP_OVERRIDE");
Packit Service f6fdc3
    if (env) {
Packit Service f6fdc3
        int serverCapOverride = atoi(env);
Packit Service f6fdc3
        wlStreamDpy->caps_override = (wlStreamDpy->supported_caps
Packit Service f6fdc3
                                      & serverCapOverride) !=
Packit Service f6fdc3
                                      wlStreamDpy->supported_caps;
Packit Service f6fdc3
        wlStreamDpy->supported_caps &= serverCapOverride;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    wlStreamDpy->wl_eglstream_interface.destroy = destroy_wl_eglstream;
Packit Service f6fdc3
    wlStreamDpy->global = wl_global_create(wlDisplay,
Packit Service f6fdc3
                                           &wl_eglstream_display_interface, 1,
Packit Service f6fdc3
                                           wlStreamDpy,
Packit Service f6fdc3
                                           wl_eglstream_display_global_bind);
Packit Service f6fdc3
Packit Service f6fdc3
    wl_list_insert(&wlStreamDpyList, &wlStreamDpy->link);
Packit Service f6fdc3
Packit Service f6fdc3
    return EGL_TRUE;
Packit Service f6fdc3
}
Packit Service f6fdc3
Packit Service f6fdc3
void
Packit Service f6fdc3
wl_eglstream_display_unbind(struct wl_eglstream_display *wlStreamDpy)
Packit Service f6fdc3
{
Packit Service f6fdc3
    wl_global_destroy(wlStreamDpy->global);
Packit Service f6fdc3
    wl_list_remove(&wlStreamDpy->link);
Packit Service f6fdc3
    free(wlStreamDpy);
Packit Service f6fdc3
}
Packit Service f6fdc3
Packit Service f6fdc3
struct wl_eglstream_display* wl_eglstream_display_get(EGLDisplay eglDisplay)
Packit Service f6fdc3
{
Packit Service f6fdc3
    struct wl_eglstream_display *wlDisplay;
Packit Service f6fdc3
Packit Service f6fdc3
    wl_list_for_each(wlDisplay, &wlStreamDpyList, link) {
Packit Service f6fdc3
        if (wlDisplay->eglDisplay == eglDisplay) {
Packit Service f6fdc3
            return wlDisplay;
Packit Service f6fdc3
        }
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    return NULL;
Packit Service f6fdc3
}
Packit Service f6fdc3
Packit Service f6fdc3
struct wl_eglstream*
Packit Service f6fdc3
wl_eglstream_display_get_stream(struct wl_eglstream_display *wlStreamDpy,
Packit Service f6fdc3
                                struct wl_resource *resource)
Packit Service f6fdc3
{
Packit Service f6fdc3
    if (resource == NULL) {
Packit Service f6fdc3
        return NULL;
Packit Service f6fdc3
    }
Packit Service f6fdc3
Packit Service f6fdc3
    if (wl_resource_instance_of(resource, &wl_buffer_interface,
Packit Service f6fdc3
                                &wlStreamDpy->wl_eglstream_interface)) {
Packit Service f6fdc3
        return wl_resource_get_user_data(resource);
Packit Service f6fdc3
    } else {
Packit Service f6fdc3
        return NULL;
Packit Service f6fdc3
    }
Packit Service f6fdc3
}
Packit Service f6fdc3