Add function add/remove dequeue callback in queue
[platform/core/uifw/libtbm.git] / src / tbm_surface_queue.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
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>
9
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:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
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.
29
30 **************************************************************************/
31
32 #include "tbm_bufmgr_int.h"
33 #include "list.h"
34
35 #define FREE_QUEUE      1
36 #define DIRTY_QUEUE     2
37 #define NODE_LIST       4
38
39 #define TBM_QUEUE_DEBUG 0
40
41 #ifdef TRACE
42 #define TBM_QUEUE_TRACE(fmt, ...)  { if (bTrace&0x1) fprintf(stderr, "[TBM:TRACE(%d)(%s:%d)] " fmt, getpid(), __func__, __LINE__, ##__VA_ARGS__); }
43 #else
44 #define TBM_QUEUE_TRACE(fmt, ...)
45 #endif /* TRACE */
46
47 #if TBM_QUEUE_DEBUG
48 #define TBM_LOCK() TBM_LOG_D("[LOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
49 #define TBM_UNLOCK() TBM_LOG_D("[UNLOCK] %s:%d surface:%p\n", __func__, __LINE__, surface_queue)
50 #else
51 #define TBM_LOCK()
52 #define TBM_UNLOCK()
53 #endif
54
55 typedef enum _queue_node_type {
56         QUEUE_NODE_TYPE_NONE,
57         QUEUE_NODE_TYPE_DEQUEUE,
58         QUEUE_NODE_TYPE_ENQUEUE,
59         QUEUE_NODE_TYPE_ACQUIRE,
60         QUEUE_NODE_TYPE_RELEASE
61 } Queue_Node_Type;
62
63 typedef struct {
64         struct list_head head;
65         int count;
66 } queue;
67
68 typedef struct {
69         tbm_surface_h surface;
70
71         struct list_head item_link;
72         struct list_head link;
73
74         Queue_Node_Type type;
75
76         unsigned int priv_flags;        /*for each queue*/
77 } queue_node;
78
79 typedef struct {
80         struct list_head link;
81
82         tbm_surface_queue_notify_cb cb;
83         void *data;
84 } queue_notify;
85
86 typedef struct _tbm_surface_queue_interface {
87         void (*init)(tbm_surface_queue_h queue);
88         void (*reset)(tbm_surface_queue_h queue);
89         void (*destroy)(tbm_surface_queue_h queue);
90         void (*need_attach)(tbm_surface_queue_h queue);
91
92         void (*enqueue)(tbm_surface_queue_h queue, queue_node *node);
93         void (*release)(tbm_surface_queue_h queue, queue_node *node);
94         queue_node *(*dequeue)(tbm_surface_queue_h queue);
95         queue_node *(*acquire)(tbm_surface_queue_h queue);
96 } tbm_surface_queue_interface;
97
98 struct _tbm_surface_queue {
99         int width;
100         int height;
101         int format;
102         int queue_size;
103
104         queue free_queue;
105         queue dirty_queue;
106         struct list_head list;
107
108         struct list_head destory_noti;
109         struct list_head dequeuable_noti;
110         struct list_head dequeue_noti;
111         struct list_head acquirable_noti;
112         struct list_head reset_noti;
113
114         pthread_mutex_t lock;
115         pthread_cond_t free_cond;
116         pthread_cond_t dirty_cond;
117
118         const tbm_surface_queue_interface *impl;
119         void *impl_data;
120
121         //For external buffer allocation
122         tbm_surface_alloc_cb alloc_cb;
123         tbm_surface_free_cb free_cb;
124         void *alloc_cb_data;
125 };
126
127 /* LCOV_EXCL_START */
128 static queue_node *
129 _queue_node_create(void)
130 {
131         queue_node *node = (queue_node *) calloc(1, sizeof(queue_node));
132
133         TBM_RETURN_VAL_IF_FAIL(node != NULL, NULL);
134
135         return node;
136 }
137
138 static void
139 _queue_node_delete(queue_node *node)
140 {
141         LIST_DEL(&node->item_link);
142         LIST_DEL(&node->link);
143         free(node);
144 }
145
146 static int
147 _queue_is_empty(queue *queue)
148 {
149         if (LIST_IS_EMPTY(&queue->head))
150                 return 1;
151
152         return 0;
153 }
154
155 static void
156 _queue_node_push_back(queue *queue, queue_node *node)
157 {
158         LIST_ADDTAIL(&node->item_link, &queue->head);
159         queue->count++;
160 }
161
162 static void
163 _queue_node_push_front(queue *queue, queue_node *node)
164 {
165         LIST_ADD(&node->item_link, &queue->head);
166         queue->count++;
167 }
168
169 static queue_node *
170 _queue_node_pop_front(queue *queue)
171 {
172         queue_node *node = NULL;
173
174         node = LIST_ENTRY(queue_node, queue->head.next, item_link);
175
176         LIST_DEL(&node->item_link);
177         queue->count--;
178
179         return node;
180 }
181
182 static queue_node *
183 _queue_node_pop(queue *queue, queue_node *node)
184 {
185         LIST_DEL(&node->item_link);
186         queue->count--;
187
188         return node;
189 }
190
191 static int
192 _queue_has_node_type(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
193 {
194         queue_node *node = NULL;
195         queue_node *tmp = NULL;
196
197         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
198                 if (node->type == type)
199                         return 1;
200         }
201
202         return 0;
203 }
204
205 static queue_node *
206 _queue_get_node(tbm_surface_queue_h surface_queue, int type,
207                 tbm_surface_h surface, int *out_type)
208 {
209         queue_node *node = NULL;
210         queue_node *tmp = NULL;
211
212         if (type == 0)
213                 type = FREE_QUEUE | DIRTY_QUEUE | NODE_LIST;
214         if (out_type)
215                 *out_type = 0;
216
217         if (type & FREE_QUEUE) {
218                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->free_queue.head,
219                                          item_link) {
220                         if (node->surface == surface) {
221                                 if (out_type)
222                                         *out_type = FREE_QUEUE;
223
224                                 return node;
225                         }
226                 }
227         }
228
229         if (type & DIRTY_QUEUE) {
230                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->dirty_queue.head,
231                                          item_link) {
232                         if (node->surface == surface) {
233                                 if (out_type)
234                                         *out_type = DIRTY_QUEUE;
235
236                                 return node;
237                         }
238                 }
239         }
240
241         if (type & NODE_LIST) {
242                 LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
243                         if (node->surface == surface) {
244                                 if (out_type)
245                                         *out_type = NODE_LIST;
246
247                                 return node;
248                         }
249                 }
250         }
251
252         return NULL;
253 }
254
255 static void
256 _queue_delete_node(tbm_surface_queue_h surface_queue, queue_node *node)
257 {
258         if (node->surface) {
259                 if (surface_queue->free_cb) {
260                         surface_queue->free_cb(surface_queue,
261                                         surface_queue->alloc_cb_data,
262                                         node->surface);
263                 }
264
265                 tbm_surface_destroy(node->surface);
266         }
267
268         _queue_node_delete(node);
269 }
270
271 static void
272 _queue_init(queue *queue)
273 {
274         LIST_INITHEAD(&queue->head);
275
276         queue->count = 0;
277 }
278
279 static void
280 _notify_add(struct list_head *list, tbm_surface_queue_notify_cb cb,
281             void *data)
282 {
283         TBM_RETURN_IF_FAIL(cb != NULL);
284
285         queue_notify *item = (queue_notify *)calloc(1, sizeof(queue_notify));
286
287         TBM_RETURN_IF_FAIL(item != NULL);
288
289         LIST_INITHEAD(&item->link);
290         item->cb = cb;
291         item->data = data;
292
293         LIST_ADDTAIL(&item->link, list);
294 }
295
296 static void
297 _notify_remove(struct list_head *list,
298                tbm_surface_queue_notify_cb cb, void *data)
299 {
300         queue_notify *item = NULL, *tmp = NULL;
301
302         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
303                 if (item->cb == cb && item->data == data) {
304                         LIST_DEL(&item->link);
305                         free(item);
306                         return;
307                 }
308         }
309
310         TBM_LOG_E("Cannot find notifiy\n");
311 }
312
313 static void
314 _notify_remove_all(struct list_head *list)
315 {
316         queue_notify *item = NULL, *tmp = NULL;
317
318         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
319                 LIST_DEL(&item->link);
320                 free(item);
321         }
322 }
323
324 static void
325 _notify_emit(tbm_surface_queue_h surface_queue,
326              struct list_head *list)
327 {
328         queue_notify *item = NULL, *tmp = NULL;
329
330         LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
331                 item->cb(surface_queue, item->data);
332         }
333 }
334
335 static int
336 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
337 {
338         queue_node *node = NULL;
339         queue_node *tmp = NULL;
340         int count = 0;
341
342         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
343                 if (node->type == type)
344                         count++;
345         }
346
347         return count;
348 }
349
350 void
351 _tbm_surface_queue_attach(tbm_surface_queue_h surface_queue,
352                           tbm_surface_h surface)
353 {
354         queue_node *node = NULL;
355
356         node = _queue_node_create();
357         TBM_RETURN_IF_FAIL(node != NULL);
358
359         tbm_surface_internal_ref(surface);
360         node->surface = surface;
361
362         LIST_ADDTAIL(&node->link, &surface_queue->list);
363         _queue_node_push_back(&surface_queue->free_queue, node);
364 }
365
366 void
367 _tbm_surface_queue_detach(tbm_surface_queue_h surface_queue,
368                           tbm_surface_h surface)
369 {
370         queue_node *node = NULL;
371         int queue_type;
372
373         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
374         if (node)
375                 _queue_delete_node(surface_queue, node);
376 }
377
378 void
379 _tbm_surface_queue_enqueue(tbm_surface_queue_h surface_queue,
380                            queue_node *node, int push_back)
381 {
382         if (push_back)
383                 _queue_node_push_back(&surface_queue->dirty_queue, node);
384         else
385                 _queue_node_push_front(&surface_queue->dirty_queue, node);
386 }
387
388 queue_node *
389 _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
390 {
391         queue_node *node = NULL;
392
393         if (_queue_is_empty(&surface_queue->free_queue)) {
394                 if (surface_queue->impl && surface_queue->impl->need_attach)
395                         surface_queue->impl->need_attach(surface_queue);
396
397                 if (_queue_is_empty(&surface_queue->free_queue))
398                         return NULL;
399         }
400
401         node = _queue_node_pop_front(&surface_queue->free_queue);
402
403         return node;
404 }
405
406 queue_node *
407 _tbm_surface_queue_acquire(tbm_surface_queue_h surface_queue)
408 {
409         queue_node *node = NULL;
410
411         if (_queue_is_empty(&surface_queue->dirty_queue))
412                 return NULL;
413
414         node = _queue_node_pop_front(&surface_queue->dirty_queue);
415
416         return node;
417 }
418
419 void
420 _tbm_surface_queue_release(tbm_surface_queue_h surface_queue,
421                            queue_node *node, int push_back)
422 {
423         if (push_back)
424                 _queue_node_push_back(&surface_queue->free_queue, node);
425         else
426                 _queue_node_push_front(&surface_queue->free_queue, node);
427 }
428
429 void
430 _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
431                         int queue_size,
432                         int width, int height, int format,
433                         const tbm_surface_queue_interface *impl, void *data)
434 {
435         TBM_RETURN_IF_FAIL(surface_queue != NULL);
436         TBM_RETURN_IF_FAIL(impl != NULL);
437
438         memset(surface_queue, 0x00, sizeof(struct _tbm_surface_queue));
439
440         pthread_mutex_init(&surface_queue->lock, NULL);
441         pthread_cond_init(&surface_queue->free_cond, NULL);
442         pthread_cond_init(&surface_queue->dirty_cond, NULL);
443
444         surface_queue->queue_size = queue_size;
445         surface_queue->width = width;
446         surface_queue->height = height;
447         surface_queue->format = format;
448         surface_queue->impl = impl;
449         surface_queue->impl_data = data;
450
451         _queue_init(&surface_queue->free_queue);
452         _queue_init(&surface_queue->dirty_queue);
453         LIST_INITHEAD(&surface_queue->list);
454
455         LIST_INITHEAD(&surface_queue->destory_noti);
456         LIST_INITHEAD(&surface_queue->acquirable_noti);
457         LIST_INITHEAD(&surface_queue->dequeuable_noti);
458         LIST_INITHEAD(&surface_queue->dequeue_noti);
459         LIST_INITHEAD(&surface_queue->reset_noti);
460
461         if (surface_queue->impl && surface_queue->impl->init)
462                 surface_queue->impl->init(surface_queue);
463 }
464
465 tbm_surface_queue_error_e
466 tbm_surface_queue_add_destroy_cb(
467         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
468         void *data)
469 {
470         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
471                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
472
473         pthread_mutex_lock(&surface_queue->lock);
474
475         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
476
477         _notify_add(&surface_queue->destory_noti, destroy_cb, data);
478
479         pthread_mutex_unlock(&surface_queue->lock);
480
481         return TBM_SURFACE_QUEUE_ERROR_NONE;
482 }
483
484 tbm_surface_queue_error_e
485 tbm_surface_queue_remove_destroy_cb(
486         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb,
487         void *data)
488 {
489         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
490                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
491
492         pthread_mutex_lock(&surface_queue->lock);
493
494         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
495
496         _notify_remove(&surface_queue->destory_noti, destroy_cb, data);
497
498         pthread_mutex_unlock(&surface_queue->lock);
499
500         return TBM_SURFACE_QUEUE_ERROR_NONE;
501 }
502
503 tbm_surface_queue_error_e
504 tbm_surface_queue_add_dequeuable_cb(
505         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
506         void *data)
507 {
508         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
509                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
510
511         pthread_mutex_lock(&surface_queue->lock);
512
513         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
514
515         _notify_add(&surface_queue->dequeuable_noti, dequeuable_cb, data);
516
517         pthread_mutex_unlock(&surface_queue->lock);
518
519         return TBM_SURFACE_QUEUE_ERROR_NONE;
520 }
521
522 tbm_surface_queue_error_e
523 tbm_surface_queue_remove_dequeuable_cb(
524         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb,
525         void *data)
526 {
527         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
528                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
529
530         pthread_mutex_lock(&surface_queue->lock);
531
532         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
533
534         _notify_remove(&surface_queue->dequeuable_noti, dequeuable_cb, data);
535
536         pthread_mutex_unlock(&surface_queue->lock);
537
538         return TBM_SURFACE_QUEUE_ERROR_NONE;
539 }
540
541 tbm_surface_queue_error_e
542 tbm_surface_queue_add_dequeue_cb(
543         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
544         void *data)
545 {
546         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
547                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
548
549         pthread_mutex_lock(&surface_queue->lock);
550
551         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
552
553         _notify_add(&surface_queue->dequeue_noti, dequeue_cb, data);
554
555         pthread_mutex_unlock(&surface_queue->lock);
556
557         return TBM_SURFACE_QUEUE_ERROR_NONE;
558 }
559
560 tbm_surface_queue_error_e
561 tbm_surface_queue_remove_dequeue_cb(
562         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeue_cb,
563         void *data)
564 {
565         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
566                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
567
568         pthread_mutex_lock(&surface_queue->lock);
569
570         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
571
572         _notify_remove(&surface_queue->dequeue_noti, dequeue_cb, data);
573
574         pthread_mutex_unlock(&surface_queue->lock);
575
576         return TBM_SURFACE_QUEUE_ERROR_NONE;
577 }
578
579 tbm_surface_queue_error_e
580 tbm_surface_queue_add_acquirable_cb(
581         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
582         void *data)
583 {
584         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
585                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
586
587         pthread_mutex_lock(&surface_queue->lock);
588
589         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
590
591         _notify_add(&surface_queue->acquirable_noti, acquirable_cb, data);
592
593         pthread_mutex_unlock(&surface_queue->lock);
594
595         return TBM_SURFACE_QUEUE_ERROR_NONE;
596 }
597
598 tbm_surface_queue_error_e
599 tbm_surface_queue_remove_acquirable_cb(
600         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
601         void *data)
602 {
603         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
604                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
605
606         pthread_mutex_lock(&surface_queue->lock);
607
608         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
609
610         _notify_remove(&surface_queue->acquirable_noti, acquirable_cb, data);
611
612         pthread_mutex_unlock(&surface_queue->lock);
613
614         return TBM_SURFACE_QUEUE_ERROR_NONE;
615 }
616
617 tbm_surface_queue_error_e
618 tbm_surface_queue_set_alloc_cb(
619         tbm_surface_queue_h surface_queue,
620         tbm_surface_alloc_cb alloc_cb,
621         tbm_surface_free_cb free_cb,
622         void *data)
623 {
624         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
625                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
626
627         pthread_mutex_lock(&surface_queue->lock);
628
629         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
630
631         surface_queue->alloc_cb = alloc_cb;
632         surface_queue->free_cb = free_cb;
633         surface_queue->alloc_cb_data = data;
634
635         pthread_mutex_unlock(&surface_queue->lock);
636
637         return TBM_SURFACE_QUEUE_ERROR_NONE;
638 }
639
640 int
641 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
642 {
643         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
644
645         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
646
647         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
648
649         return surface_queue->width;
650 }
651
652 int
653 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
654 {
655         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
656
657         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
658
659         return surface_queue->height;
660 }
661
662 int
663 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
664 {
665         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
666
667         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
668
669         return surface_queue->format;
670 }
671
672 int
673 tbm_surface_queue_get_size(tbm_surface_queue_h surface_queue)
674 {
675         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
676
677         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
678
679         return surface_queue->queue_size;
680 }
681
682 tbm_surface_queue_error_e
683 tbm_surface_queue_add_reset_cb(
684         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
685         void *data)
686 {
687         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
688                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
689
690         pthread_mutex_lock(&surface_queue->lock);
691
692         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
693
694         _notify_add(&surface_queue->reset_noti, reset_cb, data);
695
696         pthread_mutex_unlock(&surface_queue->lock);
697
698         return TBM_SURFACE_QUEUE_ERROR_NONE;
699 }
700
701 tbm_surface_queue_error_e
702 tbm_surface_queue_remove_reset_cb(
703         tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb,
704         void *data)
705 {
706         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
707                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
708
709         pthread_mutex_lock(&surface_queue->lock);
710
711         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
712
713         _notify_remove(&surface_queue->reset_noti, reset_cb, data);
714
715         pthread_mutex_unlock(&surface_queue->lock);
716
717         return TBM_SURFACE_QUEUE_ERROR_NONE;
718 }
719
720 tbm_surface_queue_error_e
721 tbm_surface_queue_enqueue(tbm_surface_queue_h
722                           surface_queue, tbm_surface_h surface)
723 {
724         queue_node *node = NULL;
725         int queue_type;
726
727         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
728                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
729         TBM_RETURN_VAL_IF_FAIL(surface != NULL,
730                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
731
732         if (b_dump_queue)
733                 tbm_surface_internal_dump_buffer(surface, "enqueue");
734
735         pthread_mutex_lock(&surface_queue->lock);
736
737         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
738
739         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
740         if (node == NULL || queue_type != NODE_LIST) {
741                 TBM_LOG_E("tbm_surface_queue_enqueue::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
742                         node, queue_type);
743                 pthread_mutex_unlock(&surface_queue->lock);
744                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
745         }
746
747         if (surface_queue->impl && surface_queue->impl->enqueue)
748                 surface_queue->impl->enqueue(surface_queue, node);
749         else
750                 _tbm_surface_queue_enqueue(surface_queue, node, 1);
751
752         if (_queue_is_empty(&surface_queue->dirty_queue)) {
753                 pthread_mutex_unlock(&surface_queue->lock);
754                 return TBM_SURFACE_QUEUE_ERROR_NONE;
755         }
756
757         node->type = QUEUE_NODE_TYPE_ENQUEUE;
758
759         pthread_mutex_unlock(&surface_queue->lock);
760         pthread_cond_signal(&surface_queue->dirty_cond);
761
762         _notify_emit(surface_queue, &surface_queue->acquirable_noti);
763
764         return TBM_SURFACE_QUEUE_ERROR_NONE;
765 }
766
767 tbm_surface_queue_error_e
768 tbm_surface_queue_dequeue(tbm_surface_queue_h
769                           surface_queue, tbm_surface_h *surface)
770 {
771         queue_node *node = NULL;
772
773         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
774                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
775         TBM_RETURN_VAL_IF_FAIL(surface != NULL,
776                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
777
778         pthread_mutex_lock(&surface_queue->lock);
779
780         if (surface_queue->impl && surface_queue->impl->dequeue)
781                 node = surface_queue->impl->dequeue(surface_queue);
782         else
783                 node = _tbm_surface_queue_dequeue(surface_queue);
784
785         if (node == NULL) {
786                 *surface = NULL;
787                 pthread_mutex_unlock(&surface_queue->lock);
788                 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
789         }
790
791         if (node->surface == NULL) {
792                 *surface = NULL;
793                 TBM_LOG_E("_queue_node_pop_front  failed\n");
794                 pthread_mutex_unlock(&surface_queue->lock);
795                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
796         }
797
798         node->type = QUEUE_NODE_TYPE_DEQUEUE;
799         *surface = node->surface;
800
801         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
802
803         pthread_mutex_unlock(&surface_queue->lock);
804
805         _notify_emit(surface_queue, &surface_queue->dequeue_noti);
806
807         return TBM_SURFACE_QUEUE_ERROR_NONE;
808 }
809
810 int
811 tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
812 {
813         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
814
815         pthread_mutex_lock(&surface_queue->lock);
816
817         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
818
819         if (_queue_is_empty(&surface_queue->free_queue)) {
820                 if (surface_queue->impl && surface_queue->impl->need_attach)
821                         surface_queue->impl->need_attach(surface_queue);
822         }
823
824         if (_queue_is_empty(&surface_queue->free_queue)) {
825                 if (wait &&
826                         _tbm_surface_queue_get_node_count(surface_queue,QUEUE_NODE_TYPE_ACQUIRE)) {
827
828                         pthread_cond_wait(&surface_queue->free_cond, &surface_queue->lock);
829                         pthread_mutex_unlock(&surface_queue->lock);
830                         return 1;
831                 }
832
833                 pthread_mutex_unlock(&surface_queue->lock);
834                 return 0;
835         }
836
837         pthread_mutex_unlock(&surface_queue->lock);
838
839         return 1;
840 }
841
842 tbm_surface_queue_error_e
843 tbm_surface_queue_release(tbm_surface_queue_h
844                           surface_queue, tbm_surface_h surface)
845 {
846         queue_node *node = NULL;
847         int queue_type;
848
849         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
850                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
851         TBM_RETURN_VAL_IF_FAIL(surface != NULL,
852                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
853
854         pthread_mutex_lock(&surface_queue->lock);
855
856         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, surface);
857
858         node = _queue_get_node(surface_queue, 0, surface, &queue_type);
859         if (node == NULL || queue_type != NODE_LIST) {
860                 TBM_LOG_E("tbm_surface_queue_release::Surface exist in free_queue or dirty_queue node:%p, queue:%d\n",
861                         node, queue_type);
862                 pthread_mutex_unlock(&surface_queue->lock);
863                 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
864         }
865
866         if (surface_queue->impl && surface_queue->impl->release)
867                 surface_queue->impl->release(surface_queue, node);
868         else
869                 _tbm_surface_queue_release(surface_queue, node, 1);
870
871         if (_queue_is_empty(&surface_queue->free_queue)) {
872                 pthread_mutex_unlock(&surface_queue->lock);
873                 return TBM_SURFACE_QUEUE_ERROR_NONE;
874         }
875
876         node->type = QUEUE_NODE_TYPE_RELEASE;
877
878         pthread_mutex_unlock(&surface_queue->lock);
879         pthread_cond_signal(&surface_queue->free_cond);
880
881         _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
882
883         return TBM_SURFACE_QUEUE_ERROR_NONE;
884 }
885
886 tbm_surface_queue_error_e
887 tbm_surface_queue_acquire(tbm_surface_queue_h
888                           surface_queue, tbm_surface_h *surface)
889 {
890         queue_node *node = NULL;
891
892         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
893                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
894         TBM_RETURN_VAL_IF_FAIL(surface != NULL,
895                                TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
896
897         pthread_mutex_lock(&surface_queue->lock);
898
899         if (surface_queue->impl && surface_queue->impl->acquire)
900                 node = surface_queue->impl->acquire(surface_queue);
901         else
902                 node = _tbm_surface_queue_acquire(surface_queue);
903
904         if (node == NULL) {
905                 *surface = NULL;
906                 pthread_mutex_unlock(&surface_queue->lock);
907                 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
908         }
909
910         if (node->surface == NULL) {
911                 *surface = NULL;
912                 TBM_LOG_E("_queue_node_pop_front  failed\n");
913                 pthread_mutex_unlock(&surface_queue->lock);
914                 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
915         }
916
917         node->type = QUEUE_NODE_TYPE_ACQUIRE;
918
919         *surface = node->surface;
920
921         TBM_QUEUE_TRACE("tbm_surface_queue(%p) tbm_surface(%p)\n", surface_queue, *surface);
922
923         pthread_mutex_unlock(&surface_queue->lock);
924
925         if (b_dump_queue)
926                 tbm_surface_internal_dump_buffer(*surface, "acquire");
927
928         return TBM_SURFACE_QUEUE_ERROR_NONE;
929 }
930
931 int
932 tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
933 {
934         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, 0);
935
936         pthread_mutex_lock(&surface_queue->lock);
937
938         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
939
940         if (_queue_is_empty(&surface_queue->dirty_queue)) {
941                 if (wait &&
942                         _tbm_surface_queue_get_node_count(surface_queue,QUEUE_NODE_TYPE_DEQUEUE)) {
943
944                         if (!_queue_has_node_type(surface_queue, QUEUE_NODE_TYPE_DEQUEUE)) {
945                                 TBM_LOG_E("Deosn't have dequeue type node\n");
946                                 pthread_mutex_unlock(&surface_queue->lock);
947                                 return 0;
948                         }
949
950                         pthread_cond_wait(&surface_queue->dirty_cond, &surface_queue->lock);
951                         pthread_mutex_unlock(&surface_queue->lock);
952                         return 1;
953                 }
954
955                 pthread_mutex_unlock(&surface_queue->lock);
956                 return 0;
957         }
958
959         pthread_mutex_unlock(&surface_queue->lock);
960
961         return 1;
962 }
963
964 void
965 tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
966 {
967         queue_node *node = NULL, *tmp = NULL;
968
969         TBM_RETURN_IF_FAIL(surface_queue != NULL);
970
971         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
972
973         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
974                 _queue_delete_node(surface_queue, node);
975         }
976
977         _notify_emit(surface_queue, &surface_queue->destory_noti);
978
979         if (surface_queue->impl && surface_queue->impl->destroy)
980                 surface_queue->impl->destroy(surface_queue);
981
982         _notify_remove_all(&surface_queue->destory_noti);
983         _notify_remove_all(&surface_queue->acquirable_noti);
984         _notify_remove_all(&surface_queue->dequeuable_noti);
985         _notify_remove_all(&surface_queue->reset_noti);
986
987         pthread_mutex_destroy(&surface_queue->lock);
988         free(surface_queue);
989 }
990
991 tbm_surface_queue_error_e
992 tbm_surface_queue_reset(tbm_surface_queue_h
993                         surface_queue, int width, int height, int format)
994 {
995         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
996                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
997
998         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
999
1000         queue_node *node = NULL, *tmp = NULL;
1001
1002         if (width == surface_queue->width && height == surface_queue->height &&
1003             format == surface_queue->format)
1004                 return TBM_SURFACE_QUEUE_ERROR_NONE;
1005
1006         pthread_mutex_lock(&surface_queue->lock);
1007
1008         surface_queue->width = width;
1009         surface_queue->height = height;
1010         surface_queue->format = format;
1011
1012         /* Destory surface and Push to free_queue */
1013         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1014                 _queue_delete_node(surface_queue, node);
1015         }
1016
1017         /* Reset queue */
1018         _queue_init(&surface_queue->free_queue);
1019         _queue_init(&surface_queue->dirty_queue);
1020         LIST_INITHEAD(&surface_queue->list);
1021
1022         if (surface_queue->impl && surface_queue->impl->reset)
1023                 surface_queue->impl->reset(surface_queue);
1024
1025         pthread_mutex_unlock(&surface_queue->lock);
1026         pthread_cond_signal(&surface_queue->free_cond);
1027
1028         _notify_emit(surface_queue, &surface_queue->reset_noti);
1029
1030         return TBM_SURFACE_QUEUE_ERROR_NONE;
1031 }
1032
1033 tbm_surface_queue_error_e
1034 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
1035 {
1036         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
1037                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1038
1039         queue_node *node = NULL, *tmp = NULL;
1040
1041         pthread_mutex_lock(&surface_queue->lock);
1042
1043         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1044
1045         /* Destory surface and Push to free_queue */
1046         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1047                 _queue_delete_node(surface_queue, node);
1048         }
1049
1050         /* Reset queue */
1051         _queue_init(&surface_queue->free_queue);
1052         _queue_init(&surface_queue->dirty_queue);
1053         LIST_INITHEAD(&surface_queue->list);
1054
1055         if (surface_queue->impl && surface_queue->impl->reset)
1056                 surface_queue->impl->reset(surface_queue);
1057
1058         pthread_mutex_unlock(&surface_queue->lock);
1059         pthread_cond_signal(&surface_queue->free_cond);
1060
1061         _notify_emit(surface_queue, &surface_queue->reset_noti);
1062
1063         return TBM_SURFACE_QUEUE_ERROR_NONE;
1064 }
1065
1066 tbm_surface_queue_error_e
1067 tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
1068                         tbm_surface_h *surfaces, int *num)
1069 {
1070         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL,
1071                                TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
1072         TBM_RETURN_VAL_IF_FAIL(num != NULL,
1073                                TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
1074
1075         queue_node *node = NULL;
1076         queue_node *tmp = NULL;
1077
1078         pthread_mutex_lock(&surface_queue->lock);
1079
1080         *num = 0;
1081         LIST_FOR_EACH_ENTRY_SAFE(node, tmp, &surface_queue->list, link) {
1082                 if (surfaces)
1083                         surfaces[*num] = node->surface;
1084
1085                 *num = *num + 1;
1086         }
1087
1088         pthread_mutex_unlock(&surface_queue->lock);
1089
1090         return TBM_SURFACE_QUEUE_ERROR_NONE;
1091 }
1092
1093 typedef struct {
1094         int queue_size;
1095         int num_attached;
1096         int flags;
1097 } tbm_queue_default;
1098
1099 static void
1100 __tbm_queue_default_init(tbm_surface_queue_h surface_queue)
1101 {
1102         tbm_queue_default *data = surface_queue->impl_data;
1103
1104         data->num_attached = 0;
1105 }
1106
1107 static void
1108 __tbm_queue_default_reset(tbm_surface_queue_h surface_queue)
1109 {
1110         tbm_queue_default *data = surface_queue->impl_data;
1111
1112         data->num_attached = 0;
1113 }
1114
1115 static void
1116 __tbm_queue_default_destroy(tbm_surface_queue_h surface_queue)
1117 {
1118         free(surface_queue->impl_data);
1119 }
1120
1121 static void
1122 __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
1123 {
1124         tbm_queue_default *data = surface_queue->impl_data;
1125         tbm_surface_h surface;
1126
1127         if (data->queue_size == data->num_attached)
1128                 return;
1129
1130         if (surface_queue->alloc_cb) {
1131                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1132                 TBM_RETURN_IF_FAIL(surface != NULL);
1133                 tbm_surface_internal_ref(surface);
1134         } else {
1135                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1136                                 surface_queue->height,
1137                                 surface_queue->format,
1138                                 data->flags);
1139                 TBM_RETURN_IF_FAIL(surface != NULL);
1140         }
1141
1142         _tbm_surface_queue_attach(surface_queue, surface);
1143         tbm_surface_internal_unref(surface);
1144         data->num_attached++;
1145 }
1146
1147 static const tbm_surface_queue_interface tbm_queue_default_impl = {
1148         __tbm_queue_default_init,
1149         __tbm_queue_default_reset,
1150         __tbm_queue_default_destroy,
1151         __tbm_queue_default_need_attach,
1152         NULL,                           /*__tbm_queue_default_enqueue*/
1153         NULL,                           /*__tbm_queue_default_release*/
1154         NULL,                           /*__tbm_queue_default_dequeue*/
1155         NULL,                           /*__tbm_queue_default_acquire*/
1156 };
1157
1158 tbm_surface_queue_h
1159 tbm_surface_queue_create(int queue_size, int width,
1160                          int height, int format, int flags)
1161 {
1162         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1163         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1164         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1165         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1166
1167         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1168                                             sizeof(struct _tbm_surface_queue));
1169         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1170
1171         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1172
1173         tbm_queue_default *data = (tbm_queue_default *) calloc(1,
1174                                   sizeof(tbm_queue_default));
1175         if (data == NULL) {
1176                 free(surface_queue);
1177                 return NULL;
1178         }
1179
1180         data->queue_size = queue_size;
1181         data->flags = flags;
1182         _tbm_surface_queue_init(surface_queue,
1183                                 data->queue_size,
1184                                 width, height, format,
1185                                 &tbm_queue_default_impl, data);
1186
1187         return surface_queue;
1188 }
1189
1190 typedef struct {
1191         int queue_size;
1192         int num_attached;
1193         int flags;
1194         queue dequeue_list;
1195 } tbm_queue_sequence;
1196
1197 static void
1198 __tbm_queue_sequence_init(tbm_surface_queue_h surface_queue)
1199 {
1200         tbm_queue_sequence *data = surface_queue->impl_data;
1201
1202         data->num_attached = 0;
1203         _queue_init(&data->dequeue_list);
1204 }
1205
1206 static void
1207 __tbm_queue_sequence_reset(tbm_surface_queue_h surface_queue)
1208 {
1209         tbm_queue_sequence *data = surface_queue->impl_data;
1210
1211         data->num_attached = 0;
1212         _queue_init(&data->dequeue_list);
1213 }
1214
1215 static void
1216 __tbm_queue_sequence_destroy(tbm_surface_queue_h surface_queue)
1217 {
1218         free(surface_queue->impl_data);
1219 }
1220
1221 static void
1222 __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
1223 {
1224         tbm_queue_sequence *data = surface_queue->impl_data;
1225         tbm_surface_h surface;
1226
1227         if (data->queue_size == data->num_attached)
1228                 return;
1229
1230         if (surface_queue->alloc_cb) {
1231                 surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
1232                 TBM_RETURN_IF_FAIL(surface != NULL);
1233                 tbm_surface_internal_ref(surface);
1234         } else {
1235                 surface = tbm_surface_internal_create_with_flags(surface_queue->width,
1236                                 surface_queue->height,
1237                                 surface_queue->format,
1238                                 data->flags);
1239                 TBM_RETURN_IF_FAIL(surface != NULL);
1240         }
1241
1242         _tbm_surface_queue_attach(surface_queue, surface);
1243         tbm_surface_internal_unref(surface);
1244         data->num_attached++;
1245 }
1246
1247 static void
1248 __tbm_queue_sequence_enqueue(tbm_surface_queue_h surface_queue,
1249                              queue_node *node)
1250 {
1251         tbm_queue_sequence *data = surface_queue->impl_data;
1252         queue_node *next = NULL;
1253         queue_node *tmp = NULL;
1254
1255         node->priv_flags = 0;
1256
1257         LIST_FOR_EACH_ENTRY_SAFE(next, tmp, &data->dequeue_list.head, item_link) {
1258                 if (next->priv_flags)
1259                         break;
1260                 _queue_node_pop(&data->dequeue_list, next);
1261                 _tbm_surface_queue_enqueue(surface_queue, next, 1);
1262         }
1263 }
1264
1265 static queue_node *
1266 __tbm_queue_sequence_dequeue(tbm_surface_queue_h
1267                              surface_queue)
1268 {
1269         tbm_queue_sequence *data = surface_queue->impl_data;
1270         queue_node *node = NULL;
1271
1272         node = _tbm_surface_queue_dequeue(surface_queue);
1273         if (node) {
1274                 _queue_node_push_back(&data->dequeue_list, node);
1275                 node->priv_flags = 1;
1276         }
1277
1278         return node;
1279 }
1280
1281 static const tbm_surface_queue_interface tbm_queue_sequence_impl = {
1282         __tbm_queue_sequence_init,
1283         __tbm_queue_sequence_reset,
1284         __tbm_queue_sequence_destroy,
1285         __tbm_queue_sequence_need_attach,
1286         __tbm_queue_sequence_enqueue,
1287         NULL,                                   /*__tbm_queue_sequence_release*/
1288         __tbm_queue_sequence_dequeue,
1289         NULL,                                   /*__tbm_queue_sequence_acquire*/
1290 };
1291
1292 tbm_surface_queue_h
1293 tbm_surface_queue_sequence_create(int queue_size, int width,
1294                                   int height, int format, int flags)
1295 {
1296         TBM_RETURN_VAL_IF_FAIL(queue_size > 0, NULL);
1297         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
1298         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
1299         TBM_RETURN_VAL_IF_FAIL(format > 0, NULL);
1300
1301         tbm_surface_queue_h surface_queue = (tbm_surface_queue_h) calloc(1,
1302                                             sizeof(struct _tbm_surface_queue));
1303         TBM_RETURN_VAL_IF_FAIL(surface_queue != NULL, NULL);
1304
1305         TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
1306
1307         tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
1308                                    sizeof(tbm_queue_sequence));
1309         if (data == NULL) {
1310                 free(surface_queue);
1311                 return NULL;
1312         }
1313
1314         data->queue_size = queue_size;
1315         data->flags = flags;
1316         _tbm_surface_queue_init(surface_queue,
1317                                 data->queue_size,
1318                                 width, height, format,
1319                                 &tbm_queue_sequence_impl, data);
1320
1321         return surface_queue;
1322 }
1323 /* LCOV_EXCL_STOP */