e_comp_hwc: native surface set at the deactivated. 27/67627/11
authorSooChan Lim <sc1.lim@samsung.com>
Wed, 27 Apr 2016 12:50:07 +0000 (21:50 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 2 May 2016 10:48:41 +0000 (19:48 +0900)
At the time of the transition from the nocomposite to the composite mode,
the last buffer commited at the nocompiste has to set the native surface
to the evas object of the cw. The hwc makes the copied surface and sets
the native surface set with the tbm surface type to the evas object.
The copied surface is destoryed when the next buffer commit of the wl_surface
is done by the client.

Change-Id: I44d40f4c6b7304871a1e058302d7410f4ccdc7cd

src/bin/e_comp_hwc.c
src/bin/e_comp_hwc.h [changed mode: 0644->0755]
src/bin/e_comp_object.c
src/bin/e_comp_wl.c

index 7978945..29ddee9 100755 (executable)
 # include <tdm_helper.h>
 # include <wayland-tbm-server.h>
 
+//#define USE_DLOG_HWC
+#ifdef USE_DLOG_HWC
+#define LOG_TAG "HWC"
+#include <dlog.h>
+#define HWC_DLOG(fmt, args...) LOGE("[HWC]" fmt, ##args)
+#endif
+
 # define HWC_DRM_MODE_DPMS_OFF 3
 # ifndef CLEAR
 # define CLEAR(x) memset(&(x), 0, sizeof (x))
@@ -30,6 +37,19 @@ typedef struct _E_Comp_Hwc_Output E_Comp_Hwc_Output;
 typedef struct _E_Comp_Hwc_Layer E_Comp_Hwc_Layer;
 typedef struct _E_Comp_Hwc_Renderer E_Comp_Hwc_Renderer;
 typedef struct _E_Comp_Hwc_Commit_Data E_Comp_Hwc_Commit_Data;
+typedef struct _E_Comp_Hwc_Client E_Comp_Hwc_Client;
+
+struct _E_Comp_Hwc_Client
+{
+   E_Client *ec;
+
+   Eina_Bool activated;
+
+   E_Comp_Wl_Buffer *buffer;
+   E_Comp_Wl_Buffer *backup_buffer;
+
+   Eina_Bool wait_for_commit;
+};
 
 struct _E_Comp_Hwc_Commit_Data {
    E_Comp_Hwc_Layer *hwc_layer;
@@ -94,6 +114,8 @@ struct _E_Comp_Hwc {
    Eina_List *hwc_outputs;
 
    Eina_Bool trace_debug;
+
+   Eina_List *hwc_clients;
 };
 
 // Global variable.
@@ -120,6 +142,86 @@ _e_output_free(E_Output *output)
    free(output);
 }
 
+static tbm_surface_h
+_e_comp_hwc_create_copied_surface(E_Client *ec, Eina_Bool refresh)
+{
+   tbm_surface_h tsurface = NULL;
+   tbm_surface_h new_tsurface = NULL;
+   E_Pixmap *pixmap = NULL;
+   E_Comp_Wl_Buffer *buffer = NULL;
+   tbm_surface_info_s src_info, dst_info;
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+
+   pixmap = ec->pixmap;
+
+   if (refresh)
+     e_pixmap_image_refresh(ec->pixmap);
+
+   buffer = e_pixmap_resource_get(pixmap);
+   if (!buffer) return NULL;
+
+   tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
+
+   tbm_surface_map(tsurface, TBM_SURF_OPTION_READ, &src_info);
+   tbm_surface_unmap(tsurface);
+
+   new_tsurface = tbm_surface_create(src_info.width, src_info.height, src_info.format);
+
+   tbm_surface_map(new_tsurface, TBM_SURF_OPTION_WRITE, &dst_info);
+   tbm_surface_unmap(new_tsurface);
+
+   /* copy from src to dst */
+   memcpy(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].size);
+
+   return new_tsurface;
+}
+
+static void
+_e_comp_hwc_destroy_copied_surface(tbm_surface_h tbm_surface)
+{
+   EINA_SAFETY_ON_NULL_RETURN(tbm_surface);
+
+   tbm_surface_internal_unref(tbm_surface);
+}
+
+static E_Comp_Wl_Buffer *
+_e_comp_hwc_client_create_backup_buffer(E_Comp_Hwc_Client *hwc_client)
+{
+   E_Comp_Wl_Buffer *buffer = NULL;
+   tbm_surface_h tsurface = NULL;
+
+   tsurface = _e_comp_hwc_create_copied_surface(hwc_client->ec, EINA_TRUE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, NULL);
+
+   if (!(buffer = E_NEW(E_Comp_Wl_Buffer, 1)))
+     {
+        _e_comp_hwc_destroy_copied_surface(tsurface);
+        return NULL;
+     }
+
+   buffer->type = E_COMP_WL_BUFFER_TYPE_TBM;
+   buffer->w = tbm_surface_get_width(tsurface);
+   buffer->h = tbm_surface_get_height(tsurface);
+   buffer->resource = NULL;
+   buffer->tbm_surface = tsurface;
+   wl_signal_init(&buffer->destroy_signal);
+
+   return buffer;
+}
+
+static void
+_e_comp_hwc_client_destroy_backup_buffer(E_Comp_Wl_Buffer *buffer)
+{
+   if (!buffer) return;
+   if (buffer->tbm_surface)
+     {
+        _e_comp_hwc_destroy_copied_surface(buffer->tbm_surface);
+        buffer->tbm_surface = NULL;
+     }
+
+   E_FREE(buffer);
+}
+
 static void
 _e_comp_hwc_update_client_fps()
 {
@@ -525,6 +627,44 @@ _e_comp_hwc_renderer_can_activate(E_Comp_Hwc_Renderer *hwc_renderer, E_Client *e
    return EINA_TRUE;
 }
 
+static void
+_e_comp_hwc_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
+{
+   E_Comp_Hwc_Client *hwc_client = NULL;
+   Eina_List *l = NULL;
+
+   /* destroy the hwc_client */
+   EINA_LIST_FOREACH(g_hwc->hwc_clients, l, hwc_client)
+     {
+        if (!hwc_client) continue;
+        if (hwc_client->ec == ec)
+          {
+             g_hwc->hwc_clients = eina_list_remove_list(g_hwc->hwc_clients, l);
+             if (hwc_client->backup_buffer)
+               _e_comp_hwc_client_destroy_backup_buffer(hwc_client->backup_buffer);
+             free(hwc_client);
+             break;
+          }
+     }
+}
+
+
+E_Comp_Hwc_Client *
+_e_comp_hwc_client_find(E_Client *ec)
+{
+   E_Comp_Hwc_Client *hwc_client = NULL;
+   const Eina_List *l;
+
+   EINA_LIST_FOREACH(g_hwc->hwc_clients, l, hwc_client)
+     {
+        if (!hwc_client) continue;
+        if (hwc_client->ec == ec) return hwc_client;
+     }
+
+   return NULL;
+}
+
+
 static Eina_Bool
 _e_comp_hwc_renderer_activate(E_Comp_Hwc_Renderer *hwc_renderer, E_Client *ec)
 {
@@ -571,6 +711,29 @@ _e_comp_hwc_renderer_activate(E_Comp_Hwc_Renderer *hwc_renderer, E_Client *ec)
 
    hwc_renderer->activated_ec = ec;
 
+   /* register the hwc client */
+   E_Comp_Hwc_Client *hwc_client = _e_comp_hwc_client_find(ec);
+   if (!hwc_client)
+     {
+        hwc_client = E_NEW(E_Comp_Hwc_Client, 1);
+        EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_client, EINA_FALSE);
+        hwc_client->ec = ec;
+        hwc_client->activated = EINA_TRUE;
+        /* add hwc_client to the list */
+        g_hwc->hwc_clients = eina_list_append(g_hwc->hwc_clients, hwc_client);
+#ifdef USE_DLOG_HWC
+        HWC_DLOG("hwc_client,%p created.\n", hwc_client);
+#endif
+     }
+   else
+     {
+        hwc_client->activated = EINA_TRUE;
+     }
+
+#ifdef USE_DLOG_HWC
+   HWC_DLOG("hwc_client,%p activated.\n", hwc_client);
+#endif
+
    return EINA_TRUE;
 }
 
