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 <stdio.h>
26 #include <stdbool.h>
27 #include <va/va_x11.h>
28 #include "va_display.h"
29 
30 static Display *x11_display;
31 static Window   x11_window;
32 
33 static VADisplay
va_open_display_x11(void)34 va_open_display_x11(void)
35 {
36     x11_display = XOpenDisplay(NULL);
37     if (!x11_display) {
38         fprintf(stderr, "error: can't connect to X server!\n");
39         return NULL;
40     }
41     return vaGetDisplay(x11_display);
42 }
43 
44 static void
va_close_display_x11(VADisplay va_dpy)45 va_close_display_x11(VADisplay va_dpy)
46 {
47     if (!x11_display)
48         return;
49 
50     if (x11_window) {
51         XUnmapWindow(x11_display, x11_window);
52         XDestroyWindow(x11_display, x11_window);
53         x11_window = None;
54     }
55     XCloseDisplay(x11_display);
56     x11_display = NULL;
57 }
58 
59 static int
ensure_window(unsigned int width,unsigned int height)60 ensure_window(unsigned int width, unsigned int height)
61 {
62     Window win, rootwin;
63     unsigned int black_pixel, white_pixel;
64     int screen;
65 
66     if (!x11_display)
67         return 0;
68 
69     if (x11_window) {
70         XResizeWindow(x11_display, x11_window, width, height);
71         return 1;
72     }
73 
74     screen      = DefaultScreen(x11_display);
75     rootwin     = RootWindow(x11_display, screen);
76     black_pixel = BlackPixel(x11_display, screen);
77     white_pixel = WhitePixel(x11_display, screen);
78 
79     win = XCreateSimpleWindow(
80         x11_display,
81         rootwin,
82         0, 0, width, height,
83         1, black_pixel, white_pixel
84     );
85     if (!win)
86         return 0;
87     x11_window = win;
88 
89     XMapWindow(x11_display, x11_window);
90     XSync(x11_display, False);
91     return 1;
92 }
93 
94 static inline bool
validate_rect(const VARectangle * rect)95 validate_rect(const VARectangle *rect)
96 {
97     return (rect            &&
98             rect->x >= 0    &&
99             rect->y >= 0    &&
100             rect->width > 0 &&
101             rect->height > 0);
102 }
103 
104 static VAStatus
va_put_surface_x11(VADisplay va_dpy,VASurfaceID surface,const VARectangle * src_rect,const VARectangle * dst_rect)105 va_put_surface_x11(
106     VADisplay          va_dpy,
107     VASurfaceID        surface,
108     const VARectangle *src_rect,
109     const VARectangle *dst_rect
110 )
111 {
112     unsigned int win_width, win_height;
113 
114     if (!va_dpy)
115         return VA_STATUS_ERROR_INVALID_DISPLAY;
116     if (surface == VA_INVALID_SURFACE)
117         return VA_STATUS_ERROR_INVALID_SURFACE;
118     if (!validate_rect(src_rect) || !validate_rect(dst_rect))
119         return VA_STATUS_ERROR_INVALID_PARAMETER;
120 
121     win_width  = dst_rect->x + dst_rect->width;
122     win_height = dst_rect->y + dst_rect->height;
123     if (!ensure_window(win_width, win_height))
124         return VA_STATUS_ERROR_ALLOCATION_FAILED;
125     return vaPutSurface(va_dpy, surface, x11_window,
126                         src_rect->x, src_rect->y,
127                         src_rect->width, src_rect->height,
128                         dst_rect->x, dst_rect->y,
129                         dst_rect->width, dst_rect->height,
130                         NULL, 0,
131                         VA_FRAME_PICTURE);
132 }
133 
134 const VADisplayHooks va_display_hooks_x11 = {
135     "x11",
136     va_open_display_x11,
137     va_close_display_x11,
138     va_put_surface_x11,
139 };
140