Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5361 serge 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 
26
#include 
27
#include 
28
#include 
29
#include 
30
#include 
31
#include 
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"
37
 
38
#define LIBEGL_NAME             "libEGL.so.1"
39
#define LIBWAYLAND_CLIENT_NAME  "libwayland-client.so.0"
40
 
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);
44
 
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);
51
 
52
struct wl_vtable {
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;
61
};
62
 
63
struct va_wl_output {
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;
69
};
70
 
71
/* These function are copied and adapted from the version inside
72
 * wayland-client-protocol.h
73
 */
74
static void *
75
registry_bind(
76
    struct wl_vtable          *wl_vtable,
77
    struct wl_registry        *wl_registry,
78
    uint32_t                   name,
79
    const struct wl_interface *interface,
80
    uint32_t                   version
81
)
82
{
83
    struct wl_proxy *id;
84
 
85
    id = wl_vtable->proxy_create((struct wl_proxy *) wl_registry,
86
                                 interface);
87
    if (!id)
88
      return NULL;
89
 
90
    wl_vtable->proxy_marshal((struct wl_proxy *) wl_registry,
91
                             WL_REGISTRY_BIND, name, interface->name,
92
                             version, id);
93
 
94
    return (void *) id;
95
}
96
 
97
static struct wl_registry *
98
display_get_registry(
99
    struct wl_vtable  *wl_vtable,
100
    struct wl_display *wl_display
101
)
102
{
103
    struct wl_proxy *callback;
104
 
105
    callback = wl_vtable->proxy_create((struct wl_proxy *) wl_display,
106
                                       wl_vtable->registry_interface);
107
    if (!callback)
108
      return NULL;
109
 
110
    wl_vtable->proxy_marshal((struct wl_proxy *) wl_display,
111
                             WL_DISPLAY_GET_REGISTRY, callback);
112
 
113
    return (struct wl_registry *) callback;
114
}
115
 
116
static int
117
registry_add_listener(
118
    struct wl_vtable                  *wl_vtable,
119
    struct wl_registry                *wl_registry,
120
    const struct wl_registry_listener *listener,
121
    void                              *data
122
)
123
{
124
    return wl_vtable->proxy_add_listener((struct wl_proxy *) wl_registry,
125
                                         (void (**)(void)) listener, data);
126
}
127
 
128
static void
129
registry_handle_global(
130
    void               *data,
131
    struct wl_registry *registry,
132
    uint32_t            id,
133
    const char         *interface,
134
    uint32_t            version
135
)
136
{
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;
141
 
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);
145
    }
146
}
147
 
148
static const struct wl_registry_listener registry_listener = {
149
    registry_handle_global,
150
    NULL
151
};
152
 
153
/* Ensure wl_drm instance is created */
154
static bool
155
ensure_wl_output(VADriverContextP ctx)
156
{
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;
160
 
161
    if (wl_output->wl_drm)
162
        return true;
163
 
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)
169
        return false;
170
    return true;
171
}
172
 
173
/* Create planar YUV buffer */
174
static struct wl_buffer *
175
create_planar_buffer(
176
    struct va_wl_output *wl_output,
177
    uint32_t             name,
178
    int32_t              width,
179
    int32_t              height,
180
    uint32_t             format,
181
    int32_t              offsets[3],
182
    int32_t              pitches[3]
183
)
184
{
185
    struct wl_vtable * const wl_vtable = &wl_output->vtable;
186
    struct wl_proxy *id;
187
 
188
    id = wl_vtable->proxy_create(
189
        (struct wl_proxy *)wl_output->wl_drm,
190
        wl_vtable->buffer_interface
191
    );
192
    if (!id)
193
        return NULL;
194
 
195
    wl_vtable->proxy_marshal(
196
        (struct wl_proxy *)wl_output->wl_drm,
197
        WL_DRM_CREATE_PLANAR_BUFFER,
198
        id,
199
        name,
200
        width, height, format,
201
        offsets[0], pitches[0],
202
        offsets[1], pitches[1],
203
        offsets[2], pitches[2]
204
    );
205
    return (struct wl_buffer *)id;
206
}
207
 
