tbm_surface_queue: add tbm_surface_queue_set_alloc_cb2 57/284457/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Fri, 28 Oct 2022 07:20:42 +0000 (16:20 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Thu, 17 Nov 2022 09:27:13 +0000 (18:27 +0900)
surface queue infomation can be mismatched when tbm_surface_queue_reset and
tbm_surface_queue_can_dequeue_wait_timeout are called in different thread.

1. tbm_surface_queue_can_dequeue_wait_timeout is called in thread1
   and it wait free buffer
2. tbm_surface_queue_reset is called in thread2
3. waiting of thread1 is finished but wayland_tbm create surface with queue_info
4. _handle_tbm_surface_queue_reset_notify is called and queue_info is updated

for resolving this problem, libtbm add queue infomation in alloc callback
and wayland_tbm create surface with argument of alloc callback.

Change-Id: Ie3274ee8380f0073445b7116c5e26cfbe86f60a2

include/tbm_surface_queue.h
src/tbm_surface_queue.c

index 3fce8e0..d067688 100644 (file)
@@ -60,9 +60,12 @@ typedef struct _tbm_surface_queue *tbm_surface_queue_h;
 typedef void (*tbm_surface_queue_notify_cb)(tbm_surface_queue_h surface_queue,
                void *data);
 
-typedef tbm_surface_h(*tbm_surface_alloc_cb)(tbm_surface_queue_h surface_queue,
+typedef tbm_surface_h (*tbm_surface_alloc_cb)(tbm_surface_queue_h surface_queue,
                void *data);
 
+typedef tbm_surface_h (*tbm_surface_alloc_cb2)(tbm_surface_queue_h surface_queue,
+               int width, int height, int format, int flags, void *data);
+
 typedef void (*tbm_surface_free_cb)(tbm_surface_queue_h surface_queue,
                void *data, tbm_surface_h surface);
 
@@ -167,6 +170,8 @@ void tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue);
  *        the tbm_surface_queue dequeue the tbm_surface returned in alloc_cb
  *        free_cb is called when the tbm_surface_queue unreference the tbm_surface.
  *
+ * @remarks You must use either tbm_surface_queue_set_alloc_cb or tbm_surface_queue_set_alloc_cb2
+ *
  * @param[in] surface_queue  The #tbm_surface_queue_h
  * @param[in] alloc_cb       The callback of allocate
  * @param[in] free_cb        The callback of free
@@ -182,6 +187,28 @@ tbm_surface_queue_error_e tbm_surface_queue_set_alloc_cb(
        void *data);
 
 /**
+ * @brief Sets allocate callback to the tbm_surface_queue.
+ *        alloc_cb2 is called when the tbm_surface_queue try to allocate the tbm_surface and
+ *        the tbm_surface_queue dequeue the tbm_surface returned in alloc_cb2
+ *        free_cb is called when the tbm_surface_queue unreference the tbm_surface.
+ *
+ * @remarks You must use either tbm_surface_queue_set_alloc_cb or tbm_surface_queue_set_alloc_cb2
+ *
+ * @param[in] surface_queue  The #tbm_surface_queue_h
+ * @param[in] alloc_cb2      The callback of allocate
+ * @param[in] free_cb        The callback of free
+ * @param[in] data           The user data
+ *
+ * @return  #TBM_SURFACE_QUEUE_ERROR_NONE on success,
+ *          otherwise an error status value
+ */
+tbm_surface_queue_error_e tbm_surface_queue_set_alloc_cb2(
+       tbm_surface_queue_h surface_queue,
+       tbm_surface_alloc_cb2 alloc_cb2,
+       tbm_surface_free_cb free_cb,
+       void *data);
+
+/**
  * @brief Gets the width of the tbm_surface_queue.
  *
  * @param[in] surface_queue  The #tbm_surface_queue_h
index ee93127..5d59296 100644 (file)
@@ -146,6 +146,7 @@ struct _tbm_surface_queue {
 
        //For external buffer allocation
        tbm_surface_alloc_cb alloc_cb;
+       tbm_surface_alloc_cb2 alloc_cb2;
        tbm_surface_free_cb free_cb;
        void *alloc_cb_data;
 
@@ -491,10 +492,18 @@ _tbm_surface_queue_need_attach(tbm_surface_queue_h surface_queue)
        if (surface_queue->queue_size == surface_queue->num_attached)
                return;
 
-       if (surface_queue->alloc_cb) {
-               surface = surface_queue->alloc_cb(surface_queue, surface_queue->alloc_cb_data);
+       if (surface_queue->alloc_cb2) {
+               surface = surface_queue->alloc_cb2(surface_queue,
+                               surface_queue->width, surface_queue->height,
+                               surface_queue->format, surface_queue->flags,
+                               surface_queue->alloc_cb_data);
+               if (!surface)
+                       return;
 
-               /* silent return */
+               tbm_surface_internal_ref(surface);
+       } else if (surface_queue->alloc_cb){
+               surface = surface_queue->alloc_cb(surface_queue,
+                               surface_queue->alloc_cb_data);
                if (!surface)
                        return;
 
@@ -934,6 +943,14 @@ tbm_surface_queue_set_alloc_cb(
 
        TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)\n", surface_queue);
 
+       if (surface_queue->alloc_cb2) {
+               TBM_ERR("must use either alloc_cb or alloc_cb2");
+               _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
+               pthread_mutex_unlock(&surface_queue->lock);
+               _tbm_surf_queue_mutex_unlock();
+               return TBM_ERROR_INVALID_OPERATION;
+       }
+
        surface_queue->alloc_cb = alloc_cb;
        surface_queue->free_cb = free_cb;
        surface_queue->alloc_cb_data = data;
@@ -945,6 +962,42 @@ tbm_surface_queue_set_alloc_cb(
        return TBM_SURFACE_QUEUE_ERROR_NONE;
 }
 
+tbm_surface_queue_error_e
+tbm_surface_queue_set_alloc_cb2(
+       tbm_surface_queue_h surface_queue,
+       tbm_surface_alloc_cb2 alloc_cb2,
+       tbm_surface_free_cb free_cb,
+       void *data)
+{
+       _tbm_surf_queue_mutex_lock();
+       _tbm_set_last_result(TBM_ERROR_NONE);
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       TBM_TRACE_SURFACE_QUEUE("tbm_surface_queue(%p)\n", surface_queue);
+
+       if (surface_queue->alloc_cb) {
+               TBM_ERR("must use either alloc_cb or alloc_cb2");
+               _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
+               pthread_mutex_unlock(&surface_queue->lock);
+               _tbm_surf_queue_mutex_unlock();
+               return TBM_ERROR_INVALID_OPERATION;
+       }
+
+       surface_queue->alloc_cb2 = alloc_cb2;
+       surface_queue->free_cb = free_cb;
+       surface_queue->alloc_cb_data = data;
+
+       pthread_mutex_unlock(&surface_queue->lock);
+
+       _tbm_surf_queue_mutex_unlock();
+
+       return TBM_SURFACE_QUEUE_ERROR_NONE;
+}
+
 int
 tbm_surface_queue_get_width(tbm_surface_queue_h surface_queue)
 {