1/*
2 * va_wayland.c - Wayland API
3 *
4 * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27#include "sysdeps.h"
28#include <stdarg.h>
29#include "va_wayland.h"
30#include "va_wayland_drm.h"
31#include "va_wayland_emgd.h"
32#include "va_wayland_private.h"
33#include "va_backend.h"
34#include "va_backend_wayland.h"
35
36static inline VADriverContextP
37get_driver_context(VADisplay dpy)
38{
39    if (!vaDisplayIsValid(dpy))
40        return NULL;
41    return ((VADisplayContextP)dpy)->pDriverContext;
42}
43
44void
45va_wayland_error(const char *format, ...)
46{
47    va_list args;
48
49    va_start(args, format);
50    fprintf(stderr, "VA error: wayland: ");
51    vfprintf(stderr, format, args);
52    fprintf(stderr, "\n");
53    va_end(args);
54}
55
56static int
57va_DisplayContextIsValid(VADisplayContextP pDisplayContext)
58{
59    VADriverContextP const pDriverContext = pDisplayContext->pDriverContext;
60
61    return (pDriverContext &&
62            pDriverContext->display_type == VA_DISPLAY_WAYLAND);
63}
64
65static void
66va_DisplayContextDestroy(VADisplayContextP pDisplayContext)
67{
68    VADriverContextP pDriverContext;
69    VADisplayContextWaylandP pDisplayContextWl;
70
71    if (!pDisplayContext)
72        return;
73
74    pDisplayContextWl = pDisplayContext->opaque;
75    if (pDisplayContextWl && pDisplayContextWl->destroy)
76        pDisplayContextWl->destroy(pDisplayContext);
77
78    pDriverContext = pDisplayContext->pDriverContext;
79    if (pDriverContext) {
80        free(pDriverContext->vtable_wayland);
81        pDriverContext->vtable_wayland = NULL;
82        free(pDriverContext);
83        pDisplayContext->pDriverContext = NULL;
84    }
85
86    free(pDisplayContext->opaque);
87    pDisplayContext->opaque = NULL;
88    free(pDisplayContext);
89}
90
91static VAStatus
92va_DisplayContextGetDriverName(VADisplayContextP pDisplayContext, char **name)
93{
94    *name = NULL;
95    return VA_STATUS_ERROR_UNKNOWN;
96}
97
98/* -------------------------------------------------------------------------- */
99/* --- Public interface                                                   --- */
100/* -------------------------------------------------------------------------- */
101
102struct va_wayland_backend {
103    VADisplayContextCreateFunc  create;
104    VADisplayContextDestroyFunc destroy;
105};
106
107static const struct va_wayland_backend g_backends[] = {
108    { va_wayland_drm_create,
109      va_wayland_drm_destroy },
110    { va_wayland_emgd_create,
111      va_wayland_emgd_destroy },
112    { NULL, }
113};
114
115VADisplay
116vaGetDisplayWl(struct wl_display *display)
117{
118    VADisplayContextP pDisplayContext = NULL;
119    VADriverContextP pDriverContext;
120    struct VADriverVTableWayland *vtable;
121    unsigned int i;
122
123    pDisplayContext = calloc(1, sizeof(*pDisplayContext));
124    if (!pDisplayContext)
125        return NULL;
126
127    pDisplayContext->vadpy_magic        = VA_DISPLAY_MAGIC;
128    pDisplayContext->vaIsValid          = va_DisplayContextIsValid;
129    pDisplayContext->vaDestroy          = va_DisplayContextDestroy;
130    pDisplayContext->vaGetDriverName    = va_DisplayContextGetDriverName;
131
132    pDriverContext = calloc(1, sizeof(*pDriverContext));
133    if (!pDriverContext)
134        goto error;
135    pDisplayContext->pDriverContext     = pDriverContext;
136
137    pDriverContext->native_dpy          = display;
138    pDriverContext->display_type        = VA_DISPLAY_WAYLAND;
139
140    vtable = calloc(1, sizeof(*vtable));
141    if (!vtable)
142        goto error;
143    pDriverContext->vtable_wayland      = vtable;
144
145    vtable->version                     = VA_WAYLAND_API_VERSION;
146
147    for (i = 0; g_backends[i].create != NULL; i++) {
148        if (g_backends[i].create(pDisplayContext))
149            break;
150        g_backends[i].destroy(pDisplayContext);
151    }
152
153    return (VADisplay)pDisplayContext;
154
155error:
156    va_DisplayContextDestroy(pDisplayContext);
157    return NULL;
158}
159
160VAStatus
161vaGetSurfaceBufferWl(
162    VADisplay           dpy,
163    VASurfaceID         surface,
164    unsigned int        flags,
165    struct wl_buffer  **out_buffer
166)
167{
168    VADriverContextP const ctx = get_driver_context(dpy);
169
170    if (!ctx)
171        return VA_STATUS_ERROR_INVALID_DISPLAY;
172    if (!ctx->vtable_wayland || !ctx->vtable_wayland->vaGetSurfaceBufferWl)
173        return VA_STATUS_ERROR_UNIMPLEMENTED;
174    return ctx->vtable_wayland->vaGetSurfaceBufferWl(ctx, surface, flags,
175                                                     out_buffer);
176}
177
178VAStatus
179vaGetImageBufferWl(
180    VADisplay           dpy,
181    VAImageID           image,
182    unsigned int        flags,
183    struct wl_buffer  **out_buffer
184)
185{
186    VADriverContextP const ctx = get_driver_context(dpy);
187
188    if (!ctx)
189        return VA_STATUS_ERROR_INVALID_DISPLAY;
190    if (!ctx->vtable_wayland || !ctx->vtable_wayland->vaGetImageBufferWl)
191        return VA_STATUS_ERROR_UNIMPLEMENTED;
192    return ctx->vtable_wayland->vaGetImageBufferWl(ctx, image, flags,
193                                                   out_buffer);
194}
195