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 (tbm_surface_h surface)
80 queue_node *node = (queue_node *) calloc (1, sizeof(queue_node));
81 TBM_RETURN_VAL_IF_FAIL (node != NULL, NULL);
83 node->surface = surface;
89 _queue_node_delete (queue_node *node)
91 tbm_surface_destroy (node->surface);
92 LIST_DEL (&node->item_link);
97 _queue_is_empty (queue *queue)
99 if (queue->head.next == &queue->tail)
106 _queue_node_push_back (queue *queue, queue_node *node)
108 LIST_ADDTAIL (&node->item_link, &queue->tail);
114 _queue_node_pop_front (queue *queue)
116 queue_node *node = NULL;
118 node = LIST_ENTRY (queue_node, queue->head.next, item_link);
120 LIST_DEL (&node->item_link);
127 _queue_node_exist_in_queue (queue *queue, queue_node *node)
129 queue_node *search_node = NULL;
130 queue_node *temp = NULL;
132 if (!_queue_is_empty(queue))
134 LIST_FOR_EACH_ENTRY_SAFE (search_node, temp, &queue->head, item_link)
136 if (search_node == node)
144 tbm_surface_queue_error_e
145 tbm_surface_queue_enqueue (tbm_surface_queue_h surface_queue, tbm_surface_h surface)
147 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
148 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
152 pthread_mutex_lock (&surface_queue->lock);
154 for (i = 0 ; i < surface_queue->size ; i++)
156 if (surface_queue->node_list[i]->surface == surface)
160 if (i == surface_queue->size)
162 TBM_LOG ("Can't fine surface list in queue\n");
163 pthread_mutex_unlock (&surface_queue->lock);
164 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
167 if (_queue_node_exist_in_queue (&surface_queue->duty_queue, surface_queue->node_list[i]))
169 TBM_LOG ("Surface exist in queue\n");
170 pthread_mutex_unlock (&surface_queue->lock);
171 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
174 _queue_node_push_back(&surface_queue->duty_queue, surface_queue->node_list[i]);
176 pthread_mutex_unlock (&surface_queue->lock);
177 pthread_cond_signal(&surface_queue->duty_cond);
179 if (surface_queue->acquirable_cb)
180 surface_queue->acquirable_cb(surface_queue, surface_queue->acquirable_cb_data);
182 return TBM_SURFACE_QUEUE_ERROR_NONE;
185 tbm_surface_queue_error_e
186 tbm_surface_queue_dequeue (tbm_surface_queue_h surface_queue, tbm_surface_h *surface)
188 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
189 TBM_RETURN_VAL_IF_FAIL (surface_queue->free_queue.count > 0, TBM_SURFACE_QUEUE_ERROR_EMPTY);
191 pthread_mutex_lock (&surface_queue->lock);
193 if (_queue_is_empty (&surface_queue->free_queue))
195 TBM_LOG ("Surface queue is empty\n");
196 pthread_mutex_unlock (&surface_queue->lock);
197 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
200 queue_node *node = NULL;
202 node = _queue_node_pop_front (&surface_queue->free_queue);
205 TBM_LOG ("_queue_node_pop_front is failed\n");
206 pthread_mutex_unlock (&surface_queue->lock);
207 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
210 *surface = node->surface;
212 pthread_mutex_unlock (&surface_queue->lock);
214 return TBM_SURFACE_QUEUE_ERROR_NONE;
217 tbm_surface_queue_error_e
218 tbm_surface_queue_release (tbm_surface_queue_h surface_queue, tbm_surface_h surface)
220 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
221 TBM_RETURN_VAL_IF_FAIL (surface != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE);
223 pthread_mutex_lock (&surface_queue->lock);
226 for (i = 0 ; i < surface_queue->size ; i++)
228 if (surface_queue->node_list[i]->surface == surface)
231 if (i == surface_queue->size)
233 TBM_LOG ("Can't fine surface list in queue\n");
234 pthread_mutex_unlock (&surface_queue->lock);
235 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
238 if (_queue_node_exist_in_queue (&surface_queue->free_queue, surface_queue->node_list[i]))
240 TBM_LOG ("Surface exist in queue\n");
241 pthread_mutex_unlock (&surface_queue->lock);
242 return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
245 _queue_node_push_back(&surface_queue->free_queue, surface_queue->node_list[i]);
247 pthread_mutex_unlock (&surface_queue->lock);
248 pthread_cond_signal(&surface_queue->free_cond);
250 if (surface_queue->dequeuable_cb)
251 surface_queue->dequeuable_cb (surface_queue, surface_queue->dequeuable_cb_data);
253 return TBM_SURFACE_QUEUE_ERROR_NONE;
256 tbm_surface_queue_error_e
257 tbm_surface_queue_acquire (tbm_surface_queue_h surface_queue, tbm_surface_h *surface)
259 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
260 TBM_RETURN_VAL_IF_FAIL (surface_queue->duty_queue.count > 0, TBM_SURFACE_QUEUE_ERROR_EMPTY);
262 pthread_mutex_lock (&surface_queue->lock);
264 if (_queue_is_empty (&surface_queue->duty_queue))
266 TBM_LOG ("Surface queue is empty\n");
267 pthread_mutex_unlock (&surface_queue->lock);
268 return TBM_SURFACE_QUEUE_ERROR_EMPTY;
271 queue_node *node = NULL;
273 node = _queue_node_pop_front (&surface_queue->duty_queue);
276 TBM_LOG ("_queue_node_pop_front failed\n");
277 pthread_mutex_unlock (&surface_queue->lock);
278 return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
281 *surface = node->surface;
283 pthread_mutex_unlock (&surface_queue->lock);
285 return TBM_SURFACE_QUEUE_ERROR_NONE;
289 tbm_surface_queue_can_dequeue (tbm_surface_queue_h surface_queue, int wait)
291 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
293 pthread_mutex_lock (&surface_queue->lock);
295 if (_queue_is_empty (&surface_queue->free_queue))
299 pthread_cond_wait (&surface_queue->free_cond, &surface_queue->lock);
300 pthread_mutex_unlock (&surface_queue->lock);
304 pthread_mutex_unlock (&surface_queue->lock);
308 pthread_mutex_unlock (&surface_queue->lock);
313 tbm_surface_queue_can_acquire (tbm_surface_queue_h surface_queue, int wait)
315 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
317 pthread_mutex_lock (&surface_queue->lock);
319 if (_queue_is_empty (&surface_queue->duty_queue))
323 pthread_cond_wait (&surface_queue->duty_cond, &surface_queue->lock);
324 pthread_mutex_unlock (&surface_queue->lock);
328 pthread_mutex_unlock (&surface_queue->lock);
332 pthread_mutex_unlock (&surface_queue->lock);
338 tbm_surface_queue_create(int queue_size, int width, int height, int format, int flags)
340 TBM_RETURN_VAL_IF_FAIL (queue_size > 0, NULL);
341 TBM_RETURN_VAL_IF_FAIL (width > 0, NULL);
342 TBM_RETURN_VAL_IF_FAIL (height > 0, NULL);
343 TBM_RETURN_VAL_IF_FAIL (format > 0, NULL);
346 tbm_surface_queue_h surface_queue = (tbm_surface_queue_h)calloc(1, sizeof(struct _tbm_surface_queue));
347 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, NULL);
349 pthread_mutex_init (&surface_queue->lock, NULL);
350 pthread_cond_init (&surface_queue->free_cond, NULL);
351 pthread_cond_init (&surface_queue->duty_cond, NULL);
353 surface_queue->width = width;
354 surface_queue->height = height;
355 surface_queue->format = format;
356 surface_queue->flags = flags;
357 surface_queue->size = queue_size;
358 surface_queue->node_list = (queue_node **)calloc(queue_size, sizeof(queue_node *));
359 if (!surface_queue->node_list)
361 TBM_LOG ("surface node list alloc failed");
362 free (surface_queue);
363 pthread_mutex_destroy (&surface_queue->lock);
367 LIST_INITHEAD (&surface_queue->free_queue.tail);
368 LIST_ADDTAIL (&surface_queue->free_queue.head, &surface_queue->free_queue.tail);
370 LIST_INITHEAD (&surface_queue->duty_queue.tail);
371 LIST_ADDTAIL (&surface_queue->duty_queue.head, &surface_queue->duty_queue.tail);
373 for (i = 0 ; i < queue_size; i++)
375 tbm_surface_h surface = tbm_surface_internal_create_with_flags (width, height, format, flags);
378 TBM_LOG ("tbm surface create failed");
382 queue_node *node = _queue_node_create(surface);
385 TBM_LOG ("surface node create failed");
389 surface_queue->node_list[i] = node;
390 _queue_node_push_back (&surface_queue->free_queue, node);
393 return surface_queue;
396 for (j = 0 ; j < i ; j++)
397 _queue_node_delete (surface_queue->node_list[j]);
399 free (surface_queue->node_list);
400 free (surface_queue);
401 pthread_mutex_destroy (&surface_queue->lock);
407 tbm_surface_queue_destroy (tbm_surface_queue_h surface_queue)
409 TBM_RETURN_IF_FAIL (surface_queue != NULL);
411 if (surface_queue->destroy_cb)
412 surface_queue->destroy_cb (surface_queue, surface_queue->destroy_cb_data);
416 for (i = 0 ; i < surface_queue->size ; i++)
417 _queue_node_delete (surface_queue->node_list[i]);
419 free (surface_queue->node_list);
420 free (surface_queue);
423 tbm_surface_queue_error_e
424 tbm_surface_queue_set_destroy_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb destroy_cb, void *data)
426 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
428 pthread_mutex_lock (&surface_queue->lock);
430 surface_queue->destroy_cb = destroy_cb;
431 surface_queue->destroy_cb_data = data;
433 pthread_mutex_unlock (&surface_queue->lock);
435 return TBM_SURFACE_QUEUE_ERROR_NONE;
438 tbm_surface_queue_error_e
439 tbm_surface_queue_set_dequeuable_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb dequeuable_cb, void *data)
441 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
443 pthread_mutex_lock (&surface_queue->lock);
445 surface_queue->dequeuable_cb = dequeuable_cb;
446 surface_queue->dequeuable_cb_data = data;
448 pthread_mutex_unlock (&surface_queue->lock);
450 return TBM_SURFACE_QUEUE_ERROR_NONE;
453 tbm_surface_queue_error_e
454 tbm_surface_queue_set_acquirable_cb (tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb, void *data)
456 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
458 pthread_mutex_lock (&surface_queue->lock);
460 surface_queue->acquirable_cb = acquirable_cb;
461 surface_queue->acquirable_cb_data = data;
463 pthread_mutex_unlock (&surface_queue->lock);
465 return TBM_SURFACE_QUEUE_ERROR_NONE;
469 tbm_surface_queue_get_queue_size (tbm_surface_queue_h surface_queue)
471 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
473 return surface_queue->size;
477 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
479 TBM_RETURN_VAL_IF_FAIL (surface_queue != NULL, 0);
481 return surface_queue->width;
485 tbm_surface_queue_get_height(tbm_surface_queue_h surface_queue)
487 return surface_queue->height;
491 tbm_surface_queue_get_format(tbm_surface_queue_h surface_queue)
493 return surface_queue->format;