2 * Copyright (C) 2012 Intel Corporation. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
28 #include <va/va_backend.h>
29 #include <va/va_backend_wayland.h>
30 #include <wayland-client.h>
31 #include <wayland-drm-client-protocol.h>
32 #include "intel_driver.h"
33 #include "i965_output_wayland.h"
34 #include "i965_drv_video.h"
35 #include "i965_defines.h"
36 #include "dso_utils.h"
38 #define LIBEGL_NAME "libEGL.so.1"
39 #define LIBWAYLAND_CLIENT_NAME "libwayland-client.so.0"
41 typedef uint32_t (*wl_display_get_global_func)(struct wl_display *display,
42 const char *interface, uint32_t version);
43 typedef void (*wl_display_roundtrip_func)(struct wl_display *display);
45 typedef struct wl_proxy *(*wl_proxy_create_func)(struct wl_proxy *factory,
46 const struct wl_interface *interface);
47 typedef void (*wl_proxy_destroy_func)(struct wl_proxy *proxy);
48 typedef void (*wl_proxy_marshal_func)(struct wl_proxy *p, uint32_t opcode, ...);
49 typedef int (*wl_proxy_add_listener_func) (struct wl_proxy *proxy,
50 void (**implementation)(void), void *data);
53 const struct wl_interface *buffer_interface;
54 const struct wl_interface *drm_interface;
55 const struct wl_interface *registry_interface;
56 wl_display_roundtrip_func display_roundtrip;
57 wl_proxy_create_func proxy_create;
58 wl_proxy_destroy_func proxy_destroy;
59 wl_proxy_marshal_func proxy_marshal;
60 wl_proxy_add_listener_func proxy_add_listener;
64 struct dso_handle *libegl_handle;
65 struct dso_handle *libwl_client_handle;
66 struct wl_vtable vtable;
67 struct wl_drm *wl_drm;
68 struct wl_registry *wl_registry;
71 /* These function are copied and adapted from the version inside
72 * wayland-client-protocol.h
76 struct wl_vtable *wl_vtable,
77 struct wl_registry *wl_registry,
79 const struct wl_interface *interface,
85 id = wl_vtable->proxy_create((struct wl_proxy *) wl_registry,
90 wl_vtable->proxy_marshal((struct wl_proxy *) wl_registry,
91 WL_REGISTRY_BIND, name, interface->name,
97 static struct wl_registry *
99 struct wl_vtable *wl_vtable,
100 struct wl_display *wl_display
103 struct wl_proxy *callback;
105 callback = wl_vtable->proxy_create((struct wl_proxy *) wl_display,
106 wl_vtable->registry_interface);
110 wl_vtable->proxy_marshal((struct wl_proxy *) wl_display,
111 WL_DISPLAY_GET_REGISTRY, callback);
113 return (struct wl_registry *) callback;
117 registry_add_listener(
118 struct wl_vtable *wl_vtable,
119 struct wl_registry *wl_registry,
120 const struct wl_registry_listener *listener,
124 return wl_vtable->proxy_add_listener((struct wl_proxy *) wl_registry,
125 (void (**)(void)) listener, data);
129 registry_handle_global(
131 struct wl_registry *registry,
133 const char *interface,
137 VADriverContextP ctx = data;
138 struct i965_driver_data * const i965 = i965_driver_data(ctx);
139 struct va_wl_output * const wl_output = i965->wl_output;
140 struct wl_vtable * const wl_vtable = &wl_output->vtable;
142 if (strcmp(interface, "wl_drm") == 0) {
143 wl_output->wl_drm = registry_bind(wl_vtable, wl_output->wl_registry,
144 id, wl_vtable->drm_interface, 1);
148 static const struct wl_registry_listener registry_listener = {
149 registry_handle_global,
153 /* Ensure wl_drm instance is created */
155 ensure_wl_output(VADriverContextP ctx)
157 struct i965_driver_data * const i965 = i965_driver_data(ctx);
158 struct va_wl_output * const wl_output = i965->wl_output;
159 struct wl_vtable * const wl_vtable = &wl_output->vtable;
161 if (wl_output->wl_drm)
164 wl_output->wl_registry = display_get_registry(wl_vtable, ctx->native_dpy);
165 registry_add_listener(wl_vtable, wl_output->wl_registry,
166 ®istry_listener, ctx);
167 wl_vtable->display_roundtrip(ctx->native_dpy);
168 if (!wl_output->wl_drm)
173 /* Create planar YUV buffer */
174 static struct wl_buffer *
175 create_planar_buffer(
176 struct va_wl_output *wl_output,
185 struct wl_vtable * const wl_vtable = &wl_output->vtable;
188 id = wl_vtable->proxy_create(
189 (struct wl_proxy *)wl_output->wl_drm,
190 wl_vtable->buffer_interface
195 wl_vtable->proxy_marshal(
196 (struct wl_proxy *)wl_output->wl_drm,
197 WL_DRM_CREATE_PLANAR_BUFFER,
200 width, height, format,
201 offsets[0], pitches[0],
202 offsets[1], pitches[1],
203 offsets[2], pitches[2]
205 return (struct wl_buffer *)id;
208 /* Hook to return Wayland buffer associated with the VA surface */
210 va_GetSurfaceBufferWl(
211 struct VADriverContext *ctx,
214 struct wl_buffer **out_buffer
217 struct i965_driver_data * const i965 = i965_driver_data(ctx);
218 struct object_surface *obj_surface;
219 struct wl_buffer *buffer;
220 uint32_t name, drm_format;
221 int offsets[3], pitches[3];
223 obj_surface = SURFACE(surface);
225 return VA_STATUS_ERROR_INVALID_SURFACE;
227 if (flags != VA_FRAME_PICTURE)
228 return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
231 return VA_STATUS_ERROR_INVALID_PARAMETER;
233 if (!ensure_wl_output(ctx))
234 return VA_STATUS_ERROR_INVALID_DISPLAY;
236 if (drm_intel_bo_flink(obj_surface->bo, &name) != 0)
237 return VA_STATUS_ERROR_INVALID_SURFACE;
239 switch (obj_surface->fourcc) {
240 case VA_FOURCC('N','V','1','2'):
241 drm_format = WL_DRM_FORMAT_NV12;
243 pitches[0] = obj_surface->width;
244 offsets[1] = obj_surface->width * obj_surface->y_cb_offset;
245 pitches[1] = obj_surface->cb_cr_pitch;
249 case VA_FOURCC('Y','V','1','2'):
250 case VA_FOURCC('I','4','2','0'):
251 case VA_FOURCC('I','M','C','1'):
252 switch (obj_surface->subsampling) {
253 case SUBSAMPLE_YUV411:
254 drm_format = WL_DRM_FORMAT_YUV411;
256 case SUBSAMPLE_YUV420:
257 drm_format = WL_DRM_FORMAT_YUV420;
259 case SUBSAMPLE_YUV422H:
260 case SUBSAMPLE_YUV422V:
261 drm_format = WL_DRM_FORMAT_YUV422;
263 case SUBSAMPLE_YUV444:
264 drm_format = WL_DRM_FORMAT_YUV444;
267 assert(0 && "unsupported subsampling");
268 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
271 pitches[0] = obj_surface->width;
272 offsets[1] = obj_surface->width * obj_surface->y_cb_offset;
273 pitches[1] = obj_surface->cb_cr_pitch;
274 offsets[2] = obj_surface->width * obj_surface->y_cr_offset;
275 pitches[2] = obj_surface->cb_cr_pitch;
278 assert(0 && "unsupported format");
279 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
282 buffer = create_planar_buffer(
285 obj_surface->orig_width,
286 obj_surface->orig_height,
292 return VA_STATUS_ERROR_ALLOCATION_FAILED;
294 *out_buffer = buffer;
295 return VA_STATUS_SUCCESS;
298 /* Hook to return Wayland buffer associated with the VA image */
301 struct VADriverContext *ctx,
304 struct wl_buffer **out_buffer
307 return VA_STATUS_ERROR_UNIMPLEMENTED;
311 ensure_driver_vtable(VADriverContextP ctx)
313 struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
318 vtable->vaGetSurfaceBufferWl = va_GetSurfaceBufferWl;
319 vtable->vaGetImageBufferWl = va_GetImageBufferWl;
324 i965_output_wayland_init(VADriverContextP ctx)
326 struct i965_driver_data * const i965 = i965_driver_data(ctx);
327 struct dso_handle *dso_handle;
328 struct wl_vtable *wl_vtable;
330 static const struct dso_symbol libegl_symbols[] = {
331 { "wl_drm_interface",
332 offsetof(struct wl_vtable, drm_interface) },
336 static const struct dso_symbol libwl_client_symbols[] = {
337 { "wl_buffer_interface",
338 offsetof(struct wl_vtable, buffer_interface) },
339 { "wl_registry_interface",
340 offsetof(struct wl_vtable, registry_interface) },
341 { "wl_display_roundtrip",
342 offsetof(struct wl_vtable, display_roundtrip) },
344 offsetof(struct wl_vtable, proxy_create) },
345 { "wl_proxy_destroy",
346 offsetof(struct wl_vtable, proxy_destroy) },
347 { "wl_proxy_marshal",
348 offsetof(struct wl_vtable, proxy_marshal) },
349 { "wl_proxy_add_listener",
350 offsetof(struct wl_vtable, proxy_add_listener) },
354 if (ctx->display_type != VA_DISPLAY_WAYLAND)
357 i965->wl_output = calloc(1, sizeof(struct va_wl_output));
358 if (!i965->wl_output)
361 i965->wl_output->libegl_handle = dso_open(LIBEGL_NAME);
362 if (!i965->wl_output->libegl_handle)
365 dso_handle = i965->wl_output->libegl_handle;
366 wl_vtable = &i965->wl_output->vtable;
367 if (!dso_get_symbols(dso_handle, wl_vtable, sizeof(*wl_vtable),
371 i965->wl_output->libwl_client_handle = dso_open(LIBWAYLAND_CLIENT_NAME);
372 if (!i965->wl_output->libwl_client_handle)
375 dso_handle = i965->wl_output->libwl_client_handle;
376 wl_vtable = &i965->wl_output->vtable;
377 if (!dso_get_symbols(dso_handle, wl_vtable, sizeof(*wl_vtable),
378 libwl_client_symbols))
381 if (!ensure_driver_vtable(ctx))
386 i965_output_wayland_terminate(ctx);
391 i965_output_wayland_terminate(VADriverContextP ctx)
393 struct i965_driver_data * const i965 = i965_driver_data(ctx);
394 struct va_wl_output *wl_output;
396 if (ctx->display_type != VA_DISPLAY_WAYLAND)
399 wl_output = i965->wl_output;
403 if (wl_output->wl_drm) {
404 wl_output->vtable.proxy_destroy((struct wl_proxy *)wl_output->wl_drm);
405 wl_output->wl_drm = NULL;
408 if (wl_output->libegl_handle) {
409 dso_close(wl_output->libegl_handle);
410 wl_output->libegl_handle = NULL;
413 if (wl_output->libwl_client_handle) {
414 dso_close(wl_output->libwl_client_handle);
415 wl_output->libwl_client_handle = NULL;
418 i965->wl_output = NULL;