208
/* Hook to return Wayland buffer associated with the VA surface */
209
static VAStatus
210
va_GetSurfaceBufferWl(
211
    struct VADriverContext *ctx,
212
    VASurfaceID             surface,
213
    unsigned int            flags,
214
    struct wl_buffer      **out_buffer
215
)
216
{
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];
222
 
223
    obj_surface = SURFACE(surface);
224
    if (!obj_surface)
225
        return VA_STATUS_ERROR_INVALID_SURFACE;
226
 
227
    if (flags != VA_FRAME_PICTURE)
228
        return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
229
 
230
    if (!out_buffer)
231
        return VA_STATUS_ERROR_INVALID_PARAMETER;
232
 
233
    if (!ensure_wl_output(ctx))
234
        return VA_STATUS_ERROR_INVALID_DISPLAY;
235
 
236
    if (drm_intel_bo_flink(obj_surface->bo, &name) != 0)
237
        return VA_STATUS_ERROR_INVALID_SURFACE;
238
 
239
    switch (obj_surface->fourcc) {
240
    case VA_FOURCC_NV12:
241
        drm_format = WL_DRM_FORMAT_NV12;
242
        offsets[0] = 0;
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;
246
        offsets[2] = 0;
247
        pitches[2] = 0;
248
        break;
249
    case VA_FOURCC_YV12:
250
    case VA_FOURCC_I420:
251
    case VA_FOURCC_IMC1:
252
    case VA_FOURCC_IMC3:
253
    case VA_FOURCC_422H:
254
    case VA_FOURCC_422V:
255
    case VA_FOURCC_411P:
256
    case VA_FOURCC_444P:
257
        switch (obj_surface->subsampling) {
258
        case SUBSAMPLE_YUV411:
259
            drm_format = WL_DRM_FORMAT_YUV411;
260
            break;
261
        case SUBSAMPLE_YUV420:
262
            drm_format = WL_DRM_FORMAT_YUV420;
263
            break;
264
        case SUBSAMPLE_YUV422H:
265
        case SUBSAMPLE_YUV422V:
266
            drm_format = WL_DRM_FORMAT_YUV422;
267
            break;
268
        case SUBSAMPLE_YUV444:
269
            drm_format = WL_DRM_FORMAT_YUV444;
270
            break;
271
        default:
272
            assert(0 && "unsupported subsampling");
273
            return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
274
        }
275
        offsets[0] = 0;
276
        pitches[0] = obj_surface->width;
277
        offsets[1] = obj_surface->width * obj_surface->y_cb_offset;
278
        pitches[1] = obj_surface->cb_cr_pitch;
279
        offsets[2] = obj_surface->width * obj_surface->y_cr_offset;
280
        pitches[2] = obj_surface->cb_cr_pitch;
281
        break;
282
    default:
283
        assert(0 && "unsupported format");
284
        return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
285
    }
286
 
287
    buffer = create_planar_buffer(
288
        i965->wl_output,
289
        name,
290
        obj_surface->orig_width,
291
        obj_surface->orig_height,
292
        drm_format,
293
        offsets,
294
        pitches
295
    );
296
    if (!buffer)
297
        return VA_STATUS_ERROR_ALLOCATION_FAILED;
298
 
299
    *out_buffer = buffer;
300
    return VA_STATUS_SUCCESS;
301
}
302
 
303
/* Hook to return Wayland buffer associated with the VA image */
304
static VAStatus
305
va_GetImageBufferWl(
306
    struct VADriverContext *ctx,
307
    VAImageID               image,
308
    unsigned int            flags,
309
    struct wl_buffer      **out_buffer
310
)
311
{
312
    return VA_STATUS_ERROR_UNIMPLEMENTED;
313
}
314
 
315
bool
316
ensure_driver_vtable(VADriverContextP ctx)
317
{
318
    struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
319
 
320
    if (!vtable)
321
        return false;
322
 
323
    vtable->vaGetSurfaceBufferWl = va_GetSurfaceBufferWl;
324
    vtable->vaGetImageBufferWl   = va_GetImageBufferWl;
325
    return true;
326
}
327
 
