• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef IN_LIBVA
28 # include "va/wayland/va_wayland.h"
29 #else
30 # include <va/va_wayland.h>
31 #endif
32 #include "va_display.h"
33 
34 struct display {
35     struct wl_display          *display;
36     struct wl_registry         *registry;
37     struct wl_compositor       *compositor;
38     struct wl_shell            *shell;
39     struct wl_shell_surface    *shell_surface;
40     struct wl_surface          *surface;
41     unsigned int                ref_count;
42     int                         event_fd;
43 };
44 
45 static struct display *g_display;
46 
47 static void
registry_handle_global(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)48 registry_handle_global(
49     void               *data,
50     struct wl_registry *registry,
51     uint32_t            id,
52     const char         *interface,
53     uint32_t            version
54 )
55 {
56     struct display * const d = data;
57 
58     if (strcmp(interface, "wl_compositor") == 0)
59         d->compositor =
60             wl_registry_bind(registry, id, &wl_compositor_interface, 1);
61     else if (strcmp(interface, "wl_shell") == 0)
62         d->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1);
63 }
64 
65 static const struct wl_registry_listener registry_listener = {
66     registry_handle_global,
67     NULL,
68 };
69 
70 static VADisplay
va_open_display_wayland(void)71 va_open_display_wayland(void)
72 {
73     struct display *d;
74 
75     if (g_display) {
76         d = g_display;
77         d->ref_count++;
78     } else {
79         d = calloc(1, sizeof(*d));
80         if (!d)
81             return NULL;
82         d->event_fd = -1;
83 
84         d->display = wl_display_connect(NULL);
85         if (!d->display) {
86             free(d);
87             return NULL;
88         }
89         wl_display_set_user_data(d->display, d);
90         d->registry = wl_display_get_registry(d->display);
91         wl_registry_add_listener(d->registry, &registry_listener, d);
92         d->event_fd = wl_display_get_fd(d->display);
93         wl_display_dispatch(d->display);
94 
95         d->ref_count = 1;
96         g_display = d;
97     }
98     return vaGetDisplayWl(d->display);
99 }
100 
101 static void
va_close_display_wayland(VADisplay va_dpy)102 va_close_display_wayland(VADisplay va_dpy)
103 {
104     struct display * const d = g_display;
105 
106     if (!d || --d->ref_count > 0)
107         return;
108 
109     if (d->surface) {
110         wl_surface_destroy(d->surface);
111         d->surface = NULL;
112     }
113 
114     if (d->shell_surface) {
115         wl_shell_surface_destroy(d->shell_surface);
116         d->shell_surface = NULL;
117     }
118 
119     if (d->shell) {
120         wl_shell_destroy(d->shell);
121         d->shell = NULL;
122     }
123 
124     if (d->compositor) {
125         wl_compositor_destroy(d->compositor);
126         d->compositor = NULL;
127     }
128 
129     if (d->registry) {
130         wl_registry_destroy(d->registry);
131         d->registry = NULL;
132     }
133 
134     if (d->display) {
135         wl_display_disconnect(d->display);
136         d->display = NULL;
137     }
138     free(g_display);
139     g_display = NULL;
140 }
141 
142 static int
ensure_window(VADisplay va_dpy,unsigned int width,unsigned int height)143 ensure_window(VADisplay va_dpy, unsigned int width, unsigned int height)
144 {
145     struct display * const d = g_display;
146 
147     if (!d->surface) {
148         d->surface = wl_compositor_create_surface(d->compositor);
149         if (!d->surface)
150             return 0;
151     }
152 
153     if (!d->shell_surface) {
154         d->shell_surface = wl_shell_get_shell_surface(d->shell, d->surface);
155         if (!d->shell_surface)
156             return 0;
157         wl_shell_surface_set_toplevel(d->shell_surface);
158     }
159     return 1;
160 }
161 
162 static VAStatus
va_put_surface_wayland(VADisplay va_dpy,VASurfaceID surface,const VARectangle * src_rect,const VARectangle * dst_rect)163 va_put_surface_wayland(
164     VADisplay          va_dpy,
165     VASurfaceID        surface,
166     const VARectangle *src_rect,
167     const VARectangle *dst_rect
168 )
169 {
170     struct display * const d = g_display;
171     VAStatus va_status;
172     struct wl_buffer *buffer;
173 
174     if (!ensure_window(va_dpy, dst_rect->width, dst_rect->height))
175         return VA_STATUS_ERROR_ALLOCATION_FAILED;
176 
177     va_status = vaGetSurfaceBufferWl(va_dpy, surface, VA_FRAME_PICTURE, &buffer);
178     if (va_status != VA_STATUS_SUCCESS)
179         return va_status;
180 
181     wl_surface_attach(d->surface, buffer, 0, 0);
182     wl_surface_damage(
183         d->surface,
184         dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height
185     );
186 
187     wl_surface_commit(d->surface);
188     wl_display_flush(d->display);
189     return VA_STATUS_SUCCESS;
190 }
191 
192 const VADisplayHooks va_display_hooks_wayland = {
193     "wayland",
194     va_open_display_wayland,
195     va_close_display_wayland,
196     va_put_surface_wayland,
197 };
198