2 Copyright (C) 2015 Samsung Electronics co., Ltd. All Rights Reserved.
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>
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:
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
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.
39 #include <tbm_surface.h>
40 #include <tbm_surface_queue.h>
41 #include <tbm_surface_internal.h>
45 #include "wayland-tbm-client.h"
46 #include "wayland-tbm-client-protocol.h"
47 #include "wayland-tbm-int.h"
49 struct wayland_tbm_client {
50 struct wl_display *dpy;
51 struct wl_tbm *wl_tbm;
55 struct wl_list queue_info_list;
57 struct wl_event_queue *event_queue;
60 struct wayland_tbm_buffer {
61 struct wl_buffer *wl_buffer;
62 tbm_surface_h tbm_surface;
73 struct wl_tbm_queue *wl_tbm_queue;
77 struct wayland_tbm_surface_queue {
78 struct wl_tbm_queue *wl_tbm_queue;
87 struct wl_surface *wl_surface;
92 struct wl_list attach_bufs;
94 tbm_surface_queue_h tbm_queue;
96 struct wl_tbm *wl_tbm;
102 static struct wl_tbm_monitor *tbm_monitor;
106 #define WL_TBM_TRACE(fmt, ...) if (bTrace) WL_TBM_C_LOG(fmt, ##__VA_ARGS__)
108 #define WL_TBM_TRACE(fmt, ...)
111 struct wayland_tbm_buffer *
112 _wayland_tbm_client_find_tbm_buffer_wl_buffer(struct wayland_tbm_client *tbm_client,
113 struct wl_buffer *wl_buffer);
116 _wayland_tbm_client_create_surface_from_param(tbm_bufmgr bufmgr,
124 struct wl_array *plane_buf_idx,
125 struct wl_array *plane_offset,
126 struct wl_array *plane_stride,
127 struct wl_array *plane_size,
135 handle_tbm_buffer_import_with_id(void *data,
136 struct wl_tbm *wl_tbm,
137 struct wl_buffer *wl_buffer,
144 struct wl_array *plane_buf_idx,
145 struct wl_array *plane_offset,
146 struct wl_array *plane_stride,
147 struct wl_array *plane_size,
154 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
155 tbm_surface_h tbm_surface;
156 char debug_id[64] = {0, };
158 tbm_surface = _wayland_tbm_client_create_surface_from_param(tbm_client->bufmgr, 0,
159 width, height, format, bpp, size,
161 plane_buf_idx, plane_offset, plane_stride, plane_size,
165 WL_TBM_GOTO_IF_FAIL(tbm_surface != NULL, fail);
166 wl_buffer_set_user_data(wl_buffer, tbm_surface);
168 snprintf(debug_id, sizeof(debug_id), "%u", (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
169 tbm_surface_internal_set_debug_data(tbm_surface, "id", debug_id);
172 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), wl_buffer, tbm_surface);
179 wl_buffer_destroy(wl_buffer);
183 handle_tbm_buffer_import_with_fd(void *data,
184 struct wl_tbm *wl_tbm,
185 struct wl_buffer *wl_buffer,
192 struct wl_array *plane_buf_idx,
193 struct wl_array *plane_offset,
194 struct wl_array *plane_stride,
195 struct wl_array *plane_size,
202 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
203 tbm_surface_h tbm_surface;
204 char debug_id[64] = {0, };
206 tbm_surface = _wayland_tbm_client_create_surface_from_param(tbm_client->bufmgr, 1,
207 width, height, format, bpp, size,
209 plane_buf_idx, plane_offset, plane_stride, plane_size,
213 WL_TBM_GOTO_IF_FAIL(tbm_surface != NULL, fail);
215 wl_buffer_set_user_data(wl_buffer, tbm_surface);
217 snprintf(debug_id, sizeof(debug_id), "%u", (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
218 tbm_surface_internal_set_debug_data(tbm_surface, "id", debug_id);
221 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), wl_buffer, tbm_surface);
228 wl_buffer_destroy(wl_buffer);
232 handle_buffer_destroy(void *data,
233 struct wl_tbm *wl_tbm,
234 struct wl_buffer *wl_buffer)
236 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
237 tbm_surface_h tbm_surface;
238 struct wayland_tbm_buffer *buffer = NULL;
241 WL_TBM_TRACE(" pid:%d wl_buffer:%p", getpid(), wl_buffer);
244 buffer = _wayland_tbm_client_find_tbm_buffer_wl_buffer(tbm_client, wl_buffer);
246 buffer->wl_buffer = NULL;
248 tbm_surface = wl_buffer_get_user_data(wl_buffer);
250 tbm_surface_internal_unref(tbm_surface);
252 wl_buffer_set_user_data(wl_buffer, NULL);
253 wl_buffer_destroy(wl_buffer);
258 static const struct wl_tbm_listener wl_tbm_client_listener = {
259 handle_tbm_buffer_import_with_id,
260 handle_tbm_buffer_import_with_fd,
261 handle_buffer_destroy,
264 void _waylend_tbm_monitor_client_print_show_to_file(char* show_str)
270 snprintf(tmp_file, sizeof(tmp_file), "/tmp/tbm_debug_show_%d%d", getpid(), c++);
271 if ((f = fopen(tmp_file, "a+")) != NULL) {
272 fprintf(f, "%s", show_str);
277 void _waylend_tbm_monitor_client_show(int argc, char *argv[],
278 char *reply, int *len, struct wayland_tbm_client *tbm_client)
280 struct wayland_tbm_monitor_path path = {0};
283 _wayland_tbm_util_show_path_parse(argv[2], 0, &path);
286 tbm_bufmgr_debug_show(tbm_client->bufmgr);
288 /* we have to save result to some file as reply can be very long */
289 show_str = tbm_bufmgr_debug_tbm_info_get(tbm_client->bufmgr);
291 _waylend_tbm_monitor_client_print_show_to_file(show_str);
296 /* send empty string to close the session */
297 WL_TBM_MONITOR_SNPRINTF(reply, *len, "\n");
300 void _waylend_tbm_monitor_client_dump_snapshot(int argc, char *argv[],
301 char *reply, int *len, struct wayland_tbm_client *tbm_client)
307 for (i = 1; i < argc; i++) {
308 if (_waylend_tbm_util_scale_parse(argv[i], &scale))
312 path = _wayland_tbm_dump_directory_make();
313 _waylend_tbm_util_dump_snapshot(tbm_client->bufmgr, scale, path);
314 WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): snapshot dump is done. path=%s\n", getpid(), path);
318 void _waylend_tbm_monitor_client_dump_queue(int argc, char *argv[],
319 char *reply, int *len, struct wayland_tbm_client *tbm_client)
325 st = _waylend_tbm_util_proc_state_parse(argv[1]);
327 for (i = 2; i < argc; i++) {
328 if (_waylend_tbm_util_scale_parse(argv[i], &scale))
332 st = _waylend_tbm_util_dump_queue(st, tbm_client->bufmgr, scale);
333 WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): queue dump state: %s\n", getpid(),
337 void _waylend_tbm_monitor_client_trace(int argc, char *argv[],
338 char *reply, int *len, struct wayland_tbm_client *tbm_client)
342 st = _waylend_tbm_util_trace(_waylend_tbm_util_proc_state_parse(argv[1]),
343 _waylend_tbm_util_resource_parse(argv[2]),
345 WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): trace state: %s\n", getpid() ,
349 void _waylend_tbm_monitor_client_debug_level(int argc, char *argv[],
350 char *reply, int *len, struct wayland_tbm_client *tbm_client)
352 int debug_level = TBM_LOG_LEVEL_NONE;
355 for (i = 1; i < argc; i++) {
356 if (_waylend_tbm_util_debug_level_parse(argv[i], &debug_level))
360 _waylend_tbm_util_set_log_level(debug_level);
361 WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): set tbm_log debug_level(%d)\n", getpid(), debug_level);
366 void (*func)(int argc, char *argv[], char *reply, int *len, struct wayland_tbm_client *tbm_client);
370 _waylend_tbm_monitor_client_show,
374 _waylend_tbm_monitor_client_dump_snapshot,
378 _waylend_tbm_monitor_client_dump_queue,
382 _waylend_tbm_monitor_client_trace,
386 _waylend_tbm_monitor_client_debug_level,
391 handle_tbm_monitor_client_done(void *data, struct wl_tbm_monitor *wl_tbm_monitor, const char *message)
396 handle_tbm_monitor_client_request_to_client(void *data, struct wl_tbm_monitor *wl_tbm_monitor,
397 const char * options, const char * request_id)
399 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
401 char *argv[WL_TBM_MONITOR_ARGS_MAX] = {0};
404 char message[WL_TBM_MONITOR_REPLY_MSG_LEN] = {0,};
405 int len = sizeof(message);
406 char *reply = message;
411 snprintf(temp, sizeof(temp), "%s", options);
413 argv[argc] = strtok_r(temp, " ", &end);
416 if (argc == WL_TBM_MONITOR_ARGS_MAX)
418 argv[argc] = strtok_r(NULL, " ", &end);
422 WL_TBM_TRACE("receive request_id:%s argc:%d [%s %s] options:'%s'", request_id, argc, argv[0], argv[1], temp);
426 for (i = 0; i < sizeof(option_proc) / sizeof(option_proc[0]); i++) {
427 if (argv[0][0] == '-' && !strncmp(argv[0] + 1, option_proc[i].opt, 32)) {
428 if (option_proc[i].func) {
429 option_proc[i].func(argc, argv, reply, &len, tbm_client);
436 wl_tbm_monitor_responce_to_server(tbm_monitor, message, request_id);
439 static const struct wl_tbm_monitor_listener wl_tbm_monitor_listener = {
440 handle_tbm_monitor_client_done,
441 handle_tbm_monitor_client_request_to_client,
445 _wayland_tbm_client_registry_handle_global(void *data,
446 struct wl_registry *registry, uint32_t name,
447 const char *interface, uint32_t version)
449 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
451 if (!strcmp(interface, "wl_tbm")) {
452 tbm_client->wl_tbm = wl_registry_bind(registry, name, &wl_tbm_interface,
454 WL_TBM_RETURN_IF_FAIL(tbm_client->wl_tbm != NULL);
456 wl_tbm_add_listener(tbm_client->wl_tbm, &wl_tbm_client_listener, tbm_client);
458 if (!tbm_client->bufmgr) {
459 tbm_client->bufmgr = tbm_bufmgr_init(-1);
460 if (!tbm_client->bufmgr) {
461 WL_TBM_LOG("failed to get auth_info");
462 wl_tbm_destroy(tbm_client->wl_tbm);
463 tbm_client->wl_tbm = NULL;
467 } else if (!strcmp(interface, "wl_tbm_monitor")) {
468 /*Create wl_monotor proxy by sington*/
472 tbm_monitor = wl_registry_bind(registry, name, &wl_tbm_monitor_interface, version);
473 WL_TBM_RETURN_IF_FAIL(tbm_monitor != NULL);
475 wl_proxy_set_queue((struct wl_proxy *)tbm_monitor, NULL);
477 wl_tbm_monitor_add_listener(tbm_monitor, &wl_tbm_monitor_listener, tbm_client);
482 _wayland_tbm_client_registry_remove_global(void *data, struct wl_registry *registry, uint32_t name)
486 static const struct wl_registry_listener registry_listener = {
487 _wayland_tbm_client_registry_handle_global,
488 _wayland_tbm_client_registry_remove_global
492 wayland_tbm_client_set_event_queue(struct wayland_tbm_client *tbm_client, struct wl_event_queue *queue)
494 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
496 wl_proxy_set_queue((struct wl_proxy *)tbm_client->wl_tbm, queue);
497 tbm_client->event_queue = queue;
502 struct wayland_tbm_client *
503 wayland_tbm_client_init(struct wl_display *display)
505 WL_TBM_RETURN_VAL_IF_FAIL(display != NULL, NULL);
507 struct wl_display *display_wrapper;
508 struct wayland_tbm_client *tbm_client;
509 struct wl_event_queue *wl_queue;
510 struct wl_registry *wl_registry;
512 _wayland_tbm_check_dlog_enable();
516 tbm_client = calloc(1, sizeof(struct wayland_tbm_client));
517 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
519 tbm_client->dpy = display;
521 display_wrapper = wl_proxy_create_wrapper(display);
522 if (!display_wrapper) {
523 WL_TBM_LOG("Failed to create display_wrapper.");
528 wl_queue = wl_display_create_queue(display);
530 WL_TBM_LOG("Failed to create queue.");
531 wl_proxy_wrapper_destroy(display_wrapper);
536 wl_proxy_set_queue((struct wl_proxy *)display_wrapper, wl_queue);
538 wl_registry = wl_display_get_registry(display_wrapper);
539 wl_proxy_wrapper_destroy(display_wrapper);
541 WL_TBM_LOG("Failed to get registry");
543 wl_event_queue_destroy(wl_queue);
548 wl_registry_add_listener(wl_registry, ®istry_listener, tbm_client);
549 if (wl_display_roundtrip_queue(display, wl_queue) < 0) {
550 WL_TBM_LOG("Failed to wl_display_roundtrip_queue");
552 wl_registry_destroy(wl_registry);
553 wl_event_queue_destroy(wl_queue);
558 wl_registry_destroy(wl_registry);
559 wl_event_queue_destroy(wl_queue);
562 if (!tbm_client->wl_tbm) {
563 WL_TBM_LOG("failed to create wl_tbm");
564 wayland_tbm_client_deinit(tbm_client);
569 * wl_tbm's queue is destroyed above. We should make wl_tbm's queue to
570 * use display's default_queue.
572 wl_proxy_set_queue((struct wl_proxy *)tbm_client->wl_tbm, NULL);
574 /* queue_info list */
575 wl_list_init(&tbm_client->queue_info_list);
581 wayland_tbm_client_deinit(struct wayland_tbm_client *tbm_client)
586 if (tbm_client->bufmgr)
587 tbm_bufmgr_deinit(tbm_client->bufmgr);
589 if (tbm_client->wl_tbm) {
590 wl_tbm_set_user_data(tbm_client->wl_tbm, NULL);
591 wl_tbm_destroy(tbm_client->wl_tbm);
595 && (tbm_client == wl_tbm_monitor_get_user_data(tbm_monitor))) {
596 wl_tbm_monitor_destroy(tbm_monitor);
600 wl_list_remove(&tbm_client->queue_info_list);
605 struct wayland_tbm_buffer *
606 _wayland_tbm_client_find_tbm_buffer_wl_buffer(struct wayland_tbm_client *tbm_client,
607 struct wl_buffer *wl_buffer)
609 struct wayland_tbm_surface_queue *queue_info = NULL;
611 if (wl_list_empty(&tbm_client->queue_info_list)) return NULL;
613 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
614 struct wayland_tbm_buffer *buffer = NULL;
616 pthread_mutex_lock(&queue_info->lock);
617 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
618 if (buffer->wl_buffer == wl_buffer) {
619 pthread_mutex_unlock(&queue_info->lock);
623 pthread_mutex_unlock(&queue_info->lock);
629 struct wayland_tbm_buffer *
630 _wayland_tbm_client_find_tbm_buffer_surface(struct wayland_tbm_client *tbm_client,
631 tbm_surface_h surface)
633 struct wayland_tbm_surface_queue *queue_info = NULL;
635 if (wl_list_empty(&tbm_client->queue_info_list)) return NULL;
637 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
638 struct wayland_tbm_buffer *buffer = NULL;
640 pthread_mutex_lock(&queue_info->lock);
641 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
642 if (buffer->tbm_surface == surface) {
643 pthread_mutex_unlock(&queue_info->lock);
647 pthread_mutex_unlock(&queue_info->lock);
654 wayland_tbm_client_create_buffer(struct wayland_tbm_client *tbm_client,
655 tbm_surface_h surface)
657 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
658 WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
660 int bufs[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};
661 struct wl_buffer *wl_buffer = NULL;
662 struct wayland_tbm_buffer *buffer = NULL;
663 int num_buf, is_fd = -1, i;
664 char debug_id[64] = {0, };
665 tbm_surface_info_s info;
667 struct wl_array plane_buf_idx, plane_offset, plane_stride, plane_size;
671 * if the surface is the attached surface from display server,
672 * return the wl_buffer of the attached surface
675 buffer = _wayland_tbm_client_find_tbm_buffer_surface(tbm_client, surface);
677 return buffer->wl_buffer;
679 if (tbm_surface_get_info(surface, &info) != TBM_SURFACE_ERROR_NONE) {
680 WL_TBM_LOG("Failed to create buffer from surface");
684 if (info.num_planes > 3) {
685 WL_TBM_LOG("invalid num_planes(%d)", info.num_planes);
689 num_buf = tbm_surface_internal_get_num_bos(surface);
691 WL_TBM_LOG("surface doesn't have any bo.");
695 for (i = 0; i < num_buf; i++) {
696 tbm_bo bo = tbm_surface_internal_get_bo(surface, i);
698 WL_TBM_LOG("Failed to get bo from surface");
702 /* try to get fd first */
703 if (is_fd == -1 || is_fd == 1) {
704 bufs[i] = tbm_bo_export_fd(bo);
705 if (is_fd == -1 && bufs[i] >= 0)
709 /* if fail to get fd, try to get name second */
710 if (is_fd == -1 || is_fd == 0) {
711 bufs[i] = tbm_bo_export(bo);
712 if (is_fd == -1 && bufs[i] > 0)
717 (is_fd == 1 && bufs[i] < 0) ||
718 (is_fd == 0 && bufs[i] <= 0)) {
719 WL_TBM_LOG("Failed to export(is_fd:%d, bufs:%d)", is_fd, bufs[i]);
724 wl_array_init(&plane_buf_idx);
725 wl_array_init(&plane_offset);
726 wl_array_init(&plane_stride);
727 wl_array_init(&plane_size);
729 for (i = 0; i < 3; i++) {
730 p = wl_array_add(&plane_buf_idx, sizeof(int));
731 *p = tbm_surface_internal_get_plane_bo_idx(surface, i);
732 p = wl_array_add(&plane_offset, sizeof(int));
733 *p = info.planes[i].offset;
734 p = wl_array_add(&plane_stride, sizeof(int));
735 *p = info.planes[i].stride;
736 p = wl_array_add(&plane_size, sizeof(int));
737 *p = info.planes[i].size;
741 wl_buffer = wl_tbm_create_buffer_with_fd(tbm_client->wl_tbm,
742 info.width, info.height, info.format, info.bpp, info.size, info.num_planes,
743 &plane_buf_idx, &plane_offset, &plane_stride, &plane_size,
744 flags, num_buf, bufs[0],
745 (bufs[1] == -1) ? bufs[0] : bufs[1],
746 (bufs[2] == -1) ? bufs[0] : bufs[2]);
748 wl_buffer = wl_tbm_create_buffer(tbm_client->wl_tbm,
749 info.width, info.height, info.format, info.bpp, info.size, info.num_planes,
750 &plane_buf_idx, &plane_offset, &plane_stride, &plane_size,
752 num_buf, bufs[0], bufs[1], bufs[2]);
754 wl_array_release(&plane_buf_idx);
755 wl_array_release(&plane_offset);
756 wl_array_release(&plane_stride);
757 wl_array_release(&plane_size);
760 WL_TBM_LOG("Failed to create wl_buffer");
764 for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {
765 if (is_fd == 1 && (bufs[i] >= 0))
769 wl_buffer_set_user_data(wl_buffer, surface);
771 snprintf(debug_id, sizeof(debug_id), "%u",
772 (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
773 tbm_surface_internal_set_debug_data(surface, "id", debug_id);
776 WL_TBM_TRACE(" pid:%d wl_buffer:%p tbm_surface:%p", getpid(),
783 for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {
784 if (is_fd == 1 && (bufs[i] >= 0))
792 wayland_tbm_client_destroy_buffer(struct wayland_tbm_client *tbm_client,
793 struct wl_buffer *wl_buffer)
795 struct wayland_tbm_buffer *buffer = NULL;
797 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
798 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
800 // TODO: valid check if the buffer is from this tbm_client???
803 WL_TBM_TRACE(" pid:%d wl_buffer:%p", getpid(), wl_buffer);
806 buffer = _wayland_tbm_client_find_tbm_buffer_wl_buffer(tbm_client, wl_buffer);
808 buffer->wl_buffer = NULL;
810 wl_buffer_set_user_data(wl_buffer, NULL);
811 wl_buffer_destroy(wl_buffer);
815 wayland_tbm_client_set_sync_timeline(struct wayland_tbm_client *tbm_client,
816 struct wl_buffer *wl_buffer, tbm_fd timeline)
818 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
819 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
821 wl_tbm_set_sync_timeline(tbm_client->wl_tbm, wl_buffer, timeline);
825 wayland_tbm_client_set_buffer_transform(struct wayland_tbm_client *tbm_client,
826 struct wl_buffer *wl_buffer, int transform)
828 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
829 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
830 WL_TBM_RETURN_IF_FAIL(transform >= 0);
832 wl_tbm_set_buffer_transform(tbm_client->wl_tbm, wl_buffer, transform);
836 wayland_tbm_client_set_buffer_serial(struct wayland_tbm_client *tbm_client,
837 struct wl_buffer *wl_buffer, uint32_t serial)
839 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
840 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
842 wl_tbm_set_buffer_serial(tbm_client->wl_tbm, wl_buffer, serial);
846 wayland_tbm_client_get_bufmgr(struct wayland_tbm_client *tbm_client)
848 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
850 return (void *)tbm_client->bufmgr;
854 _wayland_tbm_client_queue_get_attach_bufs(struct wayland_tbm_surface_queue *queue_info,
855 int unused, tbm_surface_h *surfaces, int *count)
857 struct wayland_tbm_buffer *buffer, *tmp;
861 wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
862 if (unused && buffer->allocated) continue;
864 surfaces[*count] = buffer->tbm_surface;
870 _wayland_tbm_client_queue_destroy_attach_bufs(struct wayland_tbm_surface_queue *queue_info)
872 struct wayland_tbm_buffer *buffer, *tmp;
874 wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
876 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), buffer->wl_buffer, buffer->tbm_surface);
878 if (buffer->wl_buffer) {
879 wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
881 if (!buffer->reuse) {
883 WL_TBM_TRACE("destroy the wl_buffer:%p", buffer->wl_buffer);
885 wl_buffer_destroy(buffer->wl_buffer);
886 buffer->wl_buffer = NULL;
890 wl_list_remove(&buffer->link);
896 _wayland_tbm_client_queue_destroy_unused_attach_bufs(struct wayland_tbm_surface_queue *queue_info, int *need_flush)
898 struct wayland_tbm_buffer *buffer, *tmp;
902 wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
903 if (buffer->allocated) {
909 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), buffer->wl_buffer, buffer->tbm_surface);
911 if (buffer->wl_buffer) {
912 wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
914 if (!buffer->reuse) {
916 WL_TBM_TRACE("destroy the wl_buffer:%p", buffer->wl_buffer);
918 wl_buffer_destroy(buffer->wl_buffer);
919 buffer->wl_buffer = NULL;
923 wl_list_remove(&buffer->link);
929 _wayland_tbm_client_create_surface_from_param(tbm_bufmgr bufmgr,
937 struct wl_array *plane_buf_idx,
938 struct wl_array *plane_offset,
939 struct wl_array *plane_stride,
940 struct wl_array *plane_size,
947 int32_t names[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};
948 tbm_surface_info_s info = { 0, };
949 tbm_bo bos[TBM_SURF_PLANE_MAX];
950 int i, numPlane, numName;
951 tbm_surface_h tbm_surface;
953 numPlane = tbm_surface_internal_get_num_planes(format);
954 WL_TBM_RETURN_VAL_IF_FAIL(numPlane == num_plane, NULL);
957 info.height = height;
958 info.format = format;
961 info.num_planes = numPlane;
964 for (i = 0; i < numPlane; i++) {
965 info.planes[i].offset = *WL_TBM_ARRAY_NTH_DATA(plane_offset, int32_t, i);
966 info.planes[i].stride = *WL_TBM_ARRAY_NTH_DATA(plane_stride, int32_t, i);
967 info.planes[i].size = *WL_TBM_ARRAY_NTH_DATA(plane_size, int32_t, i);
976 for (i = 0; i < numName; i++) {
978 bos[i] = tbm_bo_import_fd(bufmgr, names[i]);
980 bos[i] = tbm_bo_import(bufmgr, names[i]);
983 tbm_surface = tbm_surface_internal_create_with_bos(&info, bos, numName);
984 if (tbm_surface == NULL) {
999 for (i = 0; i < numName; i++)
1000 tbm_bo_unref(bos[i]);
1006 _wayland_tbm_client_is_valid_attach_bufs(struct wayland_tbm_surface_queue *queue_info,
1007 struct wayland_tbm_buffer *buffer)
1009 if (queue_info->width != buffer->width ||
1010 queue_info->height != buffer->height ||
1011 queue_info->format != buffer->format)
1017 static tbm_surface_h
1018 __wayland_tbm_client_surface_alloc_cb(tbm_surface_queue_h surface_queue, void *data)
1020 struct wayland_tbm_surface_queue *queue_info =
1021 (struct wayland_tbm_surface_queue *)data;
1022 tbm_surface_h surface = NULL;
1023 struct wayland_tbm_buffer *buffer;
1026 pthread_mutex_lock(&queue_info->lock);
1028 if (queue_info->is_active && queue_info->active_flush) {
1029 wl_list_for_each_reverse(buffer, &queue_info->attach_bufs, link) {
1030 if (!buffer->allocated && buffer->usable && !buffer->expire) {
1031 if (_wayland_tbm_client_is_valid_attach_bufs(queue_info, buffer)) {
1032 surface = buffer->tbm_surface;
1033 /* ref.. pair of __wayland_tbm_client_surface_free_cb */
1034 buffer->allocated = 1;
1036 WL_TBM_TRACE(" pid:%d wl_buffer:%p tbm_surface:%p ACTIVE", getpid(), buffer->wl_buffer, buffer->tbm_surface);
1049 pthread_mutex_unlock(&queue_info->lock);
1052 /* ref.. pair of __wayland_tbm_client_surface_free_cb */
1053 tbm_surface_internal_ref(surface);
1054 } else if (!surface && alloc) {
1055 /* ref.. pair of __wayland_tbm_client_surface_free_cb */
1056 surface = tbm_surface_internal_create_with_flags(queue_info->width,
1061 WL_TBM_TRACE(" pid:%d tbm_surface:%p DEACTIVE", getpid(), surface);
1068 __wayland_tbm_client_surface_free_cb(tbm_surface_queue_h surface_queue, void *data,
1069 tbm_surface_h surface)
1072 WL_TBM_TRACE(" pid:%d tbm_surface:%p", getpid(), surface);
1074 struct wayland_tbm_surface_queue *queue_info =
1075 (struct wayland_tbm_surface_queue *)data;
1076 struct wayland_tbm_buffer *buffer, *tmp;
1079 pthread_mutex_lock(&queue_info->lock);
1081 wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
1082 if (buffer->tbm_surface != surface) continue;
1083 if (!buffer->allocated) continue;
1085 buffer->allocated = 0;
1088 if (queue_info->is_active && !buffer->expire) continue;
1089 if (buffer->wl_buffer)
1090 wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
1093 wl_list_remove(&buffer->link);
1097 pthread_mutex_unlock(&queue_info->lock);
1100 tbm_surface_internal_unref(surface);
1102 /* unref.. pair of __wayland_tbm_client_surface_alloc_cb */
1103 tbm_surface_internal_unref(surface);
1107 handle_tbm_queue_buffer_attached(void *data,
1108 struct wl_tbm_queue *wl_tbm_queue,
1109 struct wl_buffer *wl_buffer,
1112 struct wayland_tbm_surface_queue *queue_info =
1113 (struct wayland_tbm_surface_queue *)data;
1114 struct wayland_tbm_buffer *buffer;
1116 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
1118 buffer = calloc(1, sizeof(struct wayland_tbm_buffer));
1119 WL_TBM_GOTO_IF_FAIL(buffer != NULL, fail_alloc);
1121 wl_list_init(&buffer->link);
1123 buffer->wl_tbm_queue = wl_tbm_queue;
1124 buffer->wl_buffer = wl_buffer;
1125 buffer->allocated = 0;
1127 buffer->tbm_surface = (tbm_surface_h)wl_buffer_get_user_data(wl_buffer);
1128 WL_TBM_GOTO_IF_FAIL(buffer->tbm_surface != NULL, fail_get_data);
1129 buffer->flags = flags;
1131 buffer->width = tbm_surface_get_width(buffer->tbm_surface);
1132 buffer->height = tbm_surface_get_height(buffer->tbm_surface);
1133 buffer->format = tbm_surface_get_format(buffer->tbm_surface);
1135 pthread_mutex_lock(&queue_info->lock);
1136 wl_list_insert(&queue_info->attach_bufs, &buffer->link);
1137 pthread_mutex_unlock(&queue_info->lock);
1140 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p",
1141 getpid(), buffer->wl_buffer, buffer->tbm_surface);
1149 wl_buffer_destroy(wl_buffer);
1153 handle_tbm_queue_active(void *data,
1154 struct wl_tbm_queue *wl_tbm_queue,
1156 uint32_t queue_size,
1157 uint32_t need_flush)
1159 struct wayland_tbm_surface_queue *queue_info =
1160 (struct wayland_tbm_surface_queue *)data;
1161 tbm_surface_queue_h tbm_queue = NULL;
1163 WL_TBM_LOG("active queue");
1165 pthread_mutex_lock(&queue_info->lock);
1167 if (queue_info->is_active) {
1168 WL_TBM_C_LOG("warning: queue_info is already activated");
1169 pthread_mutex_unlock(&queue_info->lock);
1173 WL_TBM_TRACE(" pid:%d", getpid());
1176 queue_info->is_active = 1;
1177 queue_info->usage = usage;
1180 queue_info->active_flush = need_flush;
1182 tbm_queue = queue_info->tbm_queue;
1184 pthread_mutex_unlock(&queue_info->lock);
1186 /* flush the allocated surfaces at the client */
1188 tbm_surface_queue_set_size(tbm_queue, queue_size, 1);
1192 handle_tbm_queue_deactive(void *data,
1193 struct wl_tbm_queue *wl_tbm_queue)
1195 struct wayland_tbm_surface_queue *queue_info =
1196 (struct wayland_tbm_surface_queue *)data;
1197 tbm_surface_queue_h tbm_queue = NULL;
1198 tbm_surface_h *surfaces = NULL;
1207 WL_TBM_TRACE(" pid:%d", getpid());
1210 WL_TBM_LOG("deactive queue");
1212 pthread_mutex_lock(&queue_info->lock);
1214 if (!queue_info->is_active) {
1215 WL_TBM_C_LOG("warning: queue_info is already deactivated");
1216 pthread_mutex_unlock(&queue_info->lock);
1220 queue_info->is_active = 0;
1222 if (queue_info->active_flush) {
1223 queue_info->active_flush = 0;
1225 length = wl_list_length(&queue_info->attach_bufs);
1227 surfaces = (tbm_surface_h *)calloc(length, sizeof(tbm_surface_h));
1229 WL_TBM_LOG_E("failed to alloc surfaces");
1230 pthread_mutex_unlock(&queue_info->lock);
1234 _wayland_tbm_client_queue_get_attach_bufs(queue_info, 1, surfaces, &count);
1235 /* flush the attached surfaces */
1236 _wayland_tbm_client_queue_destroy_unused_attach_bufs(queue_info, &flush);
1241 tbm_queue = queue_info->tbm_queue;
1242 queue_size = queue_info->queue_size;
1244 pthread_mutex_unlock(&queue_info->lock);
1247 for (i = 0; i < count; i++)
1248 tbm_surface_internal_unref(surfaces[i]);
1254 tbm_surface_queue_set_size(tbm_queue, queue_size, flush);
1258 handle_tbm_queue_flush(void *data,
1259 struct wl_tbm_queue *wl_tbm_queue)
1261 struct wayland_tbm_surface_queue *queue_info =
1262 (struct wayland_tbm_surface_queue *)data;
1263 tbm_surface_queue_h tbm_queue = NULL;
1266 WL_TBM_TRACE("pid:%d", getpid());
1268 WL_TBM_LOG("flush queue");
1270 pthread_mutex_lock(&queue_info->lock);
1272 if (queue_info->is_active && queue_info->active_flush) {
1273 WL_TBM_C_LOG("warning: Cannot flush the tbm_surface_queueu. The queue is activate.");
1274 pthread_mutex_unlock(&queue_info->lock);
1278 tbm_queue = queue_info->tbm_queue;
1280 pthread_mutex_unlock(&queue_info->lock);
1282 /* flush the allocated surfaces at the client */
1283 tbm_surface_queue_flush(tbm_queue);
1287 handle_tbm_queue_buffer_usable(void *data,
1288 struct wl_tbm_queue *wl_tbm_queue,
1289 struct wl_buffer *wl_buffer)
1291 struct wayland_tbm_surface_queue *queue_info =
1292 (struct wayland_tbm_surface_queue *)data;
1293 struct wayland_tbm_buffer *buffer;
1294 tbm_surface_queue_h tbm_queue = NULL;
1296 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
1298 pthread_mutex_lock(&queue_info->lock);
1300 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1301 if (buffer->wl_buffer == wl_buffer)
1305 tbm_queue = queue_info->tbm_queue;
1308 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p",
1309 getpid(), buffer->wl_buffer, buffer->tbm_surface);
1312 pthread_mutex_unlock(&queue_info->lock);
1314 tbm_surface_queue_notify_dequeuable(tbm_queue);
1317 const struct wl_tbm_queue_listener wl_tbm_queue_listener = {
1318 handle_tbm_queue_buffer_attached,
1319 handle_tbm_queue_active,
1320 handle_tbm_queue_deactive,
1321 handle_tbm_queue_flush,
1322 handle_tbm_queue_buffer_usable,
1325 static struct wayland_tbm_surface_queue *
1326 _wayland_tbm_client_find_queue_info_wl_surface(struct wayland_tbm_client *tbm_client,
1327 struct wl_surface *surface)
1329 /* set the debug_pid to the surface for debugging */
1330 if (!wl_list_empty(&tbm_client->queue_info_list)) {
1331 struct wayland_tbm_surface_queue *queue_info = NULL;
1333 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
1334 if (queue_info->wl_surface == surface)
1342 static struct wayland_tbm_surface_queue *
1343 _wayland_tbm_client_find_queue_info_queue(struct wayland_tbm_client *tbm_client,
1344 tbm_surface_queue_h queue)
1346 /* set the debug_pid to the surface for debugging */
1347 if (!wl_list_empty(&tbm_client->queue_info_list)) {
1348 struct wayland_tbm_surface_queue *queue_info = NULL;
1350 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
1351 if (queue_info->tbm_queue == queue)
1361 _handle_tbm_surface_queue_destroy_notify(tbm_surface_queue_h surface_queue,
1364 struct wayland_tbm_surface_queue *queue_info =
1365 (struct wayland_tbm_surface_queue *)data;
1366 tbm_surface_h *surfaces = NULL;
1372 WL_TBM_TRACE(" pid:%d", getpid());
1374 pthread_mutex_lock(&queue_info->lock);
1376 length = wl_list_length(&queue_info->attach_bufs);
1378 surfaces = (tbm_surface_h *)calloc(length, sizeof(tbm_surface_h));
1380 WL_TBM_LOG_E("failed to alloc surfaces");
1381 pthread_mutex_unlock(&queue_info->lock);
1385 _wayland_tbm_client_queue_get_attach_bufs(queue_info, 0, surfaces, &count);
1386 /* remove the attach_bufs int the queue_info */
1387 _wayland_tbm_client_queue_destroy_attach_bufs(queue_info);
1390 if (queue_info->wl_tbm_queue)
1391 wl_tbm_queue_destroy(queue_info->wl_tbm_queue);
1393 wl_list_remove(&queue_info->link);
1394 pthread_mutex_unlock(&queue_info->lock);
1395 pthread_mutex_destroy(&queue_info->lock);
1399 for (i = 0; i < count; i++)
1400 tbm_surface_internal_unref(surfaces[i]);
1407 _handle_tbm_surface_queue_reset_notify(tbm_surface_queue_h surface_queue,
1410 struct wayland_tbm_surface_queue *queue_info = data;
1416 WL_TBM_TRACE(" pid:%d", getpid());
1419 width = tbm_surface_queue_get_width(surface_queue);
1420 height = tbm_surface_queue_get_height(surface_queue);
1421 format = tbm_surface_queue_get_format(surface_queue);
1423 pthread_mutex_lock(&queue_info->lock);
1425 queue_info->width = width;
1426 queue_info->height = height;
1427 queue_info->format = format;
1429 pthread_mutex_unlock(&queue_info->lock);
1433 _handle_tbm_surface_queue_can_dequeue_notify(tbm_surface_queue_h surface_queue,
1436 struct wayland_tbm_surface_queue *queue_info = data;
1437 struct wayland_tbm_client *tbm_client = NULL;
1439 WL_TBM_RETURN_IF_FAIL(queue_info != NULL);
1441 pthread_mutex_lock(&queue_info->lock);
1442 if (!queue_info->is_active || !queue_info->active_flush) {
1443 pthread_mutex_unlock(&queue_info->lock);
1446 pthread_mutex_unlock(&queue_info->lock);
1448 tbm_client = wl_tbm_get_user_data(queue_info->wl_tbm);
1449 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
1451 if (!tbm_client->event_queue) return;
1453 if (wl_display_roundtrip_queue(tbm_client->dpy, tbm_client->event_queue) == -1) {
1456 WL_TBM_LOG_E("failed to wl_display_roundtrip_queue errno:%d", errno);
1458 dpy_err = wl_display_get_error(tbm_client->dpy);
1459 if (dpy_err == EPROTO) {
1460 const struct wl_interface *interface;
1461 uint32_t proxy_id, code;
1462 code = wl_display_get_protocol_error(tbm_client->dpy, &interface, &proxy_id);
1463 WL_TBM_LOG_E("protocol error interface:%s code:%d proxy_id:%d",
1464 interface->name, code, proxy_id);
1470 _handle_tbm_surface_queue_trace_notify(tbm_surface_queue_h surface_queue,
1471 tbm_surface_h tbm_surface, tbm_surface_queue_trace trace, void *data)
1473 struct wayland_tbm_surface_queue *queue_info = data;
1474 struct wl_buffer *wl_buffer = NULL;
1475 struct wayland_tbm_buffer *buffer = NULL;
1477 WL_TBM_RETURN_IF_FAIL(queue_info != NULL);
1479 if (trace != TBM_SURFACE_QUEUE_TRACE_DEQUEUE) return;
1481 pthread_mutex_lock(&queue_info->lock);
1483 if (!queue_info->is_active || !queue_info->active_flush) {
1484 pthread_mutex_unlock(&queue_info->lock);
1488 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1489 if (buffer->tbm_surface == tbm_surface)
1490 wl_buffer = buffer->wl_buffer;
1494 wl_tbm_queue_dequeue_buffer(queue_info->wl_tbm_queue, wl_buffer);
1496 pthread_mutex_unlock(&queue_info->lock);
1500 wayland_tbm_client_create_surface_queue(struct wayland_tbm_client *tbm_client,
1501 struct wl_surface *surface,
1503 int width, int height, tbm_format format)
1505 struct wayland_tbm_surface_queue *queue_info;
1506 struct wl_tbm_queue *queue;
1509 WL_TBM_TRACE(" pid:%d", getpid());
1512 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1513 WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
1515 queue_info = calloc(1, sizeof(struct wayland_tbm_surface_queue));
1516 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, NULL);
1518 queue_info->wl_tbm = tbm_client->wl_tbm;
1519 queue_info->bufmgr = tbm_client->bufmgr;
1520 queue_info->wl_surface = surface;
1521 wl_list_init(&queue_info->attach_bufs);
1523 queue = wl_tbm_create_surface_queue(tbm_client->wl_tbm, surface);
1524 WL_TBM_GOTO_IF_FAIL(queue != NULL, fail);
1526 queue_info->wl_tbm_queue = queue;
1528 wl_tbm_queue_add_listener(queue, &wl_tbm_queue_listener, queue_info);
1530 queue_info->width = width;
1531 queue_info->height = height;
1532 queue_info->format = format;
1533 queue_info->flag = 0;
1534 queue_info->queue_size = queue_size;
1536 queue_info->tbm_queue = tbm_surface_queue_sequence_create(queue_size,
1537 width, height, format, 0);
1538 WL_TBM_GOTO_IF_FAIL(queue_info->tbm_queue != NULL, fail);
1540 tbm_surface_queue_set_alloc_cb(queue_info->tbm_queue,
1541 __wayland_tbm_client_surface_alloc_cb,
1542 __wayland_tbm_client_surface_free_cb,
1545 tbm_surface_queue_add_destroy_cb(queue_info->tbm_queue,
1546 _handle_tbm_surface_queue_destroy_notify,
1549 tbm_surface_queue_add_reset_cb(queue_info->tbm_queue,
1550 _handle_tbm_surface_queue_reset_notify, queue_info);
1552 tbm_surface_queue_add_can_dequeue_cb(queue_info->tbm_queue,
1553 _handle_tbm_surface_queue_can_dequeue_notify, queue_info);
1555 tbm_surface_queue_add_trace_cb(queue_info->tbm_queue,
1556 _handle_tbm_surface_queue_trace_notify, queue_info);
1559 WL_TBM_C_LOG("INFO cur(%dx%d fmt:0x%x num:%d) new(%dx%d fmt:0x%x num:%d)",
1560 queue_info->width, queue_info->height,
1561 queue_info->format, queue_info->num_bufs,
1562 width, height, format, queue_size);
1565 pthread_mutex_init(&queue_info->lock, NULL);
1567 /* add queue_info to the list */
1568 wl_list_insert(&tbm_client->queue_info_list, &queue_info->link);
1570 return queue_info->tbm_queue;
1573 if (queue_info->wl_tbm_queue)
1574 wl_tbm_queue_destroy(queue_info->wl_tbm_queue);
1579 struct wl_tbm_queue *
1580 wayland_tbm_client_get_wl_tbm_queue(struct wayland_tbm_client *tbm_client, struct wl_surface *surface)
1582 struct wayland_tbm_surface_queue *queue_info = NULL;
1583 struct wl_tbm_queue *wayland_tbm_queue = NULL;
1585 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1586 WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
1588 queue_info = _wayland_tbm_client_find_queue_info_wl_surface(tbm_client, surface);
1589 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, NULL);
1591 pthread_mutex_lock(&queue_info->lock);
1593 wayland_tbm_queue = queue_info->wl_tbm_queue;
1594 if (!wayland_tbm_queue)
1595 WL_TBM_LOG_E("wl_tbm_queue is NULL");
1597 pthread_mutex_unlock(&queue_info->lock);
1599 return wayland_tbm_queue;
1603 wayland_tbm_client_get_wl_tbm(struct wayland_tbm_client *tbm_client)
1605 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1607 return tbm_client->wl_tbm;
1611 wayland_tbm_client_queue_check_activate(struct wayland_tbm_client *tbm_client, tbm_surface_queue_h queue)
1613 struct wayland_tbm_surface_queue *queue_info = NULL;
1614 struct wayland_tbm_buffer *buffer = NULL;
1616 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
1617 WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, 0);
1619 queue_info = _wayland_tbm_client_find_queue_info_queue(tbm_client, queue);
1620 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, 0);
1622 pthread_mutex_lock(&queue_info->lock);
1624 if (!queue_info->is_active) {
1625 pthread_mutex_unlock(&queue_info->lock);
1629 if (queue_info->active_flush) {
1630 if (wl_list_empty(&queue_info->attach_bufs)) {
1631 pthread_mutex_unlock(&queue_info->lock);
1635 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1636 if ((queue_info->width != buffer->width) ||
1637 (queue_info->height != buffer->height) ||
1638 (queue_info->format != buffer->format)) {
1639 pthread_mutex_unlock(&queue_info->lock);
1647 pthread_mutex_unlock(&queue_info->lock);
1653 wayland_tbm_client_queue_get_surfaces(struct wayland_tbm_client *tbm_client,
1654 tbm_surface_queue_h queue, tbm_surface_h *surfaces, int *num)
1656 struct wayland_tbm_surface_queue *queue_info = NULL;
1657 tbm_surface_h surface = NULL;
1658 struct wayland_tbm_buffer *buffer = NULL;
1659 tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
1660 tbm_surface_h *dequeued_surfaces = NULL, *get_surfaces = NULL;
1661 int get_num = 0, dequeued_num = 0, index = 0;
1664 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
1665 WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, 0);
1667 queue_info = _wayland_tbm_client_find_queue_info_queue(tbm_client, queue);
1668 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, 0);;
1670 if (!surfaces && !num) {
1671 WL_TBM_LOG_E("invalid parameter");
1675 pthread_mutex_lock(&queue_info->lock);
1677 if (queue_info->is_active && queue_info->active_flush) {
1682 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1683 if (buffer->expire) continue;
1686 surfaces[index] = buffer->tbm_surface;
1690 if (num) *num = *num + 1;
1693 pthread_mutex_unlock(&queue_info->lock);
1696 *num = queue_info->queue_size;
1699 dequeued_surfaces = (tbm_surface_h *)calloc(queue_info->queue_size, sizeof(tbm_surface_h));
1700 if (!dequeued_surfaces) {
1701 WL_TBM_LOG_E("failed to alloc get_surfaces");
1705 get_surfaces = (tbm_surface_h *)calloc(queue_info->queue_size, sizeof(tbm_surface_h));
1706 if (!get_surfaces) {
1707 WL_TBM_LOG_E("failed to alloc dequeued_surfaces");
1711 /* not need queue_info */
1712 pthread_mutex_unlock(&queue_info->lock);
1714 while (tbm_surface_queue_can_dequeue(queue, 0)) {
1715 tsq_err = tbm_surface_queue_dequeue(queue, &surface);
1716 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
1717 WL_TBM_LOG_E("failed to tbm_surface_queue_dequeue");
1721 dequeued_surfaces[dequeued_num] = surface;
1725 for (i = 0; i < dequeued_num; i++) {
1726 tsq_err = tbm_surface_queue_release(queue, dequeued_surfaces[i]);
1727 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
1728 WL_TBM_LOG_E("failed to tbm_surface_queue_release");
1731 tsq_err = tbm_surface_queue_get_surfaces(queue, get_surfaces, &get_num);
1732 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
1733 WL_TBM_LOG_E("failed to tbm_surface_queue_get_surfaces");
1737 for (i = 0; i < get_num; i++)
1738 surfaces[i] = get_surfaces[i];
1740 free(dequeued_surfaces);
1743 pthread_mutex_unlock(&queue_info->lock);
1750 pthread_mutex_unlock(&queue_info->lock);
1754 if (dequeued_surfaces)
1755 free(dequeued_surfaces);