328
bool
329
i965_output_wayland_init(VADriverContextP ctx)
330
{
331
    struct i965_driver_data * const i965 = i965_driver_data(ctx);
332
    struct dso_handle *dso_handle;
333
    struct wl_vtable *wl_vtable;
334
 
335
    static const struct dso_symbol libegl_symbols[] = {
336
        { "wl_drm_interface",
337
          offsetof(struct wl_vtable, drm_interface) },
338
        { NULL, }
339
    };
340
 
341
    static const struct dso_symbol libwl_client_symbols[] = {
342
        { "wl_buffer_interface",
343
          offsetof(struct wl_vtable, buffer_interface) },
344
        { "wl_registry_interface",
345
          offsetof(struct wl_vtable, registry_interface) },
346
        { "wl_display_roundtrip",
347
          offsetof(struct wl_vtable, display_roundtrip) },
348
        { "wl_proxy_create",
349
          offsetof(struct wl_vtable, proxy_create) },
350
        { "wl_proxy_destroy",
351
          offsetof(struct wl_vtable, proxy_destroy) },
352
        { "wl_proxy_marshal",
353
          offsetof(struct wl_vtable, proxy_marshal) },
354
        { "wl_proxy_add_listener",
355
          offsetof(struct wl_vtable, proxy_add_listener) },
356
        { NULL, }
357
    };
358
 
359
    if (ctx->display_type != VA_DISPLAY_WAYLAND)
360
        return false;
361
 
362
    i965->wl_output = calloc(1, sizeof(struct va_wl_output));
363
    if (!i965->wl_output)
364
        goto error;
365
 
366
    i965->wl_output->libegl_handle = dso_open(LIBEGL_NAME);
367
    if (!i965->wl_output->libegl_handle)
368
        goto error;
369
 
370
    dso_handle = i965->wl_output->libegl_handle;
371
    wl_vtable  = &i965->wl_output->vtable;
372
    if (!dso_get_symbols(dso_handle, wl_vtable, sizeof(*wl_vtable),
373
                         libegl_symbols))
374
        goto error;
375
 
376
    i965->wl_output->libwl_client_handle = dso_open(LIBWAYLAND_CLIENT_NAME);
377
    if (!i965->wl_output->libwl_client_handle)
378
        goto error;
379
 
380
    dso_handle = i965->wl_output->libwl_client_handle;
381
    wl_vtable  = &i965->wl_output->vtable;
382
    if (!dso_get_symbols(dso_handle, wl_vtable, sizeof(*wl_vtable),
383
                         libwl_client_symbols))
384
        goto error;
385
 
386
    if (!ensure_driver_vtable(ctx))
387
        goto error;
388
    return true;
389
 
390
error:
391
    i965_output_wayland_terminate(ctx);
392
    return false;
393
}
394
 
395
void
396
i965_output_wayland_terminate(VADriverContextP ctx)
397
{
398
    struct i965_driver_data * const i965 = i965_driver_data(ctx);
399
    struct va_wl_output *wl_output;
400
 
401
    if (ctx->display_type != VA_DISPLAY_WAYLAND)
402
        return;
403
 
404
    wl_output = i965->wl_output;
405
    if (!wl_output)
406
        return;
407
 
408
    if (wl_output->wl_drm) {
409
        wl_output->vtable.proxy_destroy((struct wl_proxy *)wl_output->wl_drm);
410
        wl_output->wl_drm = NULL;
411
    }
412
 
413
    if (wl_output->libegl_handle) {
414
        dso_close(wl_output->libegl_handle);
415
        wl_output->libegl_handle = NULL;
416
    }
417
 
418
    if (wl_output->libwl_client_handle) {
419
        dso_close(wl_output->libwl_client_handle);
420
        wl_output->libwl_client_handle = NULL;
421
    }
422
    free(wl_output);
423
    i965->wl_output = NULL;
424
}