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"
37 struct list_head head;
39 struct list_head tail;
46 tbm_surface_h surface;
48 struct list_head item_link;
51 struct _tbm_surface_queue
61 queue_node **node_list;
63 tbm_surface_queue_notify_cb destroy_cb;
64 void *destroy_cb_data;
66 tbm_surface_queue_notify_cb dequeuable_cb;
67 void *dequeuable_cb_data;
69 tbm_surface_queue_notify_cb acquirable_cb;
70 void *acquirable_cb_data;
73 pthread_cond_t free_cond;
74 pthread_cond_t duty_cond;
78 _queue_node_create (void)
80 queue_node *node = (queue_node *) calloc (1, sizeof(queue_node));
81 TBM_RETURN_VAL_IF_FAIL (node != NULL, NULL);
87 _queue_node_delete (queue_node *node)
89 tbm_surface_destroy (node->surface);
90 LIST_DEL (&node->item_link);
95 _queue_is_empty (queue *queue)
97 if (queue->head.next == &queue->tail)
104 _queue_node_push_back (queue *queue, queue_node *node)
106 LIST_ADDTAIL (&node->item_link, &queue->tail);
112 _queue_node_push_front (queue *queue, queue_node *node)
114 LIST_ADD (&node->item_link, &queue->head);
120 _queue_node_pop_front (queue *queue)
122 queue_node *node = NULL;
124 node = LIST_ENTRY (queue_node, queue->head.next, item_link);
126 LIST_DEL (&node->item_link);
133 _queue_node_exist_in_queue (queue *queue, queue_node *node)
135 queue_node *search_node = NULL;
136 queue_node *temp = NULL;
138 if (!_queue_is_empty(queue))
140 LIST_FOR_EACH_ENTRY_SAFE (search_node, temp, &queue->head, item_link)
142 if (search_node == node)
151 _queue_init (queue *queue)
153 LIST_INITHEAD (&queue->head);
154 LIST_INITHEAD (&queue->tail);
155 LIST_ADDTAIL (&queue->head, &queue->tail);
159 tbm_surface_queue_error_e
160 tbm_surface_queue_enqueue (tbm_surface_queue_h surface_queue, tbm_surface_h surface)
162 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
163 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
167 pthread_mutex_lock (&surface_queue->lock);
169 for (i = 0 ; i < surface_queue->size ; i++)
171 if (surface_queue->node_list[i]->surface == surface)
175 if (i == surface_queue->size)
177 TBM_LOG ("Can't find the surface in queue\n");
178 pthread_mutex_unlock (&surface_queue->lock);
179 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
182 if (_queue_node_exist_in_queue (&surface_queue->duty_queue, surface_queue->node_list[i]))
184 TBM_LOG ("Surface exist in queue\n");
185 pthread_mutex_unlock (&surface_queue->lock);
186 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
189 _queue_node_push_back(&surface_queue->duty_queue, surface_queue->node_list[i]);
191 pthread_mutex_unlock (&surface_queue->lock);
192 pthread_cond_signal(&surface_queue->duty_cond);
194 if (surface_queue->acquirable_cb)
195 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
197 return TBM_SURFACE_QUEUE_ERROR_NONE;
200 tbm_surface_queue_error_e
201 tbm_surface_queue_dequeue (tbm_surface_queue_h surface_queue, tbm_surface_h *surface)
203 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
204 TBM_RETURN_VAL_IF_FAIL (surface_queue->free_queue.count > 0, TBM_SURFACE_QUEUE_ERROR_EMPTY);
206 pthread_mutex_lock (&surface_queue->lock);
208 if (_queue_is_empty (&surface_queue->free_queue))
210 TBM_LOG ("Surface queue is empty\n");
211 pthread_mutex_unlock (&surface_queue->lock);
212 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
215 queue_node *node = NULL;
217 node = _queue_node_pop_front (&surface_queue->free_queue);
220 TBM_LOG ("_queue_node_pop_front is failed\n");
221 pthread_mutex_unlock (&surface_queue->lock);
222 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
227 tbm_surface_h surface = tbm_surface_internal_create_with_flags (surface_queue->width,
228 surface_queue->height,
229 surface_queue->format,
230 surface_queue->flags);
233 TBM_LOG ("tbm surface create failed");
234 pthread_mutex_unlock (&surface_queue->lock);
235 return TBM_SURFACE_QUEUE_ERROR_SURFACE_ALLOC_FAILED;
237 node->surface = surface;
240 *surface = node->surface;
242 pthread_mutex_unlock (&surface_queue->lock);
244 return TBM_SURFACE_QUEUE_ERROR_NONE;
247 tbm_surface_queue_error_e
248 tbm_surface_queue_release (tbm_surface_queue_h surface_queue, tbm_surface_h surface)
250 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
251 TBM_RETURN_VAL_IF_FAIL (surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
253 pthread_mutex_lock (&surface_queue->lock);
256 for (i = 0 ; i < surface_queue->size ; i++)
258 if (surface_queue->node_list[i]->surface == surface)
261 if (i == surface_queue->size)
263 TBM_LOG ("Can't find the surface in queue\n");
264 pthread_mutex_unlock (&surface_queue->lock);
265 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
268 if (_queue_node_exist_in_queue (&surface_queue->free_queue, surface_queue->node_list[i]))
270 TBM_LOG ("Surface exist in queue\n");
271 pthread_mutex_unlock (&surface_queue->lock);
272 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
275 _queue_node_push_front(&surface_queue->free_queue, surface_queue->node_list[i]);
277 pthread_mutex_unlock (&surface_queue->lock);
278 pthread_cond_signal(&surface_queue->free_cond);
280 if (surface_queue->dequeuable_cb)
281 surface_queue->dequeuable_cb (surface_queue, surface_queue->dequeuable_cb_data);
283 return TBM_SURFACE_QUEUE_ERROR_NONE;
286 tbm_surface_queue_error_e
287 tbm_surface_queue_acquire (tbm_surface_queue_h surface_queue, tbm_surface_h *surface)
289 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
290 TBM_RETURN_VAL_IF_FAIL (surface_queue->duty_queue.count > 0, TBM_SURFACE_QUEUE_ERROR_EMPTY);
292 pthread_mutex_lock (&surface_queue->lock);
294 if (_queue_is_empty (&surface_queue->duty_queue))
296 TBM_LOG ("Surface queue is empty\n");
297 pthread_mutex_unlock (&surface_queue->lock);
298 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
301 queue_node *node = NULL;
303 node = _queue_node_pop_front (&surface_queue->duty_queue);
306 TBM_LOG ("_queue_node_pop_front failed\n");
307 pthread_mutex_unlock (&surface_queue->lock);
308 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
311 *surface = node->surface;
313 pthread_mutex_unlock (&surface_queue->lock);
315 return TBM_SURFACE_QUEUE_ERROR_NONE;
319 tbm_surface_queue_can_dequeue (tbm_surface_queue_h surface_queue, int wait)
321 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
323 pthread_mutex_lock (&surface_queue->lock);
325 if (_queue_is_empty (&surface_queue->free_queue))
329 pthread_cond_wait (&surface_queue->free_cond, &surface_queue->lock);
330 pthread_mutex_unlock (&surface_queue->lock);
334 pthread_mutex_unlock (&surface_queue->lock);
338 pthread_mutex_unlock (&surface_queue->lock);
343 tbm_surface_queue_can_acquire (tbm_surface_queue_h surface_queue, int wait)
345 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
347 pthread_mutex_lock (&surface_queue->lock);
349 if (_queue_is_empty (&surface_queue->duty_queue))
353 pthread_cond_wait (&surface_queue->duty_cond, &surface_queue->lock);
354 pthread_mutex_unlock (&surface_queue->lock);
358 pthread_mutex_unlock (&surface_queue->lock);
362 pthread_mutex_unlock (&surface_queue->lock);
368 tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags)
370 TBM_RETURN_VAL_IF_FAIL (queue_size > 0, NULL);
371 TBM_RETURN_VAL_IF_FAIL (width > 0, NULL);
372 TBM_RETURN_VAL_IF_FAIL (height > 0, NULL);
373 TBM_RETURN_VAL_IF_FAIL (format > 0, NULL);
376 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h)calloc(1, sizeof(struct _tbm_surface_queue));
377 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, NULL);
379 pthread_mutex_init (&surface_queue->lock, NULL);
380 pthread_cond_init (&surface_queue->free_cond, NULL);
381 pthread_cond_init (&surface_queue->duty_cond, NULL);
383 surface_queue->width = width;
384 surface_queue->height = height;
385 surface_queue->format = format;
386 surface_queue->flags = flags;
387 surface_queue->size = queue_size;
388 surface_queue->node_list = (queue_node **)calloc(queue_size, sizeof(queue_node *));
389 if (!surface_queue->node_list)
391 TBM_LOG ("surface node list alloc failed");
392 free (surface_queue);
393 pthread_mutex_destroy (&surface_queue->lock);
397 _queue_init (&surface_queue->free_queue);
398 _queue_init (&surface_queue->duty_queue);
400 for (i = 0 ; i < queue_size; i++)
402 queue_node *node = _queue_node_create();
405 TBM_LOG ("surface node create failed");
409 surface_queue->node_list[i] = node;
410 _queue_node_push_back (&surface_queue->free_queue, node);
413 return surface_queue;
416 for (j = 0 ; j < i ; j++)
417 _queue_node_delete (surface_queue->node_list[j]);
419 free (surface_queue->node_list);
420 free (surface_queue);
421 pthread_mutex_destroy (&surface_queue->lock);
427 tbm_surface_queue_destroy (tbm_surface_queue_h surface_queue)
429 TBM_RETURN_IF_FAIL (surface_queue != NULL);
431 if (surface_queue->destroy_cb)
432 surface_queue->destroy_cb (surface_queue, surface_queue->destroy_cb_data);
436 for (i = 0 ; i < surface_queue->size ; i++)
437 _queue_node_delete (surface_queue->node_list[i]);
439 free (surface_queue->node_list);
440 free (surface_queue);
443 tbm_surface_queue_error_e
444 tbm_surface_queue_set_destroy_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb, void *data)
446 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
448 pthread_mutex_lock (&surface_queue->lock);
450 surface_queue->destroy_cb = destroy_cb;
451 surface_queue->destroy_cb_data = data;
453 pthread_mutex_unlock (&surface_queue->lock);
455 return TBM_SURFACE_QUEUE_ERROR_NONE;
458 tbm_surface_queue_error_e
459 tbm_surface_queue_set_dequeuable_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb, void *data)
461 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
463 pthread_mutex_lock (&surface_queue->lock);
465 surface_queue->dequeuable_cb = dequeuable_cb;
466 surface_queue->dequeuable_cb_data = data;
468 pthread_mutex_unlock (&surface_queue->lock);
470 return TBM_SURFACE_QUEUE_ERROR_NONE;
473 tbm_surface_queue_error_e
474 tbm_surface_queue_set_acquirable_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb, void *data)
476 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
478 pthread_mutex_lock (&surface_queue->lock);
480 surface_queue->acquirable_cb = acquirable_cb;
481 surface_queue->acquirable_cb_data = data;
483 pthread_mutex_unlock (&surface_queue->lock);
485 return TBM_SURFACE_QUEUE_ERROR_NONE;
489 tbm_surface_queue_get_queue_size (tbm_surface_queue_h surface_queue)
491 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
493 return surface_queue->size;
497 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
499 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
501 return surface_queue->width;
505 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
507 return surface_queue->height;
511 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
513 return surface_queue->format;