static Eina_Bool _e_hwc_window_queue_buffers_retrieve_done(E_Hwc_Window_Queue *queue);
static void _e_hwc_window_queue_unset(E_Hwc_Window_Queue *queue);
+static void _e_hwc_window_queue_copy_thread_run_cb(void *data, Ecore_Thread *th);
+static void _e_hwc_window_queue_copy_thread_run_notify_cb(void *data, Ecore_Thread *thread, void *msg_data);
+static void _e_hwc_window_queue_copy_thread_run_end_cb(void *data, Ecore_Thread *th);
+static void _e_hwc_window_queue_copy_thread_run_cancel_cb(void *data, Ecore_Thread *th);
typedef struct _E_Hwc_Window_Queue_Manager E_Hwc_Window_Queue_Manager;
typedef struct _E_Hwc_Window_Queue_Event E_Hwc_Window_Queue_Event;
+typedef struct _E_Hwc_Window_Queue_Copy_Thread_Data E_Hwc_Window_Queue_Copy_Thread_Data;
struct _E_Hwc_Window_Queue_Manager
{
Eina_List *hwc_winq_list;
Eina_List *hwc_gbm_winq_list;
Eina_List *event_handlers;
+
+ Ecore_Thread *copy_thread;
+ Eina_Bool copy_thread_canceled;
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data;
+ Eina_List *pending_copy_thread_data_list;
};
struct _E_Hwc_Window_Queue_Event
E_Hwc_Window_Queue *queue;
};
+struct _E_Hwc_Window_Queue_Copy_Thread_Data
+{
+ E_Hwc_Window_Queue *queue;
+ E_Hwc_Window *hwc_window;
+
+ tbm_surface_h src_tsurface;
+ E_Comp_Wl_Buffer_Ref src_buffer_ref;
+ int src_transform;
+
+ tbm_surface_h dst_tsurface;
+};
+
static Eina_List *hwc_window_queue_hwc_hooks = NULL;
static Eina_List *hwc_window_queue_window_hooks = NULL;
static Eina_List *hwc_window_queue_comp_wl_hooks = NULL;
+static Eina_List *hwc_window_queue_pixmap_hooks = NULL;
static E_Hwc_Window_Queue_Manager *_hwc_winq_mgr = NULL;
static uint32_t
_backup_tsurface_create(tbm_surface_h tsurface)
{
tbm_surface_h new_tsurface;
- tbm_surface_info_s src_info, dst_info;
+ tbm_surface_info_s src_info;
int ret = TBM_SURFACE_ERROR_NONE;
- ret = tbm_surface_map(tsurface, TBM_SURF_OPTION_READ, &src_info);
+ ret = tbm_surface_get_info(tsurface, &src_info);
if (ret != TBM_SURFACE_ERROR_NONE)
{
EHWQERR("fail to map the tsurface", NULL, NULL, NULL);
return NULL;
}
- EHWQINF("Backup buffer create w:%d h:%d fmt:%c%c%c%c", NULL, NULL, NULL,
+ EHWQINF("Copy Backup buffer create w:%d h:%d fmt:%c%c%c%c", NULL, NULL, NULL,
src_info.width, src_info.height, EHW_FOURCC_STR(src_info.format));
/* get the buffer from e20 module first, if no buffer from e20 module, then create the tbm_surface here. */
if (!new_tsurface)
{
EHWQERR("fail to allocate the new_tsurface", NULL, NULL, NULL);
- tbm_surface_unmap(tsurface);
return NULL;
}
}
- EHWQINF("Backup buffer create done tsurface:%p", NULL, NULL, NULL, new_tsurface);
+ EHWQINF("Copy Backup buffer create done tsurface:%p", NULL, NULL, NULL, new_tsurface);
+
+ return new_tsurface;
+}
+
+static Eina_Bool
+_e_hwc_window_queue_copy_content(tbm_surface_h src_tsurface, tbm_surface_h dst_tsurface, Ecore_Thread *thread)
+{
+ tbm_surface_info_s src_info, dst_info;
+ int ret = TBM_SURFACE_ERROR_NONE;
+ void *src_ptr, *dst_ptr;
+ int i, height, extra_size;
+ void *thread_src_ptr1, *thread_dst_ptr1;
+ void *thread_src_ptr2, *thread_dst_ptr2;
+ void *thread_src_ptr3, *thread_dst_ptr3;
+ void *thread_src_ptr4, *thread_dst_ptr4;
+ int i1, i2, i3, i4, thread_height, thread_extra_height;
+ Eina_Bool thread_canceled = EINA_FALSE;
+
+ ret = tbm_surface_map(src_tsurface, TBM_SURF_OPTION_READ, &src_info);
+ if (ret != TBM_SURFACE_ERROR_NONE)
+ {
+ EHWQERR("fail to map the tsurface", NULL, NULL, NULL);
+ return EINA_FALSE;
+ }
- ret = tbm_surface_map(new_tsurface, TBM_SURF_OPTION_WRITE, &dst_info);
+ ret = tbm_surface_map(dst_tsurface, TBM_SURF_OPTION_WRITE, &dst_info);
if (ret != TBM_SURFACE_ERROR_NONE)
{
EHWQERR("fail to map the new_tsurface", NULL, NULL, NULL);
- tbm_surface_destroy(new_tsurface);
- tbm_surface_unmap(tsurface);
- return NULL;
+ tbm_surface_unmap(src_tsurface);
+ return EINA_FALSE;
}
+ src_ptr = src_info.planes[0].ptr;
+ dst_ptr = dst_info.planes[0].ptr;
+ height = src_info.size / src_info.planes[0].stride;
+ extra_size = src_info.size % src_info.planes[0].stride;
+
/* copy from src to dst */
#if HAVE_LIBGOMP
# define LIBGOMP_COPY_THREAD_NUM 4
-# define LIBGOMP_COPY_PAGE_SIZE getpagesize()
-# define PAGE_ALIGN(addr) ((addr)&(~((LIBGOMP_COPY_PAGE_SIZE)-1)))
- if (src_info.planes[0].size > (LIBGOMP_COPY_THREAD_NUM * LIBGOMP_COPY_PAGE_SIZE))
+ thread_height = height / LIBGOMP_COPY_THREAD_NUM;
+ thread_extra_height = height % LIBGOMP_COPY_THREAD_NUM;
+ if (thread_height)
{
- size_t step[2];
- step[0] = PAGE_ALIGN(src_info.planes[0].size / LIBGOMP_COPY_THREAD_NUM);
- step[1] = src_info.planes[0].size - (step[0] * (LIBGOMP_COPY_THREAD_NUM - 1));
+ thread_src_ptr1 = src_ptr;
+ thread_dst_ptr1 = dst_ptr;
+
+ thread_src_ptr2 = src_ptr + (thread_height * src_info.planes[0].stride);
+ thread_dst_ptr2 = dst_ptr + (thread_height * src_info.planes[0].stride);
+
+ thread_src_ptr3 = src_ptr + (thread_height * src_info.planes[0].stride * 2);
+ thread_dst_ptr3 = dst_ptr + (thread_height * src_info.planes[0].stride * 2);
+
+ thread_src_ptr4 = src_ptr + (thread_height * src_info.planes[0].stride * 3);
+ thread_dst_ptr4 = dst_ptr + (thread_height * src_info.planes[0].stride * 3);
omp_set_num_threads(LIBGOMP_COPY_THREAD_NUM);
#pragma omp parallel
{
#pragma omp section
{
- memcpy(dst_info.planes[0].ptr,
- src_info.planes[0].ptr,
- step[0]);
+ for (i1 = 0; i1 < thread_height; i1++)
+ {
+ if ((thread) && (ecore_thread_check(thread)))
+ {
+ EHWQINF("Copy thread is canceled", NULL, NULL, NULL);
+ thread_canceled = EINA_TRUE;
+ break;
+ }
+
+ memcpy(thread_dst_ptr1, thread_src_ptr1, src_info.planes[0].stride);
+ thread_src_ptr1 += dst_info.planes[0].stride;
+ thread_dst_ptr1 += dst_info.planes[0].stride;
+ }
}
#pragma omp section
{
- memcpy(dst_info.planes[0].ptr + step[0],
- src_info.planes[0].ptr + step[0],
- step[0]);
+ for (i2 = 0; i2 < thread_height; i2++)
+ {
+ if (thread_canceled) break;
+
+ memcpy(thread_dst_ptr2, thread_src_ptr2, src_info.planes[0].stride);
+ thread_src_ptr2 += dst_info.planes[0].stride;
+ thread_dst_ptr2 += dst_info.planes[0].stride;
+ }
}
#pragma omp section
{
- memcpy(dst_info.planes[0].ptr + (step[0] * 2),
- src_info.planes[0].ptr + (step[0] * 2),
- step[0]);
+ for (i3 = 0; i3 < thread_height; i3++)
+ {
+ if (thread_canceled) break;
+
+ memcpy(thread_dst_ptr3, thread_src_ptr3, src_info.planes[0].stride);
+ thread_src_ptr3 += dst_info.planes[0].stride;
+ thread_dst_ptr3 += dst_info.planes[0].stride;
+ }
}
#pragma omp section
{
- memcpy(dst_info.planes[0].ptr + (step[0] * 3),
- src_info.planes[0].ptr + (step[0] * 3),
- step[1]);
+ for (i4 = 0; i4 < thread_height + thread_extra_height; i4++)
+ {
+ if (thread_canceled) break;
+
+ memcpy(thread_dst_ptr4, thread_src_ptr4, src_info.planes[0].stride);
+ thread_src_ptr4 += dst_info.planes[0].stride;
+ thread_dst_ptr4 += dst_info.planes[0].stride;
+ }
+
+ if (!thread_canceled)
+ memcpy(thread_dst_ptr4, thread_src_ptr4, extra_size);
}
}
}
else
{
- memcpy(dst_info.planes[0].ptr,
- src_info.planes[0].ptr,
- src_info.planes[0].size);
- }
-#else /* HAVE_LIBGOMP */
- memcpy(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].size);
-#endif /* end of HAVE_LIBGOMP */
-
- tbm_surface_unmap(new_tsurface);
- tbm_surface_unmap(tsurface);
-
- return new_tsurface;
-}
-
-static E_Comp_Wl_Buffer *
-_comp_wl_backup_buffer_get(tbm_surface_h tsurface)
-{
- tbm_surface_h backup_tsurface;
- E_Comp_Wl_Buffer *backup_buffer;
+ for (i = 0; i < height; i++)
+ {
+ if ((thread) && (ecore_thread_check(thread)))
+ {
+ EHWQINF("Copy thread is canceled", NULL, NULL, NULL);
+ thread_canceled = EINA_TRUE;
+ break;
+ }
- backup_tsurface = _backup_tsurface_create(tsurface);
- EINA_SAFETY_ON_NULL_RETURN_VAL(backup_tsurface, NULL);
+ memcpy(dst_ptr, src_ptr, src_info.planes[0].stride);
+ src_ptr += dst_info.planes[0].stride;
+ dst_ptr += dst_info.planes[0].stride;
+ }
- backup_buffer = e_comp_wl_tbm_buffer_get(backup_tsurface);
- if (!backup_buffer)
+ if (!thread_canceled)
+ memcpy(dst_ptr, src_ptr, extra_size);
+ }
+#else /* HAVE_LIBGOMP */
+ for (i = 0; i < height; i++)
{
- EHWQERR("Fail to e_comp_wl_tbm_buffer_get", NULL, NULL, NULL);
- tbm_surface_internal_unref(backup_tsurface);
- return NULL;
+ if ((thread) && (ecore_thread_check(thread)))
+ {
+ EHWQINF("Copy thread is canceled", NULL, NULL, NULL);
+ thread_canceled = EINA_TRUE;
+ break;
+ }
+
+ memcpy(dst_ptr, src_ptr, src_info.planes[0].stride);
+ src_ptr += dst_info.planes[0].stride;
+ dst_ptr += dst_info.planes[0].stride;
}
- tbm_surface_internal_unref(backup_tsurface);
+ if (!thread_canceled)
+ memcpy(dst_ptr, src_ptr, extra_size);
+#endif /* end of HAVE_LIBGOMP */
+
+ tbm_surface_unmap(src_tsurface);
+ tbm_surface_unmap(dst_tsurface);
- return backup_buffer;
+ return EINA_TRUE;
}
static tbm_surface_queue_h
(queue->state == E_HWC_WINDOW_QUEUE_STATE_SET_WAITING_BUFFER))
queue->state = E_HWC_WINDOW_QUEUE_STATE_SET_INVALID;
- if (!queue_buffer->acquired && queue_buffer->dequeued)
+ if ((!queue_buffer->acquired) && (queue_buffer->dequeued) && (!queue_buffer->copying))
e_hwc_window_queue_buffer_release(queue, queue_buffer);
queue_buffer->usable = EINA_FALSE;
queue_buffer->tsurface, queue->tqueue,
queue_buffer->exported_wl_buffer);
- if (!queue_buffer->acquired && queue_buffer->dequeued)
+ if ((!queue_buffer->acquired) && (queue_buffer->dequeued) && (!queue_buffer->copying))
e_hwc_window_queue_buffer_release(queue, queue_buffer);
queue_buffer->usable = EINA_FALSE;
}
static Eina_Bool
-_e_hwc_window_queue_buffers_retrieve(E_Hwc_Window_Queue *queue, E_Hwc_Window *hwc_window)
+_e_hwc_window_queue_buffers_retrieve(E_Hwc_Window_Queue *queue)
{
if (queue->user)
e_hwc_window_deactivate(queue->user);
if (queue_buffer->exported)
return EINA_FALSE;
+ if (queue_buffer->copying)
+ return EINA_FALSE;
+
if ((!queue->is_target) && (queue_buffer->acquired))
return EINA_FALSE;
}
return EINA_FALSE;
}
-static tbm_surface_h
-_e_hwc_window_queue_backup_buffer_set(E_Hwc_Window *hwc_window, Eina_Bool attach)
-{
- E_Comp_Wl_Buffer *comp_buffer, *backup_buffer;
- tbm_surface_h tsurface;
- uint32_t flags = 0;
- E_Client *ec = hwc_window->ec;
-
- if (!ec) return NULL;
-
- comp_buffer = _comp_wl_buffer_get(hwc_window->ec);
- if (!comp_buffer) return NULL;
- if (!comp_buffer->tbm_surface) return NULL;
-
- tsurface = comp_buffer->tbm_surface;
-
- if (comp_buffer->resource)
- {
- flags = _comp_wl_buffer_flags_get(comp_buffer);
- if (flags != E_HWC_WINDOW_QUEUE_BUFFER_FLAGS)
- return NULL;
- }
- else
- {
- if (tsurface != hwc_window->display.buffer.tsurface)
- return NULL;
-
- if (!hwc_window->display.buffer.from_queue)
- return NULL;
- }
-
- EHWQINF("Backup buffer get ehw:%p origin:%p",
- hwc_window->ec, hwc_window->hwc, NULL, hwc_window,
- comp_buffer->tbm_surface);
-
- backup_buffer = _comp_wl_backup_buffer_get(tsurface);
- EINA_SAFETY_ON_NULL_RETURN_VAL(backup_buffer, NULL);
-
- if (comp_buffer)
- backup_buffer->transform = comp_buffer->transform;
-
- EHWQINF("Backup buffer set ehw:%p origin:%p tsurface:%p",
- hwc_window->ec, hwc_window->hwc, NULL, hwc_window,
- comp_buffer->tbm_surface, backup_buffer->tbm_surface);
-
- if (attach)
- {
- e_comp_wl_surface_attach(ec, backup_buffer);
- }
- else
- {
- E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
- e_comp_wl_buffer_reference(&cdata->buffer_ref, backup_buffer);
- e_pixmap_resource_set(ec->pixmap, backup_buffer);
- e_pixmap_dirty(ec->pixmap);
- e_pixmap_refresh(ec->pixmap);
- }
-
- return tsurface;
-}
-
static Eina_Bool
_e_hwc_window_queue_prepare_set(E_Hwc_Window_Queue *queue, E_Hwc_Window *hwc_window)
{
}
static void
-_e_hwc_window_queue_prepare_unset(E_Hwc_Window_Queue *queue)
+_e_hwc_window_queue_copy_thread_data_destroy(E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data)
{
- E_Hwc_Window *hwc_window = queue->user;
+ E_Hwc_Window_Queue_Buffer *queue_buffer;
+
+ if (!copy_thread_data) return;
+
+ EHWQINF("Destroy Copy tdata:%p src:%p dst:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface);
+
+ queue_buffer = e_hwc_window_queue_buffer_find(copy_thread_data->queue, copy_thread_data->src_tsurface);
+ if (queue_buffer)
+ {
+ queue_buffer->copying = EINA_FALSE;
+
+ if ((!queue_buffer->acquired) && (queue_buffer->dequeued))
+ e_hwc_window_queue_buffer_release(copy_thread_data->queue, queue_buffer);
+ }
+
+ e_object_unref(E_OBJECT(copy_thread_data->queue));
+
+ e_comp_wl_buffer_reference(©_thread_data->src_buffer_ref, NULL);
+
+ if (copy_thread_data->src_tsurface)
+ tbm_surface_internal_unref(copy_thread_data->src_tsurface);
+
+ if (copy_thread_data->dst_tsurface)
+ tbm_surface_internal_unref(copy_thread_data->dst_tsurface);
+
+ e_hwc_window_unref(copy_thread_data->hwc_window);
+
+ free(copy_thread_data);
+}
+
+static E_Hwc_Window_Queue_Copy_Thread_Data *
+_e_hwc_window_queue_copy_thread_data_create(E_Hwc_Window_Queue *queue,
+ E_Hwc_Window *hwc_window,
+ E_Comp_Wl_Buffer *buffer)
+{
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data;
+ E_Hwc_Window_Queue_Buffer *queue_buffer;
+
+ copy_thread_data = E_NEW(E_Hwc_Window_Queue_Copy_Thread_Data, 1);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(copy_thread_data, NULL);
+
+ copy_thread_data->queue = queue;
+ e_object_ref(E_OBJECT(queue));
+
+ copy_thread_data->hwc_window = hwc_window;
+ e_hwc_window_ref(hwc_window);
+
+ copy_thread_data->src_tsurface = buffer->tbm_surface;
+ tbm_surface_internal_ref(buffer->tbm_surface);
+
+ copy_thread_data->src_transform = buffer->transform;
+
+ e_comp_wl_buffer_reference(©_thread_data->src_buffer_ref, buffer);
+
+ queue_buffer = e_hwc_window_queue_buffer_find(queue, buffer->tbm_surface);
+ if (queue_buffer)
+ queue_buffer->copying = EINA_TRUE;
+
+ EHWQINF("Create Copy tdata:%p src:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface);
+
+ return copy_thread_data;
+}
+
+static void
+_e_hwc_window_queue_copy_thread_cancel_buffer_reuse(E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data)
+{
+ E_Hwc_Window_Queue_Copy_Thread_Data *tdata;
+ Eina_List *l;
+ tbm_surface_info_s src_info, dst_info;
+ tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE;
+
+ if (!_hwc_winq_mgr) return;
+ if (!copy_thread_data->dst_tsurface) return;
+
+ ret = tbm_surface_get_info(copy_thread_data->dst_tsurface, &dst_info);
+ if (ret != TBM_SURFACE_ERROR_NONE)
+ {
+ EHWQERR("fail to map the tsurface", NULL, NULL, NULL);
+ return;
+ }
+
+ EINA_LIST_FOREACH(_hwc_winq_mgr->pending_copy_thread_data_list, l, tdata)
+ {
+ if (copy_thread_data == tdata) continue;
+ if (tdata->dst_tsurface) continue;
+
+ ret = tbm_surface_get_info(tdata->src_tsurface, &src_info);
+ if (ret != TBM_SURFACE_ERROR_NONE) continue;
+
+ if ((src_info.width != dst_info.width) ||
+ (src_info.height != dst_info.height) ||
+ (src_info.format != dst_info.format))
+ continue;
+
+ tbm_surface_internal_ref(copy_thread_data->dst_tsurface);
+ tdata->dst_tsurface = copy_thread_data->dst_tsurface;
+ break;
+ }
+}
+
+static void
+_e_hwc_window_queue_copy_thread_cancel(E_Hwc_Window *hwc_window,
+ E_Hwc_Window_Queue_Copy_Thread_Data *pending_except)
+{
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data;
+ Eina_List *l, *ll;
+
+ EINA_LIST_FOREACH_SAFE(_hwc_winq_mgr->pending_copy_thread_data_list, l, ll, copy_thread_data)
+ {
+ if (copy_thread_data == pending_except) continue;
+ if (copy_thread_data->hwc_window != hwc_window) continue;
+
+ _hwc_winq_mgr->pending_copy_thread_data_list =
+ eina_list_remove_list(_hwc_winq_mgr->pending_copy_thread_data_list, l);
+
+ _e_hwc_window_queue_copy_thread_cancel_buffer_reuse(copy_thread_data);
+ _e_hwc_window_queue_copy_thread_data_destroy(copy_thread_data);
+ }
+
+ if ((!_hwc_winq_mgr->copy_thread_canceled) &&
+ (_hwc_winq_mgr->copy_thread) &&
+ (_hwc_winq_mgr->copy_thread_data))
+ {
+ if (_hwc_winq_mgr->copy_thread_data->hwc_window == hwc_window)
+ {
+ EHWQINF("Cancel Copy ecore thread tdata:%p src:%p dst:%p",
+ _hwc_winq_mgr->copy_thread_data->hwc_window->ec,
+ _hwc_winq_mgr->copy_thread_data->hwc_window->hwc,
+ _hwc_winq_mgr->copy_thread_data->queue,
+ _hwc_winq_mgr->copy_thread_data,
+ _hwc_winq_mgr->copy_thread_data->src_tsurface,
+ _hwc_winq_mgr->copy_thread_data->dst_tsurface);
+
+ _e_hwc_window_queue_copy_thread_cancel_buffer_reuse(_hwc_winq_mgr->copy_thread_data);
+ ecore_thread_cancel(_hwc_winq_mgr->copy_thread);
+ _hwc_winq_mgr->copy_thread_canceled = EINA_TRUE;
+ }
+ }
+}
+
+static void
+_e_hwc_window_queue_copy_thread_sync_run(E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data)
+{
+ if (!copy_thread_data->dst_tsurface)
+ {
+ copy_thread_data->dst_tsurface = _backup_tsurface_create(copy_thread_data->src_tsurface);
+ if (!copy_thread_data->dst_tsurface)
+ {
+ EHWQERR("fail to dst_tsurface tdata:%p src:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface);
+
+ _e_hwc_window_queue_copy_thread_data_destroy(copy_thread_data);
+ return;
+ }
+ }
+
+ _hwc_winq_mgr->copy_thread_data = copy_thread_data;
+
+ _e_hwc_window_queue_copy_thread_run_cb(copy_thread_data, NULL);
+ _e_hwc_window_queue_copy_thread_run_end_cb(copy_thread_data, NULL);
+}
+
+static Eina_Bool
+_e_hwc_window_queue_copy_thread_run(E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data)
+{
+ if (!copy_thread_data->dst_tsurface)
+ {
+ copy_thread_data->dst_tsurface = _backup_tsurface_create(copy_thread_data->src_tsurface);
+ if (!copy_thread_data->dst_tsurface)
+ {
+ EHWQERR("fail to dst_tsurface tdata:%p src:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface);
+
+ return EINA_FALSE;
+ }
+ }
+
+ _hwc_winq_mgr->copy_thread_data = copy_thread_data;
+ _hwc_winq_mgr->copy_thread_canceled = EINA_FALSE;
+ _hwc_winq_mgr->copy_thread = ecore_thread_feedback_run(_e_hwc_window_queue_copy_thread_run_cb,
+ _e_hwc_window_queue_copy_thread_run_notify_cb,
+ _e_hwc_window_queue_copy_thread_run_end_cb,
+ _e_hwc_window_queue_copy_thread_run_cancel_cb,
+ copy_thread_data,
+ EINA_TRUE);
+ if (!_hwc_winq_mgr->copy_thread)
+ {
+ EHWQERR("fail to run Copy tdata:%p src:%p dst:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface);
+
+ _hwc_winq_mgr->copy_thread_data = NULL;
+ return EINA_FALSE;
+ }
+
+ EHWQINF("Run Copy tdata:%p src:%p dst:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_hwc_window_queue_pending_copy_thread_check_and_run(void)
+{
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data, *tdata;
+
+ if (!_hwc_winq_mgr) return EINA_TRUE;
+
+ if (!eina_list_count(_hwc_winq_mgr->pending_copy_thread_data_list))
+ return EINA_TRUE;
+
+ copy_thread_data = eina_list_nth(_hwc_winq_mgr->pending_copy_thread_data_list, 0);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(copy_thread_data, EINA_FALSE);
+
+ _hwc_winq_mgr->pending_copy_thread_data_list =
+ eina_list_remove(_hwc_winq_mgr->pending_copy_thread_data_list, copy_thread_data);
+
+ if (!_e_hwc_window_queue_copy_thread_run(copy_thread_data))
+ {
+ EHWQERR("fail to run copy thread tdata:%p src:%p dst:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface);
+
+ _e_hwc_window_queue_copy_thread_sync_run(copy_thread_data);
+
+ EINA_LIST_FREE(_hwc_winq_mgr->pending_copy_thread_data_list, tdata)
+ _e_hwc_window_queue_copy_thread_sync_run(tdata);
+
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_e_hwc_window_queue_copy_thread_run_cb(void *data, Ecore_Thread *thread)
+{
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data;
+
+ if (!(copy_thread_data = data)) return;
+
+ if (thread)
+ eina_thread_name_set(eina_thread_self(), "e_hwc_widnow_queue_copy_thread");
+
+ EHWQINF("Copy buffer tdata:%p src:%p dst:%p",
+ NULL,
+ NULL,
+ NULL,
+ copy_thread_data,
+ copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface);
+
+ if (!_e_hwc_window_queue_copy_content(copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface,
+ thread))
+ {
+ EHWQERR("fail to copy content tdata:%p src:%p dst:%p",
+ NULL,
+ NULL,
+ NULL,
+ copy_thread_data,
+ copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface);
+ }
+
+ EHWQINF("Copy buffer done tdata:%p src:%p dst:%p",
+ NULL,
+ NULL,
+ NULL,
+ copy_thread_data,
+ copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface);
+}
+
+static void
+_e_hwc_window_queue_copy_thread_run_notify_cb(void *data, Ecore_Thread *thread, void *msg_data)
+{
+}
+
+static void
+_e_hwc_window_queue_copy_thread_run_end_cb(void *data, Ecore_Thread *thread)
+{
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data;
+ E_Comp_Wl_Buffer *comp_buffer, *copy_comp_buffer;
+ E_Client *ec;
+ E_Hwc_Window_Queue *queue;
+
+ if (!(copy_thread_data = data)) return;
+
+ queue = copy_thread_data->queue;
+
+ e_object_ref(E_OBJECT(queue));
+
+ EHWQINF("End Copy tdata:%p src:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface);
+
+ if (!(ec = copy_thread_data->hwc_window->ec)) goto end;
+
+ if ((!evas_object_visible_get(ec->frame)) &&
+ (ec->exp_iconify.buffer_flush) &&
+ (e_policy_visibility_client_is_iconic(ec)))
+ goto end;
+
+ comp_buffer = _comp_wl_buffer_get(ec);
+ if (!comp_buffer) goto end;
+ if (!comp_buffer->tbm_surface) goto end;
+ if (comp_buffer->tbm_surface != copy_thread_data->src_tsurface) goto end;
+
+ copy_comp_buffer = e_comp_wl_tbm_buffer_get(copy_thread_data->dst_tsurface);
+ EINA_SAFETY_ON_NULL_GOTO(copy_comp_buffer, end);
+
+ copy_comp_buffer->transform = copy_thread_data->src_transform;
+
+ e_comp_wl_surface_attach(ec, copy_comp_buffer);
+ e_pixmap_image_refresh(ec->pixmap);
+ e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
+ e_comp_object_dirty(ec->frame);
+ e_comp_object_render(ec->frame);
+
+end:
+ _e_hwc_window_queue_copy_thread_data_destroy(copy_thread_data);
+
+ if (_hwc_winq_mgr)
+ {
+ _hwc_winq_mgr->copy_thread_data = NULL;
+ _hwc_winq_mgr->copy_thread_canceled = EINA_FALSE;
+ _hwc_winq_mgr->copy_thread = NULL;
+ }
+
+ if (_e_hwc_window_queue_buffers_retrieve_done(queue))
+ _e_hwc_window_queue_unset(queue);
+
+ e_object_unref(E_OBJECT(queue));
+
+ if (!thread) return;
+
+ if (!_e_hwc_window_queue_pending_copy_thread_check_and_run())
+ {
+ EHWQERR("fail to run pending copy thread", NULL, NULL, NULL);
+ return;
+ }
+}
+
+static void
+_e_hwc_window_queue_copy_thread_run_cancel_cb(void *data, Ecore_Thread *thread)
+{
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data;
+ E_Hwc_Window_Queue *queue;
+
+ if (!(copy_thread_data = data)) return;
+
+ queue = copy_thread_data->queue;
+
+ e_object_ref(E_OBJECT(queue));
+
+ EHWQINF("Cancel Copy tdata:%p src:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface);
+
+ _e_hwc_window_queue_copy_thread_data_destroy(copy_thread_data);
+
+ if (_hwc_winq_mgr)
+ {
+ _hwc_winq_mgr->copy_thread_data = NULL;
+ _hwc_winq_mgr->copy_thread_canceled = EINA_FALSE;
+ _hwc_winq_mgr->copy_thread = NULL;
+ }
+
+ if (_e_hwc_window_queue_buffers_retrieve_done(queue))
+ _e_hwc_window_queue_unset(queue);
+
+ e_object_unref(E_OBJECT(queue));
+
+ if (!thread) return;
+
+ if (!_e_hwc_window_queue_pending_copy_thread_check_and_run())
+ {
+ EHWQERR("fail to run pending copy thread", NULL, NULL, NULL);
+ return;
+ }
+}
+
+static E_Hwc_Window_Queue_Buffer *
+_e_hwc_window_queue_buffer_find_from_tbm_surface(tbm_surface_h tsurface)
+{
+ E_Hwc_Window_Queue *queue;
+ E_Hwc_Window_Queue_Buffer *queue_buffer;
+ Eina_List *l, *ll;
+
+ if (!_hwc_winq_mgr) return NULL;
+
+ EINA_LIST_FOREACH_SAFE(_hwc_winq_mgr->hwc_winq_list, l, ll, queue)
+ {
+ queue_buffer = e_hwc_window_queue_buffer_find(queue, tsurface);
+ if (!queue_buffer) continue;
+
+ return queue_buffer;
+ }
+
+ return NULL;
+}
+
+static void
+_e_hwc_window_queue_copy_thread_check_and_run(E_Hwc_Window *hwc_window)
+{
+ E_Comp_Wl_Buffer *comp_buffer;
tbm_surface_h tsurface;
+ uint32_t flags = 0;
+ E_Client *ec = hwc_window->ec;
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data;
+ E_Hwc_Window_Queue *queue;
E_Hwc_Window_Queue_Buffer *queue_buffer;
+ if (!_hwc_winq_mgr) return;
+ if (!ec) return;
+
+ comp_buffer = _comp_wl_buffer_get(hwc_window->ec);
+ if (!comp_buffer) return;
+ if (!comp_buffer->tbm_surface) return;
+
+ tsurface = comp_buffer->tbm_surface;
+
+ if (comp_buffer->resource)
+ {
+ flags = _comp_wl_buffer_flags_get(comp_buffer);
+ if (flags != E_HWC_WINDOW_QUEUE_BUFFER_FLAGS)
+ return;
+ }
+ else
+ {
+ if (tsurface != hwc_window->display.buffer.tsurface)
+ return;
+
+ if (!hwc_window->display.buffer.from_queue)
+ return;
+ }
+
+ queue_buffer = _e_hwc_window_queue_buffer_find_from_tbm_surface(tsurface);
+ EINA_SAFETY_ON_NULL_RETURN(queue_buffer);
+
+ if (queue_buffer->copying) return;
+
+ queue = queue_buffer->queue;
+ EINA_SAFETY_ON_NULL_RETURN(queue);
+
+ if (queue->state != E_HWC_WINDOW_QUEUE_STATE_UNSET_WAITING)
+ return;
+
+ copy_thread_data = _e_hwc_window_queue_copy_thread_data_create(queue, hwc_window, comp_buffer);
+ EINA_SAFETY_ON_NULL_RETURN(copy_thread_data);
+
+ if (_hwc_winq_mgr->copy_thread)
+ {
+ if (queue->is_target)
+ {
+ _hwc_winq_mgr->pending_copy_thread_data_list =
+ eina_list_prepend(_hwc_winq_mgr->pending_copy_thread_data_list, copy_thread_data);
+ }
+ else
+ {
+ _hwc_winq_mgr->pending_copy_thread_data_list =
+ eina_list_append(_hwc_winq_mgr->pending_copy_thread_data_list, copy_thread_data);
+ }
+
+ _e_hwc_window_queue_copy_thread_cancel(hwc_window, copy_thread_data);
+ }
+ else
+ {
+ if (!_e_hwc_window_queue_copy_thread_run(copy_thread_data))
+ {
+ EHWQERR("fail to run copy thread tdata:%p src:%p dst:%p",
+ copy_thread_data->hwc_window->ec,
+ copy_thread_data->hwc_window->hwc,
+ copy_thread_data->queue,
+ copy_thread_data,
+ copy_thread_data->src_tsurface,
+ copy_thread_data->dst_tsurface);
+
+ _e_hwc_window_queue_copy_thread_sync_run(copy_thread_data);
+ }
+ }
+}
+
+static void
+_e_hwc_window_queue_prepare_unset(E_Hwc_Window_Queue *queue)
+{
+ E_Hwc_Window *hwc_window = queue->user;
+
+ if (queue->state == E_HWC_WINDOW_QUEUE_STATE_UNSET_WAITING)
+ return;
+
tbm_surface_queue_remove_dequeuable_cb(queue->tqueue,
_e_hwc_window_queue_cb_dequeueable,
(void *)queue);
- if ((hwc_window) && (hwc_window->cqueue))
+ if (hwc_window->cqueue)
wayland_tbm_server_client_queue_set_wait_usable_cb(hwc_window->cqueue, NULL, NULL);
/* queue retrieve the buffers from the hwc_window */
- _e_hwc_window_queue_buffers_retrieve(queue, queue->user);
+ _e_hwc_window_queue_buffers_retrieve(queue);
+
+ queue->state = E_HWC_WINDOW_QUEUE_STATE_UNSET_WAITING;
+
+ EHWQINF("Unset Waiting user ehw:%p - {%s}",
+ hwc_window->ec, queue->hwc, queue, hwc_window,
+ (hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN"));
- if ((!hwc_window) || (!hwc_window->ec)) return;
+ if (!hwc_window->ec) return;
if ((!evas_object_visible_get(hwc_window->ec->frame)) &&
(hwc_window->ec->exp_iconify.buffer_flush) &&
(e_policy_visibility_client_is_iconic(hwc_window->ec)))
- return;
-
- tsurface = _e_hwc_window_queue_backup_buffer_set(hwc_window, EINA_TRUE);
- if (tsurface)
- {
- if(hwc_window->render_target)
- {
- e_pixmap_image_refresh(hwc_window->ec->pixmap);
- e_comp_object_damage(hwc_window->ec->frame, 0, 0,
- hwc_window->ec->w, hwc_window->ec->h);
- e_comp_object_dirty(hwc_window->ec->frame);
- e_comp_object_render(hwc_window->ec->frame);
- }
+ return;
- queue_buffer = e_hwc_window_queue_buffer_find(queue, tsurface);
- if (queue_buffer)
- {
- if (!queue_buffer->acquired && queue_buffer->dequeued)
- e_hwc_window_queue_buffer_release(queue, queue_buffer);
- }
- }
+ _e_hwc_window_queue_copy_thread_check_and_run(hwc_window);
}
static void
E_Hwc_Window_Queue_Buffer *queue_buffer;
Eina_List *l;
- if (queue->state == E_HWC_WINDOW_QUEUE_STATE_UNSET_WAITING)
- {
- queue->user = queue->user_waiting_unset;
- queue->user_waiting_unset = NULL;
- }
+ if (queue->state == E_HWC_WINDOW_QUEUE_STATE_UNSET)
+ return;
EINA_LIST_FOREACH(queue->buffers, l, queue_buffer)
{
- if (!queue_buffer->acquired && queue_buffer->dequeued)
+ if ((!queue_buffer->acquired) && (queue_buffer->dequeued))
e_hwc_window_queue_buffer_release(queue, queue_buffer);
}
}
static void
-_e_hwc_window_unkown_queue_release(tbm_surface_h tsurface)
-{
- E_Hwc_Window_Queue *queue;
- E_Hwc_Window_Queue_Buffer *queue_buffer;
- Eina_List *l, *ll;
-
- if (!_hwc_winq_mgr) return;
-
- EINA_LIST_FOREACH_SAFE(_hwc_winq_mgr->hwc_winq_list, l, ll, queue)
- {
- queue_buffer = e_hwc_window_queue_buffer_find(queue, tsurface);
- if (!queue_buffer) continue;
-
- if (!queue_buffer->acquired && queue_buffer->dequeued)
- e_hwc_window_queue_buffer_release(queue, queue_buffer);
- }
-}
-
-static void
_e_hwc_window_queue_cb_buffer_change(void *data, E_Client *ec)
{
E_Hwc_Window *hwc_window;
- E_Comp_Wl_Buffer *comp_buffer;
- uint32_t flags = 0;
- tbm_surface_h tsurface;
EINA_SAFETY_ON_NULL_RETURN(ec);
hwc_window = ec->hwc_window;
if (!hwc_window) return;
- if ((hwc_window->queue) &&
- ((e_hwc_window_device_state_available_get(hwc_window)) || (!ec->redirected)))
- {
- if (hwc_window->queue->state == E_HWC_WINDOW_QUEUE_STATE_SET)
- return;
-
- comp_buffer = _comp_wl_buffer_get(ec);
- if (!comp_buffer) return;
- if (!comp_buffer->resource) return;
- if (!comp_buffer->tbm_surface) return;
-
- flags = _comp_wl_buffer_flags_get(comp_buffer);
- if (flags != E_HWC_WINDOW_QUEUE_BUFFER_FLAGS) return;
-
- if ((hwc_window->queue->user == hwc_window) &&
- (e_hwc_window_queue_buffer_find(hwc_window->queue, comp_buffer->tbm_surface)))
- return;
- }
-
if ((ec->exp_iconify.buffer_flush) && (e_policy_visibility_client_is_iconic(ec)))
return;
- tsurface = _e_hwc_window_queue_backup_buffer_set(hwc_window, EINA_FALSE);
- if (tsurface)
- _e_hwc_window_unkown_queue_release(tsurface);
+ _e_hwc_window_queue_copy_thread_check_and_run(hwc_window);
}
void
}
}
+static void
+_e_hwc_window_queue_cb_pixmap_buffer_clear(void *data EINA_UNUSED, E_Pixmap *cp)
+{
+ E_Hwc_Window *hwc_window;
+ E_Client *ec;
+
+ if (!cp) return;
+ if (!_hwc_winq_mgr) return;
+
+ ec = e_pixmap_client_get(cp);
+ if (!ec) return;
+
+ hwc_window = ec->hwc_window;
+ if (!hwc_window) return;
+
+ _e_hwc_window_queue_copy_thread_cancel(hwc_window, NULL);
+}
+
EINTERN Eina_Bool
e_hwc_window_queue_init(void)
{
_e_hwc_window_queue_cb_accepted_state_set, NULL);
E_COMP_WL_HOOK_APPEND(hwc_window_queue_comp_wl_hooks, E_COMP_WL_HOOK_BUFFER_CHANGE,
_e_hwc_window_queue_cb_buffer_change, NULL);
+ E_PIXMAP_HOOK_APPEND(hwc_window_queue_pixmap_hooks, E_PIXMAP_HOOK_BUFFER_CLEAR,
+ _e_hwc_window_queue_cb_pixmap_buffer_clear, NULL);
return EINA_TRUE;
}
EINTERN void
e_hwc_window_queue_deinit(void)
{
+ E_Hwc_Window_Queue_Copy_Thread_Data *copy_thread_data;
+
if (!_hwc_winq_mgr) return;
+ if (_hwc_winq_mgr->copy_thread)
+ ecore_thread_cancel(_hwc_winq_mgr->copy_thread);
+
+ EINA_LIST_FREE(_hwc_winq_mgr->pending_copy_thread_data_list, copy_thread_data)
+ _e_hwc_window_queue_copy_thread_data_destroy(copy_thread_data);
+
_hwc_winq_mgr->hwc_winq_list = eina_list_free(_hwc_winq_mgr->hwc_winq_list);
E_FREE_LIST(_hwc_winq_mgr->event_handlers, ecore_event_handler_del);
E_FREE_LIST(hwc_window_queue_hwc_hooks, e_hwc_hook_del);
E_FREE_LIST(hwc_window_queue_window_hooks, e_hwc_window_hook_del);
E_FREE_LIST(hwc_window_queue_comp_wl_hooks, e_comp_wl_hook_del);
+ E_FREE_LIST(hwc_window_queue_pixmap_hooks, e_pixmap_hook_del);
E_FREE(_hwc_winq_mgr);
_hwc_winq_mgr = NULL;
if (queue->hwc != hwc_window->hwc)
queue->hwc = hwc_window->hwc;
- if (queue->user ||
- queue->state == E_HWC_WINDOW_QUEUE_STATE_UNSET_WAITING)
+ if (queue->user)
{
_e_hwc_window_queue_user_pending_set_add(queue, hwc_window);
if (_e_hwc_window_queue_buffers_retrieve_done(queue))
_e_hwc_window_queue_unset(queue);
- else
- {
- queue->state = E_HWC_WINDOW_QUEUE_STATE_UNSET_WAITING;
- queue->user_waiting_unset = queue->user;
- queue->user = NULL;
-
- EHWQINF("Unset Waiting user ehw:%p - {%s}",
- hwc_window->ec, queue->hwc, queue, hwc_window,
- (hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN"));
- }
}
static E_Hwc_Window_Queue_Buffer *
if (!queue) continue;
snprintf(info_str, sizeof(info_str),
- "[%2d] Queue(%8p) tqueue(%8p) target(%d) state(%s) user(%8p):win(0x%08zx)"
- " unset_waiting_user(%8p):win(0x%08zx)",
+ "[%2d] Queue(%8p) tqueue(%8p) target(%d) state(%s) user(%8p):win(0x%08zx)",
++idx, queue, queue->tqueue, queue->is_target,
_e_hwc_window_queue_state_string_get(queue->state),
queue->user,
- queue->user ? e_client_util_win_get(queue->user->ec) : 0,
- queue->user_waiting_unset,
- queue->user_waiting_unset ? e_client_util_win_get(queue->user_waiting_unset->ec) : 0);
+ queue->user ? e_client_util_win_get(queue->user->ec) : 0);
eldbus_message_iter_basic_append(line_array, 's', info_str);
pending_set_idx = 0;
{
snprintf(info_str, sizeof(info_str),
" └─ [%2d] Queue_Buffer(%8p) tsurface(%8p) exported_wl_buffer(%u)"
- " exported(%d) usable(%d) released(%d) acquired(%d) dequeued(%d)",
+ " exported(%d) usable(%d) released(%d) acquired(%d) dequeued(%d) copying(%d)",
++buf_idx, queue_buffer, queue_buffer->tsurface,
queue_buffer->exported_wl_buffer ? wl_resource_get_id(queue_buffer->exported_wl_buffer) : 0,
queue_buffer->exported, queue_buffer->usable, queue_buffer->released,
- queue_buffer->acquired, queue_buffer->dequeued);
+ queue_buffer->acquired, queue_buffer->dequeued, queue_buffer->copying);
eldbus_message_iter_basic_append(line_array, 's', info_str);
}
eldbus_message_iter_basic_append(line_array, 's', "");