@@ -581,6 +744,7 @@ _e_comp_hwc_renderer_deactivate(E_Comp_Hwc_Renderer *hwc_renderer)
    struct wl_resource *wl_surface = NULL;
    E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
    E_Client *ec = NULL;
+   E_Comp_Hwc_Client *hwc_client = NULL;
 
    if (!hwc_renderer->activated_ec)
      {
@@ -594,6 +758,11 @@ _e_comp_hwc_renderer_deactivate(E_Comp_Hwc_Renderer *hwc_renderer)
    if (hwc_renderer->hwc_layer->hwc->trace_debug)
      ELOGF("HWC", "Deactivate", ec->pixmap, ec);
 
+   hwc_client = _e_comp_hwc_client_find(ec);
+   EINA_SAFETY_ON_NULL_GOTO(hwc_client, done);
+
+   if (!hwc_client->activated) goto done;
+
    EINA_SAFETY_ON_NULL_GOTO(wl_comp_data, done);
 
    wl_surface = _e_comp_hwc_wl_surface_get(ec);
@@ -605,6 +774,39 @@ _e_comp_hwc_renderer_deactivate(E_Comp_Hwc_Renderer *hwc_renderer)
    /* deactive */
    wayland_tbm_server_client_queue_deactivate(cqueue);
 
+   if (hwc_client->backup_buffer)
+     {
+#ifdef USE_DLOG_HWC
+        HWC_DLOG("hwc_client,%p The previous backup_buffer exists. destroy it.\n");
+#endif
+        _e_comp_hwc_client_destroy_backup_buffer(hwc_client->backup_buffer);
+     }
+
+   /* get the tsurface for setting the native surface with it
+      compositing is processed not calling e_comp_update_cb*/
+   hwc_client->buffer = e_pixmap_resource_get(ec->pixmap);
+   hwc_client->backup_buffer = _e_comp_hwc_client_create_backup_buffer(hwc_client);
+   hwc_client->activated = EINA_FALSE;
+   hwc_client->wait_for_commit = EINA_TRUE;
+
+   /* set the backup buffer resource to the pixmap */
+   e_pixmap_resource_set(ec->pixmap, hwc_client->backup_buffer);
+
+   e_comp->nocomp = 0;
+   e_comp->nocomp_ec = NULL;
+
+   /* force update */
+   e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
+   e_comp_object_dirty(ec->frame);
+   e_comp_object_render(ec->frame);
+
+   /* set the native surface with tbm type for compositing */
+   e_comp_object_native_surface_set(ec->frame, EINA_TRUE);
+
+#ifdef USE_DLOG_HWC
+   HWC_DLOG("hwc_client,%p deactivated\n", hwc_client);
+#endif
+
 done:
    hwc_renderer->activated_ec = NULL;
 
@@ -812,6 +1014,10 @@ _e_comp_hwc_output_commit(E_Comp_Hwc_Output *hwc_output, E_Comp_Hwc_Layer *hwc_l
    E_Comp_Hwc_Commit_Data *data = NULL;
    tdm_output_dpms dpms_value;
 
+#if HWC_DUMP
+   char fname[1024] = {0, };
+#endif
+
    error = tdm_output_get_dpms(toutput, &dpms_value);
    if (error != TDM_ERROR_NONE)
      {
@@ -927,6 +1133,18 @@ _e_comp_hwc_output_commit(E_Comp_Hwc_Output *hwc_output, E_Comp_Hwc_Layer *hwc_l
           }
      }
 
+#if HWC_DUMP
+   if (is_canvas)
+     snprintf(fname, sizeof(fname), "hwc_output_commit_canvas");
+   else
+     {
+        Ecore_Window win;
+        win = e_client_util_win_get(data->ec);
+        snprintf(fname, sizeof(fname), "hwc_output_commit_0x%08x", win);
+     }
+   tbm_internal_surface_dump_buffer(tsurface, fname);
+#endif
+
    return EINA_TRUE;
 }
 
@@ -936,10 +1154,23 @@ _e_comp_hwc_output_display_client_reserved_memory(E_Comp_Hwc_Output *hwc_output,
    E_Comp_Hwc_Renderer *hwc_renderer = hwc_layer->hwc_renderer;
    E_Pixmap *pixmap = ec->pixmap;
    tbm_surface_h tsurface = NULL;
+   E_Comp_Hwc_Client *hwc_client = NULL;
 
    if (hwc_layer->hwc->trace_debug)
      ELOGF("HWC", "Display Client", ec->pixmap, ec);
 
+   hwc_client = _e_comp_hwc_client_find(ec);
+   EINA_SAFETY_ON_NULL_RETURN(hwc_client);
+
+   if (hwc_client->backup_buffer)
+     {
+#ifdef USE_DLOG_HWC
+        HWC_DLOG("hwc_client,%p display client. destroy the backup_buffer.\n", hwc_client);
+#endif
+        _e_comp_hwc_client_destroy_backup_buffer(hwc_client->backup_buffer);
+        hwc_client->backup_buffer = NULL;
+     }
+
    /* acquire the surface from the client_queue */
    tsurface = _e_comp_hwc_renderer_recieve_surface(hwc_renderer, ec);
    if (!tsurface)
@@ -1285,6 +1516,8 @@ e_comp_hwc_init(void)
 
    evas_event_callback_add(e_comp->evas, EVAS_CALLBACK_RENDER_POST, _e_comp_hwc_canvas_render_post, hwc);
 
+   e_client_hook_add(E_CLIENT_HOOK_DEL, _e_comp_hwc_client_cb_del, NULL);
+
    return EINA_TRUE;
 
 fail:
@@ -1440,6 +1673,88 @@ e_comp_hwc_trace_debug(Eina_Bool onoff)
    INF("HWC: hwc trace_debug is %s", onoff?"ON":"OFF");
 }
 
+static Eina_Bool
+_e_comp_hwc_check_buffer_scanout(E_Client *ec)
+{
+   tbm_surface_h tsurface = NULL;
+   E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+   E_Pixmap *pixmap = ec->pixmap;
+   uint32_t flags = 0;
+   E_Comp_Wl_Buffer *buffer = NULL;
+
+   buffer = e_pixmap_resource_get(pixmap);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, EINA_FALSE);
+
+   tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, EINA_FALSE);
+
+   flags = wayland_tbm_server_get_buffer_flags(wl_comp_data->tbm.server, buffer->resource);
+   if (flags != HWC_SURFACE_TYPE_PRIMARY)
+     return EINA_FALSE;;
+
+   return EINA_TRUE;
+}
+
+Eina_Bool
+e_comp_hwc_native_surface_set(E_Client *ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+   E_Comp_Hwc_Client *hwc_client = NULL;
+
+   /* check the hwc_client */
+   hwc_client = _e_comp_hwc_client_find(ec);
+   if (!hwc_client) return EINA_FALSE;
+
+#ifdef USE_DLOG_HWC
+   HWC_DLOG("hwc_client,%p update client\n", hwc_client);
+#endif
+
+   /* check the scanout buffer */
+   if (!_e_comp_hwc_check_buffer_scanout(ec))
+     {
+#ifdef USE_DLOG_HWC
+        HWC_DLOG("hwc_client,%p not scanout buffer\n", hwc_client);
+#endif
+        return EINA_FALSE;
+     }
+
+   if (hwc_client->wait_for_commit &&
+       hwc_client->backup_buffer)
+     {
+#ifdef USE_DLOG_HWC
+        HWC_DLOG("hwc_client,%p NEVER BE HEAR.\n", hwc_client);
+#endif
+        _e_comp_hwc_client_destroy_backup_buffer(hwc_client->backup_buffer);
+        hwc_client->buffer = NULL;
+     }
+
+#ifdef USE_DLOG_HWC
+   HWC_DLOG("hwc_client,%p copy and native set\n", hwc_client);
+#endif
+
+   return EINA_TRUE;
+}
+
+void
+e_comp_hwc_client_commit(E_Client *ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   E_Comp_Hwc_Client *hwc_client = NULL;
+
+   hwc_client = _e_comp_hwc_client_find(ec);
+   if (!hwc_client) return;
+
+   if (hwc_client->wait_for_commit)
+     {
+#ifdef USE_DLOG_HWC
+        HWC_DLOG("hwc_client,%p commit after deactivated....\n", hwc_client);
+#endif
+        hwc_client->wait_for_commit = EINA_FALSE;
+     }
+}
+
 EINTERN Eina_Bool
 e_comp_hwc_plane_init(E_Zone *zone)
 {
@@ -1617,6 +1932,18 @@ e_comp_hwc_trace_debug(Eina_Bool onoff)
    ;
 }
 
