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 int active_flush_invalid;
95 int active_flush_reset;
97 tbm_surface_queue_h tbm_queue;
99 struct wl_tbm *wl_tbm;
102 pthread_mutex_t lock;
105 static struct wl_tbm_monitor *tbm_monitor;
109 #define WL_TBM_TRACE(fmt, ...) if (bTrace) WL_TBM_C_LOG(fmt, ##__VA_ARGS__)
111 #define WL_TBM_TRACE(fmt, ...)
114 struct wayland_tbm_buffer *
115 _wayland_tbm_client_find_tbm_buffer_wl_buffer(struct wayland_tbm_client *tbm_client,
116 struct wl_buffer *wl_buffer);
119 _wayland_tbm_client_create_surface_from_param(tbm_bufmgr bufmgr,
127 struct wl_array *plane_buf_idx,
128 struct wl_array *plane_offset,
129 struct wl_array *plane_stride,
130 struct wl_array *plane_size,
138 handle_tbm_buffer_import_with_id(void *data,
139 struct wl_tbm *wl_tbm,
140 struct wl_buffer *wl_buffer,
147 struct wl_array *plane_buf_idx,
148 struct wl_array *plane_offset,
149 struct wl_array *plane_stride,
150 struct wl_array *plane_size,
157 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
158 tbm_surface_h tbm_surface;
159 char debug_id[64] = {0, };
161 tbm_surface = _wayland_tbm_client_create_surface_from_param(tbm_client->bufmgr, 0,
162 width, height, format, bpp, size,
164 plane_buf_idx, plane_offset, plane_stride, plane_size,
168 WL_TBM_GOTO_IF_FAIL(tbm_surface != NULL, fail);
169 wl_buffer_set_user_data(wl_buffer, tbm_surface);
171 snprintf(debug_id, sizeof(debug_id), "%u", (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
172 tbm_surface_internal_set_debug_data(tbm_surface, "id", debug_id);
175 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), wl_buffer, tbm_surface);
182 wl_buffer_destroy(wl_buffer);
186 handle_tbm_buffer_import_with_fd(void *data,
187 struct wl_tbm *wl_tbm,
188 struct wl_buffer *wl_buffer,
195 struct wl_array *plane_buf_idx,
196 struct wl_array *plane_offset,
197 struct wl_array *plane_stride,
198 struct wl_array *plane_size,
205 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
206 tbm_surface_h tbm_surface;
207 char debug_id[64] = {0, };
209 tbm_surface = _wayland_tbm_client_create_surface_from_param(tbm_client->bufmgr, 1,
210 width, height, format, bpp, size,
212 plane_buf_idx, plane_offset, plane_stride, plane_size,
216 WL_TBM_GOTO_IF_FAIL(tbm_surface != NULL, fail);
218 wl_buffer_set_user_data(wl_buffer, tbm_surface);
220 snprintf(debug_id, sizeof(debug_id), "%u", (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
221 tbm_surface_internal_set_debug_data(tbm_surface, "id", debug_id);
224 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), wl_buffer, tbm_surface);
231 wl_buffer_destroy(wl_buffer);
235 handle_buffer_destroy(void *data,
236 struct wl_tbm *wl_tbm,
237 struct wl_buffer *wl_buffer)
239 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
240 tbm_surface_h tbm_surface;
241 struct wayland_tbm_buffer *buffer = NULL;
244 WL_TBM_TRACE(" pid:%d wl_buffer:%p", getpid(), wl_buffer);
247 buffer = _wayland_tbm_client_find_tbm_buffer_wl_buffer(tbm_client, wl_buffer);
249 buffer->wl_buffer = NULL;
251 tbm_surface = wl_buffer_get_user_data(wl_buffer);
253 tbm_surface_internal_unref(tbm_surface);
255 wl_buffer_set_user_data(wl_buffer, NULL);
256 wl_buffer_destroy(wl_buffer);
261 static const struct wl_tbm_listener wl_tbm_client_listener = {
262 handle_tbm_buffer_import_with_id,
263 handle_tbm_buffer_import_with_fd,
264 handle_buffer_destroy,
267 void _waylend_tbm_monitor_client_print_show_to_file(char* show_str)
273 snprintf(tmp_file, sizeof(tmp_file), "/tmp/tbm_debug_show_%d%d", getpid(), c++);
274 if ((f = fopen(tmp_file, "a+")) != NULL) {
275 WL_TBM_LOG_E("fail to open tmp_file.");
276 fprintf(f, "%s", show_str);
281 void _waylend_tbm_monitor_client_show(int argc, char *argv[],
282 char *reply, int *len, struct wayland_tbm_client *tbm_client)
284 struct wayland_tbm_monitor_path path = {0};
287 _wayland_tbm_util_show_path_parse(argv[2], 0, &path);
290 tbm_bufmgr_debug_show(tbm_client->bufmgr);
292 /* we have to save result to some file as reply can be very long */
293 show_str = tbm_bufmgr_debug_tbm_info_get(tbm_client->bufmgr);
295 _waylend_tbm_monitor_client_print_show_to_file(show_str);
300 /* send empty string to close the session */
301 WL_TBM_MONITOR_SNPRINTF(reply, *len, "\n");
304 void _waylend_tbm_monitor_client_dump_snapshot(int argc, char *argv[],
305 char *reply, int *len, struct wayland_tbm_client *tbm_client)
311 for (i = 1; i < argc; i++) {
312 if (_waylend_tbm_util_scale_parse(argv[i], &scale))
316 path = _wayland_tbm_dump_directory_make();
317 _waylend_tbm_util_dump_snapshot(tbm_client->bufmgr, scale, path);
318 WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): snapshot dump is done. path=%s\n", getpid(), path);
322 void _waylend_tbm_monitor_client_dump_queue(int argc, char *argv[],
323 char *reply, int *len, struct wayland_tbm_client *tbm_client)
329 st = _waylend_tbm_util_proc_state_parse(argv[1]);
331 for (i = 2; i < argc; i++) {
332 if (_waylend_tbm_util_scale_parse(argv[i], &scale))
336 st = _waylend_tbm_util_dump_queue(st, tbm_client->bufmgr, scale);
337 WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): queue dump state: %s\n", getpid(),
341 void _waylend_tbm_monitor_client_trace(int argc, char *argv[],
342 char *reply, int *len, struct wayland_tbm_client *tbm_client)
346 st = _waylend_tbm_util_trace(_waylend_tbm_util_proc_state_parse(argv[1]),
347 _waylend_tbm_util_resource_parse(argv[2]),
349 WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): trace state: %s\n", getpid() ,
353 void _waylend_tbm_monitor_client_debug_level(int argc, char *argv[],
354 char *reply, int *len, struct wayland_tbm_client *tbm_client)
356 int debug_level = TBM_LOG_LEVEL_NONE;
359 for (i = 1; i < argc; i++) {
360 if (_waylend_tbm_util_debug_level_parse(argv[i], &debug_level))
364 _waylend_tbm_util_set_log_level(debug_level);
365 WL_TBM_MONITOR_SNPRINTF(reply, *len, "client(%d): set tbm_log debug_level(%d)\n", getpid(), debug_level);
370 void (*func)(int argc, char *argv[], char *reply, int *len, struct wayland_tbm_client *tbm_client);
374 _waylend_tbm_monitor_client_show,
378 _waylend_tbm_monitor_client_dump_snapshot,
382 _waylend_tbm_monitor_client_dump_queue,
386 _waylend_tbm_monitor_client_trace,
390 _waylend_tbm_monitor_client_debug_level,
395 handle_tbm_monitor_client_done(void *data, struct wl_tbm_monitor *wl_tbm_monitor, const char *message)
400 handle_tbm_monitor_client_request_to_client(void *data, struct wl_tbm_monitor *wl_tbm_monitor,
401 const char * options, const char * request_id)
403 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
405 char *argv[WL_TBM_MONITOR_ARGS_MAX] = {0};
408 char message[WL_TBM_MONITOR_REPLY_MSG_LEN] = {0,};
409 int len = sizeof(message);
410 char *reply = message;
415 snprintf(temp, sizeof(temp), "%s", options);
417 argv[argc] = strtok_r(temp, " ", &end);
420 if (argc == WL_TBM_MONITOR_ARGS_MAX)
422 argv[argc] = strtok_r(NULL, " ", &end);
426 WL_TBM_TRACE("receive request_id:%s argc:%d [%s %s] options:'%s'", request_id, argc, argv[0], argv[1], temp);
430 for (i = 0; i < sizeof(option_proc) / sizeof(option_proc[0]); i++) {
431 if (argv[0][0] == '-' && !strncmp(argv[0] + 1, option_proc[i].opt, 32)) {
432 if (option_proc[i].func) {
433 option_proc[i].func(argc, argv, reply, &len, tbm_client);
440 wl_tbm_monitor_responce_to_server(tbm_monitor, message, request_id);
443 static const struct wl_tbm_monitor_listener wl_tbm_monitor_listener = {
444 handle_tbm_monitor_client_done,
445 handle_tbm_monitor_client_request_to_client,
449 _wayland_tbm_client_registry_handle_global(void *data,
450 struct wl_registry *registry, uint32_t name,
451 const char *interface, uint32_t version)
453 struct wayland_tbm_client *tbm_client = (struct wayland_tbm_client *)data;
455 if (!strcmp(interface, "wl_tbm")) {
456 tbm_client->wl_tbm = wl_registry_bind(registry, name, &wl_tbm_interface,
458 WL_TBM_RETURN_IF_FAIL(tbm_client->wl_tbm != NULL);
460 wl_tbm_add_listener(tbm_client->wl_tbm, &wl_tbm_client_listener, tbm_client);
462 if (!tbm_client->bufmgr) {
463 tbm_client->bufmgr = tbm_bufmgr_init(-1);
464 if (!tbm_client->bufmgr) {
465 WL_TBM_LOG_E("failed to get auth_info");
466 wl_tbm_destroy(tbm_client->wl_tbm);
467 tbm_client->wl_tbm = NULL;
471 } else if (!strcmp(interface, "wl_tbm_monitor")) {
472 /*Create wl_monotor proxy by sington*/
476 tbm_monitor = wl_registry_bind(registry, name, &wl_tbm_monitor_interface, version);
477 WL_TBM_RETURN_IF_FAIL(tbm_monitor != NULL);
479 wl_proxy_set_queue((struct wl_proxy *)tbm_monitor, NULL);
481 wl_tbm_monitor_add_listener(tbm_monitor, &wl_tbm_monitor_listener, tbm_client);
486 _wayland_tbm_client_registry_remove_global(void *data, struct wl_registry *registry, uint32_t name)
490 static const struct wl_registry_listener registry_listener = {
491 _wayland_tbm_client_registry_handle_global,
492 _wayland_tbm_client_registry_remove_global
496 wayland_tbm_client_set_event_queue(struct wayland_tbm_client *tbm_client, struct wl_event_queue *queue)
498 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
500 wl_proxy_set_queue((struct wl_proxy *)tbm_client->wl_tbm, queue);
501 tbm_client->event_queue = queue;
506 struct wayland_tbm_client *
507 wayland_tbm_client_init(struct wl_display *display)
509 WL_TBM_RETURN_VAL_IF_FAIL(display != NULL, NULL);
511 struct wl_display *display_wrapper;
512 struct wayland_tbm_client *tbm_client;
513 struct wl_event_queue *wl_queue;
514 struct wl_registry *wl_registry;
516 _wayland_tbm_check_dlog_enable();
520 tbm_client = calloc(1, sizeof(struct wayland_tbm_client));
521 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
523 tbm_client->dpy = display;
525 display_wrapper = wl_proxy_create_wrapper(display);
526 if (!display_wrapper) {
527 WL_TBM_LOG_E("Failed to create display_wrapper.");
532 wl_queue = wl_display_create_queue(display);
534 WL_TBM_LOG_E("Failed to create queue.");
535 wl_proxy_wrapper_destroy(display_wrapper);
540 wl_proxy_set_queue((struct wl_proxy *)display_wrapper, wl_queue);
542 wl_registry = wl_display_get_registry(display_wrapper);
543 wl_proxy_wrapper_destroy(display_wrapper);
545 WL_TBM_LOG_E("Failed to get registry");
547 wl_event_queue_destroy(wl_queue);
552 wl_registry_add_listener(wl_registry, ®istry_listener, tbm_client);
553 if (wl_display_roundtrip_queue(display, wl_queue) < 0) {
554 WL_TBM_LOG_E("Failed to wl_display_roundtrip_queue");
556 wl_registry_destroy(wl_registry);
557 wl_event_queue_destroy(wl_queue);
562 wl_registry_destroy(wl_registry);
563 wl_event_queue_destroy(wl_queue);
565 /* queue_info list */
566 wl_list_init(&tbm_client->queue_info_list);
569 if (!tbm_client->wl_tbm) {
570 WL_TBM_LOG_E("failed to create wl_tbm");
571 wayland_tbm_client_deinit(tbm_client);
576 * wl_tbm's queue is destroyed above. We should make wl_tbm's queue to
577 * use display's default_queue.
579 wl_proxy_set_queue((struct wl_proxy *)tbm_client->wl_tbm, NULL);
585 wayland_tbm_client_deinit(struct wayland_tbm_client *tbm_client)
590 if (tbm_client->bufmgr)
591 tbm_bufmgr_deinit(tbm_client->bufmgr);
593 if (tbm_client->wl_tbm) {
594 wl_tbm_set_user_data(tbm_client->wl_tbm, NULL);
595 wl_tbm_destroy(tbm_client->wl_tbm);
599 && (tbm_client == wl_tbm_monitor_get_user_data(tbm_monitor))) {
600 wl_tbm_monitor_destroy(tbm_monitor);
604 wl_list_remove(&tbm_client->queue_info_list);
609 struct wayland_tbm_buffer *
610 _wayland_tbm_client_find_tbm_buffer_wl_buffer(struct wayland_tbm_client *tbm_client,
611 struct wl_buffer *wl_buffer)
613 struct wayland_tbm_surface_queue *queue_info = NULL;
615 if (wl_list_empty(&tbm_client->queue_info_list)) return NULL;
617 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
618 struct wayland_tbm_buffer *buffer = NULL;
620 pthread_mutex_lock(&queue_info->lock);
621 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
622 if (buffer->wl_buffer == wl_buffer) {
623 pthread_mutex_unlock(&queue_info->lock);
627 pthread_mutex_unlock(&queue_info->lock);
633 struct wayland_tbm_buffer *
634 _wayland_tbm_client_find_tbm_buffer_surface(struct wayland_tbm_client *tbm_client,
635 tbm_surface_h surface)
637 struct wayland_tbm_surface_queue *queue_info = NULL;
639 if (wl_list_empty(&tbm_client->queue_info_list)) return NULL;
641 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
642 struct wayland_tbm_buffer *buffer = NULL;
644 pthread_mutex_lock(&queue_info->lock);
645 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
646 if (buffer->tbm_surface == surface) {
647 pthread_mutex_unlock(&queue_info->lock);
651 pthread_mutex_unlock(&queue_info->lock);
658 wayland_tbm_client_create_buffer(struct wayland_tbm_client *tbm_client,
659 tbm_surface_h surface)
661 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
662 WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
664 int bufs[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};
665 struct wl_buffer *wl_buffer = NULL;
666 struct wayland_tbm_buffer *buffer = NULL;
667 int num_buf, is_fd = -1, i;
668 char debug_id[64] = {0, };
669 tbm_surface_info_s info;
671 struct wl_array plane_buf_idx, plane_offset, plane_stride, plane_size;
675 * if the surface is the attached surface from display server,
676 * return the wl_buffer of the attached surface
679 buffer = _wayland_tbm_client_find_tbm_buffer_surface(tbm_client, surface);
681 return buffer->wl_buffer;
683 if (tbm_surface_get_info(surface, &info) != TBM_SURFACE_ERROR_NONE) {
684 WL_TBM_LOG_E("Failed to create buffer from surface");
688 if (info.num_planes > 3) {
689 WL_TBM_LOG_E("invalid num_planes(%d)", info.num_planes);
693 num_buf = tbm_surface_internal_get_num_bos(surface);
695 WL_TBM_LOG_E("surface doesn't have any bo.");
699 for (i = 0; i < num_buf; i++) {
700 tbm_bo bo = tbm_surface_internal_get_bo(surface, i);
702 WL_TBM_LOG_E("Failed to get bo from surface");
706 /* try to get fd first */
707 if (is_fd == -1 || is_fd == 1) {
708 bufs[i] = tbm_bo_export_fd(bo);
709 if (is_fd == -1 && bufs[i] >= 0)
713 /* if fail to get fd, try to get name second */
714 if (is_fd == -1 || is_fd == 0) {
715 bufs[i] = tbm_bo_export(bo);
716 if (is_fd == -1 && bufs[i] > 0)
721 (is_fd == 1 && bufs[i] < 0) ||
722 (is_fd == 0 && bufs[i] <= 0)) {
723 WL_TBM_LOG_E("Failed to export(is_fd:%d, bufs:%d)", is_fd, bufs[i]);
728 wl_array_init(&plane_buf_idx);
729 wl_array_init(&plane_offset);
730 wl_array_init(&plane_stride);
731 wl_array_init(&plane_size);
733 for (i = 0; i < 3; i++) {
734 p = wl_array_add(&plane_buf_idx, sizeof(int));
735 *p = tbm_surface_internal_get_plane_bo_idx(surface, i);
736 p = wl_array_add(&plane_offset, sizeof(int));
737 *p = info.planes[i].offset;
738 p = wl_array_add(&plane_stride, sizeof(int));
739 *p = info.planes[i].stride;
740 p = wl_array_add(&plane_size, sizeof(int));
741 *p = info.planes[i].size;
745 wl_buffer = wl_tbm_create_buffer_with_fd(tbm_client->wl_tbm,
746 info.width, info.height, info.format, info.bpp, info.size, info.num_planes,
747 &plane_buf_idx, &plane_offset, &plane_stride, &plane_size,
748 flags, num_buf, bufs[0],
749 (bufs[1] == -1) ? bufs[0] : bufs[1],
750 (bufs[2] == -1) ? bufs[0] : bufs[2]);
752 wl_buffer = wl_tbm_create_buffer(tbm_client->wl_tbm,
753 info.width, info.height, info.format, info.bpp, info.size, info.num_planes,
754 &plane_buf_idx, &plane_offset, &plane_stride, &plane_size,
756 num_buf, bufs[0], bufs[1], bufs[2]);
758 wl_array_release(&plane_buf_idx);
759 wl_array_release(&plane_offset);
760 wl_array_release(&plane_stride);
761 wl_array_release(&plane_size);
764 WL_TBM_LOG_E("Failed to create wl_buffer");
768 for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {
769 if (is_fd == 1 && (bufs[i] >= 0))
773 wl_buffer_set_user_data(wl_buffer, surface);
775 snprintf(debug_id, sizeof(debug_id), "%u",
776 (unsigned int)wl_proxy_get_id((struct wl_proxy *)wl_buffer));
777 tbm_surface_internal_set_debug_data(surface, "id", debug_id);
780 WL_TBM_TRACE(" pid:%d wl_buffer:%p tbm_surface:%p", getpid(),
787 for (i = 0; i < TBM_SURF_PLANE_MAX; i++) {
788 if (is_fd == 1 && (bufs[i] >= 0))
796 wayland_tbm_client_destroy_buffer(struct wayland_tbm_client *tbm_client,
797 struct wl_buffer *wl_buffer)
799 struct wayland_tbm_buffer *buffer = NULL;
801 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
802 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
804 // TODO: valid check if the buffer is from this tbm_client???
807 WL_TBM_TRACE(" pid:%d wl_buffer:%p", getpid(), wl_buffer);
810 buffer = _wayland_tbm_client_find_tbm_buffer_wl_buffer(tbm_client, wl_buffer);
812 buffer->wl_buffer = NULL;
814 wl_buffer_set_user_data(wl_buffer, NULL);
815 wl_buffer_destroy(wl_buffer);
819 wayland_tbm_client_set_sync_timeline(struct wayland_tbm_client *tbm_client,
820 struct wl_buffer *wl_buffer, tbm_fd timeline)
822 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
823 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
825 wl_tbm_set_sync_timeline(tbm_client->wl_tbm, wl_buffer, timeline);
829 wayland_tbm_client_set_buffer_transform(struct wayland_tbm_client *tbm_client,
830 struct wl_buffer *wl_buffer, int transform)
832 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
833 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
834 WL_TBM_RETURN_IF_FAIL(transform >= 0);
836 wl_tbm_set_buffer_transform(tbm_client->wl_tbm, wl_buffer, transform);
840 wayland_tbm_client_set_buffer_serial(struct wayland_tbm_client *tbm_client,
841 struct wl_buffer *wl_buffer, uint32_t serial)
843 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
844 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
846 wl_tbm_set_buffer_serial(tbm_client->wl_tbm, wl_buffer, serial);
850 wayland_tbm_client_get_bufmgr(struct wayland_tbm_client *tbm_client)
852 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
854 return (void *)tbm_client->bufmgr;
858 _wayland_tbm_client_queue_get_attach_bufs(struct wayland_tbm_surface_queue *queue_info,
859 int unused, tbm_surface_h *surfaces, int *count)
861 struct wayland_tbm_buffer *buffer, *tmp;
865 wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
866 if (unused && buffer->allocated) continue;
868 surfaces[*count] = buffer->tbm_surface;
874 _wayland_tbm_client_queue_destroy_attach_bufs(struct wayland_tbm_surface_queue *queue_info)
876 struct wayland_tbm_buffer *buffer, *tmp;
878 wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
880 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), buffer->wl_buffer, buffer->tbm_surface);
882 if (buffer->wl_buffer) {
883 wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
885 if (!buffer->reuse) {
887 WL_TBM_TRACE("destroy the wl_buffer:%p", buffer->wl_buffer);
889 wl_buffer_destroy(buffer->wl_buffer);
890 buffer->wl_buffer = NULL;
894 wl_list_remove(&buffer->link);
900 _wayland_tbm_client_queue_destroy_unused_attach_bufs(struct wayland_tbm_surface_queue *queue_info, int *need_flush)
902 struct wayland_tbm_buffer *buffer, *tmp;
906 wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
907 if (buffer->allocated) {
913 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p", getpid(), buffer->wl_buffer, buffer->tbm_surface);
915 if (buffer->wl_buffer) {
916 wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
918 if (!buffer->reuse) {
920 WL_TBM_TRACE("destroy the wl_buffer:%p", buffer->wl_buffer);
922 wl_buffer_destroy(buffer->wl_buffer);
923 buffer->wl_buffer = NULL;
927 wl_list_remove(&buffer->link);
933 _wayland_tbm_client_create_surface_from_param(tbm_bufmgr bufmgr,
941 struct wl_array *plane_buf_idx,
942 struct wl_array *plane_offset,
943 struct wl_array *plane_stride,
944 struct wl_array *plane_size,
951 int32_t names[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1};
952 tbm_surface_info_s info = { 0, };
953 tbm_bo bos[TBM_SURF_PLANE_MAX];
954 int i, numPlane, numName;
955 tbm_surface_h tbm_surface;
957 numPlane = tbm_surface_internal_get_num_planes(format);
958 WL_TBM_RETURN_VAL_IF_FAIL(numPlane == num_plane, NULL);
961 info.height = height;
962 info.format = format;
965 info.num_planes = numPlane;
968 for (i = 0; i < numPlane; i++) {
969 info.planes[i].offset = *WL_TBM_ARRAY_NTH_DATA(plane_offset, int32_t, i);
970 info.planes[i].stride = *WL_TBM_ARRAY_NTH_DATA(plane_stride, int32_t, i);
971 info.planes[i].size = *WL_TBM_ARRAY_NTH_DATA(plane_size, int32_t, i);
980 for (i = 0; i < numName; i++) {
982 bos[i] = tbm_bo_import_fd(bufmgr, names[i]);
984 bos[i] = tbm_bo_import(bufmgr, names[i]);
987 tbm_surface = tbm_surface_internal_create_with_bos(&info, bos, numName);
988 if (tbm_surface == NULL) {
1003 for (i = 0; i < numName; i++)
1004 tbm_bo_unref(bos[i]);
1010 _wayland_tbm_client_is_valid_attach_bufs(struct wayland_tbm_surface_queue *queue_info,
1011 struct wayland_tbm_buffer *buffer)
1013 if (queue_info->width != buffer->width ||
1014 queue_info->height != buffer->height ||
1015 queue_info->format != buffer->format)
1021 static tbm_surface_h
1022 __wayland_tbm_client_surface_alloc_cb(tbm_surface_queue_h surface_queue, void *data)
1024 struct wayland_tbm_surface_queue *queue_info =
1025 (struct wayland_tbm_surface_queue *)data;
1026 tbm_surface_h surface = NULL;
1027 struct wayland_tbm_buffer *buffer;
1030 pthread_mutex_lock(&queue_info->lock);
1032 if (queue_info->is_active && queue_info->active_flush && !queue_info->active_flush_invalid) {
1033 wl_list_for_each_reverse(buffer, &queue_info->attach_bufs, link) {
1034 if (!buffer->allocated && buffer->usable && !buffer->expire) {
1035 if (_wayland_tbm_client_is_valid_attach_bufs(queue_info, buffer)) {
1036 surface = buffer->tbm_surface;
1037 /* ref.. pair of __wayland_tbm_client_surface_free_cb */
1038 buffer->allocated = 1;
1040 WL_TBM_TRACE(" pid:%d wl_buffer:%p tbm_surface:%p ACTIVE", getpid(), buffer->wl_buffer, buffer->tbm_surface);
1053 pthread_mutex_unlock(&queue_info->lock);
1056 /* ref.. pair of __wayland_tbm_client_surface_free_cb */
1057 tbm_surface_internal_ref(surface);
1058 } else if (!surface && alloc) {
1059 /* ref.. pair of __wayland_tbm_client_surface_free_cb */
1060 surface = tbm_surface_internal_create_with_flags(queue_info->width,
1065 WL_TBM_TRACE(" pid:%d tbm_surface:%p DEACTIVE", getpid(), surface);
1072 __wayland_tbm_client_surface_free_cb(tbm_surface_queue_h surface_queue, void *data,
1073 tbm_surface_h surface)
1076 WL_TBM_TRACE(" pid:%d tbm_surface:%p", getpid(), surface);
1078 struct wayland_tbm_surface_queue *queue_info =
1079 (struct wayland_tbm_surface_queue *)data;
1080 struct wayland_tbm_buffer *buffer, *tmp;
1083 pthread_mutex_lock(&queue_info->lock);
1085 wl_list_for_each_safe(buffer, tmp, &queue_info->attach_bufs, link) {
1086 if (buffer->tbm_surface != surface) continue;
1087 if (!buffer->allocated) continue;
1089 buffer->allocated = 0;
1092 if (queue_info->is_active && !buffer->expire) continue;
1093 if (buffer->wl_buffer)
1094 wl_tbm_queue_detach_buffer(queue_info->wl_tbm_queue, buffer->wl_buffer);
1097 wl_list_remove(&buffer->link);
1101 pthread_mutex_unlock(&queue_info->lock);
1104 tbm_surface_internal_unref(surface);
1106 /* unref.. pair of __wayland_tbm_client_surface_alloc_cb */
1107 tbm_surface_internal_unref(surface);
1111 handle_tbm_queue_buffer_attached(void *data,
1112 struct wl_tbm_queue *wl_tbm_queue,
1113 struct wl_buffer *wl_buffer,
1116 struct wayland_tbm_surface_queue *queue_info =
1117 (struct wayland_tbm_surface_queue *)data;
1118 struct wayland_tbm_buffer *buffer;
1120 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
1122 buffer = calloc(1, sizeof(struct wayland_tbm_buffer));
1123 WL_TBM_GOTO_IF_FAIL(buffer != NULL, fail_alloc);
1125 wl_list_init(&buffer->link);
1127 buffer->wl_tbm_queue = wl_tbm_queue;
1128 buffer->wl_buffer = wl_buffer;
1129 buffer->allocated = 0;
1131 buffer->tbm_surface = (tbm_surface_h)wl_buffer_get_user_data(wl_buffer);
1132 WL_TBM_GOTO_IF_FAIL(buffer->tbm_surface != NULL, fail_get_data);
1133 buffer->flags = flags;
1135 buffer->width = tbm_surface_get_width(buffer->tbm_surface);
1136 buffer->height = tbm_surface_get_height(buffer->tbm_surface);
1137 buffer->format = tbm_surface_get_format(buffer->tbm_surface);
1139 pthread_mutex_lock(&queue_info->lock);
1140 wl_list_insert(&queue_info->attach_bufs, &buffer->link);
1141 pthread_mutex_unlock(&queue_info->lock);
1144 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p",
1145 getpid(), buffer->wl_buffer, buffer->tbm_surface);
1153 wl_buffer_destroy(wl_buffer);
1157 _wayland_tbm_client_is_active_flush_valid(struct wayland_tbm_surface_queue *queue_info)
1159 struct wayland_tbm_buffer *buffer;
1161 if (wl_list_empty(&queue_info->attach_bufs)) return 0;
1163 wl_list_for_each_reverse(buffer, &queue_info->attach_bufs, link) {
1164 if (buffer->expire) continue;
1166 if (_wayland_tbm_client_is_valid_attach_bufs(queue_info, buffer))
1174 handle_tbm_queue_active(void *data,
1175 struct wl_tbm_queue *wl_tbm_queue,
1177 uint32_t queue_size,
1178 uint32_t need_flush)
1180 struct wayland_tbm_surface_queue *queue_info =
1181 (struct wayland_tbm_surface_queue *)data;
1182 tbm_surface_queue_h tbm_queue = NULL;
1184 WL_TBM_LOG("active queue");
1186 pthread_mutex_lock(&queue_info->lock);
1188 if (queue_info->is_active) {
1189 WL_TBM_LOG_E("warning: queue_info is already activated");
1190 pthread_mutex_unlock(&queue_info->lock);
1194 WL_TBM_TRACE(" pid:%d", getpid());
1197 queue_info->is_active = 1;
1198 queue_info->usage = usage;
1201 queue_info->active_flush = need_flush;
1203 if (!_wayland_tbm_client_is_active_flush_valid(queue_info)) {
1204 WL_TBM_LOG("active_flush invalid queue");
1205 queue_info->active_flush_invalid = 1;
1206 pthread_mutex_unlock(&queue_info->lock);
1210 queue_info->active_flush_reset = 1;
1213 tbm_queue = queue_info->tbm_queue;
1215 pthread_mutex_unlock(&queue_info->lock);
1217 /* flush the allocated surfaces at the client */
1219 tbm_surface_queue_set_size(tbm_queue, queue_size, 1);
1223 handle_tbm_queue_deactive(void *data,
1224 struct wl_tbm_queue *wl_tbm_queue)
1226 struct wayland_tbm_surface_queue *queue_info =
1227 (struct wayland_tbm_surface_queue *)data;
1228 tbm_surface_queue_h tbm_queue = NULL;
1229 tbm_surface_h *surfaces = NULL;
1238 WL_TBM_TRACE(" pid:%d", getpid());
1241 WL_TBM_LOG("deactive queue");
1243 pthread_mutex_lock(&queue_info->lock);
1245 if (!queue_info->is_active) {
1246 WL_TBM_LOG_E("warning: queue_info is already deactivated");
1247 pthread_mutex_unlock(&queue_info->lock);
1251 if (queue_info->active_flush) {
1252 queue_info->active_flush = 0;
1254 length = wl_list_length(&queue_info->attach_bufs);
1256 surfaces = (tbm_surface_h *)calloc(length, sizeof(tbm_surface_h));
1258 WL_TBM_LOG_E("failed to alloc surfaces");
1259 pthread_mutex_unlock(&queue_info->lock);
1263 _wayland_tbm_client_queue_get_attach_bufs(queue_info, 1, surfaces, &count);
1264 /* flush the attached surfaces */
1265 _wayland_tbm_client_queue_destroy_unused_attach_bufs(queue_info, &flush);
1267 if (!queue_info->active_flush_invalid)
1272 queue_info->is_active = 0;
1273 queue_info->active_flush_invalid = 0;
1275 tbm_queue = queue_info->tbm_queue;
1276 queue_size = queue_info->queue_size;
1278 pthread_mutex_unlock(&queue_info->lock);
1281 for (i = 0; i < count; i++)
1282 tbm_surface_internal_unref(surfaces[i]);
1288 tbm_surface_queue_set_size(tbm_queue, queue_size, flush);
1292 handle_tbm_queue_flush(void *data,
1293 struct wl_tbm_queue *wl_tbm_queue)
1295 struct wayland_tbm_surface_queue *queue_info =
1296 (struct wayland_tbm_surface_queue *)data;
1297 tbm_surface_queue_h tbm_queue = NULL;
1300 WL_TBM_TRACE("pid:%d", getpid());
1302 WL_TBM_LOG("flush queue");
1304 pthread_mutex_lock(&queue_info->lock);
1306 if (queue_info->is_active && queue_info->active_flush) {
1307 WL_TBM_LOG_E("warning: Cannot flush the tbm_surface_queueu. The queue is activate.");
1308 pthread_mutex_unlock(&queue_info->lock);
1312 tbm_queue = queue_info->tbm_queue;
1314 pthread_mutex_unlock(&queue_info->lock);
1316 /* flush the allocated surfaces at the client */
1317 tbm_surface_queue_flush(tbm_queue);
1321 handle_tbm_queue_buffer_usable(void *data,
1322 struct wl_tbm_queue *wl_tbm_queue,
1323 struct wl_buffer *wl_buffer)
1325 struct wayland_tbm_surface_queue *queue_info =
1326 (struct wayland_tbm_surface_queue *)data;
1327 struct wayland_tbm_buffer *buffer;
1328 tbm_surface_queue_h tbm_queue = NULL;
1331 WL_TBM_RETURN_IF_FAIL(wl_buffer != NULL);
1333 pthread_mutex_lock(&queue_info->lock);
1335 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1336 if (buffer->wl_buffer == wl_buffer)
1340 tbm_queue = queue_info->tbm_queue;
1341 is_active = queue_info->is_active;
1344 WL_TBM_TRACE("pid:%d wl_buffer:%p tbm_surface:%p",
1345 getpid(), buffer->wl_buffer, buffer->tbm_surface);
1348 pthread_mutex_unlock(&queue_info->lock);
1351 tbm_surface_queue_notify_dequeuable(tbm_queue);
1354 const struct wl_tbm_queue_listener wl_tbm_queue_listener = {
1355 handle_tbm_queue_buffer_attached,
1356 handle_tbm_queue_active,
1357 handle_tbm_queue_deactive,
1358 handle_tbm_queue_flush,
1359 handle_tbm_queue_buffer_usable,
1362 static struct wayland_tbm_surface_queue *
1363 _wayland_tbm_client_find_queue_info_wl_surface(struct wayland_tbm_client *tbm_client,
1364 struct wl_surface *surface)
1366 /* set the debug_pid to the surface for debugging */
1367 if (!wl_list_empty(&tbm_client->queue_info_list)) {
1368 struct wayland_tbm_surface_queue *queue_info = NULL;
1370 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
1371 if (queue_info->wl_surface == surface)
1379 static struct wayland_tbm_surface_queue *
1380 _wayland_tbm_client_find_queue_info_queue(struct wayland_tbm_client *tbm_client,
1381 tbm_surface_queue_h queue)
1383 /* set the debug_pid to the surface for debugging */
1384 if (!wl_list_empty(&tbm_client->queue_info_list)) {
1385 struct wayland_tbm_surface_queue *queue_info = NULL;
1387 wl_list_for_each(queue_info, &tbm_client->queue_info_list, link) {
1388 if (queue_info->tbm_queue == queue)
1398 _handle_tbm_surface_queue_destroy_notify(tbm_surface_queue_h surface_queue,
1401 struct wayland_tbm_surface_queue *queue_info =
1402 (struct wayland_tbm_surface_queue *)data;
1403 tbm_surface_h *surfaces = NULL;
1409 WL_TBM_TRACE(" pid:%d", getpid());
1411 pthread_mutex_lock(&queue_info->lock);
1413 length = wl_list_length(&queue_info->attach_bufs);
1415 surfaces = (tbm_surface_h *)calloc(length, sizeof(tbm_surface_h));
1417 WL_TBM_LOG_E("failed to alloc surfaces");
1418 pthread_mutex_unlock(&queue_info->lock);
1422 _wayland_tbm_client_queue_get_attach_bufs(queue_info, 0, surfaces, &count);
1423 /* remove the attach_bufs int the queue_info */
1424 _wayland_tbm_client_queue_destroy_attach_bufs(queue_info);
1427 if (queue_info->wl_tbm_queue)
1428 wl_tbm_queue_destroy(queue_info->wl_tbm_queue);
1430 wl_list_remove(&queue_info->link);
1431 pthread_mutex_unlock(&queue_info->lock);
1432 pthread_mutex_destroy(&queue_info->lock);
1436 for (i = 0; i < count; i++)
1437 tbm_surface_internal_unref(surfaces[i]);
1444 _handle_tbm_surface_queue_reset_notify(tbm_surface_queue_h surface_queue,
1447 struct wayland_tbm_surface_queue *queue_info = data;
1448 int recover_size = 0;
1455 WL_TBM_TRACE(" pid:%d", getpid());
1458 width = tbm_surface_queue_get_width(surface_queue);
1459 height = tbm_surface_queue_get_height(surface_queue);
1460 format = tbm_surface_queue_get_format(surface_queue);
1461 queue_size = tbm_surface_queue_get_size(surface_queue);
1463 pthread_mutex_lock(&queue_info->lock);
1465 queue_info->width = width;
1466 queue_info->height = height;
1467 queue_info->format = format;
1469 if (queue_info->is_active && queue_info->active_flush) {
1470 if (queue_info->active_flush_reset) {
1471 queue_info->active_flush_reset = 0;
1473 WL_TBM_LOG("active_flush invalid queue");
1474 queue_info->active_flush_invalid = 1;
1475 if (queue_size != queue_info->queue_size)
1476 recover_size = queue_info->queue_size;
1480 pthread_mutex_unlock(&queue_info->lock);
1483 tbm_surface_queue_set_size(surface_queue, recover_size, 0);
1487 _handle_tbm_surface_queue_can_dequeue_notify(tbm_surface_queue_h surface_queue,
1490 struct wayland_tbm_surface_queue *queue_info = data;
1491 struct wayland_tbm_client *tbm_client = NULL;
1493 WL_TBM_RETURN_IF_FAIL(queue_info != NULL);
1495 pthread_mutex_lock(&queue_info->lock);
1496 if (!queue_info->is_active || !queue_info->active_flush) {
1497 pthread_mutex_unlock(&queue_info->lock);
1500 pthread_mutex_unlock(&queue_info->lock);
1502 tbm_client = wl_tbm_get_user_data(queue_info->wl_tbm);
1503 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
1505 if (!tbm_client->event_queue) return;
1507 if (wl_display_roundtrip_queue(tbm_client->dpy, tbm_client->event_queue) == -1) {
1510 WL_TBM_LOG_E("failed to wl_display_roundtrip_queue errno:%d", errno);
1512 dpy_err = wl_display_get_error(tbm_client->dpy);
1513 if (dpy_err == EPROTO) {
1514 const struct wl_interface *interface;
1515 uint32_t proxy_id, code;
1516 code = wl_display_get_protocol_error(tbm_client->dpy, &interface, &proxy_id);
1517 WL_TBM_LOG_E("protocol error interface:%s code:%d proxy_id:%d",
1518 interface->name, code, proxy_id);
1524 _handle_tbm_surface_queue_trace_notify(tbm_surface_queue_h surface_queue,
1525 tbm_surface_h tbm_surface, tbm_surface_queue_trace trace, void *data)
1527 struct wayland_tbm_surface_queue *queue_info = data;
1528 struct wl_buffer *wl_buffer = NULL;
1529 struct wayland_tbm_buffer *buffer = NULL;
1531 WL_TBM_RETURN_IF_FAIL(queue_info != NULL);
1533 if (trace != TBM_SURFACE_QUEUE_TRACE_DEQUEUE) return;
1535 pthread_mutex_lock(&queue_info->lock);
1537 if (!queue_info->is_active || !queue_info->active_flush) {
1538 pthread_mutex_unlock(&queue_info->lock);
1542 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1543 if (buffer->tbm_surface == tbm_surface)
1544 wl_buffer = buffer->wl_buffer;
1548 wl_tbm_queue_dequeue_buffer(queue_info->wl_tbm_queue, wl_buffer);
1550 pthread_mutex_unlock(&queue_info->lock);
1554 wayland_tbm_client_create_surface_queue(struct wayland_tbm_client *tbm_client,
1555 struct wl_surface *surface,
1557 int width, int height, tbm_format format)
1559 struct wayland_tbm_surface_queue *queue_info;
1560 struct wl_tbm_queue *queue;
1563 WL_TBM_TRACE(" pid:%d", getpid());
1566 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1567 WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
1569 queue_info = calloc(1, sizeof(struct wayland_tbm_surface_queue));
1570 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, NULL);
1572 queue_info->wl_tbm = tbm_client->wl_tbm;
1573 queue_info->bufmgr = tbm_client->bufmgr;
1574 queue_info->wl_surface = surface;
1575 wl_list_init(&queue_info->attach_bufs);
1577 queue = wl_tbm_create_surface_queue(tbm_client->wl_tbm, surface);
1578 WL_TBM_GOTO_IF_FAIL(queue != NULL, fail);
1580 queue_info->wl_tbm_queue = queue;
1582 wl_tbm_queue_add_listener(queue, &wl_tbm_queue_listener, queue_info);
1584 queue_info->width = width;
1585 queue_info->height = height;
1586 queue_info->format = format;
1587 queue_info->flag = 0;
1588 queue_info->queue_size = queue_size;
1590 queue_info->tbm_queue = tbm_surface_queue_sequence_create(queue_size,
1591 width, height, format, 0);
1592 WL_TBM_GOTO_IF_FAIL(queue_info->tbm_queue != NULL, fail);
1594 tbm_surface_queue_set_alloc_cb(queue_info->tbm_queue,
1595 __wayland_tbm_client_surface_alloc_cb,
1596 __wayland_tbm_client_surface_free_cb,
1599 tbm_surface_queue_add_destroy_cb(queue_info->tbm_queue,
1600 _handle_tbm_surface_queue_destroy_notify,
1603 tbm_surface_queue_add_reset_cb(queue_info->tbm_queue,
1604 _handle_tbm_surface_queue_reset_notify, queue_info);
1606 tbm_surface_queue_add_can_dequeue_cb(queue_info->tbm_queue,
1607 _handle_tbm_surface_queue_can_dequeue_notify, queue_info);
1609 tbm_surface_queue_add_trace_cb(queue_info->tbm_queue,
1610 _handle_tbm_surface_queue_trace_notify, queue_info);
1613 WL_TBM_C_LOG("INFO cur(%dx%d fmt:0x%x num:%d) new(%dx%d fmt:0x%x num:%d)",
1614 queue_info->width, queue_info->height,
1615 queue_info->format, queue_info->num_bufs,
1616 width, height, format, queue_size);
1619 pthread_mutex_init(&queue_info->lock, NULL);
1621 /* add queue_info to the list */
1622 wl_list_insert(&tbm_client->queue_info_list, &queue_info->link);
1624 return queue_info->tbm_queue;
1627 if (queue_info->wl_tbm_queue)
1628 wl_tbm_queue_destroy(queue_info->wl_tbm_queue);
1633 struct wl_tbm_queue *
1634 wayland_tbm_client_get_wl_tbm_queue(struct wayland_tbm_client *tbm_client, struct wl_surface *surface)
1636 struct wayland_tbm_surface_queue *queue_info = NULL;
1637 struct wl_tbm_queue *wayland_tbm_queue = NULL;
1639 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1640 WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
1642 queue_info = _wayland_tbm_client_find_queue_info_wl_surface(tbm_client, surface);
1643 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, NULL);
1645 pthread_mutex_lock(&queue_info->lock);
1647 wayland_tbm_queue = queue_info->wl_tbm_queue;
1648 if (!wayland_tbm_queue)
1649 WL_TBM_LOG_E("wl_tbm_queue is NULL");
1651 pthread_mutex_unlock(&queue_info->lock);
1653 return wayland_tbm_queue;
1657 wayland_tbm_client_get_wl_tbm(struct wayland_tbm_client *tbm_client)
1659 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1661 return tbm_client->wl_tbm;
1665 wayland_tbm_client_queue_check_activate(struct wayland_tbm_client *tbm_client, tbm_surface_queue_h queue)
1667 struct wayland_tbm_surface_queue *queue_info = NULL;
1668 struct wayland_tbm_buffer *buffer = NULL;
1670 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
1671 WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, 0);
1673 queue_info = _wayland_tbm_client_find_queue_info_queue(tbm_client, queue);
1674 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, 0);
1676 pthread_mutex_lock(&queue_info->lock);
1678 if (!queue_info->is_active) {
1679 pthread_mutex_unlock(&queue_info->lock);
1683 if (queue_info->active_flush) {
1684 if (queue_info->active_flush_invalid) {
1685 pthread_mutex_unlock(&queue_info->lock);
1689 if (wl_list_empty(&queue_info->attach_bufs)) {
1690 pthread_mutex_unlock(&queue_info->lock);
1694 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1695 if ((queue_info->width != buffer->width) ||
1696 (queue_info->height != buffer->height) ||
1697 (queue_info->format != buffer->format)) {
1698 pthread_mutex_unlock(&queue_info->lock);
1704 pthread_mutex_unlock(&queue_info->lock);
1710 wayland_tbm_client_queue_get_surfaces(struct wayland_tbm_client *tbm_client,
1711 tbm_surface_queue_h queue, tbm_surface_h *surfaces, int *num)
1713 struct wayland_tbm_surface_queue *queue_info = NULL;
1714 tbm_surface_h surface = NULL;
1715 struct wayland_tbm_buffer *buffer = NULL;
1716 tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
1717 tbm_surface_h *dequeued_surfaces = NULL, *get_surfaces = NULL;
1718 int get_num = 0, dequeued_num = 0, index = 0;
1721 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
1722 WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, 0);
1724 queue_info = _wayland_tbm_client_find_queue_info_queue(tbm_client, queue);
1725 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, 0);;
1727 if (!surfaces && !num) {
1728 WL_TBM_LOG_E("invalid parameter");
1732 pthread_mutex_lock(&queue_info->lock);
1734 if (queue_info->is_active && queue_info->active_flush) {
1739 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1740 if (buffer->expire) continue;
1743 surfaces[index] = buffer->tbm_surface;
1747 if (num) *num = *num + 1;
1750 pthread_mutex_unlock(&queue_info->lock);
1753 *num = queue_info->queue_size;
1756 dequeued_surfaces = (tbm_surface_h *)calloc(queue_info->queue_size, sizeof(tbm_surface_h));
1757 if (!dequeued_surfaces) {
1758 WL_TBM_LOG_E("failed to alloc get_surfaces");
1762 get_surfaces = (tbm_surface_h *)calloc(queue_info->queue_size, sizeof(tbm_surface_h));
1763 if (!get_surfaces) {
1764 WL_TBM_LOG_E("failed to alloc dequeued_surfaces");
1768 /* not need queue_info */
1769 pthread_mutex_unlock(&queue_info->lock);
1771 while (tbm_surface_queue_can_dequeue(queue, 0)) {
1772 tsq_err = tbm_surface_queue_dequeue(queue, &surface);
1773 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
1774 WL_TBM_LOG_E("failed to tbm_surface_queue_dequeue");
1778 dequeued_surfaces[dequeued_num] = surface;
1782 for (i = 0; i < dequeued_num; i++) {
1783 tsq_err = tbm_surface_queue_release(queue, dequeued_surfaces[i]);
1784 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
1785 WL_TBM_LOG_E("failed to tbm_surface_queue_release");
1788 tsq_err = tbm_surface_queue_get_surfaces(queue, get_surfaces, &get_num);
1789 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
1790 WL_TBM_LOG_E("failed to tbm_surface_queue_get_surfaces");
1794 for (i = 0; i < get_num; i++)
1795 surfaces[i] = get_surfaces[i];
1797 free(dequeued_surfaces);
1800 pthread_mutex_unlock(&queue_info->lock);
1807 pthread_mutex_unlock(&queue_info->lock);
1811 if (dequeued_surfaces)
1812 free(dequeued_surfaces);