1 /**************************************************************************
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
32 #include "tbm_bufmgr_int.h"
42 #define TBM_TRACE() TBM_LOG("[TRACE] %s:%d surface:%p\n", __FUNCTION__, __LINE__, surface_queue)
43 #define TBM_LOCK() TBM_LOG("[LOCK] %s:%d surface:%p\n", __FUNCTION__, __LINE__, surface_queue)
44 #define TBM_UNLOCK() TBM_LOG("[UNLOCK] %s:%d surface:%p\n", __FUNCTION__, __LINE__, surface_queue)
52 struct list_head head;
53 struct list_head tail;
59 tbm_surface_h surface;
61 struct list_head item_link;
62 struct list_head link;
64 unsigned int priv_flags; /*for each queue*/
67 typedef struct _tbm_surface_queue_interface {
68 void (*init)(tbm_surface_queue_h queue);
69 void (*reset)(tbm_surface_queue_h queue);
70 void (*destroy)(tbm_surface_queue_h queue);
71 void (*need_attach)(tbm_surface_queue_h queue);
73 void (*enqueue)(tbm_surface_queue_h queue, queue_node* node);
74 void (*release)(tbm_surface_queue_h queue, queue_node* node);
75 queue_node* (*dequeue)(tbm_surface_queue_h queue);
76 queue_node* (*acquire)(tbm_surface_queue_h queue);
77 }tbm_surface_queue_interface;
79 struct _tbm_surface_queue {
86 struct list_head list;
88 tbm_surface_queue_notify_cb destroy_cb;
89 void *destroy_cb_data;
91 tbm_surface_queue_notify_cb dequeuable_cb;
92 void *dequeuable_cb_data;
94 tbm_surface_queue_notify_cb acquirable_cb;
95 void *acquirable_cb_data;
97 tbm_surface_queue_notify_cb reset_cb;
100 pthread_mutex_t lock;
101 pthread_cond_t free_cond;
102 pthread_cond_t dirty_cond;
104 const tbm_surface_queue_interface *impl;
108 static queue_node *_queue_node_create(void)
110 queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
111 TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
116 static void _queue_node_delete(queue_node * node)
119 tbm_surface_destroy(node->surface);
121 LIST_DEL(&node->item_link);
122 LIST_DEL(&node->link);
126 static int _queue_is_empty(queue * queue)
128 if (queue->head.next == &queue->tail)
134 static void _queue_node_push_back(queue * queue, queue_node * node)
136 LIST_ADDTAIL(&node->item_link, &queue->tail);
141 static void _queue_node_push_front(queue * queue, queue_node * node)
143 LIST_ADD(&node->item_link, &queue->head);
148 static queue_node *_queue_node_pop_front(queue * queue)
150 queue_node *node = NULL;
152 node = LIST_ENTRY(queue_node, queue->head.next, item_link);
154 LIST_DEL(&node->item_link);
160 static queue_node *_queue_node_pop(queue * queue, queue_node* node)
162 LIST_DEL(&node->item_link);
168 static queue_node* _queue_get_node(tbm_surface_queue_h surface_queue, int type, tbm_surface_h surface, int *out_type)
170 queue_node *node = NULL;
171 queue_node *tmp = NULL;
174 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
178 if (type & FREE_QUEUE)
180 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head, item_link) {
181 if (node->surface == surface)
183 if (out_type) *out_type = FREE_QUEUE;
189 if (type & DIRTY_QUEUE)
191 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head, item_link) {
192 if (node->surface == surface)
194 if (out_type) *out_type = DIRTY_QUEUE;
200 if (type & NODE_LIST)
202 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
203 if (node->surface == surface)
205 if (out_type) *out_type = NODE_LIST;
214 static void _queue_init(queue * queue)
216 LIST_INITHEAD(&queue->head);
217 LIST_INITHEAD(&queue->tail);
218 LIST_ADDTAIL(&queue->head, &queue->tail);
222 void _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue, tbm_surface_h surface)
224 queue_node *node = NULL;
226 node = _queue_node_create();
227 TBM_RETURN_IF_FAIL(node != NULL);
229 tbm_surface_internal_ref(surface);
230 node->surface = surface;
232 LIST_ADDTAIL(&node->link, &surface_queue->list);
233 _queue_node_push_back(&surface_queue->free_queue, node);
236 void _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue, tbm_surface_h surface)
238 queue_node *node = NULL;
241 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
243 _queue_node_delete(node);
246 void _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, queue_node* node, int push_back)
249 _queue_node_push_back(&surface_queue->dirty_queue, node);
251 _queue_node_push_front(&surface_queue->dirty_queue, node);
254 queue_node* _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
256 queue_node *node = NULL;
258 if (_queue_is_empty(&surface_queue->free_queue)) {
259 if (surface_queue->impl && surface_queue->impl->need_attach)
260 surface_queue->impl->need_attach(surface_queue);
262 if (_queue_is_empty(&surface_queue->free_queue)) {
267 node = _queue_node_pop_front(&surface_queue->free_queue);
272 queue_node* _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
274 queue_node *node = NULL;
276 if (_queue_is_empty(&surface_queue->dirty_queue)) {
280 node = _queue_node_pop_front(&surface_queue->dirty_queue);
285 void _tbm_surface_queue_release(tbm_surface_queue_h surface_queue, queue_node* node, int push_back)
288 _queue_node_push_back(&surface_queue->free_queue, node);
290 _queue_node_push_front(&surface_queue->free_queue, node);
293 void _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
294 int width, int height, int format,
295 const tbm_surface_queue_interface* impl, void *data)
297 TBM_RETURN_IF_FAIL(surface_queue != NULL);
298 TBM_RETURN_IF_FAIL(impl != NULL);
300 memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
302 pthread_mutex_init(&surface_queue->lock, NULL);
303 pthread_cond_init(&surface_queue->free_cond, NULL);
304 pthread_cond_init(&surface_queue->dirty_cond, NULL);
306 surface_queue->width = width;
307 surface_queue->height = height;
308 surface_queue->format = format;
309 surface_queue->impl = impl;
310 surface_queue->impl_data = data;
312 _queue_init(&surface_queue->free_queue);
313 _queue_init(&surface_queue->dirty_queue);
314 LIST_INITHEAD(&surface_queue->list);
316 if (surface_queue->impl && surface_queue->impl->init)
317 surface_queue->impl->init(surface_queue);
320 tbm_surface_queue_error_e tbm_surface_queue_set_destroy_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb, void *data)
322 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
324 pthread_mutex_lock(&surface_queue->lock);
326 surface_queue->destroy_cb = destroy_cb;
327 surface_queue->destroy_cb_data = data;
329 pthread_mutex_unlock(&surface_queue->lock);
331 return TBM_SURFACE_QUEUE_ERROR_NONE;
334 tbm_surface_queue_error_e tbm_surface_queue_set_dequeuable_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb, void *data)
336 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
338 pthread_mutex_lock(&surface_queue->lock);
340 surface_queue->dequeuable_cb = dequeuable_cb;
341 surface_queue->dequeuable_cb_data = data;
343 pthread_mutex_unlock(&surface_queue->lock);
345 return TBM_SURFACE_QUEUE_ERROR_NONE;
348 tbm_surface_queue_error_e tbm_surface_queue_set_acquirable_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb, void *data)
350 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
352 pthread_mutex_lock(&surface_queue->lock);
354 surface_queue->acquirable_cb = acquirable_cb;
355 surface_queue->acquirable_cb_data = data;
357 pthread_mutex_unlock(&surface_queue->lock);
359 return TBM_SURFACE_QUEUE_ERROR_NONE;
362 int tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
364 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
366 return surface_queue->width;
369 int tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
371 return surface_queue->height;
374 int tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
376 return surface_queue->format;
379 tbm_surface_queue_error_e tbm_surface_queue_set_reset_cb(tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb, void *data)
381 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
383 pthread_mutex_lock(&surface_queue->lock);
385 surface_queue->reset_cb = reset_cb;
386 surface_queue->reset_cb_data = data;
388 pthread_mutex_unlock(&surface_queue->lock);
390 return TBM_SURFACE_QUEUE_ERROR_NONE;
394 tbm_surface_queue_error_e tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue, tbm_surface_h surface)
396 queue_node *node = NULL;
399 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
400 TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
402 pthread_mutex_lock(&surface_queue->lock);
404 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
405 if (node == NULL || queue_type != NODE_LIST)
407 TBM_LOG("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n", node, queue_type);
408 pthread_mutex_unlock(&surface_queue->lock);
409 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
412 if (surface_queue->impl && surface_queue->impl->enqueue)
413 surface_queue->impl->enqueue(surface_queue, node);
415 _tbm_surface_queue_enqueue(surface_queue, node, 1);
417 if (_queue_is_empty(&surface_queue->dirty_queue)) {
418 pthread_mutex_unlock(&surface_queue->lock);
419 return TBM_SURFACE_QUEUE_ERROR_NONE;
422 pthread_mutex_unlock(&surface_queue->lock);
423 pthread_cond_signal(&surface_queue->dirty_cond);
425 if (surface_queue->acquirable_cb)
426 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
428 return TBM_SURFACE_QUEUE_ERROR_NONE;
431 tbm_surface_queue_error_e tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue, tbm_surface_h * surface)
433 queue_node *node = NULL;
435 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
436 TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
438 pthread_mutex_lock(&surface_queue->lock);
440 if (surface_queue->impl && surface_queue->impl->dequeue)
441 node = surface_queue->impl->dequeue(surface_queue);
443 node = _tbm_surface_queue_dequeue(surface_queue);
447 pthread_mutex_unlock(&surface_queue->lock);
448 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
451 if (node->surface == NULL) {
453 TBM_LOG("_queue_node_pop_front failed\n");
454 pthread_mutex_unlock(&surface_queue->lock);
455 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
458 *surface = node->surface;
460 pthread_mutex_unlock(&surface_queue->lock);
462 return TBM_SURFACE_QUEUE_ERROR_NONE;
465 int tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
467 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
469 pthread_mutex_lock(&surface_queue->lock);
471 if (_queue_is_empty(&surface_queue->free_queue)) {
472 if (surface_queue->impl && surface_queue->impl->need_attach)
473 surface_queue->impl->need_attach(surface_queue);
476 if (_queue_is_empty(&surface_queue->free_queue)) {
478 pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
479 pthread_mutex_unlock(&surface_queue->lock);
483 pthread_mutex_unlock(&surface_queue->lock);
487 pthread_mutex_unlock(&surface_queue->lock);
492 tbm_surface_queue_error_e tbm_surface_queue_release(tbm_surface_queue_h surface_queue, tbm_surface_h surface)
494 queue_node *node = NULL;
497 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
498 TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
500 pthread_mutex_lock(&surface_queue->lock);
502 node = _queue_get_node(surface_queue, 0, surface, &queue_type);
503 if (node == NULL || queue_type != NODE_LIST)
505 TBM_LOG("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n", node, queue_type);
506 pthread_mutex_unlock(&surface_queue->lock);
507 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
510 if (surface_queue->impl && surface_queue->impl->release)
511 surface_queue->impl->release(surface_queue, node);
513 _tbm_surface_queue_release(surface_queue, node, 1);
515 if (_queue_is_empty(&surface_queue->free_queue)) {
516 pthread_mutex_unlock(&surface_queue->lock);
517 return TBM_SURFACE_QUEUE_ERROR_NONE;
520 pthread_mutex_unlock(&surface_queue->lock);
521 pthread_cond_signal(&surface_queue->free_cond);
523 if (surface_queue->dequeuable_cb)
524 surface_queue->dequeuable_cb(surface_queue, surface_queue->dequeuable_cb_data);
526 return TBM_SURFACE_QUEUE_ERROR_NONE;
529 tbm_surface_queue_error_e tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue, tbm_surface_h * surface)
531 queue_node *node = NULL;
533 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
534 TBM_RETURN_VAL_IF_FAIL(surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
536 pthread_mutex_lock(&surface_queue->lock);
538 if (surface_queue->impl && surface_queue->impl->acquire)
539 node = surface_queue->impl->acquire(surface_queue);
541 node = _tbm_surface_queue_acquire(surface_queue);
545 pthread_mutex_unlock(&surface_queue->lock);
546 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
549 if (node->surface == NULL) {
551 TBM_LOG("_queue_node_pop_front failed\n");
552 pthread_mutex_unlock(&surface_queue->lock);
553 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
556 *surface = node->surface;
558 pthread_mutex_unlock(&surface_queue->lock);
560 return TBM_SURFACE_QUEUE_ERROR_NONE;
563 int tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
565 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
567 pthread_mutex_lock(&surface_queue->lock);
569 if (_queue_is_empty(&surface_queue->dirty_queue)) {
571 pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
572 pthread_mutex_unlock(&surface_queue->lock);
576 pthread_mutex_unlock(&surface_queue->lock);
580 pthread_mutex_unlock(&surface_queue->lock);
585 void tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
587 queue_node *node = NULL, *tmp = NULL;
589 TBM_RETURN_IF_FAIL(surface_queue != NULL);
591 if (surface_queue->destroy_cb)
592 surface_queue->destroy_cb(surface_queue, surface_queue->destroy_cb_data);
594 if (surface_queue->impl && surface_queue->impl->destroy)
595 surface_queue->impl->destroy(surface_queue);
597 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
598 _queue_node_delete(node);
601 pthread_mutex_destroy(&surface_queue->lock);
605 tbm_surface_queue_error_e tbm_surface_queue_reset(tbm_surface_queue_h surface_queue, int width, int height, int format)
607 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
609 queue_node *node = NULL, *tmp = NULL;
611 if (width == surface_queue->width && height == surface_queue->height && format == surface_queue->format)
612 return TBM_SURFACE_QUEUE_ERROR_NONE;
614 pthread_mutex_lock(&surface_queue->lock);
616 surface_queue->width = width;
617 surface_queue->height = height;
618 surface_queue->format = format;
620 /* Destory surface and Push to free_queue */
621 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link)
623 _queue_node_delete(node);
627 _queue_init(&surface_queue->free_queue);
628 _queue_init(&surface_queue->dirty_queue);
629 LIST_INITHEAD(&surface_queue->list);
631 if (surface_queue->impl && surface_queue->impl->reset)
632 surface_queue->impl->reset(surface_queue);
634 pthread_mutex_unlock(&surface_queue->lock);
635 pthread_cond_signal(&surface_queue->free_cond);
637 if (surface_queue->reset_cb)
638 surface_queue->reset_cb(surface_queue, surface_queue->reset_cb_data);
640 return TBM_SURFACE_QUEUE_ERROR_NONE;
650 static void __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
652 tbm_queue_default* data = surface_queue->impl_data;
653 data->num_attached = 0;
656 static void __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
658 tbm_queue_default* data = surface_queue->impl_data;
659 data->num_attached = 0;
662 static void __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
664 free(surface_queue->impl_data);
667 static void __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
669 tbm_queue_default* data = surface_queue->impl_data;
670 tbm_surface_h surface;
672 if (data->queue_size == data->num_attached)
675 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
676 surface_queue->height,
677 surface_queue->format,
679 TBM_RETURN_IF_FAIL(surface != NULL);
680 _tbm_surface_queue_attach(surface_queue, surface);
681 tbm_surface_internal_unref(surface);
682 data->num_attached++;
685 static const tbm_surface_queue_interface tbm_queue_default_impl =
687 __tbm_queue_default_init,
688 __tbm_queue_default_reset,
689 __tbm_queue_default_destroy,
690 __tbm_queue_default_need_attach,
691 NULL, /*__tbm_queue_default_enqueue*/
692 NULL, /*__tbm_queue_default_release*/
693 NULL, /*__tbm_queue_default_dequeue*/
694 NULL, /*__tbm_queue_default_acquire*/
697 tbm_surface_queue_h tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags)
699 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
700 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
701 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
702 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
704 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1, sizeof(struct _tbm_surface_queue));
705 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
707 tbm_queue_default *data = (tbm_queue_default *) calloc(1, sizeof(tbm_queue_default));
714 data->queue_size = queue_size;
716 _tbm_surface_queue_init(surface_queue,
717 width, height, format,
718 &tbm_queue_default_impl, data);
720 return surface_queue;
731 static void __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
733 tbm_queue_sequence* data = surface_queue->impl_data;
735 data->num_attached = 0;
736 _queue_init(&data->dequeue_list);
739 static void __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
741 tbm_queue_sequence* data = surface_queue->impl_data;
743 data->num_attached = 0;
744 _queue_init(&data->dequeue_list);
747 static void __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
749 free(surface_queue->impl_data);
752 static void __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
754 tbm_queue_sequence* data = surface_queue->impl_data;
755 tbm_surface_h surface;
757 if (data->queue_size == data->num_attached)
760 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
761 surface_queue->height,
762 surface_queue->format,
764 TBM_RETURN_IF_FAIL(surface != NULL);
765 _tbm_surface_queue_attach(surface_queue, surface);
766 tbm_surface_internal_unref(surface);
767 data->num_attached++;
770 static void __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue, queue_node* node)
772 tbm_queue_sequence* data = surface_queue->impl_data;
773 queue_node *next = NULL;
774 queue_node *tmp = NULL;
776 node->priv_flags = 0;
778 LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
779 if (next->priv_flags) break;
780 _queue_node_pop(&data->dequeue_list, next);
781 _tbm_surface_queue_enqueue(surface_queue, next, 1);
785 static queue_node* __tbm_queue_sequence_dequeue(tbm_surface_queue_h surface_queue)
787 tbm_queue_sequence* data = surface_queue->impl_data;
788 queue_node* node = NULL;
790 node = _tbm_surface_queue_dequeue(surface_queue);
793 _queue_node_push_back(&data->dequeue_list, node);
794 node->priv_flags = 1;
800 static const tbm_surface_queue_interface tbm_queue_sequence_impl =
802 __tbm_queue_sequence_init,
803 __tbm_queue_sequence_reset,
804 __tbm_queue_sequence_destroy,
805 __tbm_queue_sequence_need_attach,
806 __tbm_queue_sequence_enqueue,
807 NULL, /*__tbm_queue_sequence_release*/
808 __tbm_queue_sequence_dequeue,
809 NULL, /*__tbm_queue_sequence_acquire*/
812 tbm_surface_queue_h tbm_surface_queue_sequence_create(int queue_size, int width, int height, int format, int flags)
814 TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
815 TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
816 TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
817 TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
819 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1, sizeof(struct _tbm_surface_queue));
820 TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
822 tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1, sizeof(tbm_queue_sequence));
829 data->queue_size = queue_size;
831 _tbm_surface_queue_init(surface_queue,
832 width, height, format,
833 &tbm_queue_sequence_impl, data);
835 return surface_queue;