Home | History | Annotate | Download | only in common
      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
     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
     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     }
     79     else {
     80         d = calloc(1, sizeof(*d));
     81         if (!d)
     82             return NULL;
     83         d->event_fd = -1;
     84 
     85         d->display = wl_display_connect(NULL);
     86         if (!d->display) {
     87             free(d);
     88             return NULL;
     89         }
     90         wl_display_set_user_data(d->display, d);
     91         d->registry = wl_display_get_registry(d->display);
     92         wl_registry_add_listener(d->registry, &registry_listener, d);
     93         d->event_fd = wl_display_get_fd(d->display);
     94         wl_display_dispatch(d->display);
     95 
     96         d->ref_count = 1;
     97         g_display = d;
     98     }
     99     return vaGetDisplayWl(d->display);
    100 }
    101 
    102 static void
    103 va_close_display_wayland(VADisplay va_dpy)
    104 {
    105     struct display * const d = g_display;
    106 
    107     if (!d || --d->ref_count > 0)
    108         return;
    109 
    110     if (d->surface) {
    111         wl_surface_destroy(d->surface);
    112         d->surface = NULL;
    113     }
    114 
    115     if (d->shell_surface) {
    116         wl_shell_surface_destroy(d->shell_surface);
    117         d->shell_surface = NULL;
    118     }
    119 
    120     if (d->shell) {
    121         wl_shell_destroy(d->shell);
    122         d->shell = NULL;
    123     }
    124 
    125     if (d->compositor) {
    126         wl_compositor_destroy(d->compositor);
    127         d->compositor = NULL;
    128     }
    129 
    130     if (d->display) {
    131         wl_display_disconnect(d->display);
    132         d->display = NULL;
    133     }
    134     free(g_display);
    135     g_display = NULL;
    136 }
    137 
    138 static int
    139 ensure_window(VADisplay va_dpy, unsigned int width, unsigned int height)
    140 {
    141     struct display * const d = g_display;
    142 
    143     if (!d->surface) {
    144         d->surface = wl_compositor_create_surface(d->compositor);
    145         if (!d->surface)
    146             return 0;
    147     }
    148 
    149     if (!d->shell_surface) {
    150         d->shell_surface = wl_shell_get_shell_surface(d->shell, d->surface);
    151         if (!d->shell_surface)
    152             return 0;
    153         wl_shell_surface_set_toplevel(d->shell_surface);
    154     }
    155     return 1;
    156 }
    157 
    158 static VAStatus
    159 va_put_surface_wayland(
    160     VADisplay          va_dpy,
    161     VASurfaceID        surface,
    162     const VARectangle *src_rect,
    163     const VARectangle *dst_rect
    164 )
    165 {
    166     struct display * const d = g_display;
    167     VAStatus va_status;
    168     struct wl_buffer *buffer;
    169 
    170     if (!ensure_window(va_dpy, dst_rect->width, dst_rect->height))
    171         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    172 
    173     va_status = vaGetSurfaceBufferWl(va_dpy, surface, VA_FRAME_PICTURE, &buffer);
    174     if (va_status != VA_STATUS_SUCCESS)
    175         return va_status;
    176 
    177     wl_surface_attach(d->surface, buffer, 0, 0);
    178     wl_surface_damage(
    179          d->surface,
    180          dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height
    181      );
    182 
    183     wl_surface_commit(d->surface);
    184     wl_display_flush(d->display);
    185     return VA_STATUS_SUCCESS;
    186 }
    187 
    188 const VADisplayHooks va_display_hooks_wayland = {
    189     "wayland",
    190     va_open_display_wayland,
    191     va_close_display_wayland,
    192     va_put_surface_wayland,
    193 };
    194