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;
72 tbm_surface_queue_notify_cb reset_cb;
76 pthread_cond_t free_cond;
77 pthread_cond_t duty_cond;
81 _queue_node_create (void)
83 queue_node *node = (queue_node *) calloc (1, sizeof(queue_node));
84 TBM_RETURN_VAL_IF_FAIL (node != NULL, NULL);
90 _queue_node_delete (queue_node *node)
93 tbm_surface_destroy (node->surface);
94 LIST_DEL (&node->item_link);
99 _queue_is_empty (queue *queue)
101 if (queue->head.next == &queue->tail)
108 _queue_node_push_back (queue *queue, queue_node *node)
110 LIST_ADDTAIL (&node->item_link, &queue->tail);
116 _queue_node_push_front (queue *queue, queue_node *node)
118 LIST_ADD (&node->item_link, &queue->head);
124 _queue_node_pop_front (queue *queue)
126 queue_node *node = NULL;
128 node = LIST_ENTRY (queue_node, queue->head.next, item_link);
130 LIST_DEL (&node->item_link);
137 _queue_node_exist_in_queue (queue *queue, queue_node *node)
139 queue_node *search_node = NULL;
140 queue_node *temp = NULL;
142 if (!_queue_is_empty(queue))
144 LIST_FOR_EACH_ENTRY_SAFE (search_node, temp, &queue->head, item_link)
146 if (search_node == node)
155 _queue_init (queue *queue)
157 LIST_INITHEAD (&queue->head);
158 LIST_INITHEAD (&queue->tail);
159 LIST_ADDTAIL (&queue->head, &queue->tail);
163 tbm_surface_queue_error_e
164 tbm_surface_queue_enqueue (tbm_surface_queue_h surface_queue, tbm_surface_h surface)
166 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
167 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
171 pthread_mutex_lock (&surface_queue->lock);
173 for (i = 0 ; i < surface_queue->size ; i++)
175 if (surface_queue->node_list[i]->surface == surface)
179 if (i == surface_queue->size)
181 TBM_LOG ("Can't find the surface in queue\n");
182 pthread_mutex_unlock (&surface_queue->lock);
183 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
186 if (_queue_node_exist_in_queue (&surface_queue->duty_queue, surface_queue->node_list[i]))
188 TBM_LOG ("Surface exist in queue\n");
189 pthread_mutex_unlock (&surface_queue->lock);
190 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
193 _queue_node_push_back(&surface_queue->duty_queue, surface_queue->node_list[i]);
195 pthread_mutex_unlock (&surface_queue->lock);
196 pthread_cond_signal(&surface_queue->duty_cond);
198 if (surface_queue->acquirable_cb)
199 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
201 return TBM_SURFACE_QUEUE_ERROR_NONE;
204 tbm_surface_queue_error_e
205 tbm_surface_queue_dequeue (tbm_surface_queue_h surface_queue, tbm_surface_h *surface)
207 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
208 TBM_RETURN_VAL_IF_FAIL (surface_queue->free_queue.count > 0, TBM_SURFACE_QUEUE_ERROR_EMPTY);
210 pthread_mutex_lock (&surface_queue->lock);
212 if (_queue_is_empty (&surface_queue->free_queue))
214 TBM_LOG ("Surface queue is empty\n");
215 pthread_mutex_unlock (&surface_queue->lock);
216 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
219 queue_node *node = NULL;
221 node = _queue_node_pop_front (&surface_queue->free_queue);
224 TBM_LOG ("_queue_node_pop_front is failed\n");
225 pthread_mutex_unlock (&surface_queue->lock);
226 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
231 tbm_surface_h surface = tbm_surface_internal_create_with_flags (surface_queue->width,
232 surface_queue->height,
233 surface_queue->format,
234 surface_queue->flags);
237 TBM_LOG ("tbm surface create failed");
238 pthread_mutex_unlock (&surface_queue->lock);
239 return TBM_SURFACE_QUEUE_ERROR_SURFACE_ALLOC_FAILED;
241 node->surface = surface;
244 *surface = node->surface;
246 pthread_mutex_unlock (&surface_queue->lock);
248 return TBM_SURFACE_QUEUE_ERROR_NONE;
251 tbm_surface_queue_error_e
252 tbm_surface_queue_release (tbm_surface_queue_h surface_queue, tbm_surface_h surface)
254 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
255 TBM_RETURN_VAL_IF_FAIL (surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
257 pthread_mutex_lock (&surface_queue->lock);
260 for (i = 0 ; i < surface_queue->size ; i++)
262 if (surface_queue->node_list[i]->surface == surface)
265 if (i == surface_queue->size)
267 TBM_LOG ("Can't find the surface in queue\n");
268 pthread_mutex_unlock (&surface_queue->lock);
269 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
272 if (_queue_node_exist_in_queue (&surface_queue->free_queue, surface_queue->node_list[i]))
274 TBM_LOG ("Surface exist in queue\n");
275 pthread_mutex_unlock (&surface_queue->lock);
276 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
279 _queue_node_push_front(&surface_queue->free_queue, surface_queue->node_list[i]);
281 pthread_mutex_unlock (&surface_queue->lock);
282 pthread_cond_signal(&surface_queue->free_cond);
284 if (surface_queue->dequeuable_cb)
285 surface_queue->dequeuable_cb (surface_queue, surface_queue->dequeuable_cb_data);
287 return TBM_SURFACE_QUEUE_ERROR_NONE;
290 tbm_surface_queue_error_e
291 tbm_surface_queue_acquire (tbm_surface_queue_h surface_queue, tbm_surface_h *surface)
293 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
294 TBM_RETURN_VAL_IF_FAIL (surface_queue->duty_queue.count > 0, TBM_SURFACE_QUEUE_ERROR_EMPTY);
296 pthread_mutex_lock (&surface_queue->lock);
298 if (_queue_is_empty (&surface_queue->duty_queue))
300 TBM_LOG ("Surface queue is empty\n");
301 pthread_mutex_unlock (&surface_queue->lock);
302 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
305 queue_node *node = NULL;
307 node = _queue_node_pop_front (&surface_queue->duty_queue);
310 TBM_LOG ("_queue_node_pop_front failed\n");
311 pthread_mutex_unlock (&surface_queue->lock);
312 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
315 *surface = node->surface;
317 pthread_mutex_unlock (&surface_queue->lock);
319 return TBM_SURFACE_QUEUE_ERROR_NONE;
323 tbm_surface_queue_can_dequeue (tbm_surface_queue_h surface_queue, int wait)
325 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
327 pthread_mutex_lock (&surface_queue->lock);
329 if (_queue_is_empty (&surface_queue->free_queue))
333 pthread_cond_wait (&surface_queue->free_cond, &surface_queue->lock);
334 pthread_mutex_unlock (&surface_queue->lock);
338 pthread_mutex_unlock (&surface_queue->lock);
342 pthread_mutex_unlock (&surface_queue->lock);
347 tbm_surface_queue_can_acquire (tbm_surface_queue_h surface_queue, int wait)
349 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
351 pthread_mutex_lock (&surface_queue->lock);
353 if (_queue_is_empty (&surface_queue->duty_queue))
357 pthread_cond_wait (&surface_queue->duty_cond, &surface_queue->lock);
358 pthread_mutex_unlock (&surface_queue->lock);
362 pthread_mutex_unlock (&surface_queue->lock);
366 pthread_mutex_unlock (&surface_queue->lock);
372 tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags)
374 TBM_RETURN_VAL_IF_FAIL (queue_size > 0, NULL);
375 TBM_RETURN_VAL_IF_FAIL (width > 0, NULL);
376 TBM_RETURN_VAL_IF_FAIL (height > 0, NULL);
377 TBM_RETURN_VAL_IF_FAIL (format > 0, NULL);
380 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h)calloc(1, sizeof(struct _tbm_surface_queue));
381 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, NULL);
383 pthread_mutex_init (&surface_queue->lock, NULL);
384 pthread_cond_init (&surface_queue->free_cond, NULL);
385 pthread_cond_init (&surface_queue->duty_cond, NULL);
387 surface_queue->width = width;
388 surface_queue->height = height;
389 surface_queue->format = format;
390 surface_queue->flags = flags;
391 surface_queue->size = queue_size;
392 surface_queue->node_list = (queue_node **)calloc(queue_size, sizeof(queue_node *));
393 if (!surface_queue->node_list)
395 TBM_LOG ("surface node list alloc failed");
396 free (surface_queue);
397 pthread_mutex_destroy (&surface_queue->lock);
401 _queue_init (&surface_queue->free_queue);
402 _queue_init (&surface_queue->duty_queue);
404 for (i = 0 ; i < queue_size; i++)
406 queue_node *node = _queue_node_create();
409 TBM_LOG ("surface node create failed");
413 surface_queue->node_list[i] = node;
414 _queue_node_push_back (&surface_queue->free_queue, node);
417 return surface_queue;
420 for (j = 0 ; j < i ; j++)
421 _queue_node_delete (surface_queue->node_list[j]);
423 free (surface_queue->node_list);
424 free (surface_queue);
425 pthread_mutex_destroy (&surface_queue->lock);
431 tbm_surface_queue_destroy (tbm_surface_queue_h surface_queue)
433 TBM_RETURN_IF_FAIL (surface_queue != NULL);
435 if (surface_queue->destroy_cb)
436 surface_queue->destroy_cb (surface_queue, surface_queue->destroy_cb_data);
440 for (i = 0 ; i < surface_queue->size ; i++)
441 _queue_node_delete (surface_queue->node_list[i]);
443 free (surface_queue->node_list);
444 free (surface_queue);
447 tbm_surface_queue_error_e
448 tbm_surface_queue_set_destroy_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb, void *data)
450 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
452 pthread_mutex_lock (&surface_queue->lock);
454 surface_queue->destroy_cb = destroy_cb;
455 surface_queue->destroy_cb_data = data;
457 pthread_mutex_unlock (&surface_queue->lock);
459 return TBM_SURFACE_QUEUE_ERROR_NONE;
462 tbm_surface_queue_error_e
463 tbm_surface_queue_set_dequeuable_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb, void *data)
465 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
467 pthread_mutex_lock (&surface_queue->lock);
469 surface_queue->dequeuable_cb = dequeuable_cb;
470 surface_queue->dequeuable_cb_data = data;
472 pthread_mutex_unlock (&surface_queue->lock);
474 return TBM_SURFACE_QUEUE_ERROR_NONE;
477 tbm_surface_queue_error_e
478 tbm_surface_queue_set_acquirable_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb, void *data)
480 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
482 pthread_mutex_lock (&surface_queue->lock);
484 surface_queue->acquirable_cb = acquirable_cb;
485 surface_queue->acquirable_cb_data = data;
487 pthread_mutex_unlock (&surface_queue->lock);
489 return TBM_SURFACE_QUEUE_ERROR_NONE;
493 tbm_surface_queue_get_queue_size (tbm_surface_queue_h surface_queue)
495 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
497 return surface_queue->size;
501 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
503 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
505 return surface_queue->width;
509 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
511 return surface_queue->height;
515 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
517 return surface_queue->format;
520 tbm_surface_queue_error_e
521 tbm_surface_queue_reset(tbm_surface_queue_h surface_queue, int width, int height, int format)
523 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
526 queue_node *node = NULL;
528 if (width == surface_queue->width &&
529 height == surface_queue->height &&
530 format == surface_queue->format)
531 return TBM_SURFACE_QUEUE_ERROR_NONE;
533 pthread_mutex_lock (&surface_queue->lock);
535 surface_queue->width = width;
536 surface_queue->height = height;
537 surface_queue->format = format;
540 _queue_init(&surface_queue->free_queue);
541 _queue_init(&surface_queue->duty_queue);
543 //Destory surface and Push to free_queue
544 for (i = 0 ; i < surface_queue->size; i++)
546 node = surface_queue->node_list[i];
549 tbm_surface_destroy(node->surface);
550 node->surface = NULL;
553 _queue_node_push_back(&surface_queue->free_queue, node);
556 pthread_mutex_unlock (&surface_queue->lock);
557 pthread_cond_signal(&surface_queue->free_cond);
559 if (surface_queue->reset_cb)
560 surface_queue->reset_cb (surface_queue, surface_queue->reset_cb_data);
562 return TBM_SURFACE_QUEUE_ERROR_NONE;
565 tbm_surface_queue_error_e
566 tbm_surface_queue_set_reset_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb reset_cb, void *data)
568 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
570 pthread_mutex_lock (&surface_queue->lock);
572 surface_queue->reset_cb = reset_cb;
573 surface_queue->reset_cb_data = data;
575 pthread_mutex_unlock (&surface_queue->lock);
577 return TBM_SURFACE_QUEUE_ERROR_NONE;