a2f6a571292ba41684451c52318053cbfbeadf72
[platform/core/uifw/libtbm.git] / src / tbm_wayland.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33
34 #include "tbm_bufmgr_int.h"
35 #include <xf86drm.h>
36
37 #include <stdint.h>
38 #include <stddef.h>
39 #include <wayland-client.h>
40
41 #include "wayland-util.h"
42
43 extern const struct wl_interface wl_buffer_interface;
44
45 static const struct wl_interface *types[] = {
46     NULL,
47     NULL,
48     NULL,
49     &wl_buffer_interface,
50     NULL,
51     NULL,
52     NULL,
53     NULL,
54     NULL,
55     NULL,
56     NULL,
57     NULL,
58     NULL,
59     NULL,
60     NULL,
61     NULL,
62     NULL,
63     NULL,
64     NULL,
65     NULL,
66     NULL,
67     NULL,
68     &wl_buffer_interface,
69     NULL,
70     NULL,
71     NULL,
72     NULL,
73     NULL,
74     NULL,
75     NULL,
76     NULL,
77     NULL,
78     NULL,
79     NULL,
80     NULL,
81     NULL,
82     NULL,
83     NULL,
84     NULL,
85     NULL,
86     NULL,
87 };
88
89 static const struct wl_message wl_tbm_requests[] = {
90     { "create_buffer", "niiuiiiiiiiiiiuiuuu", types + 3 },
91     { "create_buffer_with_fd", "niiuiiiiiiiiiiuihhh", types + 22 },
92     { "get_authentication_info", "", types + 0 },
93 };
94
95 static const struct wl_message wl_tbm_events[] = {
96     { "authentication_info", "suh", types + 0 },
97 };
98
99 WL_EXPORT const struct wl_interface wl_tbm_interface = {
100     "wl_tbm", 1,
101     3, wl_tbm_requests,
102     1, wl_tbm_events,
103 };
104
105 struct wl_buffer;
106 struct wl_tbm;
107
108 extern const struct wl_interface wl_tbm_interface;
109
110 #ifndef WL_TBM_ERROR_ENUM
111 #define WL_TBM_ERROR_ENUM
112 enum wl_tbm_error {
113     WL_TBM_ERROR_AUTHENTICATE_FAIL = 0,
114     WL_TBM_ERROR_INVALID_FORMAT = 1,
115     WL_TBM_ERROR_INVALID_NAME = 2,
116 };
117 #endif /* WL_TBM_ERROR_ENUM */
118
119 struct wl_tbm_listener {
120     /**
121      * authentication_info - (none)
122      * @device_name: (none)
123      * @capabilities: (none)
124      * @auth_fd: (none)
125      */
126     void (*authentication_info)(void *data,
127                     struct wl_tbm *wl_tbm,
128                     const char *device_name,
129                     uint32_t capabilities,
130                     int32_t auth_fd);
131 };
132
133 static inline int
134 wl_tbm_add_listener(struct wl_tbm *wl_tbm,
135             const struct wl_tbm_listener *listener, void *data)
136 {
137     return wl_proxy_add_listener((struct wl_proxy *) wl_tbm,
138                      (void (**)(void)) listener, data);
139 }
140
141 #define WL_TBM_CREATE_BUFFER    0
142 #define WL_TBM_CREATE_BUFFER_WITH_FD    1
143 #define WL_TBM_GET_AUTHENTICATION_INFO  2
144
145 static inline void
146 wl_tbm_set_user_data(struct wl_tbm *wl_tbm, void *user_data)
147 {
148     wl_proxy_set_user_data((struct wl_proxy *) wl_tbm, user_data);
149 }
150
151 static inline void *
152 wl_tbm_get_user_data(struct wl_tbm *wl_tbm)
153 {
154     return wl_proxy_get_user_data((struct wl_proxy *) wl_tbm);
155 }
156
157 static inline void
158 wl_tbm_destroy(struct wl_tbm *wl_tbm)
159 {
160     wl_proxy_destroy((struct wl_proxy *) wl_tbm);
161 }
162
163 static inline void
164 wl_tbm_get_authentication_info(struct wl_tbm *wl_tbm)
165 {
166     wl_proxy_marshal((struct wl_proxy *) wl_tbm,
167              WL_TBM_GET_AUTHENTICATION_INFO);
168 }
169
170 struct wl_tbm_info
171 {
172    struct wl_display* dpy;
173    struct wl_event_queue *wl_queue;
174    struct wl_tbm* wl_tbm;
175
176    uint32_t capabilities;
177    char *device;
178    int32_t fd;
179 };
180
181 static void
182 handle_tbm_authentication_info(void *data,
183                     struct wl_tbm *wl_tbm,
184                     const char *device_name,
185                     uint32_t capabilities,
186                     int32_t auth_fd)
187 {
188    struct wl_tbm_info *info = (struct wl_tbm_info *)data;
189
190    info->fd = auth_fd;
191    info->capabilities = capabilities;
192    if (device_name)
193       info->device = strndup(device_name, 256);
194 }
195
196 static const struct wl_tbm_listener wl_tbm_client_listener = {
197    handle_tbm_authentication_info
198 };
199
200 static void wl_client_registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
201 {
202     struct wl_tbm_info *info = (struct wl_tbm_info *)data;
203
204     if (!strcmp(interface, "wl_tbm"))
205     {
206         info->wl_tbm = wl_registry_bind(registry, name, &wl_tbm_interface, version);
207         if (!info->wl_tbm)
208         {
209             printf("Failed to bind wl_tbm\n");
210             return;
211         }
212
213         wl_tbm_add_listener(info->wl_tbm, &wl_tbm_client_listener, info);
214         wl_proxy_set_queue((struct wl_proxy *)info->wl_tbm, info->wl_queue);
215     }
216 }
217
218 static int tbm_util_get_drm_fd(void *dpy, int *fd)
219 {
220     struct wl_display *disp = NULL;
221     struct wl_registry *wl_registry;
222     struct wl_tbm_info info = {
223                             .dpy = NULL,
224                             .wl_queue = NULL,
225                             .wl_tbm = NULL,
226                             .capabilities = 0,
227                             .device = NULL,
228                             .fd = 0,
229                             };
230
231     static const struct wl_registry_listener registry_listener = {
232         wl_client_registry_handle_global,
233         NULL
234     };
235
236     if (!fd) {
237         return -1;
238     }
239
240     if (!dpy) {
241         disp = wl_display_connect(NULL);
242         if (!disp) {
243             printf("Failed to create a new display connection\n");
244             return -1;
245         }
246         dpy = disp;
247     }
248
249     info.dpy = dpy;
250     info.wl_queue = wl_display_create_queue(dpy);
251     if (!info.wl_queue) {
252         printf("Failed to create a WL Queue\n");
253         if (disp == dpy) {
254             wl_display_disconnect(disp);
255         }
256         return -1;
257     }
258
259     wl_registry = wl_display_get_registry(dpy);
260     if (!wl_registry) {
261         printf("Failed to get registry\n");
262         wl_event_queue_destroy(info.wl_queue);
263         if (disp == dpy) {
264             wl_display_disconnect(disp);
265         }
266         return -1;
267     }
268     wl_proxy_set_queue((struct wl_proxy *)wl_registry, info.wl_queue);
269     wl_registry_add_listener(wl_registry, &registry_listener, &info);
270     wl_display_roundtrip_queue(dpy, info.wl_queue);
271
272     wl_tbm_get_authentication_info(info.wl_tbm);
273     wl_display_roundtrip_queue(dpy, info.wl_queue);
274
275     *fd = info.fd;
276
277     wl_event_queue_destroy(info.wl_queue);
278     wl_registry_destroy(wl_registry);
279
280     free(info.device);
281     wl_tbm_set_user_data (info.wl_tbm, NULL);
282     wl_tbm_destroy(info.wl_tbm);
283
284     if (disp == dpy) {
285         wl_display_disconnect(disp);
286     }
287
288     return *fd >= 0 ? 0 : -1;
289 }
290
291 int
292 tbm_bufmgr_get_drm_fd_wayland()
293 {
294     int fd = -1;
295
296     if(tbm_util_get_drm_fd(NULL, &fd))
297     {
298         printf("Failed to get drm_fd\n");
299     }
300
301     return fd;
302 }