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.
29 #include <va/va_backend.h>
30 #include <va/va_backend_wayland.h>
31 #include <wayland-client.h>
32 #include <wayland-drm-client-protocol.h>
33 #include "intel_driver.h"
34 #include "i965_output_wayland.h"
35 #include "i965_drv_video.h"
36 #include "i965_defines.h"
37 #include "dso_utils.h"
39 #define LIBEGL_NAME "libEGL.so.1"
40 #define LIBWAYLAND_CLIENT_NAME "libwayland-client.so.0"
42 typedef uint32_t (*wl_display_get_global_func)(struct wl_display *display,
43 const char *interface, uint32_t version);
44 typedef void (*wl_display_roundtrip_func)(struct wl_display *display);
46 typedef struct wl_proxy *(*wl_proxy_create_func)(struct wl_proxy *factory,
47 const struct wl_interface *interface);
48 typedef void (*wl_proxy_destroy_func)(struct wl_proxy *proxy);
49 typedef void (*wl_proxy_marshal_func)(struct wl_proxy *p, uint32_t opcode, ...);
50 typedef int (*wl_proxy_add_listener_func) (struct wl_proxy *proxy,
51 void (**implementation)(void), void *data);
54 const struct wl_interface *buffer_interface;
55 const struct wl_interface *drm_interface;
56 const struct wl_interface *registry_interface;
57 wl_display_roundtrip_func display_roundtrip;
58 wl_proxy_create_func proxy_create;
59 wl_proxy_destroy_func proxy_destroy;
60 wl_proxy_marshal_func proxy_marshal;
61 wl_proxy_add_listener_func proxy_add_listener;
65 struct dso_handle *libegl_handle;
66 struct dso_handle *libwl_client_handle;
67 struct wl_vtable vtable;
68 struct wl_drm *wl_drm;
69 struct wl_registry *wl_registry;
72 /* These function are copied and adapted from the version inside
73 * wayland-client-protocol.h
77 struct wl_vtable *wl_vtable,
78 struct wl_registry *wl_registry,
80 const struct wl_interface *interface,
86 id = wl_vtable->proxy_create((struct wl_proxy *) wl_registry,
91 wl_vtable->proxy_marshal((struct wl_proxy *) wl_registry,
92 WL_REGISTRY_BIND, name, interface->name,
98 static struct wl_registry *
100 struct wl_vtable *wl_vtable,
101 struct wl_display *wl_display
104 struct wl_proxy *callback;
106 callback = wl_vtable->proxy_create((struct wl_proxy *) wl_display,
107 wl_vtable->registry_interface);
111 wl_vtable->proxy_marshal((struct wl_proxy *) wl_display,
112 WL_DISPLAY_GET_REGISTRY, callback);
114 return (struct wl_registry *) callback;
118 registry_add_listener(
119 struct wl_vtable *wl_vtable,
120 struct wl_registry *wl_registry,
121 const struct wl_registry_listener *listener,
125 return wl_vtable->proxy_add_listener((struct wl_proxy *) wl_registry,
126 (void (**)(void)) listener, data);
130 registry_handle_global(
132 struct wl_registry *registry,
134 const char *interface,
138 VADriverContextP ctx = data;
139 struct i965_driver_data * const i965 = i965_driver_data(ctx);
140 struct va_wl_output * const wl_output = i965->wl_output;
141 struct wl_vtable * const wl_vtable = &wl_output->vtable;
143 if (strcmp(interface, "wl_drm") == 0) {
144 wl_output->wl_drm = registry_bind(wl_vtable, wl_output->wl_registry,
145 id, wl_vtable->drm_interface, 2);
149 static const struct wl_registry_listener registry_listener = {
150 registry_handle_global,
154 /* Ensure wl_drm instance is created */
156 ensure_wl_output(VADriverContextP ctx)
158 struct i965_driver_data * const i965 = i965_driver_data(ctx);
159 struct va_wl_output * const wl_output = i965->wl_output;
160 struct wl_vtable * const wl_vtable = &wl_output->vtable;
162 if (wl_output->wl_drm)
165 wl_output->wl_registry = display_get_registry(wl_vtable, ctx->native_dpy);
166 registry_add_listener(wl_vtable, wl_output->wl_registry,
167 ®istry_listener, ctx);
168 wl_vtable->display_roundtrip(ctx->native_dpy);
169 if (!wl_output->wl_drm)
174 /* Create planar/prime YUV buffer
175 * Create a prime buffer if fd is not -1, otherwise a
178 static struct wl_buffer *
179 create_prime_or_planar_buffer(
180 struct va_wl_output *wl_output,
190 struct wl_vtable * const wl_vtable = &wl_output->vtable;
193 id = wl_vtable->proxy_create(
194 (struct wl_proxy *)wl_output->wl_drm,
195 wl_vtable->buffer_interface
200 wl_vtable->proxy_marshal(
201 (struct wl_proxy *)wl_output->wl_drm,
202 (fd != -1) ? WL_DRM_CREATE_PRIME_BUFFER : WL_DRM_CREATE_PLANAR_BUFFER,
204 (fd != -1) ? fd : name,
205 width, height, format,
206 offsets[0], pitches[0],
207 offsets[1], pitches[1],
208 offsets[2], pitches[2]
210 return (struct wl_buffer *)id;
213 /* Hook to return Wayland buffer associated with the VA surface */
215 va_GetSurfaceBufferWl(
216 struct VADriverContext *ctx,
219 struct wl_buffer **out_buffer
222 struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
223 struct i965_driver_data * const i965 = i965_driver_data(ctx);
224 struct object_surface *obj_surface;
225 struct wl_buffer *buffer;
226 uint32_t name, drm_format;
227 int offsets[3], pitches[3];
230 obj_surface = SURFACE(surface);
232 return VA_STATUS_ERROR_INVALID_SURFACE;
234 if (flags != VA_FRAME_PICTURE)
235 return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
238 return VA_STATUS_ERROR_INVALID_PARAMETER;
240 if (!ensure_wl_output(ctx))
241 return VA_STATUS_ERROR_INVALID_DISPLAY;
243 if (!vtable->has_prime_sharing || (drm_intel_bo_gem_export_to_prime(obj_surface->bo, &fd) != 0)) {
246 if (drm_intel_bo_flink(obj_surface->bo, &name) != 0)
247 return VA_STATUS_ERROR_INVALID_SURFACE;
250 switch (obj_surface->fourcc) {
252 drm_format = WL_DRM_FORMAT_NV12;
254 pitches[0] = obj_surface->width;
255 offsets[1] = obj_surface->width * obj_surface->y_cb_offset;
256 pitches[1] = obj_surface->cb_cr_pitch;
268 switch (obj_surface->subsampling) {
269 case SUBSAMPLE_YUV411:
270 drm_format = WL_DRM_FORMAT_YUV411;
272 case SUBSAMPLE_YUV420:
273 drm_format = WL_DRM_FORMAT_YUV420;
275 case SUBSAMPLE_YUV422H:
276 case SUBSAMPLE_YUV422V:
277 drm_format = WL_DRM_FORMAT_YUV422;
279 case SUBSAMPLE_YUV444:
280 drm_format = WL_DRM_FORMAT_YUV444;
283 assert(0 && "unsupported subsampling");
284 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
287 pitches[0] = obj_surface->width;
288 offsets[1] = obj_surface->width * obj_surface->y_cb_offset;
289 pitches[1] = obj_surface->cb_cr_pitch;
290 offsets[2] = obj_surface->width * obj_surface->y_cr_offset;
291 pitches[2] = obj_surface->cb_cr_pitch;
294 assert(0 && "unsupported format");
295 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
298 buffer = create_prime_or_planar_buffer(
302 obj_surface->orig_width,
303 obj_surface->orig_height,
313 return VA_STATUS_ERROR_ALLOCATION_FAILED;
315 *out_buffer = buffer;
316 return VA_STATUS_SUCCESS;
319 /* Hook to return Wayland buffer associated with the VA image */
322 struct VADriverContext *ctx,
325 struct wl_buffer **out_buffer
328 return VA_STATUS_ERROR_UNIMPLEMENTED;
332 ensure_driver_vtable(VADriverContextP ctx)
334 struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
339 vtable->vaGetSurfaceBufferWl = va_GetSurfaceBufferWl;
340 vtable->vaGetImageBufferWl = va_GetImageBufferWl;
345 i965_output_wayland_init(VADriverContextP ctx)
347 struct i965_driver_data * const i965 = i965_driver_data(ctx);
348 struct dso_handle *dso_handle;
349 struct wl_vtable *wl_vtable;
351 static const struct dso_symbol libegl_symbols[] = {
352 { "wl_drm_interface",
353 offsetof(struct wl_vtable, drm_interface) },
357 static const struct dso_symbol libwl_client_symbols[] = {
358 { "wl_buffer_interface",
359 offsetof(struct wl_vtable, buffer_interface) },
360 { "wl_registry_interface",
361 offsetof(struct wl_vtable, registry_interface) },
362 { "wl_display_roundtrip",
363 offsetof(struct wl_vtable, display_roundtrip) },
365 offsetof(struct wl_vtable, proxy_create) },
366 { "wl_proxy_destroy",
367 offsetof(struct wl_vtable, proxy_destroy) },
368 { "wl_proxy_marshal",
369 offsetof(struct wl_vtable, proxy_marshal) },
370 { "wl_proxy_add_listener",
371 offsetof(struct wl_vtable, proxy_add_listener) },
375 if (ctx->display_type != VA_DISPLAY_WAYLAND)
378 i965->wl_output = calloc(1, sizeof(struct va_wl_output));
379 if (!i965->wl_output)
382 i965->wl_output->libegl_handle = dso_open(LIBEGL_NAME);
383 if (!i965->wl_output->libegl_handle)
386 dso_handle = i965->wl_output->libegl_handle;
387 wl_vtable = &i965->wl_output->vtable;
388 if (!dso_get_symbols(dso_handle, wl_vtable, sizeof(*wl_vtable),
392 i965->wl_output->libwl_client_handle = dso_open(LIBWAYLAND_CLIENT_NAME);
393 if (!i965->wl_output->libwl_client_handle)
396 dso_handle = i965->wl_output->libwl_client_handle;
397 wl_vtable = &i965->wl_output->vtable;
398 if (!dso_get_symbols(dso_handle, wl_vtable, sizeof(*wl_vtable),
399 libwl_client_symbols))
402 if (!ensure_driver_vtable(ctx))
407 i965_output_wayland_terminate(ctx);
412 i965_output_wayland_terminate(VADriverContextP ctx)
414 struct i965_driver_data * const i965 = i965_driver_data(ctx);
415 struct va_wl_output *wl_output;
417 if (ctx->display_type != VA_DISPLAY_WAYLAND)
420 wl_output = i965->wl_output;
424 if (wl_output->wl_drm) {
425 wl_output->vtable.proxy_destroy((struct wl_proxy *)wl_output->wl_drm);
426 wl_output->wl_drm = NULL;
429 if (wl_output->libegl_handle) {
430 dso_close(wl_output->libegl_handle);
431 wl_output->libegl_handle = NULL;
434 if (wl_output->libwl_client_handle) {
435 dso_close(wl_output->libwl_client_handle);
436 wl_output->libwl_client_handle = NULL;
439 i965->wl_output = NULL;