wl_egl: Implement status_sync to improve buffers finalize logic. 73/319373/2
authorTaeHyeon Jeong <thyeon.jeong@samsung.com>
Tue, 22 Oct 2024 06:39:04 +0000 (15:39 +0900)
committerTaeHyeon Jeong <thyeon.jeong@samsung.com>
Tue, 5 Nov 2024 08:05:22 +0000 (17:05 +0900)
AS-IS
- When wl_egl_display->thread is idle, call the __idle_cb_buffers_finalize() to check the buffer status and change the buffer status to RELEASED.
- If the buffer status cannot be changed to RELEASED, continue to call the function until possible.
PROBLEMS
- Call the function even if the buffer status has not changed. So the function is unnecessarily called a lot.
TO-BE
- Call the function only when the buffer status changes.

Change-Id: I76d401a1413d144dcde2e4743162d9a09bc86983

src/tpl_wl_egl_thread.c

index b4886ff0d9e36f9a1623cb1ccf722a3d2df87143..3eb76f47b35ae5521a5922c73b4190d3e93e3f2b 100755 (executable)
@@ -46,6 +46,8 @@ typedef struct _surface_vblank     tpl_surface_vblank_t;
 #define wl_egl_buffer(ptr) *wl_egl_buffer = (tpl_wl_egl_buffer_t *)ptr;
 #define tizen_private(ptr) *tizen_private = (struct tizen_private *)ptr;
 
