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);
566 if (!tbm_client->wl_tbm) {
567 WL_TBM_LOG_E("failed to create wl_tbm");
568 wayland_tbm_client_deinit(tbm_client);
573 * wl_tbm's queue is destroyed above. We should make wl_tbm's queue to
574 * use display's default_queue.
576 wl_proxy_set_queue((struct wl_proxy *)tbm_client->wl_tbm, NULL);
578 /* queue_info list */
579 wl_list_init(&tbm_client->queue_info_list);
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;
1474 WL_TBM_LOG("active_flush invalid queue");
1475 queue_info->active_flush_invalid = 1;
1476 if (queue_size != queue_info->queue_size)
1477 recover_size = queue_info->queue_size;
1481 pthread_mutex_unlock(&queue_info->lock);
1484 tbm_surface_queue_set_size(surface_queue, recover_size, 0);
1488 _handle_tbm_surface_queue_can_dequeue_notify(tbm_surface_queue_h surface_queue,
1491 struct wayland_tbm_surface_queue *queue_info = data;
1492 struct wayland_tbm_client *tbm_client = NULL;
1494 WL_TBM_RETURN_IF_FAIL(queue_info != NULL);
1496 pthread_mutex_lock(&queue_info->lock);
1497 if (!queue_info->is_active || !queue_info->active_flush) {
1498 pthread_mutex_unlock(&queue_info->lock);
1501 pthread_mutex_unlock(&queue_info->lock);
1503 tbm_client = wl_tbm_get_user_data(queue_info->wl_tbm);
1504 WL_TBM_RETURN_IF_FAIL(tbm_client != NULL);
1506 if (!tbm_client->event_queue) return;
1508 if (wl_display_roundtrip_queue(tbm_client->dpy, tbm_client->event_queue) == -1) {
1511 WL_TBM_LOG_E("failed to wl_display_roundtrip_queue errno:%d", errno);
1513 dpy_err = wl_display_get_error(tbm_client->dpy);
1514 if (dpy_err == EPROTO) {
1515 const struct wl_interface *interface;
1516 uint32_t proxy_id, code;
1517 code = wl_display_get_protocol_error(tbm_client->dpy, &interface, &proxy_id);
1518 WL_TBM_LOG_E("protocol error interface:%s code:%d proxy_id:%d",
1519 interface->name, code, proxy_id);
1525 _handle_tbm_surface_queue_trace_notify(tbm_surface_queue_h surface_queue,
1526 tbm_surface_h tbm_surface, tbm_surface_queue_trace trace, void *data)
1528 struct wayland_tbm_surface_queue *queue_info = data;
1529 struct wl_buffer *wl_buffer = NULL;
1530 struct wayland_tbm_buffer *buffer = NULL;
1532 WL_TBM_RETURN_IF_FAIL(queue_info != NULL);
1534 if (trace != TBM_SURFACE_QUEUE_TRACE_DEQUEUE) return;
1536 pthread_mutex_lock(&queue_info->lock);
1538 if (!queue_info->is_active || !queue_info->active_flush) {
1539 pthread_mutex_unlock(&queue_info->lock);
1543 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1544 if (buffer->tbm_surface == tbm_surface)
1545 wl_buffer = buffer->wl_buffer;
1549 wl_tbm_queue_dequeue_buffer(queue_info->wl_tbm_queue, wl_buffer);
1551 pthread_mutex_unlock(&queue_info->lock);
1555 wayland_tbm_client_create_surface_queue(struct wayland_tbm_client *tbm_client,
1556 struct wl_surface *surface,
1558 int width, int height, tbm_format format)
1560 struct wayland_tbm_surface_queue *queue_info;
1561 struct wl_tbm_queue *queue;
1564 WL_TBM_TRACE(" pid:%d", getpid());
1567 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1568 WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
1570 queue_info = calloc(1, sizeof(struct wayland_tbm_surface_queue));
1571 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, NULL);
1573 queue_info->wl_tbm = tbm_client->wl_tbm;
1574 queue_info->bufmgr = tbm_client->bufmgr;
1575 queue_info->wl_surface = surface;
1576 wl_list_init(&queue_info->attach_bufs);
1578 queue = wl_tbm_create_surface_queue(tbm_client->wl_tbm, surface);
1579 WL_TBM_GOTO_IF_FAIL(queue != NULL, fail);
1581 queue_info->wl_tbm_queue = queue;
1583 wl_tbm_queue_add_listener(queue, &wl_tbm_queue_listener, queue_info);
1585 queue_info->width = width;
1586 queue_info->height = height;
1587 queue_info->format = format;
1588 queue_info->flag = 0;
1589 queue_info->queue_size = queue_size;
1591 queue_info->tbm_queue = tbm_surface_queue_sequence_create(queue_size,
1592 width, height, format, 0);
1593 WL_TBM_GOTO_IF_FAIL(queue_info->tbm_queue != NULL, fail);
1595 tbm_surface_queue_set_alloc_cb(queue_info->tbm_queue,
1596 __wayland_tbm_client_surface_alloc_cb,
1597 __wayland_tbm_client_surface_free_cb,
1600 tbm_surface_queue_add_destroy_cb(queue_info->tbm_queue,
1601 _handle_tbm_surface_queue_destroy_notify,
1604 tbm_surface_queue_add_reset_cb(queue_info->tbm_queue,
1605 _handle_tbm_surface_queue_reset_notify, queue_info);
1607 tbm_surface_queue_add_can_dequeue_cb(queue_info->tbm_queue,
1608 _handle_tbm_surface_queue_can_dequeue_notify, queue_info);
1610 tbm_surface_queue_add_trace_cb(queue_info->tbm_queue,
1611 _handle_tbm_surface_queue_trace_notify, queue_info);
1614 WL_TBM_C_LOG("INFO cur(%dx%d fmt:0x%x num:%d) new(%dx%d fmt:0x%x num:%d)",
1615 queue_info->width, queue_info->height,
1616 queue_info->format, queue_info->num_bufs,
1617 width, height, format, queue_size);
1620 pthread_mutex_init(&queue_info->lock, NULL);
1622 /* add queue_info to the list */
1623 wl_list_insert(&tbm_client->queue_info_list, &queue_info->link);
1625 return queue_info->tbm_queue;
1628 if (queue_info->wl_tbm_queue)
1629 wl_tbm_queue_destroy(queue_info->wl_tbm_queue);
1634 struct wl_tbm_queue *
1635 wayland_tbm_client_get_wl_tbm_queue(struct wayland_tbm_client *tbm_client, struct wl_surface *surface)
1637 struct wayland_tbm_surface_queue *queue_info = NULL;
1638 struct wl_tbm_queue *wayland_tbm_queue = NULL;
1640 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1641 WL_TBM_RETURN_VAL_IF_FAIL(surface != NULL, NULL);
1643 queue_info = _wayland_tbm_client_find_queue_info_wl_surface(tbm_client, surface);
1644 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, NULL);
1646 pthread_mutex_lock(&queue_info->lock);
1648 wayland_tbm_queue = queue_info->wl_tbm_queue;
1649 if (!wayland_tbm_queue)
1650 WL_TBM_LOG_E("wl_tbm_queue is NULL");
1652 pthread_mutex_unlock(&queue_info->lock);
1654 return wayland_tbm_queue;
1658 wayland_tbm_client_get_wl_tbm(struct wayland_tbm_client *tbm_client)
1660 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, NULL);
1662 return tbm_client->wl_tbm;
1666 wayland_tbm_client_queue_check_activate(struct wayland_tbm_client *tbm_client, tbm_surface_queue_h queue)
1668 struct wayland_tbm_surface_queue *queue_info = NULL;
1669 struct wayland_tbm_buffer *buffer = NULL;
1671 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
1672 WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, 0);
1674 queue_info = _wayland_tbm_client_find_queue_info_queue(tbm_client, queue);
1675 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, 0);
1677 pthread_mutex_lock(&queue_info->lock);
1679 if (!queue_info->is_active) {
1680 pthread_mutex_unlock(&queue_info->lock);
1684 if (queue_info->active_flush) {
1685 if (queue_info->active_flush_invalid) {
1686 pthread_mutex_unlock(&queue_info->lock);
1690 if (wl_list_empty(&queue_info->attach_bufs)) {
1691 pthread_mutex_unlock(&queue_info->lock);
1695 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1696 if ((queue_info->width != buffer->width) ||
1697 (queue_info->height != buffer->height) ||
1698 (queue_info->format != buffer->format)) {
1699 pthread_mutex_unlock(&queue_info->lock);
1705 pthread_mutex_unlock(&queue_info->lock);
1711 wayland_tbm_client_queue_get_surfaces(struct wayland_tbm_client *tbm_client,
1712 tbm_surface_queue_h queue, tbm_surface_h *surfaces, int *num)
1714 struct wayland_tbm_surface_queue *queue_info = NULL;
1715 tbm_surface_h surface = NULL;
1716 struct wayland_tbm_buffer *buffer = NULL;
1717 tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
1718 tbm_surface_h *dequeued_surfaces = NULL, *get_surfaces = NULL;
1719 int get_num = 0, dequeued_num = 0, index = 0;
1722 WL_TBM_RETURN_VAL_IF_FAIL(tbm_client != NULL, 0);
1723 WL_TBM_RETURN_VAL_IF_FAIL(queue != NULL, 0);
1725 queue_info = _wayland_tbm_client_find_queue_info_queue(tbm_client, queue);
1726 WL_TBM_RETURN_VAL_IF_FAIL(queue_info != NULL, 0);;
1728 if (!surfaces && !num) {
1729 WL_TBM_LOG_E("invalid parameter");
1733 pthread_mutex_lock(&queue_info->lock);
1735 if (queue_info->is_active && queue_info->active_flush) {
1740 wl_list_for_each(buffer, &queue_info->attach_bufs, link) {
1741 if (buffer->expire) continue;
1744 surfaces[index] = buffer->tbm_surface;
1748 if (num) *num = *num + 1;
1751 pthread_mutex_unlock(&queue_info->lock);
1754 *num = queue_info->queue_size;
1757 dequeued_surfaces = (tbm_surface_h *)calloc(queue_info->queue_size, sizeof(tbm_surface_h));
1758 if (!dequeued_surfaces) {
1759 WL_TBM_LOG_E("failed to alloc get_surfaces");
1763 get_surfaces = (tbm_surface_h *)calloc(queue_info->queue_size, sizeof(tbm_surface_h));
1764 if (!get_surfaces) {
1765 WL_TBM_LOG_E("failed to alloc dequeued_surfaces");
1769 /* not need queue_info */
1770 pthread_mutex_unlock(&queue_info->lock);
1772 while (tbm_surface_queue_can_dequeue(queue, 0)) {
1773 tsq_err = tbm_surface_queue_dequeue(queue, &surface);
1774 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
1775 WL_TBM_LOG_E("failed to tbm_surface_queue_dequeue");
1779 dequeued_surfaces[dequeued_num] = surface;
1783 for (i = 0; i < dequeued_num; i++) {
1784 tsq_err = tbm_surface_queue_release(queue, dequeued_surfaces[i]);
1785 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
1786 WL_TBM_LOG_E("failed to tbm_surface_queue_release");
1789 tsq_err = tbm_surface_queue_get_surfaces(queue, get_surfaces, &get_num);
1790 if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
1791 WL_TBM_LOG_E("failed to tbm_surface_queue_get_surfaces");
1795 for (i = 0; i < get_num; i++)
1796 surfaces[i] = get_surfaces[i];
1798 free(dequeued_surfaces);
1801 pthread_mutex_unlock(&queue_info->lock);
1808 pthread_mutex_unlock(&queue_info->lock);
1812 if (dequeued_surfaces)
1813 free(dequeued_surfaces);