+Eina_Bool
+e_comp_hwc_native_surface_set(E_Client *ec)
+{
+   return EINA_FALSE;
+}
+
+void
+e_comp_hwc_client_commit(E_Client *ec)
+{
+   ;
+}
+
 EINTERN Eina_Bool
 e_comp_hwc_plane_init(E_Zone *zone)
 {
old mode 100644 (file)
new mode 100755 (executable)
index d8b3ffe..6f85ac9
@@ -33,6 +33,9 @@ EINTERN void      e_comp_hwc_shutdown(void);
 EINTERN Eina_Bool e_comp_hwc_mode_nocomp(E_Client *ec);
 EINTERN void      e_comp_hwc_display_client(E_Client *ec);
 EINTERN void      e_comp_hwc_trace_debug(Eina_Bool onoff);
+Eina_Bool         e_comp_hwc_native_surface_set(E_Client *ec);
+void              e_comp_hwc_client_commit(E_Client *ec);
+
 EINTERN Eina_Bool e_comp_hwc_plane_init(E_Zone *zone);
 
 E_API E_Output * e_output_new(E_Zone *zone);
index 389e3ce..5efbcd8 100644 (file)
@@ -3602,7 +3602,18 @@ e_comp_object_dirty(Evas_Object *obj)
         ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
         return;
      }
+
+#ifdef HAVE_HWC
+   if (e_comp->hwc)
+     {
+        if (!e_comp_hwc_native_surface_set(cw->ec))
+          e_comp_object_native_surface_set(obj, e_comp->gl);
+     }
+   else
+     e_comp_object_native_surface_set(obj, e_comp->gl);
+#else
    e_comp_object_native_surface_set(obj, e_comp->gl);
+#endif
    it = eina_tiler_iterator_new(cw->updates);
    EINA_ITERATOR_FOREACH(it, rect)
      {
index b7912e6..f3133a0 100644 (file)
@@ -2282,6 +2282,8 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
      {
         e_comp_hwc_display_client(ec);
      }
+   if (e_comp->hwc)
+     e_comp_hwc_client_commit(ec);
 #endif
 
    if ((buffer && buffer->type == E_COMP_WL_BUFFER_TYPE_VIDEO) &&