If drm fd is negative value, get fd with wayland protocol
[platform/adaptation/spreadtrum/libtbm-sprd.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 <xf86drm.h>
35
36 #include <stdint.h>
37 #include <stddef.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <wayland-client.h>
42
43 #include "wayland-util.h"
44
45 extern const struct wl_interface wl_buffer_interface;
46
47 static const struct wl_interface *types[] = {
48         NULL,
49         NULL,
50         NULL,
51         &wl_buffer_interface,
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         NULL,
69         NULL,
70         &wl_buffer_interface,
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         NULL,
88         NULL,
89 };
90
91 static const struct wl_message wl_tbm_requests[] = {
92         {"create_buffer", "niiuiiiiiiiiiiuiuuu", types + 3},
93         {"create_buffer_with_fd", "niiuiiiiiiiiiiuihhh", types + 22},
94         {"get_authentication_info", "", types + 0},
95 };
96
97 static const struct wl_message wl_tbm_events[] = {
98         {"authentication_info", "suh", types + 0},
99 };
100
101 WL_EXPORT const struct wl_interface wl_tbm_interface = {
102         "wl_tbm", 1,
103         3, wl_tbm_requests,
104         1, wl_tbm_events,
105 };
106
107 struct wl_buffer;
108 struct wl_tbm;
109
110 extern const struct wl_interface wl_tbm_interface;
111
112 #ifndef WL_TBM_ERROR_ENUM
113 #define WL_TBM_ERROR_ENUM
114 enum wl_tbm_error {
115         WL_TBM_ERROR_AUTHENTICATE_FAIL = 0,
116         WL_TBM_ERROR_INVALID_FORMAT = 1,
117         WL_TBM_ERROR_INVALID_NAME = 2,
118 };
119 #endif                                                  /* WL_TBM_ERROR_ENUM */
120
121 struct wl_tbm_listener {
122         /**
123      * authentication_info - (none)
124      * @device_name: (none)
125      * @capabilities: (none)
126      * @auth_fd: (none)
127      */
128         void (*authentication_info) (void *data, struct wl_tbm * wl_tbm, const char *device_name, uint32_t capabilities, int32_t auth_fd);
129 };
130
131 static inline int wl_tbm_add_listener(struct wl_tbm *wl_tbm, const struct wl_tbm_listener *listener, void *data)
132 {
133         return wl_proxy_add_listener((struct wl_proxy *)wl_tbm, (void (**)(void))listener, data);
134 }
135
136 #define WL_TBM_CREATE_BUFFER    0
137 #define WL_TBM_CREATE_BUFFER_WITH_FD    1
138 #define WL_TBM_GET_AUTHENTICATION_INFO  2
139
140 static inline void wl_tbm_set_user_data(struct wl_tbm *wl_tbm, void *user_data)
141 {
142         wl_proxy_set_user_data((struct wl_proxy *)wl_tbm, user_data);
143 }
144
145 static inline void *wl_tbm_get_user_data(struct wl_tbm *wl_tbm)
146 {
147         return wl_proxy_get_user_data((struct wl_proxy *)wl_tbm);
148 }
149
150 static inline void wl_tbm_destroy(struct wl_tbm *wl_tbm)
151 {
152         wl_proxy_destroy((struct wl_proxy *)wl_tbm);
153 }
154
155 static inline void wl_tbm_get_authentication_info(struct wl_tbm *wl_tbm)
156 {
157         wl_proxy_marshal((struct wl_proxy *)wl_tbm, WL_TBM_GET_AUTHENTICATION_INFO);
158 }
159
160 struct wl_tbm_info {
161         struct wl_display *dpy;
162         struct wl_event_queue *wl_queue;
163         struct wl_tbm *wl_tbm;
164
165         uint32_t capabilities;
166         char *device;
167         int32_t fd;
168 };
169
170 static void handle_tbm_authentication_info(void *data, struct wl_tbm *wl_tbm, const char *device_name, uint32_t capabilities, int32_t auth_fd)
171 {
172         struct wl_tbm_info *info = (struct wl_tbm_info *)data;
173
174         info->fd = auth_fd;
175         info->capabilities = capabilities;
176         if (device_name)
177                 info->device = strndup(device_name, 256);
178 }
179
180 static const struct wl_tbm_listener wl_tbm_client_listener = {
181         handle_tbm_authentication_info
182 };
183
184 static void wl_client_registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
185 {
186         struct wl_tbm_info *info = (struct wl_tbm_info *)data;
187
188         if (!strcmp(interface, "wl_tbm")) {
189                 info->wl_tbm = wl_registry_bind(registry, name, &wl_tbm_interface, version);
190                 if (!info->wl_tbm) {
191                         printf("Failed to bind wl_tbm\n");
192                         return;
193                 }
194
195                 wl_tbm_add_listener(info->wl_tbm, &wl_tbm_client_listener, info);
196                 wl_proxy_set_queue((struct wl_proxy *)info->wl_tbm, info->wl_queue);
197         }
198 }
199
200 static int tbm_util_get_drm_fd(void *dpy, int *fd)
201 {
202         struct wl_display *disp = NULL;
203         struct wl_registry *wl_registry;
204         struct wl_tbm_info info = {
205                 .dpy = NULL,
206                 .wl_queue = NULL,
207                 .wl_tbm = NULL,
208                 .capabilities = 0,
209                 .device = NULL,
210                 .fd = 0,
211         };
212
213         static const struct wl_registry_listener registry_listener = {
214                 wl_client_registry_handle_global,
215                 NULL
216         };
217
218         if (!fd)
219                 return -1;
220
221         if (!dpy) {
222                 disp = wl_display_connect(NULL);
223                 if (!disp) {
224                         printf("Failed to create a new display connection\n");
225                         return -1;
226                 }
227                 dpy = disp;
228         }
229
230         info.dpy = dpy;
231         info.wl_queue = wl_display_create_queue(dpy);
232         if (!info.wl_queue) {
233                 printf("Failed to create a WL Queue\n");
234                 if (disp == dpy)
235                         wl_display_disconnect(disp);
236
237                 return -1;
238         }
239
240         wl_registry = wl_display_get_registry(dpy);
241         if (!wl_registry) {
242                 printf("Failed to get registry\n");
243                 wl_event_queue_destroy(info.wl_queue);
244                 if (disp == dpy)
245                         wl_display_disconnect(disp);
246
247                 return -1;
248         }
249         wl_proxy_set_queue((struct wl_proxy *)wl_registry, info.wl_queue);
250         wl_registry_add_listener(wl_registry, &registry_listener, &info);
251         wl_display_roundtrip_queue(dpy, info.wl_queue);
252
253         wl_tbm_get_authentication_info(info.wl_tbm);
254         wl_display_roundtrip_queue(dpy, info.wl_queue);
255
256         *fd = info.fd;
257
258         wl_event_queue_destroy(info.wl_queue);
259         wl_registry_destroy(wl_registry);
260
261         free(info.device);
262         wl_tbm_set_user_data(info.wl_tbm, NULL);
263         wl_tbm_destroy(info.wl_tbm);
264
265         if (disp == dpy)
266                 wl_display_disconnect(disp);
267
268         return *fd >= 0 ? 0 : -1;
269 }
270
271 int tbm_bufmgr_get_drm_fd_wayland()
272 {
273         int fd = -1;
274
275         if (tbm_util_get_drm_fd(NULL, &fd))
276                 printf("Failed to get drm_fd\n");
277
278         return fd;
279 }