Home | History | Annotate | Download | only in putsurface
      1 /*
      2  * Copyright (c) 2011 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 <stddef.h>
     26 #include <errno.h>
     27 #include <sys/select.h>
     28 #ifdef IN_LIBVA
     29 # include "va/wayland/va_wayland.h"
     30 #else
     31 # include <va/va_wayland.h>
     32 #endif
     33 #include <wayland-server.h>
     34 
     35 static void *open_display(void);
     36 static void close_display(void *win_display);
     37 static int create_window(void *win_display,
     38              int x, int y, int width, int height);
     39 static int check_window_event(void *win_display, void *drawable,
     40                   int *width, int *height, int *quit);
     41 
     42 struct display;
     43 struct drawable;
     44 
     45 static VAStatus
     46 va_put_surface(
     47     VADisplay           dpy,
     48     struct drawable    *wl_drawable,
     49     VASurfaceID         va_surface,
     50     const VARectangle  *src_rect,
     51     const VARectangle  *dst_rect,
     52     const VARectangle  *cliprects,
     53     unsigned int        num_cliprects,
     54     unsigned int        flags
     55 );
     56 
     57 /* Glue code for the current PutSurface test design */
     58 #define CAST_DRAWABLE(a)  (struct drawable *)(a)
     59 
     60 static inline VADisplay
     61 vaGetDisplay(VANativeDisplay native_dpy)
     62 {
     63     return vaGetDisplayWl(native_dpy);
     64 }
     65 
     66 static VAStatus
     67 vaPutSurface(
     68     VADisplay           dpy,
     69     VASurfaceID         surface,
     70     struct drawable    *wl_drawable,
     71     short               src_x,
     72     short               src_y,
     73     unsigned short      src_w,
     74     unsigned short      src_h,
     75     short               dst_x,
     76     short               dst_y,
     77     unsigned short      dst_w,
     78     unsigned short      dst_h,
     79     const VARectangle  *cliprects,
     80     unsigned int        num_cliprects,
     81     unsigned int        flags
     82 )
     83 {
     84     VARectangle src_rect, dst_rect;
     85 
     86     src_rect.x      = src_x;
     87     src_rect.y      = src_y;
     88     src_rect.width  = src_w;
     89     src_rect.height = src_h;
     90 
     91     dst_rect.x      = src_x;
     92     dst_rect.y      = src_y;
     93     dst_rect.width  = src_w;
     94     dst_rect.height = src_h;
     95     return va_put_surface(dpy, wl_drawable, surface, &src_rect, &dst_rect,
     96                           cliprects, num_cliprects, flags);
     97 }
     98 
     99 #include "putsurface_common.c"
    100 
    101 struct display {
    102     struct wl_display  *display;
    103     struct wl_compositor *compositor;
    104     struct wl_shell    *shell;
    105     struct wl_registry *registry;
    106     int                 event_fd;
    107 };
    108 
    109 struct drawable {
    110     struct wl_display  *display;
    111     struct wl_surface  *surface;
    112     unsigned int        redraw_pending  : 1;
    113 };
    114 
    115 static void
    116 frame_redraw_callback(void *data, struct wl_callback *callback, uint32_t time)
    117 {
    118     struct drawable * const drawable = data;
    119 
    120     drawable->redraw_pending = 0;
    121     wl_callback_destroy(callback);
    122 }
    123 
    124 static const struct wl_callback_listener frame_callback_listener = {
    125     frame_redraw_callback
    126 };
    127 
    128 static VAStatus
    129 va_put_surface(
    130     VADisplay           dpy,
    131     struct drawable    *wl_drawable,
    132     VASurfaceID         va_surface,
    133     const VARectangle  *src_rect,
    134     const VARectangle  *dst_rect,
    135     const VARectangle  *cliprects,
    136     unsigned int        num_cliprects,
    137     unsigned int        flags
    138 )
    139 {
    140     struct display *d;
    141     struct wl_callback *callback;
    142     VAStatus va_status;
    143     struct wl_buffer *buffer;
    144 
    145     if (!wl_drawable)
    146         return VA_STATUS_ERROR_INVALID_SURFACE;
    147 
    148     d = wl_display_get_user_data(wl_drawable->display);
    149     if (!d)
    150         return VA_STATUS_ERROR_INVALID_DISPLAY;
    151 
    152     /* Wait for the previous frame to complete redraw */
    153     if (wl_drawable->redraw_pending) {
    154         wl_display_flush(d->display);
    155         while (wl_drawable->redraw_pending)
    156             wl_display_dispatch(wl_drawable->display);
    157     }
    158 
    159     va_status = vaGetSurfaceBufferWl(va_dpy, va_surface, VA_FRAME_PICTURE, &buffer);
    160     if (va_status != VA_STATUS_SUCCESS)
    161         return va_status;
    162 
    163     wl_surface_attach(wl_drawable->surface, buffer, 0, 0);
    164     wl_surface_damage(
    165         wl_drawable->surface,
    166         dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height
    167     );
    168 
    169     wl_display_flush(d->display);
    170     wl_drawable->redraw_pending = 1;
    171     callback = wl_surface_frame(wl_drawable->surface);
    172     wl_surface_commit(wl_drawable->surface);
    173     wl_callback_add_listener(callback, &frame_callback_listener, wl_drawable);
    174     return VA_STATUS_SUCCESS;
    175 }
    176 
    177 static void
    178 registry_handle_global(
    179     void               *data,
    180     struct wl_registry *registry,
    181     uint32_t            id,
    182     const char         *interface,
    183     uint32_t            version
    184 )
    185 {
    186     struct display * const d = data;
    187 
    188     if (strcmp(interface, "wl_compositor") == 0)
    189         d->compositor =
    190             wl_registry_bind(registry, id, &wl_compositor_interface, 1);
    191     else if (strcmp(interface, "wl_shell") == 0)
    192         d->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1);
    193 }
    194 
    195 static const struct wl_registry_listener registry_listener = {
    196     registry_handle_global,
    197     NULL,
    198 };
    199 
    200 static void *
    201 open_display(void)
    202 {
    203     struct display *d;
    204 
    205     d = calloc(1, sizeof *d);
    206     if (!d)
    207         return NULL;
    208 
    209     d->display = wl_display_connect(NULL);
    210     if (!d->display)
    211         return NULL;
    212 
    213     wl_display_set_user_data(d->display, d);
    214     d->registry = wl_display_get_registry(d->display);
    215     wl_registry_add_listener(d->registry, &registry_listener, d);
    216     d->event_fd = wl_display_get_fd(d->display);
    217     wl_display_dispatch(d->display);
    218     return d->display;
    219 }
    220 
    221 static void
    222 close_display(void *win_display)
    223 {
    224     struct display * const d = wl_display_get_user_data(win_display);
    225 
    226     if (d->shell) {
    227         wl_shell_destroy(d->shell);
    228         d->shell = NULL;
    229     }
    230 
    231     if (d->compositor) {
    232         wl_compositor_destroy(d->compositor);
    233         d->compositor = NULL;
    234     }
    235 
    236     if (d->display) {
    237         wl_display_disconnect(d->display);
    238         d->display = NULL;
    239     }
    240     free(d);
    241 }
    242 
    243 static int
    244 create_window(void *win_display, int x, int y, int width, int height)
    245 {
    246     struct wl_display * const display = win_display;
    247     struct display * const d = wl_display_get_user_data(display);
    248     struct wl_surface *surface1, *surface2;
    249     struct wl_shell_surface *shell_surface;
    250     struct wl_shell_surface *shell_surface_2;
    251     struct drawable *drawable1, *drawable2;
    252 
    253     surface1 = wl_compositor_create_surface(d->compositor);
    254     shell_surface = wl_shell_get_shell_surface(d->shell, surface1);
    255     wl_shell_surface_set_toplevel(shell_surface);
    256 
    257     drawable1 = malloc(sizeof(*drawable1));
    258     drawable1->display          = display;
    259     drawable1->surface          = surface1;
    260     drawable1->redraw_pending   = 0;
    261 
    262     /* global out */
    263     drawable_thread0 = drawable1;
    264 
    265     if (multi_thread == 0)
    266         return 0;
    267 
    268     surface2 = wl_compositor_create_surface(d->compositor);
    269     shell_surface_2 = wl_shell_get_shell_surface(d->shell, surface2);
    270     wl_shell_surface_set_toplevel(shell_surface_2);
    271 
    272     drawable2 = malloc(sizeof(*drawable2));
    273     drawable2->display          = display;
    274     drawable1->surface          = surface2;
    275     drawable2->redraw_pending   = 0;
    276 
    277     /* global out */
    278     drawable_thread1 = drawable2;
    279     return 0;
    280 }
    281 
    282 static int
    283 check_window_event(
    284     void *win_display,
    285     void *drawable,
    286     int  *width,
    287     int  *height,
    288     int  *quit
    289 )
    290 {
    291     struct wl_display * const display = win_display;
    292     struct display * const d = wl_display_get_user_data(display);
    293     struct timeval tv;
    294     fd_set rfds;
    295     int retval;
    296 
    297     if (check_event == 0)
    298         return 0;
    299 
    300     tv.tv_sec  = 0;
    301     tv.tv_usec = 0;
    302     do {
    303         FD_ZERO(&rfds);
    304         FD_SET(d->event_fd, &rfds);
    305 
    306         retval = select(d->event_fd + 1, &rfds, NULL, NULL, &tv);
    307         if (retval < 0) {
    308             perror("select");
    309             break;
    310         }
    311         if (retval == 1)
    312             wl_display_dispatch(d->display);
    313     } while (retval > 0);
    314 
    315 #if 0
    316     /* bail on any focused key press */
    317     if(event.type == KeyPress) {
    318         *quit = 1;
    319         return 0;
    320     }
    321 #endif
    322 
    323 #if 0
    324     /* rescale the video to fit the window */
    325     if(event.type == ConfigureNotify) {
    326         *width = event.xconfigure.width;
    327         *height = event.xconfigure.height;
    328         printf("Scale window to %dx%d\n", width, height);
    329     }
    330 #endif
    331     return 0;
    332 }
    333