+#define rightmost_zero(x) (~(x) & ((x) + 1))
+
 struct _tpl_wl_egl_display {
        tpl_gsource                  *disp_source;
        tpl_gthread                  *thread;
@@ -92,6 +94,7 @@ typedef enum surf_message {
        ACQUIRABLE = 2,
        FORCE_FLUSH = 4,
        QUEUE_RESIZE = 8,
+       BUFFERS_FINALIZE = 16,
 } surf_message;
 
 struct _tpl_wl_egl_surface {
@@ -128,6 +131,7 @@ struct _tpl_wl_egl_surface {
        tpl_list_t                   *buffers;
        int                           buffer_cnt; /* the number of using wl_egl_buffers */
        tpl_gmutex_rec                buffers_mutex;
+       int                           in_use;
 
        tpl_list_t                   *presentation_feedbacks; /* for tracing presentation feedbacks */
 
@@ -141,12 +145,19 @@ struct _tpl_wl_egl_surface {
                int                       fd;
        } presentation_sync;
 
+       struct {
+               tpl_gmutex                mutex;
+               tpl_gcond                 cond;
+               int                       condition; /* store status of buffers in each bit */
+       } status_sync;
+
        tpl_gmutex                    surf_mutex;
        tpl_gcond                     surf_cond;
 
        surf_message                  sent_message;
 
        tpl_bool_t                    is_activated;
+       tpl_bool_t                    is_finalized;
        tpl_bool_t                    reset; /* TRUE if queue reseted by external  */
        tpl_bool_t                    need_to_enqueue;
        tpl_bool_t                    prerotation_capability;
@@ -236,6 +247,9 @@ struct _tpl_wl_egl_buffer {
        buffer_status                 status; /* for tracing buffer status */
        double                        changed_time; /* the time when buffer status changed */
 
+       /* creation order between same tpl_wl_egl_surface */
+       int                           order;
+
        /* for damage region */
        int                           num_rects;
        int                          *rects;
@@ -387,11 +401,17 @@ static void
 _update_buffer_status(tpl_wl_egl_buffer_t *wl_egl_buffer, buffer_status status)
 {
        double current_time = _get_current_time();
+       tpl_wl_egl_surface_t wl_egl_surface(wl_egl_buffer->wl_egl_surface);
+       int *condition = &wl_egl_surface->status_sync.condition;
+       tpl_bool_t is_removable = TPL_FALSE;
 
+       tpl_gmutex_lock(&wl_egl_surface->status_sync.mutex);
        switch (status)
        {
        case CREATED:
+       case CANCELED:
        case RELEASED:
+               is_removable = TPL_TRUE;
        case DEQUEUED:
                /* do nothing */
                break;
@@ -401,8 +421,15 @@ _update_buffer_status(tpl_wl_egl_buffer_t *wl_egl_buffer, buffer_status status)
                break;
        }
 
+       if (is_removable)
+               *condition &= ~wl_egl_buffer->order;
+       else
+               *condition |= wl_egl_buffer->order;
+
        wl_egl_buffer->status = status;
        wl_egl_buffer->changed_time = current_time;
+
+       tpl_gmutex_unlock(&wl_egl_surface->status_sync.mutex);
 }
 
 static void
@@ -1941,7 +1968,9 @@ __tpl_wl_egl_surface_init(tpl_surface_t *surface)
 
        wl_egl_surface->reset                  = TPL_FALSE;
        wl_egl_surface->is_activated           = TPL_FALSE;
+       wl_egl_surface->is_finalized           = TPL_FALSE;
        wl_egl_surface->need_to_enqueue        = TPL_TRUE;
+       wl_egl_surface->need_force_release     = TPL_FALSE;
        wl_egl_surface->prerotation_capability = TPL_FALSE;
        wl_egl_surface->vblank_done            = TPL_TRUE;
        wl_egl_surface->serial_updated         = TPL_FALSE;
@@ -1966,10 +1995,12 @@ __tpl_wl_egl_surface_init(tpl_surface_t *surface)
 
        wl_egl_surface->commit_sync.fd         = -1;
        wl_egl_surface->presentation_sync.fd   = -1;
+       wl_egl_surface->status_sync.condition  = 0;
 
        wl_egl_surface->sent_message           = NONE_MESSAGE;
 
        wl_egl_surface->buffers = __tpl_list_alloc();
+       wl_egl_surface->in_use = 0;
 
        {
                struct tizen_private *tizen_private = wl_egl_tizen_get_tizen_private(wl_egl_window);
@@ -2002,6 +2033,9 @@ __tpl_wl_egl_surface_init(tpl_surface_t *surface)
        tpl_gmutex_init(&wl_egl_surface->commit_sync.mutex);
        tpl_gmutex_init(&wl_egl_surface->presentation_sync.mutex);
 
+       tpl_gmutex_init(&wl_egl_surface->status_sync.mutex);
+       tpl_gcond_init(&wl_egl_surface->status_sync.cond);
+
        tpl_gmutex_rec_init(&wl_egl_surface->buffers_mutex);
 
        tpl_gmutex_init(&wl_egl_surface->surf_mutex);
@@ -2544,6 +2578,9 @@ __tpl_wl_egl_surface_fini(tpl_surface_t *surface)
        tpl_gmutex_clear(&wl_egl_surface->presentation_sync.mutex);
        tpl_gmutex_clear(&wl_egl_surface->perf_trace.mutex);
 
+       tpl_gcond_clear(&wl_egl_surface->status_sync.cond);
+       tpl_gmutex_clear(&wl_egl_surface->status_sync.mutex);
+
        tpl_gcond_clear(&wl_egl_surface->surf_cond);
        tpl_gmutex_clear(&wl_egl_surface->surf_mutex);
 
@@ -2763,8 +2800,6 @@ _wl_egl_buffer_create(tpl_wl_egl_surface_t *wl_egl_surface,
                wl_egl_buffer->bo_name                  = _get_tbm_surface_bo_name(tbm_surface);
                wl_egl_buffer->wl_egl_surface           = wl_egl_surface;
 
-               _update_buffer_status(wl_egl_buffer, CREATED);
-
                wl_egl_buffer->acquire_fence_fd         = -1;
                wl_egl_buffer->commit_sync_fd           = -1;
                wl_egl_buffer->presentation_sync_fd     = -1;
@@ -2780,9 +2815,13 @@ _wl_egl_buffer_create(tpl_wl_egl_surface_t *wl_egl_surface,
                tpl_gmutex_init(&wl_egl_buffer->mutex);
 
                tpl_gmutex_rec_lock(&wl_egl_surface->buffers_mutex);
+               wl_egl_buffer->order = rightmost_zero(wl_egl_surface->in_use);
+               wl_egl_surface->in_use |= wl_egl_buffer->order;
                __tpl_list_push_back(wl_egl_surface->buffers, (void *)wl_egl_buffer);
                tpl_gmutex_rec_unlock(&wl_egl_surface->buffers_mutex);
 
+               _update_buffer_status(wl_egl_buffer, CREATED);
+
                TPL_INFO("[WL_EGL_BUFFER_CREATE]",
                                 "wl_egl_surface(%p) wl_egl_buffer(%p) tbm_surface(%p) bo(%d)",
                                 wl_egl_surface, wl_egl_buffer, tbm_surface,
@@ -4034,6 +4073,7 @@ __cb_wl_egl_buffer_free(tpl_wl_egl_buffer_t *wl_egl_buffer)
                         wl_egl_buffer->tbm_surface, wl_egl_buffer->bo_name);
 
        tpl_gmutex_rec_lock(&wl_egl_surface->buffers_mutex);
+       wl_egl_surface->in_use &= ~wl_egl_buffer->order;
        if (wl_egl_surface->buffers) {
                __tpl_list_remove_data(wl_egl_surface->buffers, (void *)wl_egl_buffer,
                                                           TPL_FIRST, NULL);