1694b7aafcc8b6587ea6fce70e1aad187e376795
[platform/core/uifw/wayland-tbm.git] / src / wayland-tbm-client.c
1 /*
2 Copyright (C) 2015 Samsung Electronics co., Ltd. All Rights Reserved.
3
4 Contact:
5       SooChan Lim <sc1.lim@samsung.com>,
6       Sangjin Lee <lsj119@samsung.com>,
7       Boram Park <boram1288.park@samsung.com>,
8       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 "Software"),
12 to deal in the Software without restriction, including without limitation
13 the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 and/or sell copies of the Software, and to permit persons to whom the
15 Software is furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice (including the next
18 paragraph) shall be included in all copies or substantial portions of the
19 Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 DEALINGS IN THE SOFTWARE.
28 */
29
30 #include "config.h"
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stddef.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38
39 #include <tbm_surface.h>
40 #include <tbm_surface_queue.h>
41 #include <tbm_surface_internal.h>
42 #include <tbm_sync.h>
43
44 #include "wayland-tbm-client.h"
45 #include "wayland-tbm-client-protocol.h"
46 #include "wayland-tbm-int.h"
47
48 struct wayland_tbm_client {
49         struct wl_display *dpy;
50         struct wl_tbm *wl_tbm;
51
52         tbm_bufmgr bufmgr;
53
54         struct wl_list queue_info_list;
55
56         struct wl_event_queue *event_queue;
57 };
58
59 struct wayland_tbm_buffer {
60         struct wl_buffer *wl_buffer;
61         tbm_surface_h tbm_surface;
62         uint32_t flags;
63         int allocated;
64         int reuse;
65         int usable;
66
67         struct wl_tbm_queue *wl_tbm_queue;
68         struct wl_list link;
69 };
70
71 struct wayland_tbm_surface_queue {
72         struct wl_tbm_queue *wl_tbm_queue;
73         tbm_bufmgr bufmgr;
74
75         int width;
76         int height;
77         int format;
78         int flag;
79         uint num_bufs;
80         uint queue_size;
81         struct wl_surface *wl_surface;
82
83         int is_active;
84         int active_flush;
85         int usage;
86         struct wl_list attach_bufs;
87
88         tbm_surface_queue_h tbm_queue;
89
90         struct wl_tbm *wl_tbm;
91         struct wl_list link;
92 };
93
94 static struct wl_tbm_monitor *tbm_monitor;
95
96 #define DEBUG_TRACE
97 #ifdef DEBUG_TRACE
98 #define WL_TBM_TRACE(fmt, ...)   if (bTrace) WL_TBM_C_LOG(fmt, ##__VA_ARGS__)
99 #else
100 #define WL_TBM_TRACE(fmt, ...)
101 #endif
102
103 struct wayland_tbm_buffer *
104 _wayland_tbm_client_find_tbm_buffer_wl_buffer(struct wayland_tbm_client *tbm_client,
105                                 struct wl_buffer *wl_buffer);
106
107 static tbm_surface_h
108 _wayland_tbm_client_create_surface_from_param(tbm_bufmgr bufmgr,
109                          int is_fd,
110                          int32_t width,
111                          int32_t height,
112                          uint32_t format,
113                          int32_t bpp,
114                          int32_t size,
115                          int32_t num_plane,
116                          struct wl_array *plane_buf_idx,
117                          struct wl_array *plane_offset,
118                          struct wl_array *plane_stride,
119                          struct wl_array *plane_size,
120                          uint32_t flags,
121                          int32_t num_buf,
122                          uint32_t buf0,
123                          uint32_t buf1,
124                          uint32_t buf2);
125
126 static void
127 handle_tbm_buffer_import_with_id(void *data,
128                 struct wl_tbm *wl_tbm,
129                 struct wl_buffer *wl_buffer,
130                 int32_t width,
131                 int32_t height,
132                 uint32_t format,
133                 int32_t bpp,
134                 int32_t size,
135                 int32_t num_plane,
136                 struct wl_array *plane_buf_idx,
137                 struct wl_array *plane_offset,
138                 struct wl_array *plane_stride,
139                 struct wl_array *plane_size,
140                 uint32_t flags,
141                 int32_t num_buf,
142                 uint32_t buf0,
143                 uint32_t buf1,
144                 uint32_t buf2)
145 {
146         struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
147         tbm_surface_h tbm_surface;
148         char debug_id[64] = {0, };
149
150         tbm_surface = _wayland_tbm_client_create_surface_from_param(tbm_client->bufmgr, 0,
151                               width, height, format, bpp, size,
152                               num_plane,
153                               plane_buf_idx, plane_offset, plane_stride, plane_size,
154                               0,
155                               num_buf,
156                               buf0, buf1, buf2);
157         WL_TBM_GOTO_IF_FAIL(tbm_surface != NULL, fail);
158         wl_buffer_set_user_data(wl_buffer, tbm_surface);
159
160         snprintf(debug_id, sizeof(debug_id), "%u", (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
161         tbm_surface_internal_set_debug_data(tbm_surface, "id", debug_id);
162
163 #ifdef DEBUG_TRACE
164         WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), wl_buffer, tbm_surface);
165 #endif
166
167         return;
168
169 fail:
170         if (wl_buffer)
171                 wl_buffer_destroy(wl_buffer);
172 }
173
174 static void
175 handle_tbm_buffer_import_with_fd(void *data,
176                 struct wl_tbm *wl_tbm,
177                 struct wl_buffer *wl_buffer,
178                 int32_t width,
179                 int32_t height,
180                 uint32_t format,
181                 int32_t bpp,
182                 int32_t size,
183                 int32_t num_plane,
184                 struct wl_array *plane_buf_idx,
185                 struct wl_array *plane_offset,
186                 struct wl_array *plane_stride,
187                 struct wl_array *plane_size,
188                 uint32_t flags,
189                 int32_t num_buf,
190                 int32_t buf0,
191                 int32_t buf1,
192                 int32_t buf2)
193 {
194         struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
195         tbm_surface_h tbm_surface;
196         char debug_id[64] = {0, };
197
198         tbm_surface = _wayland_tbm_client_create_surface_from_param(tbm_client->bufmgr, 1,
199                               width, height, format, bpp, size,
200                               num_plane,
201                               plane_buf_idx, plane_offset, plane_stride, plane_size,
202                               0,
203                               num_buf,
204                               buf0, buf1, buf2);
205         WL_TBM_GOTO_IF_FAIL(tbm_surface != NULL, fail);
206
207         wl_buffer_set_user_data(wl_buffer, tbm_surface);
208
209         snprintf(debug_id, sizeof(debug_id), "%u", (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
210         tbm_surface_internal_set_debug_data(tbm_surface, "id", debug_id);
211
212 #ifdef DEBUG_TRACE
213         WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), wl_buffer, tbm_surface);
214 #endif
215
216         return;
217
218 fail:
219         if (wl_buffer)
220                 wl_buffer_destroy(wl_buffer);
221 }
222
223 static void
224 handle_buffer_destroy(void *data,
225                 struct wl_tbm *wl_tbm,
226                 struct wl_buffer *wl_buffer)
227 {
228         struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
229         tbm_surface_h tbm_surface;
230         struct wayland_tbm_buffer *buffer = NULL;
231
232 #ifdef DEBUG_TRACE
233         WL_TBM_TRACE("       pid:%d wl_buffer:%p", getpid(), wl_buffer);
234 #endif
235
236         buffer = _wayland_tbm_client_find_tbm_buffer_wl_buffer(tbm_client, wl_buffer);
237         if (buffer)
238                 buffer->wl_buffer = NULL;
239
240         tbm_surface = wl_buffer_get_user_data(wl_buffer);
241         if (tbm_surface)
242                 tbm_surface_internal_unref(tbm_surface);
243
244         wl_buffer_set_user_data(wl_buffer, NULL);
245         wl_buffer_destroy(wl_buffer);
246
247         return;
248 }
249
250 static const struct wl_tbm_listener wl_tbm_client_listener = {
251         handle_tbm_buffer_import_with_id,
252         handle_tbm_buffer_import_with_fd,
253         handle_buffer_destroy,
254 };
255
256 void _waylend_tbm_monitor_client_print_show_to_file(char* show_str)
257 {
258         FILE * f = NULL;
259         static int c = 0;
260         char tmp_file[256];
261
262         snprintf(tmp_file, sizeof(tmp_file), "/tmp/tbm_debug_show_%d%d", getpid(), c++);
263         if ((f = fopen(tmp_file, "a+")) != NULL) {
264                 fprintf(f, "%s", show_str);
265                 fclose(f);
266         }
267 }
268
269 void _waylend_tbm_monitor_client_show(int argc, char *argv[],
270                                       char *reply, int *len, struct wayland_tbm_client *tbm_client)
271 {
272         struct wayland_tbm_monitor_path path = {0};
273         char *show_str;
274
275         _wayland_tbm_util_show_path_parse(argv[2], 0, &path);
276
277         if (path.dlog)
278                 tbm_bufmgr_debug_show(tbm_client->bufmgr);
279
280         /* we have to save result to some file as reply can be very long */
281         show_str = tbm_bufmgr_debug_tbm_info_get(tbm_client->bufmgr);
282         if (show_str) {
283                 _waylend_tbm_monitor_client_print_show_to_file(show_str);
284                 free(show_str);
285         }
286
287
288         /* send empty string to close the session */
289         WL_TBM_MONITOR_SNPRINTF(reply, *len, "\n");
290 }
291
292 void _waylend_tbm_monitor_client_dump_snapshot(int argc, char *argv[],
293                                       char *reply, int *len, struct wayland_tbm_client *tbm_client)
294 {
295         double scale = 0;
296         int i;
297
298         for (i = 1; i < argc; i++) {
299                 if (_waylend_tbm_util_scale_parse(argv[i], &scale))
300                         break;
301         }
302
303         _waylend_tbm_util_dump_snapshot(tbm_client->bufmgr, scale);
304         WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): snapshot dump is done\n", getpid());
305 }
306
307 void _waylend_tbm_monitor_client_dump_queue(int argc, char *argv[],
308                                       char *reply, int *len, struct wayland_tbm_client *tbm_client)
309 {
310         int st;
311         double scale = 0;
312         int i;
313
314         st = _waylend_tbm_util_proc_state_parse(argv[1]);
315
316         for (i = 2; i < argc; i++) {
317                 if (_waylend_tbm_util_scale_parse(argv[i], &scale))
318                         break;
319         }
320
321         st = _waylend_tbm_util_dump_queue(st, tbm_client->bufmgr, scale);
322         WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): queue dump state: %s\n", getpid(),
323                                                         st ? "on" : "off");
324 }
325
326 void _waylend_tbm_monitor_client_trace(int argc, char *argv[],
327                                       char *reply, int *len, struct wayland_tbm_client *tbm_client)
328 {
329         int st;
330
331         st = _waylend_tbm_util_trace(_waylend_tbm_util_proc_state_parse(argv[1]), tbm_client->bufmgr);
332         WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): trace state: %s\n", getpid() ,
333                                                         st ? "on" : "off");
334 }
335
336 static struct {
337         const char *opt;
338         void (*func)(int argc, char *argv[], char *reply, int *len, struct wayland_tbm_client *tbm_client);
339 } option_proc[] = {
340         {
341                 "show",
342                 _waylend_tbm_monitor_client_show,
343         },
344         {
345                 "dump_snapshot",
346                 _waylend_tbm_monitor_client_dump_snapshot,
347         },
348         {
349                 "dump_queue",
350                 _waylend_tbm_monitor_client_dump_queue,
351         },
352         {
353                 "trace",
354                 _waylend_tbm_monitor_client_trace,
355         },
356 };
357
358 static void
359 handle_tbm_monitor_client_done(void *data, struct wl_tbm_monitor *wl_tbm_monitor, const char *message)
360 {
361 }
362
363 static void
364 handle_tbm_monitor_client_request_to_client(void *data, struct wl_tbm_monitor *wl_tbm_monitor,
365                                 const char * options, const char * request_id)
366 {
367         struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
368         char temp[1024];
369         char *argv[WL_TBM_MONITOR_ARGS_MAX] = {0};
370         int argc = 0;
371
372         char message[WL_TBM_MONITOR_REPLY_MSG_LEN] = {0,};
373         int len = sizeof(message);
374         char *reply = message;
375
376         char *end = NULL;
377         int i;
378
379         snprintf(temp, sizeof(temp), "%s", options);
380
381         argv[argc] = strtok_r(temp, " ", &end);
382         while (argv[argc]) {
383                 argc++;
384                 if (argc == WL_TBM_MONITOR_ARGS_MAX)
385                         break;
386                 argv[argc] = strtok_r(NULL, " ", &end);
387         }
388
389 #ifdef DEBUG_TRACE
390         WL_TBM_TRACE("receive request_id:%s argc:%d [%s %s] options:'%s'", request_id, argc, argv[0], argv[1], temp);
391 #endif
392
393         if (argc > 0) {
394                 for (i = 0; i < sizeof(option_proc) / sizeof(option_proc[0]); i++) {
395                         if (argv[0][0] == '-' && !strncmp(argv[0] + 1, option_proc[i].opt, 32)) {
396                                 if (option_proc[i].func) {
397                                         option_proc[i].func(argc, argv, reply, &len, tbm_client);
398                                         break;
399                                 }
400                         }
401                 }
402         }
403
404         wl_tbm_monitor_responce_to_server(tbm_monitor, message, request_id);
405 }
406
407 static const struct wl_tbm_monitor_listener wl_tbm_monitor_listener = {
408                 handle_tbm_monitor_client_done,
409                 handle_tbm_monitor_client_request_to_client,
410 };
411
412 static void
413 _wayland_tbm_client_registry_handle_global(void *data,
414                                 struct wl_registry *registry, uint32_t name,
415                                 const char *interface, uint32_t version)
416 {
417         struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
418
419         if (!strcmp(interface, "wl_tbm")) {
420                 tbm_client->wl_tbm = wl_registry_bind(registry, name, &wl_tbm_interface,
421                                                       version);
422                 WL_TBM_RETURN_IF_FAIL(tbm_client->wl_tbm != NULL);
423
424                 wl_tbm_add_listener(tbm_client->wl_tbm, &wl_tbm_client_listener, tbm_client);
425
426                 if (!tbm_client->bufmgr) {
427                         tbm_client->bufmgr = tbm_bufmgr_init(-1);
428                         if (!tbm_client->bufmgr) {
429                                 WL_TBM_LOG("failed to get auth_info");
430                                 wl_tbm_destroy(tbm_client->wl_tbm);
431                                 tbm_client->wl_tbm = NULL;
432                                 return;
433                         }
434                 }
435         } else if (!strcmp(interface, "wl_tbm_monitor")) {
436                 /*Create wl_monotor proxy by sington*/
437                 if (tbm_monitor)
438                         return;
439
440                 tbm_monitor = wl_registry_bind(registry, name, &wl_tbm_monitor_interface, version);
441                 WL_TBM_RETURN_IF_FAIL(tbm_monitor != NULL);
442
443                 wl_proxy_set_queue((struct wl_proxy *)tbm_monitor, NULL);
444
445                 wl_tbm_monitor_add_listener(tbm_monitor, &wl_tbm_monitor_listener, tbm_client);
446         }
447 }
448
449 static const struct wl_registry_listener registry_listener = {
450         _wayland_tbm_client_registry_handle_global,
451         NULL
452 };
453
454 int
455 wayland_tbm_client_set_event_queue(struct wayland_tbm_client *tbm_client, struct wl_event_queue *queue)
456 {
457         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
458
459         wl_proxy_set_queue((struct wl_proxy *)tbm_client->wl_tbm, queue);
460         tbm_client->event_queue = queue;
461
462         return 1;
463 }
464
465 struct wayland_tbm_client *
466 wayland_tbm_client_init(struct wl_display *display)
467 {
468         WL_TBM_RETURN_VAL_IF_FAIL(display != NULL, NULL);
469
470         struct wl_display *display_wrapper;
471         struct wayland_tbm_client *tbm_client;
472         struct wl_event_queue *wl_queue;
473         struct wl_registry *wl_registry;
474
475         _wayland_tbm_check_dlog_enable();
476
477         bTrace = 0;
478
479         tbm_client = calloc(1, sizeof(struct wayland_tbm_client));
480         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
481
482         tbm_client->dpy = display;
483
484         display_wrapper = wl_proxy_create_wrapper(display);
485         if (!display_wrapper) {
486                 WL_TBM_LOG("Failed to create display_wrapper.");
487                 free(tbm_client);
488                 return NULL;
489         }
490
491         wl_queue = wl_display_create_queue(display);
492         if (!wl_queue) {
493                 WL_TBM_LOG("Failed to create queue.");
494                 wl_proxy_wrapper_destroy(display_wrapper);
495                 free(tbm_client);
496                 return NULL;
497         }
498
499         wl_proxy_set_queue((struct wl_proxy *)display_wrapper, wl_queue);
500
501         wl_registry = wl_display_get_registry(display_wrapper);
502         wl_proxy_wrapper_destroy(display_wrapper);
503         if (!wl_registry) {
504                 WL_TBM_LOG("Failed to get registry");
505
506                 wl_event_queue_destroy(wl_queue);
507                 free(tbm_client);
508                 return NULL;
509         }
510
511         wl_registry_add_listener(wl_registry, &registry_listener, tbm_client);
512         if (wl_display_roundtrip_queue(display, wl_queue) < 0) {
513                 WL_TBM_LOG("Failed to wl_display_roundtrip_queue");
514
515                 wl_registry_destroy(wl_registry);
516                 wl_event_queue_destroy(wl_queue);
517                 free(tbm_client);
518                 return NULL;
519         }
520
521         wl_event_queue_destroy(wl_queue);
522         wl_registry_destroy(wl_registry);
523
524         /* check wl_tbm */
525         if (!tbm_client->wl_tbm) {
526                 WL_TBM_LOG("failed to create wl_tbm");
527                 wayland_tbm_client_deinit(tbm_client);
528                 return NULL;
529         }
530
531         /*
532          * wl_tbm's queue is destroyed above. We should make wl_tbm's queue to
533          * use display's default_queue.
534          */
535         wl_proxy_set_queue((struct wl_proxy *)tbm_client->wl_tbm, NULL);
536
537         /* queue_info list */
538         wl_list_init(&tbm_client->queue_info_list);
539
540         return tbm_client;
541 }
542
543 void
544 wayland_tbm_client_deinit(struct wayland_tbm_client *tbm_client)
545 {
546         if (!tbm_client)
547                 return;
548
549         if (tbm_client->bufmgr)
550                 tbm_bufmgr_deinit(tbm_client->bufmgr);
551
552         if (tbm_client->wl_tbm) {
553                 wl_tbm_set_user_data(tbm_client->wl_tbm, NULL);
554                 wl_tbm_destroy(tbm_client->wl_tbm);
555         }
556
557         if (tbm_monitor
558                 && (tbm_client == wl_tbm_monitor_get_user_data(tbm_monitor))) {
559                 wl_tbm_monitor_destroy(tbm_monitor);
560                 tbm_monitor = NULL;
561         }
562
563         free(tbm_client);
564 }
565
566 struct wayland_tbm_buffer *
567 _wayland_tbm_client_find_tbm_buffer_wl_buffer(struct wayland_tbm_client *tbm_client,
568                                 struct wl_buffer *wl_buffer)
569 {
570         struct wayland_tbm_surface_queue *queue_info = NULL;
571
572         if (wl_list_empty(&tbm_client->queue_info_list)) return NULL;
573
574         wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
575                 struct wayland_tbm_buffer *buffer = NULL;
576
577                 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
578                         if (buffer->wl_buffer == wl_buffer)
579                                 return buffer;
580                 }
581         }
582
583         return NULL;
584 }
585
586 struct wayland_tbm_buffer *
587 _wayland_tbm_client_find_tbm_buffer_surface(struct wayland_tbm_client *tbm_client,
588                                 tbm_surface_h surface)
589 {
590         struct wayland_tbm_surface_queue *queue_info = NULL;
591
592         if (wl_list_empty(&tbm_client->queue_info_list)) return NULL;
593
594         wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
595                 struct wayland_tbm_buffer *buffer = NULL;
596
597                 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
598                         if (buffer->tbm_surface == surface)
599                                 return buffer;
600                 }
601         }
602
603         return NULL;
604 }
605
606 struct wl_buffer *
607 wayland_tbm_client_create_buffer(struct wayland_tbm_client *tbm_client,
608                                  tbm_surface_h surface)
609 {
610         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
611         WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
612
613         int bufs[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};
614         struct wl_buffer *wl_buffer = NULL;
615         struct wayland_tbm_buffer *buffer = NULL;
616         int num_buf, is_fd = -1, i;
617         char debug_id[64] = {0, };
618         tbm_surface_info_s info;
619         uint32_t flags = 0;
620         struct wl_array plane_buf_idx, plane_offset, plane_stride, plane_size;
621         int *p;
622
623         /*
624          * if the surface is the attached surface from display server,
625          * return the wl_buffer of the attached surface
626          */
627
628         buffer = _wayland_tbm_client_find_tbm_buffer_surface(tbm_client, surface);
629         if (buffer)
630                 return buffer->wl_buffer;
631
632         if (tbm_surface_get_info(surface, &info) != TBM_SURFACE_ERROR_NONE) {
633                 WL_TBM_LOG("Failed to create buffer from surface");
634                 return NULL;
635         }
636
637         if (info.num_planes > 3) {
638                 WL_TBM_LOG("invalid num_planes(%d)", info.num_planes);
639                 return NULL;
640         }
641
642         num_buf = tbm_surface_internal_get_num_bos(surface);
643         if (num_buf == 0) {
644                 WL_TBM_LOG("surface doesn't have any bo.");
645                 return NULL;
646         }
647
648         for (i = 0; i < num_buf; i++) {
649                 tbm_bo bo = tbm_surface_internal_get_bo(surface, i);
650                 if (bo == NULL) {
651                         WL_TBM_LOG("Failed to get bo from surface");
652                         goto err;
653                 }
654
655                 /* try to get fd first */
656                 if (is_fd == -1 || is_fd == 1) {
657                         bufs[i] = tbm_bo_export_fd(bo);
658                         if (is_fd == -1 && bufs[i] >= 0)
659                                 is_fd = 1;
660                 }
661
662                 /* if fail to get fd, try to get name second */
663                 if (is_fd == -1 || is_fd == 0) {
664                         bufs[i] = tbm_bo_export(bo);
665                         if (is_fd == -1 && bufs[i] > 0)
666                                 is_fd = 0;
667                 }
668
669                 if (is_fd == -1 ||
670                     (is_fd == 1 && bufs[i] < 0) ||
671                     (is_fd == 0 && bufs[i] <= 0)) {
672                         WL_TBM_LOG("Failed to export(is_fd:%d, bufs:%d)", is_fd, bufs[i]);
673                         goto err;
674                 }
675         }
676
677         wl_array_init(&plane_buf_idx);
678         wl_array_init(&plane_offset);
679         wl_array_init(&plane_stride);
680         wl_array_init(&plane_size);
681
682         for (i = 0; i < 3; i++) {
683                 p = wl_array_add(&plane_buf_idx, sizeof(int));
684                 *p = tbm_surface_internal_get_plane_bo_idx(surface, i);
685                 p = wl_array_add(&plane_offset, sizeof(int));
686                 *p = info.planes[i].offset;
687                 p = wl_array_add(&plane_stride, sizeof(int));
688                 *p = info.planes[i].stride;
689                 p = wl_array_add(&plane_size, sizeof(int));
690                 *p = info.planes[i].size;
691         }
692
693         if (is_fd == 1)
694                 wl_buffer = wl_tbm_create_buffer_with_fd(tbm_client->wl_tbm,
695                                 info.width, info.height, info.format, info.bpp, info.size, info.num_planes,
696                                 &plane_buf_idx, &plane_offset, &plane_stride, &plane_size,
697                                 flags, num_buf, bufs[0],
698                                 (bufs[1] == -1) ? bufs[0] : bufs[1],
699                                 (bufs[2] == -1) ? bufs[0] : bufs[2]);
700         else
701                 wl_buffer = wl_tbm_create_buffer(tbm_client->wl_tbm,
702                                  info.width, info.height, info.format, info.bpp, info.size, info.num_planes,
703                                  &plane_buf_idx, &plane_offset, &plane_stride, &plane_size,
704                                  flags,
705                                  num_buf, bufs[0], bufs[1], bufs[2]);
706
707         wl_array_release(&plane_buf_idx);
708         wl_array_release(&plane_offset);
709         wl_array_release(&plane_stride);
710         wl_array_release(&plane_size);
711
712         if (!wl_buffer) {
713                 WL_TBM_LOG("Failed to create wl_buffer");
714                 goto err;
715         }
716
717         for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {
718                 if (is_fd == 1 && (bufs[i] >= 0))
719                         close(bufs[i]);
720         }
721
722         wl_buffer_set_user_data(wl_buffer, surface);
723
724         snprintf(debug_id, sizeof(debug_id), "%u",
725                 (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
726         tbm_surface_internal_set_debug_data(surface, "id", debug_id);
727
728 #ifdef DEBUG_TRACE
729         WL_TBM_TRACE("        pid:%d wl_buffer:%p tbm_surface:%p", getpid(),
730                         wl_buffer, surface);
731 #endif
732
733         return wl_buffer;
734
735 err:
736         for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {
737                 if (is_fd == 1 && (bufs[i] >= 0))
738                         close(bufs[i]);
739         }
740
741         return NULL;
742 }
743
744 void
745 wayland_tbm_client_destroy_buffer(struct wayland_tbm_client *tbm_client,
746                                   struct wl_buffer *wl_buffer)
747 {
748         struct wayland_tbm_buffer *buffer = NULL;
749
750         WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
751         WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
752
753         // TODO: valid check if the buffer is from this tbm_client???
754
755 #ifdef DEBUG_TRACE
756         WL_TBM_TRACE("       pid:%d wl_buffer:%p", getpid(), wl_buffer);
757 #endif
758
759         buffer = _wayland_tbm_client_find_tbm_buffer_wl_buffer(tbm_client, wl_buffer);
760         if (buffer)
761                 buffer->wl_buffer = NULL;
762
763         wl_buffer_set_user_data(wl_buffer, NULL);
764         wl_buffer_destroy(wl_buffer);
765 }
766
767 void
768 wayland_tbm_client_set_sync_timeline(struct wayland_tbm_client *tbm_client,
769                                                                 struct wl_buffer *wl_buffer, tbm_fd timeline)
770 {
771         WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
772         WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
773
774         wl_tbm_set_sync_timeline(tbm_client->wl_tbm, wl_buffer, timeline);
775 }
776
777 void
778 wayland_tbm_client_set_buffer_transform(struct wayland_tbm_client *tbm_client,
779                                                                 struct wl_buffer *wl_buffer, int transform)
780 {
781         WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
782         WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
783         WL_TBM_RETURN_IF_FAIL(transform >= 0);
784
785         wl_tbm_set_buffer_transform(tbm_client->wl_tbm, wl_buffer, transform);
786 }
787
788 void *
789 wayland_tbm_client_get_bufmgr(struct wayland_tbm_client *tbm_client)
790 {
791         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
792
793         return (void *)tbm_client->bufmgr;
794 }
795
796 static void
797 _wayland_tbm_client_queue_destroy_attach_bufs(struct wayland_tbm_surface_queue *queue_info)
798 {
799         struct wayland_tbm_buffer *buffer, *tmp;
800
801         wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
802 #ifdef DEBUG_TRACE
803                 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), buffer->wl_buffer, buffer->tbm_surface);
804 #endif
805                 if (buffer->wl_buffer) {
806                         wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
807
808                         if (!buffer->reuse) {
809 #ifdef DEBUG_TRACE
810                                 WL_TBM_TRACE("destroy the wl_buffer:%p", buffer->wl_buffer);
811 #endif
812                                 wl_buffer_destroy(buffer->wl_buffer);
813                                 buffer->wl_buffer = NULL;
814                         }
815                 }
816
817                 tbm_surface_internal_unref(buffer->tbm_surface);
818                 wl_list_remove(&buffer->link);
819                 free(buffer);
820         }
821 }
822
823 static void
824 _wayland_tbm_client_queue_destroy_unused_attach_bufs(struct wayland_tbm_surface_queue *queue_info)
825 {
826         struct wayland_tbm_buffer *buffer, *tmp;
827
828         wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
829                 if (buffer->allocated) continue;
830 #ifdef DEBUG_TRACE
831                 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), buffer->wl_buffer, buffer->tbm_surface);
832 #endif
833                 if (buffer->wl_buffer) {
834                         wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
835
836                         if (!buffer->reuse) {
837 #ifdef DEBUG_TRACE
838                                 WL_TBM_TRACE("destroy the wl_buffer:%p", buffer->wl_buffer);
839 #endif
840                                 wl_buffer_destroy(buffer->wl_buffer);
841                                 buffer->wl_buffer = NULL;
842                         }
843                 }
844
845                 tbm_surface_internal_unref(buffer->tbm_surface);
846                 wl_list_remove(&buffer->link);
847                 free(buffer);
848         }
849 }
850
851 static void
852 _wayland_tbm_client_surface_queue_flush(struct wayland_tbm_surface_queue *queue_info)
853 {
854 #ifdef DEBUG_TRACE
855         WL_TBM_TRACE("pid:%d", getpid());
856 #endif
857
858         _wayland_tbm_client_queue_destroy_unused_attach_bufs(queue_info);
859         tbm_surface_queue_set_size(queue_info->tbm_queue, queue_info->queue_size, 1);
860 }
861
862 static tbm_surface_h
863 _wayland_tbm_client_create_surface_from_param(tbm_bufmgr bufmgr,
864                                                          int is_fd,
865                                                          int32_t width,
866                                                          int32_t height,
867                                                          uint32_t format,
868                                                          int32_t bpp,
869                                                          int32_t size,
870                                                          int32_t num_plane,
871                                                          struct wl_array *plane_buf_idx,
872                                                          struct wl_array *plane_offset,
873                                                          struct wl_array *plane_stride,
874                                                          struct wl_array *plane_size,
875                                                          uint32_t flags,
876                                                          int32_t num_buf,
877                                                          uint32_t buf0,
878                                                          uint32_t buf1,
879                                                          uint32_t buf2)
880 {
881         int32_t names[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};
882         tbm_surface_info_s info = { 0, };
883         tbm_bo bos[TBM_SURF_PLANE_MAX];
884         int i, numPlane, numName;
885         tbm_surface_h tbm_surface;
886
887         numPlane = tbm_surface_internal_get_num_planes(format);
888         WL_TBM_RETURN_VAL_IF_FAIL(numPlane == num_plane, NULL);
889
890         info.width = width;
891         info.height = height;
892         info.format = format;
893         info.bpp = bpp;
894         info.size = size;
895         info.num_planes = numPlane;
896
897         /*Fill plane info*/
898         for (i = 0; i < numPlane; i++) {
899                 info.planes[i].offset = *WL_TBM_ARRAY_NTH_DATA(plane_offset, int32_t, i);
900                 info.planes[i].stride = *WL_TBM_ARRAY_NTH_DATA(plane_stride, int32_t, i);
901                 info.planes[i].size = *WL_TBM_ARRAY_NTH_DATA(plane_size, int32_t, i);
902         }
903
904         /*Fill buffer*/
905         numName = num_buf;
906         names[0] = buf0;
907         names[1] = buf1;
908         names[2] = buf2;
909
910         for (i = 0; i < numName; i++) {
911                 if (is_fd)
912                         bos[i] = tbm_bo_import_fd(bufmgr, names[i]);
913                 else
914                         bos[i] = tbm_bo_import(bufmgr, names[i]);
915         }
916
917         tbm_surface = tbm_surface_internal_create_with_bos(&info, bos, numName);
918         if (tbm_surface == NULL) {
919                 if (is_fd) {
920                         close(buf0);
921                         close(buf1);
922                         close(buf2);
923                 }
924                 return NULL;
925         }
926
927         if (is_fd) {
928                 close(buf0);
929                 close(buf1);
930                 close(buf2);
931         }
932
933         for (i = 0; i < numName; i++)
934                 tbm_bo_unref(bos[i]);
935
936         return tbm_surface;
937 }
938
939 static int
940 _wayland_tbm_client_is_valid_attach_bufs(struct wayland_tbm_surface_queue *queue_info,
941          struct wayland_tbm_buffer *buffer)
942 {
943         int width, height, format;
944
945         width = tbm_surface_get_width(buffer->tbm_surface);
946         height = tbm_surface_get_height(buffer->tbm_surface);
947         format = tbm_surface_get_format(buffer->tbm_surface);
948
949         if (queue_info->width != width ||
950                 queue_info->height != height ||
951                 queue_info->format != format)
952                 return 0;
953
954         return 1;
955 }
956
957 static tbm_surface_h
958 __wayland_tbm_client_surface_alloc_cb(tbm_surface_queue_h surface_queue, void *data)
959 {
960         struct wayland_tbm_surface_queue *queue_info =
961                                 (struct wayland_tbm_surface_queue *)data;
962         struct wayland_tbm_buffer *buffer;
963         tbm_surface_h surface = NULL;
964
965         if (queue_info->is_active && queue_info->active_flush) {
966                 wl_list_for_each_reverse(buffer, &queue_info->attach_bufs, link) {
967                         if (!buffer->allocated && buffer->usable) {
968                                 if (_wayland_tbm_client_is_valid_attach_bufs(queue_info, buffer)) {
969                                         surface = buffer->tbm_surface;
970                                         /* ref.. pair of __wayland_tbm_client_surface_free_cb */
971                                         tbm_surface_internal_ref(surface);
972                                         buffer->allocated = 1;
973 #ifdef DEBUG_TRACE
974                                         WL_TBM_TRACE("   pid:%d wl_buffer:%p tbm_surface:%p ACTIVE", getpid(), buffer->wl_buffer, buffer->tbm_surface);
975 #endif
976                                 } else {
977                                         surface = tbm_surface_internal_create_with_flags(queue_info->width,
978                                                 queue_info->height,
979                                                 queue_info->format,
980                                                 queue_info->flag);
981 #ifdef DEBUG_TRACE
982                                         WL_TBM_TRACE("   pid:%d tbm_surface:%p invalid attach_bufs fallback", getpid(), surface);
983 #endif
984                                 }
985
986                                 break;
987                         }
988                 }
989         } else {
990                 /* ref.. pair of __wayland_tbm_client_surface_free_cb */
991                 surface = tbm_surface_internal_create_with_flags(queue_info->width,
992                                                         queue_info->height,
993                                                         queue_info->format,
994                                                         queue_info->flag);
995
996 #ifdef DEBUG_TRACE
997                 WL_TBM_TRACE("   pid:%d tbm_surface:%p DEACTIVE", getpid(), surface);
998 #endif
999         }
1000
1001         return surface;
1002 }
1003
1004 static void
1005 __wayland_tbm_client_surface_free_cb(tbm_surface_queue_h surface_queue, void *data,
1006                       tbm_surface_h surface)
1007 {
1008 #ifdef DEBUG_TRACE
1009         WL_TBM_TRACE("    pid:%d tbm_surface:%p", getpid(), surface);
1010 #endif
1011         struct wayland_tbm_surface_queue *queue_info =
1012                                 (struct wayland_tbm_surface_queue *)data;
1013         struct wayland_tbm_buffer *buffer, *tmp;
1014
1015         wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
1016                 if (buffer->tbm_surface != surface) continue;
1017                 if (!buffer->allocated) continue;
1018
1019                 buffer->allocated = 0;
1020                 buffer->reuse = 1;
1021
1022                 if (queue_info->is_active) continue;
1023                 if (buffer->wl_buffer)
1024                         wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
1025
1026                 tbm_surface_internal_unref(buffer->tbm_surface);
1027                 wl_list_remove(&buffer->link);
1028                 free(buffer);
1029         }
1030
1031         /* unref.. pair of __wayland_tbm_client_surface_alloc_cb */
1032         tbm_surface_internal_unref(surface);
1033 }
1034
1035 static void
1036 handle_tbm_queue_buffer_attached(void *data,
1037                                         struct wl_tbm_queue *wl_tbm_queue,
1038                                         struct wl_buffer *wl_buffer,
1039                                         uint32_t flags)
1040 {
1041         struct wayland_tbm_surface_queue *queue_info =
1042                                 (struct wayland_tbm_surface_queue *)data;
1043         struct wayland_tbm_buffer *buffer;
1044
1045         WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
1046
1047         buffer = calloc(1, sizeof(struct wayland_tbm_buffer));
1048         WL_TBM_GOTO_IF_FAIL(buffer != NULL, fail_alloc);
1049
1050         wl_list_init(&buffer->link);
1051
1052         buffer->wl_tbm_queue = wl_tbm_queue;
1053         buffer->wl_buffer = wl_buffer;
1054         buffer->allocated = 0;
1055
1056         buffer->tbm_surface = (tbm_surface_h)wl_buffer_get_user_data(wl_buffer);
1057         WL_TBM_GOTO_IF_FAIL(buffer->tbm_surface != NULL, fail_get_data);
1058         buffer->flags = flags;
1059
1060         wl_list_insert(&queue_info->attach_bufs, &buffer->link);
1061
1062 #ifdef DEBUG_TRACE
1063         WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p",
1064                         getpid(), buffer->wl_buffer, buffer->tbm_surface);
1065 #endif
1066
1067         return;
1068
1069 fail_get_data:
1070         free(buffer);
1071 fail_alloc:
1072         wl_buffer_destroy(wl_buffer);
1073 }
1074
1075 static void
1076 handle_tbm_queue_active(void *data,
1077                         struct wl_tbm_queue *wl_tbm_queue,
1078                         uint32_t usage,
1079                         uint32_t queue_size,
1080                         uint32_t need_flush)
1081 {
1082         struct wayland_tbm_surface_queue *queue_info =
1083                                 (struct wayland_tbm_surface_queue *)data;
1084
1085         WL_TBM_LOG("active queue");
1086
1087         if (queue_info->is_active) {
1088                 WL_TBM_C_LOG("warning: queue_info is already activated");
1089                 return;
1090         }
1091 #ifdef DEBUG_TRACE
1092         WL_TBM_TRACE("                  pid:%d", getpid());
1093 #endif
1094
1095         queue_info->is_active = 1;
1096         queue_info->usage = usage;
1097
1098         if (need_flush) {
1099                 /* flush the allocated surfaces at the client */
1100                 queue_info->active_flush = need_flush;
1101                 tbm_surface_queue_set_size(queue_info->tbm_queue, queue_size, 1);
1102         }
1103 }
1104
1105 static void
1106 handle_tbm_queue_deactive(void *data,
1107                           struct wl_tbm_queue *wl_tbm_queue)
1108 {
1109         struct wayland_tbm_surface_queue *queue_info =
1110                                 (struct wayland_tbm_surface_queue *)data;
1111
1112 #ifdef DEBUG_TRACE
1113         WL_TBM_TRACE("                  pid:%d", getpid());
1114 #endif
1115
1116         WL_TBM_LOG("deactive queue");
1117
1118         if (!queue_info->is_active) {
1119                 WL_TBM_C_LOG("warning: queue_info is already deactivated");
1120                 return;
1121         }
1122
1123         queue_info->is_active = 0;
1124
1125         if (queue_info->active_flush) {
1126                 queue_info->active_flush = 0;
1127                 /* flush the attached surfaces */
1128                 _wayland_tbm_client_surface_queue_flush(queue_info);
1129         }
1130 }
1131
1132 static void
1133 handle_tbm_queue_flush(void *data,
1134                        struct wl_tbm_queue *wl_tbm_queue)
1135 {
1136         struct wayland_tbm_surface_queue *queue_info =
1137                                 (struct wayland_tbm_surface_queue *)data;
1138
1139 #ifdef DEBUG_TRACE
1140         WL_TBM_TRACE("pid:%d", getpid());
1141 #endif
1142         WL_TBM_LOG("flush queue");
1143
1144         if (queue_info->is_active && queue_info->active_flush) {
1145                 WL_TBM_C_LOG("warning: Cannot flush the tbm_surface_queueu. The queue is activate.");
1146                 return;
1147         }
1148
1149         /* flush the allocated surfaces at the client */
1150         tbm_surface_queue_flush(queue_info->tbm_queue);
1151 }
1152
1153 static void
1154 handle_tbm_queue_buffer_usable(void *data,
1155                                         struct wl_tbm_queue *wl_tbm_queue,
1156                                         struct wl_buffer *wl_buffer)
1157 {
1158         struct wayland_tbm_surface_queue *queue_info =
1159                                 (struct wayland_tbm_surface_queue *)data;
1160         struct wayland_tbm_buffer *buffer;
1161
1162         WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
1163
1164         wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1165                 if (buffer->wl_buffer == wl_buffer)
1166                         buffer->usable = 1;
1167         }
1168
1169 #ifdef DEBUG_TRACE
1170         WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p",
1171                         getpid(), buffer->wl_buffer, buffer->tbm_surface);
1172 #endif
1173
1174         tbm_surface_queue_notify_dequeuable(queue_info->tbm_queue);
1175
1176         return;
1177 }
1178
1179 const struct wl_tbm_queue_listener wl_tbm_queue_listener = {
1180         handle_tbm_queue_buffer_attached,
1181         handle_tbm_queue_active,
1182         handle_tbm_queue_deactive,
1183         handle_tbm_queue_flush,
1184         handle_tbm_queue_buffer_usable,
1185 };
1186
1187 static struct wayland_tbm_surface_queue *
1188 _wayland_tbm_client_find_queue_info_wl_surface(struct wayland_tbm_client *tbm_client,
1189                                         struct wl_surface *surface)
1190 {
1191         /* set the debug_pid to the surface for debugging */
1192         if (!wl_list_empty(&tbm_client->queue_info_list)) {
1193                 struct wayland_tbm_surface_queue *queue_info = NULL;
1194
1195                 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
1196                         if (queue_info->wl_surface == surface)
1197                                 return queue_info;
1198                 }
1199         }
1200
1201         return NULL;
1202 }
1203
1204 static struct wayland_tbm_surface_queue *
1205 _wayland_tbm_client_find_queue_info_queue(struct wayland_tbm_client *tbm_client,
1206                                         tbm_surface_queue_h queue)
1207 {
1208         /* set the debug_pid to the surface for debugging */
1209         if (!wl_list_empty(&tbm_client->queue_info_list)) {
1210                 struct wayland_tbm_surface_queue *queue_info = NULL;
1211
1212                 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
1213                         if (queue_info->tbm_queue == queue)
1214                                 return queue_info;
1215                 }
1216         }
1217
1218         return NULL;
1219 }
1220
1221
1222 static void
1223 _handle_tbm_surface_queue_destroy_notify(tbm_surface_queue_h surface_queue,
1224                 void *data)
1225 {
1226         struct wayland_tbm_surface_queue *queue_info =
1227                                 (struct wayland_tbm_surface_queue *)data;
1228
1229 #ifdef DEBUG_TRACE
1230         WL_TBM_TRACE(" pid:%d", getpid());
1231 #endif
1232
1233         /* remove the attach_bufs int the queue_info */
1234         _wayland_tbm_client_queue_destroy_attach_bufs(queue_info);
1235
1236         if (queue_info->wl_tbm_queue)
1237                 wl_tbm_queue_destroy(queue_info->wl_tbm_queue);
1238
1239         wl_list_remove(&queue_info->link);
1240         free(queue_info);
1241 }
1242
1243 static void
1244 _handle_tbm_surface_queue_reset_notify(tbm_surface_queue_h surface_queue,
1245                 void *data)
1246 {
1247         struct wayland_tbm_surface_queue *queue_info = data;
1248         int width;
1249         int height;
1250         int format;
1251
1252 #ifdef DEBUG_TRACE
1253         WL_TBM_TRACE(" pid:%d", getpid());
1254 #endif
1255
1256         width = tbm_surface_queue_get_width(surface_queue);
1257         height = tbm_surface_queue_get_height(surface_queue);
1258         format = tbm_surface_queue_get_format(surface_queue);
1259
1260         queue_info->width = width;
1261         queue_info->height = height;
1262         queue_info->format = format;
1263 }
1264
1265 static void
1266 _handle_tbm_surface_queue_can_dequeue_notify(tbm_surface_queue_h surface_queue,
1267                 void *data)
1268 {
1269         struct wayland_tbm_surface_queue *queue_info = data;
1270         struct wayland_tbm_client *tbm_client = NULL;
1271
1272         WL_TBM_RETURN_IF_FAIL(queue_info != NULL);
1273
1274         if (!queue_info->is_active || !queue_info->active_flush) return;
1275
1276         tbm_client = wl_tbm_get_user_data(queue_info->wl_tbm);
1277         WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
1278
1279         if (!tbm_client->event_queue) return;
1280
1281         if (wl_display_roundtrip_queue(tbm_client->dpy, tbm_client->event_queue) == -1) {
1282                 int dpy_err;
1283
1284                 WL_TBM_LOG_E("failed to wl_display_roundtrip_queue errno:%d", errno);
1285
1286                 dpy_err = wl_display_get_error(tbm_client->dpy);
1287                 if (dpy_err == EPROTO) {
1288                         const struct wl_interface *interface;
1289                         uint32_t proxy_id, code;
1290                         code = wl_display_get_protocol_error(tbm_client->dpy, &interface, &proxy_id);
1291                         WL_TBM_LOG_E("protocol error interface:%s code:%d proxy_id:%d",
1292                                                  interface->name, code, proxy_id);
1293                 }
1294         }
1295 }
1296
1297 static void
1298 _handle_tbm_surface_queue_trace_notify(tbm_surface_queue_h surface_queue,
1299                 tbm_surface_h tbm_surface, tbm_surface_queue_trace trace, void *data)
1300 {
1301         struct wayland_tbm_surface_queue *queue_info = data;
1302         struct wl_buffer *wl_buffer = NULL;
1303         struct wayland_tbm_buffer *buffer = NULL;
1304
1305         WL_TBM_RETURN_IF_FAIL(queue_info != NULL);
1306
1307         if (trace != TBM_SURFACE_QUEUE_TRACE_DEQUEUE) return;
1308         if (!queue_info->is_active || !queue_info->active_flush) return;
1309
1310         wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1311                 if (buffer->tbm_surface == tbm_surface)
1312                         wl_buffer = buffer->wl_buffer;
1313         }
1314
1315         if (!wl_buffer) return;
1316
1317         wl_tbm_queue_dequeue_buffer(queue_info->wl_tbm_queue, wl_buffer);
1318 }
1319
1320 tbm_surface_queue_h
1321 wayland_tbm_client_create_surface_queue(struct wayland_tbm_client *tbm_client,
1322                                         struct wl_surface *surface,
1323                                         int queue_size,
1324                                         int width, int height, tbm_format format)
1325 {
1326         struct wayland_tbm_surface_queue *queue_info;
1327         struct wl_tbm_queue *queue;
1328
1329 #ifdef DEBUG_TRACE
1330         WL_TBM_TRACE(" pid:%d", getpid());
1331 #endif
1332
1333         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1334         WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
1335
1336         queue_info = calloc(1, sizeof(struct wayland_tbm_surface_queue));
1337         WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, NULL);
1338
1339         queue_info->wl_tbm = tbm_client->wl_tbm;
1340         queue_info->bufmgr = tbm_client->bufmgr;
1341         queue_info->wl_surface = surface;
1342         wl_list_init(&queue_info->attach_bufs);
1343
1344         queue = wl_tbm_create_surface_queue(tbm_client->wl_tbm, surface);
1345         WL_TBM_GOTO_IF_FAIL(queue != NULL, fail);
1346
1347         queue_info->wl_tbm_queue = queue;
1348
1349         wl_tbm_queue_add_listener(queue, &wl_tbm_queue_listener, queue_info);
1350
1351         queue_info->width = width;
1352         queue_info->height = height;
1353         queue_info->format = format;
1354         queue_info->flag = 0;
1355         queue_info->queue_size = queue_size;
1356
1357         queue_info->tbm_queue = tbm_surface_queue_sequence_create(queue_size,
1358                                 width, height, format, 0);
1359         WL_TBM_GOTO_IF_FAIL(queue_info->tbm_queue != NULL, fail);
1360
1361         tbm_surface_queue_set_alloc_cb(queue_info->tbm_queue,
1362                                         __wayland_tbm_client_surface_alloc_cb,
1363                                         __wayland_tbm_client_surface_free_cb,
1364                                         queue_info);
1365
1366         tbm_surface_queue_add_destroy_cb(queue_info->tbm_queue,
1367                                         _handle_tbm_surface_queue_destroy_notify,
1368                                         queue_info);
1369
1370         tbm_surface_queue_add_reset_cb(queue_info->tbm_queue,
1371                                         _handle_tbm_surface_queue_reset_notify, queue_info);
1372
1373         tbm_surface_queue_add_can_dequeue_cb(queue_info->tbm_queue,
1374                                         _handle_tbm_surface_queue_can_dequeue_notify, queue_info);
1375
1376         tbm_surface_queue_add_trace_cb(queue_info->tbm_queue,
1377                                         _handle_tbm_surface_queue_trace_notify, queue_info);
1378
1379 #ifdef DEBUG_TRACE
1380         WL_TBM_C_LOG("INFO cur(%dx%d fmt:0x%x num:%d) new(%dx%d fmt:0x%x num:%d)",
1381                 queue_info->width, queue_info->height,
1382                 queue_info->format, queue_info->num_bufs,
1383                 width, height, format, queue_size);
1384 #endif
1385
1386         /* add queue_info to the list */
1387         wl_list_insert(&tbm_client->queue_info_list, &queue_info->link);
1388
1389         return queue_info->tbm_queue;
1390
1391 fail:
1392         if (queue_info->wl_tbm_queue)
1393                 wl_tbm_queue_destroy(queue_info->wl_tbm_queue);
1394         free(queue_info);
1395         return NULL;
1396 }
1397
1398 struct wl_tbm_queue *
1399 wayland_tbm_client_get_wl_tbm_queue(struct wayland_tbm_client *tbm_client, struct wl_surface *surface)
1400 {
1401         struct wayland_tbm_surface_queue *queue_info = NULL;
1402
1403         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1404         WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
1405
1406         queue_info = _wayland_tbm_client_find_queue_info_wl_surface(tbm_client, surface);
1407         WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, NULL);
1408         WL_TBM_RETURN_VAL_IF_FAIL(queue_info->wl_tbm_queue != NULL, NULL);
1409
1410         return queue_info->wl_tbm_queue;
1411 }
1412
1413 struct wl_tbm *
1414 wayland_tbm_client_get_wl_tbm(struct wayland_tbm_client *tbm_client)
1415 {
1416         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1417
1418         return tbm_client->wl_tbm;
1419 }
1420
1421 int
1422 wayland_tbm_client_queue_check_activate(struct wayland_tbm_client *tbm_client, tbm_surface_queue_h queue)
1423 {
1424         struct wayland_tbm_surface_queue *queue_info = NULL;
1425
1426         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
1427         WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, 0);
1428
1429         queue_info = _wayland_tbm_client_find_queue_info_queue(tbm_client, queue);
1430         WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, 0);
1431
1432         if (queue_info->is_active) return 1;
1433
1434         return 0;
1435 }
1436
1437 int
1438 wayland_tbm_client_queue_get_surfaces(struct wayland_tbm_client *tbm_client,
1439                                         tbm_surface_queue_h queue, tbm_surface_h *surfaces, int *num)
1440 {
1441         struct wayland_tbm_surface_queue *queue_info = NULL;
1442         tbm_surface_h surface = NULL;
1443         struct wayland_tbm_buffer *buffer = NULL;
1444         tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
1445         tbm_surface_h *get_surfaces;
1446         int get_num = 0, dequeued_num = 0, index = 0;
1447         int i;
1448
1449         WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
1450         WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, 0);
1451
1452         queue_info = _wayland_tbm_client_find_queue_info_queue(tbm_client, queue);
1453         WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, 0);;
1454
1455         if (!surfaces && !num) {
1456                 WL_TBM_LOG_E("invalid parameter");
1457                 return 0;
1458         }
1459
1460         if (num) {
1461                 if (queue_info->is_active && queue_info->active_flush)
1462                         *num = wl_list_length(&queue_info->attach_bufs);
1463                 else
1464                         *num = queue_info->queue_size;
1465         }
1466
1467         if (surfaces) {
1468                 if (queue_info->is_active && queue_info->active_flush) {
1469                         wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1470                                 surfaces[index] = buffer->tbm_surface;
1471                                 index++;
1472                         }
1473                 } else {
1474                         get_surfaces = (tbm_surface_h *)calloc(queue_info->queue_size, sizeof(tbm_surface_h));
1475                         if (!get_surfaces) {
1476                                 WL_TBM_LOG_E("failed to alloc get_surfaces");
1477                                 goto fail;
1478                         }
1479
1480                         tsq_err = tbm_surface_queue_get_surfaces(queue, get_surfaces, &get_num);
1481                         if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
1482                                 WL_TBM_LOG_E("failed to tbm_surface_queue_get_surfaces");
1483                                 goto fail;
1484                         }
1485
1486                         for (i = 0; i < get_num; i++) {
1487                                 surfaces[index] = get_surfaces[i];
1488                                 index++;
1489                         }
1490
1491                         if (get_num < queue_info->queue_size) {
1492                                 for (i = 0; i < queue_info->queue_size - get_num; i++) {
1493                                         tsq_err  = tbm_surface_queue_dequeue(queue, &surface);
1494                                         if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
1495                                                 WL_TBM_LOG_E("failed to tbm_surface_queue_dequeue");
1496                                                 goto fail;
1497                                         }
1498
1499                                         dequeued_num++;
1500                                         surfaces[index] = surface;
1501                                         index++;
1502                                 }
1503                         }
1504
1505                         for (i = 0; i < dequeued_num; i++) {
1506                                 tsq_err  = tbm_surface_queue_release(queue, surfaces[get_num + i]);
1507                                 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
1508                                         WL_TBM_LOG_E("failed to tbm_surface_queue_release");
1509                         }
1510
1511                         if (get_surfaces)
1512                                 free(get_surfaces);
1513                 }
1514         }
1515
1516         return 1;
1517
1518 fail:
1519         if (num) *num = 0;
1520
1521         if (surfaces) {
1522                 for (i = 0; i < dequeued_num; i++) {
1523                         tsq_err  = tbm_surface_queue_release(queue, surfaces[get_num + i]);
1524                         if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
1525                                 WL_TBM_LOG_E("failed to tbm_surface_queue_release");
1526                 }
1527
1528                 if (get_surfaces)
1529                         free(get_surfaces);
1530         }
1531
1532         return 0;
1533 }