Add the code for hwc windows(Vendor Driven HWC).
It uses the tdm_hwc with which
the hwc policy is decided by the tdm backends and
E20 does not use the E_Plane(tdm_layer).
Change-Id: Ifc8c3ee8f44741ee6d781403b86f55859fc82c35
src/bin/e_comp_wl_input.h \
src/bin/e_comp_wl.h \
src/bin/e_output_hwc.h \
-src/bin/e_output_hwc_planes.h
+src/bin/e_output_hwc_planes.h \
+src/bin/e_output_hwc_windows.h \
+src/bin/e_hwc_window.h
if HAVE_WAYLAND_TBM
ENLIGHTENMENTHEADERS += \
src/bin/e_comp_wl.c \
src/bin/e_output_hwc.c \
src/bin/e_output_hwc_planes.c \
+src/bin/e_output_hwc_windows.c \
+src/bin/e_hwc_window.c \
$(ENLIGHTENMENTHEADERS)
if HAVE_WAYLAND_TBM
Eina_Bool use_splash : 1;
Eina_Bool saved_img : 1; // indicates that window has been saved as the image file even once
Eina_Bool skip_save_img: 1; // indicates that window doesn't want to save its image file
+
+ E_Hwc_Window *hwc_window; // hwc window for the tdm_output_hwc.
};
#define e_client_focus_policy_click(ec) \
Eina_List *l, *ll;
E_Output *eout;
E_Plane *ep;
+ E_Hwc_Window *hwc_window;
- if (!ec) return EINA_FALSE;
- if (!ec->zone || !ec->zone->output_id) return EINA_FALSE;
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(!ec, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(!ec->zone, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(!ec->zone->output_id, EINA_FALSE);
eout = e_output_find(ec->zone->output_id);
if (!eout) return EINA_FALSE;
- if (!e_output_hwc_mode_get(eout->output_hwc)) return EINA_FALSE;
- EINA_LIST_FOREACH_SAFE(eout->planes, l, ll, ep)
+ if (e_output_hwc_policy_get(eout->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
{
- E_Client *overlay_ec = ep->ec;
- if (overlay_ec == ec) return EINA_TRUE;
+ if (!e_output_hwc_mode_get(eout->output_hwc)) return EINA_FALSE;
+
+ EINA_LIST_FOREACH_SAFE(eout->planes, l, ll, ep)
+ {
+ E_Client *overlay_ec = ep->ec;
+ if (overlay_ec == ec) return EINA_TRUE;
+ }
+ }
+ else
+ {
+ hwc_window = ec->hwc_window;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (e_hwc_window_is_on_hw_overlay(hwc_window)) return EINA_TRUE;
}
return EINA_FALSE;
e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
}
+
+static void
+_e_comp_object_pixels_noti(void *data, Evas_Object *obj EINA_UNUSED)
+{
+ E_Comp_Object *cw = data;
+ E_Client *ec = cw->ec;
+
+ if (e_object_is_del(E_OBJECT(ec))) return;
+ if (cw->external_content) return;
+
+ if (!ec->hwc_window) return;
+
+ e_hwc_window_render_list_add(ec->hwc_window);
+}
+
/////////////////////////////////////////////
static void
evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
e_util_size_debug_set(cw->obj, 1);
evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
+ evas_object_image_pixels_noti_callback_set(cw->obj, _e_comp_object_pixels_noti, cw);
evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
evas_object_name_set(cw->obj, "cw->obj");
evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l_o, ll_o, output)
{
if (!output) continue;
- tdm_output_get_conn_status(output->toutput, &conn_status);
- if (conn_status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue;
-
- INF("HWC: HWC Output(%d):(x, y, w, h)=(%d, %d, %d, %d) Information.",
- ++output_idx,
- output->config.geom.x, output->config.geom.y, output->config.geom.w, output->config.geom.h);
- INF("HWC: num_layers=%d", output->plane_count);
- EINA_LIST_FOREACH_SAFE(output->planes, l_l, ll_l, plane)
+
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
{
- if (!plane) continue;
- tdm_layer_get_capabilities(plane->tlayer, &layer_capabilities);
- snprintf(layer_cap, sizeof(layer_cap), "%s%s%s%s%s%s%s%s",
- _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_CURSOR),
- _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_PRIMARY),
- _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_OVERLAY),
- _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_GRAPHIC),
- _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_VIDEO),
- _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_TRANSFORM),
- _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_RESEVED_MEMORY),
- _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_NO_CROP));
- INF("HWC: index=%d zpos=%d ec=%p %s",
- plane->index, plane->zpos,
- plane->ec?plane->ec:NULL,
- layer_cap);
+ tdm_output_get_conn_status(output->toutput, &conn_status);
+ if (conn_status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue;
+
+ INF("HWC: HWC Output(%d):(x, y, w, h)=(%d, %d, %d, %d) Information.",
+ ++output_idx,
+ output->config.geom.x, output->config.geom.y, output->config.geom.w, output->config.geom.h);
+ INF("HWC: num_layers=%d", output->plane_count);
+ EINA_LIST_FOREACH_SAFE(output->planes, l_l, ll_l, plane)
+ {
+ if (!plane) continue;
+ /* FIXME: hwc extension doesn't provide thing like layer */
+ tdm_layer_get_capabilities(plane->tlayer, &layer_capabilities);
+ snprintf(layer_cap, sizeof(layer_cap), "%s%s%s%s%s%s%s%s",
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_CURSOR),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_PRIMARY),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_OVERLAY),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_GRAPHIC),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_VIDEO),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_TRANSFORM),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_RESEVED_MEMORY),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_NO_CROP));
+ INF("HWC: index=%d zpos=%d ec=%p %s",
+ plane->index, plane->zpos,
+ plane->ec?plane->ec:NULL,
+ layer_cap);
+ }
+ }
+ else
+ {
+ /* TODO: construct debug info for outputs managed by the hwc-wins */
+ INF("HWC: HWC Output(%d) managed by hwc-wins.", ++output_idx);
+ continue;
}
}
INF("HWC: =========================================================================");
E_Video *video;
tdm_layer *tdm_layer;
+
+ /* for hwc_window */
+ E_Video_Info_Layer info;
+ tbm_surface_h cur_tsurface; // tsurface to be set this layer.
+ E_Client *e_client;
};
struct _E_Video
return NULL;
}
+static E_Output*
+_get_e_output(tdm_output *output)
+{
+ Eina_List *l;
+ E_Output *eo;
+
+ EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, eo)
+ if (eo->toutput == output)
+ return eo;
+
+ return NULL;
+}
static Eina_Bool
-_e_video_tdm_output_has_video_layer(tdm_output *output)
+_e_video_tdm_output_has_video_layer(tdm_output *toutput)
{
+ E_Output *output = NULL;
tdm_layer *layer;
tdm_layer_capability lyr_capabilities = 0;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(toutput, EINA_FALSE);
+
+ output = _get_e_output(toutput);
EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
- /* get the first suitable layer */
- layer = _e_video_tdm_video_layer_get(output);
- tdm_layer_get_capabilities(layer, &lyr_capabilities);
- if (lyr_capabilities & TDM_LAYER_CAPABILITY_VIDEO)
- return EINA_TRUE;
+ if (e_output_hwc_policy_get(output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
+ {
+ /* get the first suitable layer */
+ layer = _e_video_tdm_video_layer_get(output);
+ tdm_layer_get_capabilities(layer, &lyr_capabilities);
+ if (lyr_capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+ return EINA_TRUE;
+ }
+ else
+ {
+ /* TODO: add the hwc_window video support */
+ ;;;;
+ }
return EINA_FALSE;
}
_e_video_avaiable_video_layer_get(E_Video *video)
{
E_Video_Layer *layer = NULL;
+ E_Hwc_Window *hwc_window = NULL;
EINA_SAFETY_ON_NULL_RETURN_VAL(video, NULL);
layer = calloc(1, sizeof(E_Video_Layer));
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
- layer->tdm_layer = _e_video_tdm_avaiable_video_layer_get(video->output);
- if (!layer->tdm_layer)
+ layer->video = video;
+ layer->e_client = video->ec;
+
+ if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
+ {
+ layer->tdm_layer = _e_video_tdm_avaiable_video_layer_get(video->output);
+ if (!layer->tdm_layer)
+ {
+ free(layer);
+ return NULL;
+ }
+ _e_video_tdm_set_layer_usable(layer->tdm_layer, EINA_FALSE);
+ }
+ else
{
- free(layer);
- return NULL;
+ /*
+ * Try to create a video hwc window.
+ * In this moment the video resource will be held.
+ */
+ hwc_window = e_hwc_window_new(video->e_output->output_hwc, video->ec, E_HWC_WINDOW_STATE_VIDEO);
+ if (!hwc_window)
+ {
+ VER("hwc_opt: cannot create new video hwc window for ec(%p)", video->ec);
+ free(layer);
+ return NULL;
+ }
+
+ /* free previous hwc_window */
+ if (video->ec->hwc_window)
+ e_hwc_window_free(video->ec->hwc_window);
+
+ /* set new hwc_window to the e_client */
+ video->ec->hwc_window = hwc_window;
}
- _e_video_tdm_set_layer_usable(layer->tdm_layer, EINA_FALSE);
return layer;
}
static void
_e_video_get_available_formats(const tbm_format **formats, int *count)
{
- tdm_output *output;
+ E_Output *output;
+ tdm_output *toutput;
tdm_layer *layer;
+ tdm_error error;
*count = 0;
/* get the first output */
- output = tdm_display_get_output(e_comp->e_comp_screen->tdisplay, 0, NULL);
+ toutput = tdm_display_get_output(e_comp->e_comp_screen->tdisplay, 0, NULL);
+ EINA_SAFETY_ON_NULL_RETURN(toutput);
+
+ output = _get_e_output(toutput);
EINA_SAFETY_ON_NULL_RETURN(output);
- /* get the first suitable layer */
- layer = _e_video_tdm_video_layer_get(output);
- if (layer)
+ if (e_output_hwc_policy_get(output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
{
- tdm_layer_get_available_formats(layer, formats, count);
+ /* get the first suitable layer */
+ layer = _e_video_tdm_video_layer_get(output);
+ if (layer)
+ {
+ tdm_layer_get_available_formats(layer, formats, count);
+ }
+ else
+ {
+ *formats = sw_formats;
+ *count = NUM_SW_FORMAT;
+ }
}
else
{
- *formats = sw_formats;
- *count = NUM_SW_FORMAT;
+ error = tdm_output_hwc_get_video_supported_formats(output, formats, count);
+ if (error != TDM_ERROR_NONE)
+ {
+ *formats = sw_formats;
+ *count = NUM_SW_FORMAT;
+ }
}
}
const tdm_prop *props;
int i, count = 0;
- layer = _e_video_tdm_video_layer_get(video->output);
- tdm_layer_get_available_properties(layer, &props, &count);
-
- for (i = 0; i < count; i++)
+ if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
{
- if (!strncmp(name, props[i].name, TDM_NAME_LEN))
+ layer = _e_video_tdm_video_layer_get(video->output);
+ tdm_layer_get_available_properties(layer, &props, &count);
+
+ for (i = 0; i < count; i++)
{
- VDB("check property(%s)", name);
- return props[i].id;
+ if (!strncmp(name, props[i].name, TDM_NAME_LEN))
+ {
+ VDB("check property(%s)", name);
+ return props[i].id;
+ }
}
}
+ else
+ {
+ // TODO: hwc windows don't have any properties yet
+ // video hwc_window has to get and set the property id.
+ // tdm_error tdm_hwc_window_video_get_property(tdm_hwc_window *hwc_window, uint32_t id, tdm_value *value);
+ ;;;;;
+ }
return -1;
}
+// TODO: this function has to be removed.....
+// Use. e_output_hwc_policy_get();
+static Eina_Bool
+_is_video_hwc_windows(E_Video *video)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(video, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(video->e_output, EINA_FALSE);
+
+ if (e_output_hwc_policy_get(video->e_output->output_hwc) == E_OUTPUT_HWC_POLICY_WINDOWS)
+ return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
static tdm_error
_e_video_layer_get_info(E_Video_Layer *layer, E_Video_Info_Layer *vinfo)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_INVALID_PARAMETER);
EINA_SAFETY_ON_NULL_RETURN_VAL(vinfo, TDM_ERROR_INVALID_PARAMETER);
- ret = tdm_layer_get_info(layer->tdm_layer, &tinfo);
- EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
+ if (_is_video_hwc_windows(layer->video))
+ memcpy(vinfo, &layer->info, sizeof(E_Video_Info_Layer));
+ else
+ {
+ ret = tdm_layer_get_info(layer->tdm_layer, &tinfo);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
- memcpy(&vinfo->src_config, &tinfo.src_config, sizeof(tdm_info_config));
- memcpy(&vinfo->dst_pos, &tinfo.dst_pos, sizeof(tdm_pos));
- vinfo->transform = tinfo.transform;
+ memcpy(&vinfo->src_config, &tinfo.src_config, sizeof(tdm_info_config));
+ memcpy(&vinfo->dst_pos, &tinfo.dst_pos, sizeof(tdm_pos));
+ vinfo->transform = tinfo.transform;
+ }
return ret;
}
static tdm_error
_e_video_layer_set_info(E_Video_Layer *layer, E_Video_Info_Layer *vinfo)
{
- tdm_error ret;
+ tdm_error ret = TDM_ERROR_NONE;
tdm_info_layer info_layer = {0};
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_INVALID_PARAMETER);
EINA_SAFETY_ON_NULL_RETURN_VAL(vinfo, TDM_ERROR_INVALID_PARAMETER);
- memcpy(&info_layer.src_config, &vinfo->src_config, sizeof(tdm_info_config));
- memcpy(&info_layer.dst_pos, &vinfo->dst_pos, sizeof(tdm_pos));
- info_layer.transform = vinfo->transform;
+ if (_is_video_hwc_windows(layer->video))
+ memcpy(&layer->info, vinfo, sizeof(E_Video_Info_Layer));
+ else
+ {
+
+ memcpy(&info_layer.src_config, &vinfo->src_config, sizeof(tdm_info_config));
+ memcpy(&info_layer.dst_pos, &vinfo->dst_pos, sizeof(tdm_pos));
+ info_layer.transform = vinfo->transform;
- ret = tdm_layer_set_info(layer->tdm_layer, &info_layer);
+ ret = tdm_layer_set_info(layer->tdm_layer, &info_layer);
+ }
return ret;
}
static tdm_error
_e_video_layer_set_buffer(E_Video_Layer * layer, tbm_surface_h buff)
{
- tdm_error ret;
+ tdm_error ret = TDM_ERROR_NONE;
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
EINA_SAFETY_ON_NULL_RETURN_VAL(buff, TDM_ERROR_BAD_REQUEST);
- ret = tdm_layer_set_buffer(layer->tdm_layer, buff);
+ if (_is_video_hwc_windows(layer->video))
+ layer->cur_tsurface = buff; // set the buffer to the tdm at the e_hwc_window_buffer_update();
+ else
+ ret = tdm_layer_set_buffer(layer->tdm_layer, buff);
return ret;
}
_e_video_layer_unset_buffer(E_Video_Layer *layer)
{
tdm_error ret;
+ E_Hwc_Window *hwc_window;
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
- ret = tdm_layer_unset_buffer(layer->tdm_layer);
+ if (_is_video_hwc_windows(layer->video))
+ {
+ hwc_window = layer->e_client->hwc_window;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, TDM_ERROR_OPERATION_FAILED);
+
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+ layer->cur_tsurface = NULL; // set the buffer to the tdm at the e_hwc_window_buffer_update();
+
+ ret = TDM_ERROR_NONE;
+ }
+ else
+ ret = tdm_layer_unset_buffer(layer->tdm_layer);
return ret;
}
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
EINA_SAFETY_ON_NULL_RETURN_VAL(usable, TDM_ERROR_BAD_REQUEST);
+ if (_is_video_hwc_windows(layer->video))
+ {
+ E_Hwc_Window *hwc_window;
+ E_Hwc_Window_State state;
+
+ hwc_window = layer->e_client->hwc_window;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, TDM_ERROR_OPERATION_FAILED);
+
+ state = e_hwc_window_state_get(hwc_window);
+ if (state == E_HWC_WINDOW_STATE_NONE || state == E_HWC_WINDOW_STATE_CLIENT)
+ *usable = 1;
+ else
+ *usable = 0;
+
+ return TDM_ERROR_NONE;
+ }
+
ret = tdm_layer_is_usable(layer->tdm_layer, usable);
return ret;
}
static tdm_error
_e_video_layer_commit(E_Video_Layer *layer, tdm_layer_commit_handler func, void *user_data)
{
- tdm_error ret;
+ tdm_error ret = TDM_ERROR_NONE;
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
- ret = tdm_layer_commit(layer->tdm_layer, func, user_data);
+ if (_is_video_hwc_windows(layer->video))
+ ret = TDM_ERROR_NONE;
+ else
+ ret = tdm_layer_commit(layer->tdm_layer, func, user_data);
+
return ret;
}
if (tdm_error)
*tdm_error = TDM_ERROR_OPERATION_FAILED;
+ if (_is_video_hwc_windows(layer->video))
+ {
+ E_Hwc_Window *hwc_window;
+ E_Video *video;
+
+ hwc_window = layer->e_client->hwc_window;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
+
+ video = find_video_with_surface(layer->e_client->comp_data->surface);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(video, EINA_FALSE);
+
+ if (tdm_error)
+ *tdm_error = TDM_ERROR_NONE;
+
+ return e_hwc_window_displaying_surface_get(hwc_window);
+ }
+
return tdm_layer_get_displaying_buffer(layer->tdm_layer, tdm_error);
}
EINA_SAFETY_ON_NULL_RETURN_VAL(props, TDM_ERROR_BAD_REQUEST);
EINA_SAFETY_ON_NULL_RETURN_VAL(count, TDM_ERROR_BAD_REQUEST);
- tdm_layer *tlayer = layer->tdm_layer;
- /* if layer wasn't set then get an any available tdm_layer */
- if (tlayer == NULL)
- tlayer = _e_video_tdm_avaiable_video_layer_get(layer->video->output);
- ret = tdm_layer_get_available_properties(tlayer, props, count);
+ if (_is_video_hwc_windows(layer->video))
+ {
+ *count = 0;
+ if (layer->e_client->hwc_window->thwc_window)
+ ret = tdm_hwc_window_video_get_available_properties(
+ layer->e_client->hwc_window->thwc_window, props, count);
+ }
+ else
+ {
+ tdm_layer *tlayer = layer->tdm_layer;
+ /* if layer wasn't set then get an any available tdm_layer */
+ if (tlayer == NULL)
+ tlayer = _e_video_tdm_avaiable_video_layer_get(layer->video->output);
+ ret = tdm_layer_get_available_properties(tlayer, props, count);
+ }
return ret;
}
static tdm_error
_e_video_layer_get_property(E_Video_Layer * layer, unsigned id, tdm_value *value)
{
- tdm_error ret;
+ tdm_error ret = TDM_ERROR_OPERATION_FAILED;
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
EINA_SAFETY_ON_NULL_RETURN_VAL(value, TDM_ERROR_BAD_REQUEST);
- ret = tdm_layer_get_property(layer->tdm_layer, id, value);
+ if (_is_video_hwc_windows(layer->video))
+ {
+ if (layer->e_client->hwc_window->thwc_window)
+ ret = tdm_hwc_window_video_get_property(
+ layer->e_client->hwc_window->thwc_window, id, value);
+
+ ret = TDM_ERROR_BAD_MODULE;
+ }
+ else
+ ret = tdm_layer_get_property(layer->tdm_layer, id, value);
return ret;
}
EINA_SAFETY_ON_NULL_RETURN_VAL(layer, TDM_ERROR_BAD_REQUEST);
+ if (_is_video_hwc_windows(layer->video))
+ return TDM_ERROR_BAD_MODULE;
+
ret = tdm_layer_set_property(layer->tdm_layer, prop->id, prop->value);
return ret;
}
{
EINA_SAFETY_ON_NULL_RETURN(layer);
+ if (layer->e_client && layer->e_client->hwc_window)
+ {
+ E_Hwc_Window *hwc_window;
+
+ hwc_window = layer->e_client->hwc_window;
+ EINA_SAFETY_ON_FALSE_RETURN(hwc_window);
+
+ e_hwc_window_free(hwc_window);
+ layer->e_client->hwc_window = NULL;
+
+ /* to re-evaluate the window policy */
+ e_comp_render_queue();
+ }
+
if (layer->tdm_layer)
_e_video_tdm_set_layer_usable(layer->tdm_layer, EINA_TRUE);
{
unsigned int usable = 1;
if (!video->layer) return EINA_TRUE;
+
_e_video_layer_is_usable(video->layer, &usable);
if (!usable && !video->waiting_video_set)
{
_e_video_layer_unset_buffer(video->layer);
_e_video_layer_commit(video->layer, NULL, NULL);
}
+
VIN("release layer: %p", video->layer);
_e_video_layer_destroy(video->layer);
video->layer = NULL;
video->old_comp_buffer = NULL;
- e_plane_video_set(video->e_plane, EINA_FALSE, NULL);
- video->e_plane = NULL;
+ if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
+ {
+ e_plane_video_set(video->e_plane, EINA_FALSE, NULL);
+ video->e_plane = NULL;
+ }
+
video->waiting_video_set = EINA_FALSE;
if (video->video_set_hook)
{
return EINA_FALSE;
}
- ret = tdm_layer_get_zpos(video->layer->tdm_layer, &zpos);
- if (ret == TDM_ERROR_NONE)
- video->e_plane = e_output_plane_get_by_zpos(video->e_output, zpos);
-
- if (!video->e_plane)
- {
- VWR("fail get e_plane");
- _e_video_layer_destroy(video->layer);
- video->layer = NULL;
- return EINA_FALSE;
- }
- if (!e_plane_video_set(video->e_plane, EINA_TRUE, &video->waiting_video_set))
- {
- VWR("fail set video to e_plane");
- _e_video_layer_destroy(video->layer);
- video->layer = NULL;
- video->e_plane = NULL;
- return EINA_FALSE;
- }
- if (video->waiting_video_set)
+ if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
{
- if (!video->video_set_hook)
- video->video_set_hook = e_plane_hook_add(E_PLANE_HOOK_VIDEO_SET, _e_video_video_set_hook, video);
+ ret = tdm_layer_get_zpos(video->layer->tdm_layer, &zpos);
+ if (ret == TDM_ERROR_NONE)
+ video->e_plane = e_output_plane_get_by_zpos(video->e_output, zpos);
+
+ if (!video->e_plane)
+ {
+ VWR("fail get e_plane");
+ _e_video_layer_destroy(video->layer);
+ video->layer = NULL;
+ return EINA_FALSE;
+ }
+
+ if (!e_plane_video_set(video->e_plane, EINA_TRUE, &video->waiting_video_set))
+ {
+ VWR("fail set video to e_plane");
+ _e_video_layer_destroy(video->layer);
+ video->layer = NULL;
+ video->e_plane = NULL;
+ return EINA_FALSE;
+ }
+ if (video->waiting_video_set)
+ {
+ if (!video->video_set_hook)
+ video->video_set_hook = e_plane_hook_add(E_PLANE_HOOK_VIDEO_SET, _e_video_video_set_hook, video);
+ }
}
VIN("assign layer: %p", video->layer);
VDB("current_fb(%d)", MSTAMP(video->current_fb));
}
+EINTERN void
+e_comp_wl_video_hwc_window_commit_data_release(E_Hwc_Window *hwc_window, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec)
+{
+ E_Client *ec = NULL;
+ E_Video *video = NULL;
+ Eina_List *l = NULL;
+ E_Video_Layer *video_layer;
+
+ EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+ ec = hwc_window->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ EINA_LIST_FOREACH(video_list, l, video)
+ if (video->ec == ec) break;
+ EINA_SAFETY_ON_NULL_RETURN(video);
+
+ video_layer = video->layer;
+ EINA_SAFETY_ON_NULL_RETURN(video_layer);
+
+ _e_video_commit_handler(NULL, sequence, tv_sec, tv_usec, video);
+}
+
+EINTERN tbm_surface_h
+e_comp_wl_video_hwc_widow_surface_get(E_Hwc_Window *hwc_window)
+{
+ E_Client *ec = NULL;
+ Eina_List *l = NULL;
+ E_Video *video = NULL;
+ E_Video_Layer *video_layer;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
+
+ if (!e_hwc_window_is_video(hwc_window))
+ {
+ ERR("ehw:%p is NOT Video HWC window.", hwc_window);
+ return NULL;
+ }
+
+ ec = hwc_window->ec;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
+
+ EINA_LIST_FOREACH(video_list, l, video)
+ if (video->ec == ec) break;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(video, NULL);
+
+ video_layer = video->layer;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(video_layer, NULL);
+
+ return video_layer->cur_tsurface;
+}
+
+EINTERN Eina_Bool
+e_comp_wl_video_hwc_window_info_get(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info)
+{
+ E_Client *ec = NULL;
+ Eina_List *l = NULL;
+ E_Video *video = NULL;
+ E_Video_Layer *video_layer;
+ E_Video_Info_Layer *vinfo;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (!e_hwc_window_is_video(hwc_window))
+ {
+ ERR("ehw:%p is NOT Video HWC window.", hwc_window);
+ return EINA_FALSE;
+ }
+
+ ec = hwc_window->ec;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ EINA_LIST_FOREACH(video_list, l, video)
+ if (video->ec == ec) break;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(video,EINA_FALSE);
+
+ video_layer = video->layer;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(video_layer, EINA_FALSE);
+
+ vinfo = &video_layer->info;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(vinfo, EINA_FALSE);
+
+ memcpy(&hwc_win_info->src_config, &vinfo->src_config, sizeof(tdm_info_config));
+ memcpy(&hwc_win_info->dst_pos, &vinfo->dst_pos, sizeof(tdm_pos));
+ hwc_win_info->transform = vinfo->transform;
+
+ return EINA_TRUE;
+}
+
static void
_e_video_vblank_handler(tdm_output *output, unsigned int sequence,
unsigned int tv_sec, unsigned int tv_usec,
if (e_object_is_del(E_OBJECT(video->ec))) return;
+ if (!video->ec->comp_data->video_client)
+ return;
+
if (video->need_force_render)
{
VIN("video forcely rendering..");
if (e_object_is_del(E_OBJECT(video->ec))) return;
+ if (!video->ec->comp_data->video_client)
+ return;
+
/* if stand_alone is true, not hide */
if (video->ec->comp_data->sub.data && video->ec->comp_data->sub.data->stand_alone)
{
EINA_SAFETY_ON_NULL_RETURN(video->output);
}
- if (_e_video_tdm_output_has_video_layer(video->output))
+ if (video_to_primary)
+ {
+ VIN("show video to primary layer");
+ ec->comp_data->video_client = 0;
+ ec->animatable = 0;
+ }
+ else if (_e_video_tdm_output_has_video_layer(video->output))
{
/* If tdm offers video layers, we will assign a tdm layer when showing */
VIN("video client");
}
}
- if (video_to_primary)
- {
- VIN("show video to primary layer");
- ec->comp_data->video_client = 0;
- ec->animatable = 0;
- }
-
tdm_output_get_available_size(video->output, &ominw, &ominh, &omaxw, &omaxh, &video->output_align);
tdm_display_get_capabilities(e_comp->e_comp_screen->tdisplay, &disp_capabilities);
const tbm_format *formats;
Eina_Bool found = EINA_FALSE;
tdm_layer_capability capabilities = 0;
- tdm_layer *layer = _e_video_tdm_video_layer_get(video->output);
+ tdm_error error;
- tdm_layer_get_capabilities(layer, &capabilities);
+ if (e_output_hwc_policy_get(video->e_output->output_hwc) != E_OUTPUT_HWC_POLICY_WINDOWS)
+ {
+ tdm_layer *layer = _e_video_tdm_video_layer_get(video->output);
- /* don't need pp if a layer has TDM_LAYER_CAPABILITY_VIDEO capability*/
- if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
- return EINA_FALSE;
+ tdm_layer_get_capabilities(layer, &capabilities);
- /* check formats */
- tdm_layer_get_available_formats(layer, &formats, &count);
- for (i = 0; i < count; i++)
- if (formats[i] == video->tbmfmt)
- {
- found = EINA_TRUE;
- break;
- }
+ /* don't need pp if a layer has TDM_LAYER_CAPABILITY_VIDEO capability*/
+ if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+ return EINA_FALSE;
+
+ /* check formats */
+ tdm_layer_get_available_formats(layer, &formats, &count);
+ for (i = 0; i < count; i++)
+ if (formats[i] == video->tbmfmt)
+ {
+ found = EINA_TRUE;
+ break;
+ }
+
+ if (!found)
+ {
+ if (formats && count > 0)
+ video->pp_tbmfmt = formats[0];
+ else
+ {
+ WRN("No layer format information!!!");
+ video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+ }
+ return EINA_TRUE;
+ }
+
+ /* check size */
+ if (capabilities & TDM_LAYER_CAPABILITY_SCANOUT)
+ goto need_pp;
+
+ if (video->geo.input_r.w != video->geo.output_r.w || video->geo.input_r.h != video->geo.output_r.h)
+ if (!(capabilities & TDM_LAYER_CAPABILITY_SCALE))
+ goto need_pp;
- if (!found)
+ /* check rotate */
+ if (video->geo.transform || e_comp->e_comp_screen->rotation > 0)
+ if (!(capabilities & TDM_LAYER_CAPABILITY_TRANSFORM))
+ goto need_pp;
+ }
+ else
{
- if (formats && count > 0)
- video->pp_tbmfmt = formats[0];
- else
+ E_Hwc_Window *hwc_window = video->ec->hwc_window;
+ tdm_hwc_window_video_capability capabilities = 0;
+
+ error = tdm_output_hwc_get_video_supported_formats(video->output, &formats, &count);
+ if (error != TDM_ERROR_NONE)
{
- WRN("No layer format information!!!");
video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+ return EINA_TRUE;
}
- return EINA_TRUE;
- }
+ for (i = 0; i < count; i++)
+ if (formats[i] == video->tbmfmt)
+ {
+ found = EINA_TRUE;
+ break;
+ }
- /* check size */
- if (capabilities & TDM_LAYER_CAPABILITY_SCANOUT)
- goto need_pp;
+ if (!found)
+ {
+ video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+ return EINA_TRUE;
+ }
- if (video->geo.input_r.w != video->geo.output_r.w || video->geo.input_r.h != video->geo.output_r.h)
- if (!(capabilities & TDM_LAYER_CAPABILITY_SCALE))
- goto need_pp;
+ error = tdm_hwc_window_video_get_capability(hwc_window->thwc_window, &capabilities);
+ if (error != TDM_ERROR_NONE)
+ {
+ video->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+ return EINA_TRUE;
+ }
- /* check rotate */
- if (video->geo.transform || e_comp->e_comp_screen->rotation > 0)
- if (!(capabilities & TDM_LAYER_CAPABILITY_TRANSFORM))
- goto need_pp;
+ /* check size */
+ if (capabilities & TDM_HWC_WINDOW_VIDEO_CAPABILITY_SCANOUT)
+ goto need_pp;
+
+ if (video->geo.input_r.w != video->geo.output_r.w || video->geo.input_r.h != video->geo.output_r.h)
+ if (!(capabilities & TDM_HWC_WINDOW_VIDEO_CAPABILITY_SCALE))
+ goto need_pp;
+
+ /* check rotate */
+ if (video->geo.transform || e_comp->e_comp_screen->rotation > 0)
+ if (!(capabilities & TDM_HWC_WINDOW_VIDEO_CAPABILITY_TRANSFORM))
+ goto need_pp;
+ }
return EINA_FALSE;
EINTERN tdm_layer* e_comp_wl_video_layer_get(tdm_output *output);
+EINTERN void e_comp_wl_video_hwc_window_commit_data_release(E_Hwc_Window *hwc_window, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec);
+EINTERN tbm_surface_h e_comp_wl_video_hwc_widow_surface_get(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_comp_wl_video_hwc_window_info_get(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info);
+
#define C(b,m) (((b) >> (m)) & 0xFF)
#define FOURCC_STR(id) C(id,0), C(id,8), C(id,16), C(id,24)
#define IS_RGB(f) ((f) == TBM_FORMAT_XRGB8888 || (f) == TBM_FORMAT_ARGB8888)
--- /dev/null
+#include "e.h"
+
+# include <Evas_Engine_GL_Drm.h>
+# include <Evas_Engine_GL_Tbm.h>
+# include <Evas_Engine_Software_Tbm.h>
+# include <sys/eventfd.h>
+# include <gbm/gbm_tbm.h>
+# include <pixman.h>
+
+static E_Client_Hook *client_hook_new = NULL;
+static E_Client_Hook *client_hook_del = NULL;
+static Ecore_Event_Handler *zone_set_event_handler = NULL;
+static uint64_t ee_rendered_hw_list_key;
+
+static E_Comp_Wl_Buffer *
+_e_hwc_window_comp_wl_buffer_get(E_Hwc_Window *hwc_window)
+{
+ E_Client *ec = hwc_window->ec;
+ E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
+ E_Comp_Wl_Buffer_Ref *buffer_ref;
+
+ if (!cdata) return NULL;
+
+ buffer_ref = &cdata->buffer_ref;
+
+ return buffer_ref->buffer;
+}
+
+struct wayland_tbm_client_queue *
+_get_wayland_tbm_client_queue(E_Client *ec)
+{
+ struct wayland_tbm_client_queue * cqueue = NULL;
+ struct wl_resource *wl_surface = NULL;
+ E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+ E_Comp_Wl_Client_Data *cdata = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(wl_comp_data, NULL);
+
+ cdata = (E_Comp_Wl_Client_Data *)e_pixmap_cdata_get(ec->pixmap);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, NULL);
+
+ wl_surface = cdata->wl_surface;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(wl_surface, NULL);
+
+ cqueue = wayland_tbm_server_client_queue_get(wl_comp_data->tbm.server, wl_surface);
+ if (!cqueue)
+ {
+ ELOGF("HWC-WINS", " ehw:%p has no wl_tbm_server_client_queue. -- {%25s}, state:%s, zpos:%d, deleted:%s",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title,
+ e_hwc_window_state_string_get(ec->hwc_window->state),
+ ec->hwc_window->zpos, ec->hwc_window->is_deleted ? "yes" : "no");
+ }
+ EINA_SAFETY_ON_NULL_RETURN_VAL(cqueue, NULL);
+
+ return cqueue;
+}
+
+static tbm_surface_queue_h
+_get_tbm_surface_queue()
+{
+ return e_comp->e_comp_screen->tqueue;
+}
+
+static tdm_hwc_window_composition
+_get_composition_type(E_Hwc_Window_State state)
+{
+ tdm_hwc_window_composition composition_type = TDM_COMPOSITION_NONE;
+
+ switch (state)
+ {
+ case E_HWC_WINDOW_STATE_NONE:
+ composition_type = TDM_COMPOSITION_NONE;
+ break;
+ case E_HWC_WINDOW_STATE_CLIENT:
+ composition_type = TDM_COMPOSITION_CLIENT;
+ break;
+ case E_HWC_WINDOW_STATE_DEVICE:
+ composition_type = TDM_COMPOSITION_DEVICE;
+ break;
+ case E_HWC_WINDOW_STATE_DEVICE_CANDIDATE:
+ composition_type = TDM_COMPOSITION_DEVICE_CANDIDATE;
+ break;
+ case E_HWC_WINDOW_STATE_CURSOR:
+ composition_type = TDM_COMPOSITION_CURSOR;
+ break;
+ case E_HWC_WINDOW_STATE_VIDEO:
+ composition_type = TDM_COMPOSITION_VIDEO;
+ break;
+ default:
+ composition_type = TDM_COMPOSITION_NONE;
+ ERR("hwc-opt: unknown state of hwc_window.");
+ }
+
+ return composition_type;
+}
+
+static unsigned int
+_get_aligned_width(tbm_surface_h tsurface)
+{
+ unsigned int aligned_width = 0;
+ tbm_surface_info_s surf_info;
+
+ tbm_surface_get_info(tsurface, &surf_info);
+
+ switch (surf_info.format)
+ {
+ case TBM_FORMAT_YUV420:
+ case TBM_FORMAT_YVU420:
+ case TBM_FORMAT_YUV422:
+ case TBM_FORMAT_YVU422:
+ case TBM_FORMAT_NV12:
+ case TBM_FORMAT_NV21:
+ aligned_width = surf_info.planes[0].stride;
+ break;
+ case TBM_FORMAT_YUYV:
+ case TBM_FORMAT_UYVY:
+ aligned_width = surf_info.planes[0].stride >> 1;
+ break;
+ case TBM_FORMAT_ARGB8888:
+ case TBM_FORMAT_XRGB8888:
+ aligned_width = surf_info.planes[0].stride >> 2;
+ break;
+ default:
+ ERR("not supported format: %x", surf_info.format);
+ }
+
+ return aligned_width;
+}
+
+static tbm_surface_h
+_e_hwc_window_target_window_surface_acquire(E_Hwc_Window_Target *target_hwc_window)
+{
+ tbm_surface_queue_h queue = NULL;
+ tbm_surface_h surface = NULL;
+ tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, NULL);
+
+ queue = target_hwc_window->queue;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(queue, NULL);
+
+ if (tbm_surface_queue_can_acquire(queue, 0))
+ {
+ tsq_err = tbm_surface_queue_acquire(queue, &surface);
+
+ if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
+ {
+ ERR("Failed to acquire tbm_surface from tbm_surface_queue(%p): tsq_err = %d", queue, tsq_err);
+ return NULL;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ return surface;
+}
+
+static void
+_e_hwc_window_target_window_surface_release(E_Hwc_Window_Target *target_hwc_window, tbm_surface_h tsurface)
+{
+ tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+ tbm_surface_queue_h tqueue = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
+ EINA_SAFETY_ON_NULL_RETURN(tsurface);
+
+ tqueue = target_hwc_window->queue;
+ EINA_SAFETY_ON_NULL_RETURN(tqueue);
+
+ tsq_err = tbm_surface_queue_release(tqueue, tsurface);
+ if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
+ {
+ ERR("Failed to release tbm_surface(%p) from tbm_surface_queue(%p): tsq_err = %d", tsurface, tqueue, tsq_err);
+ return;
+ }
+}
+
+static void
+_e_hwc_window_target_window_surface_data_free(void *data)
+{
+ Eina_List *ee_rendered_hw_list = (Eina_List *)data;
+
+ eina_list_free(ee_rendered_hw_list);
+}
+
+/* gets called as somebody modifies target_window's queue */
+static void
+_e_hwc_window_target_window_surface_queue_trace_cb(tbm_surface_queue_h surface_queue,
+ tbm_surface_h tsurface, tbm_surface_queue_trace trace, void *data)
+{
+ E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
+
+ /* gets called as evas_renderer dequeues a new buffer from the queue */
+ if (trace == TBM_SURFACE_QUEUE_TRACE_DEQUEUE)
+ {
+ ELOGF("HWC-WINS", " ehw:%p gets dequeue noti ts:%p -- {%s}.",
+ NULL, NULL, target_hwc_window, tsurface, "@TARGET WINDOW@");
+
+ tbm_surface_internal_add_user_data(tsurface, ee_rendered_hw_list_key, _e_hwc_window_target_window_surface_data_free);
+ target_hwc_window->dequeued_tsurface = tsurface;
+ }
+ /* gets called as evas_renderer enqueues a new buffer into the queue */
+ if (trace == TBM_SURFACE_QUEUE_TRACE_ENQUEUE)
+ {
+ uint64_t value = 1;
+ int ret;
+
+ ret = write(target_hwc_window->event_fd, &value, sizeof(value));
+ if (ret == -1)
+ ERR("failed to send acquirable event:%m");
+
+ ELOGF("HWC-WINS", " ehw:%p gets enqueue noti ts:%p -- {%s}.",
+ NULL, NULL, target_hwc_window, tsurface, "@TARGET WINDOW@");
+
+ tbm_surface_internal_add_user_data(tsurface, ee_rendered_hw_list_key, _e_hwc_window_target_window_surface_data_free);
+ target_hwc_window->dequeued_tsurface = tsurface;
+ }
+ /* tsurface has been released at the queue */
+ if (trace == TBM_SURFACE_QUEUE_TRACE_RELEASE)
+ {
+ tbm_surface_internal_delete_user_data(tsurface, ee_rendered_hw_list_key);
+ ELOGF("HWC-WINS", " ehw:%p gets release noti ts:%p -- {%s}.",
+ NULL, NULL, target_hwc_window, tsurface, "@TARGET WINDOW@");
+ }
+}
+
+/* gets called as evas_renderer enqueues a new buffer into the queue */
+static void
+_e_hwc_window_target_window_surface_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
+{
+ // TODO: This function to be deprecated.
+#if 0
+ E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
+ uint64_t value = 1;
+ int ret;
+
+ ret = write(target_hwc_window->event_fd, &value, sizeof(value));
+ if (ret == -1)
+ ERR("failed to send acquirable event:%m");
+#endif
+}
+
+/* gets called at the beginning of an ecore_main_loop iteration */
+static Eina_Bool
+_e_hwc_window_target_window_render_finished_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ int len;
+ int fd;
+ char buffer[64];
+
+ ELOGF("HWC-WINS", " ecore_main_loop: the new iteration.", NULL, NULL);
+
+ fd = ecore_main_fd_handler_fd_get(fd_handler);
+ len = read(fd, buffer, sizeof(buffer));
+ if (len == -1)
+ ERR("failed to read queue acquire event fd:%m");
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_e_hwc_window_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
+ Eina_List *ee_rendered_hw_list;
+
+ ELOGF("HWC-WINS", " ehw:%p gets render_flush_post noti ------ {@TARGET WINDOW@}", NULL, NULL, target_hwc_window);
+
+ /* all ecs have been composited so we can attach a list of composited e_thwc_windows to the surface
+ * which contains their ecs composited */
+
+ ee_rendered_hw_list = eina_list_clone(target_hwc_window->ee_rendered_hw_list);
+
+ tbm_surface_internal_set_user_data(target_hwc_window->dequeued_tsurface,
+ ee_rendered_hw_list_key, ee_rendered_hw_list);
+
+ eina_list_free(target_hwc_window->ee_rendered_hw_list);
+ target_hwc_window->ee_rendered_hw_list = NULL;
+ target_hwc_window->dequeued_tsurface = NULL;
+}
+
+static E_Hwc_Window_Target *
+_e_hwc_window_target_new(E_Output_Hwc *output_hwc)
+{
+ const char *name = NULL;
+ E_Hwc_Window_Target *target_hwc_window = NULL;
+
+ name = ecore_evas_engine_name_get(e_comp->ee);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
+
+ if (!strcmp("gl_drm", name))
+ {
+ Evas_Engine_Info_GL_Drm *einfo = NULL;
+ /* get the evas_engine_gl_drm information */
+ einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(e_comp->evas);
+ if (!einfo)
+ {
+ ERR("fail to get the GL_Drm einfo.");
+ goto fail;
+ }
+ /* enable hwc to evas engine gl_drm */
+ einfo->info.hwc_enable = EINA_TRUE;
+ ecore_evas_manual_render_set(e_comp->ee, 1);
+ }
+ else if(!strcmp("gl_drm_tbm", name))
+ {
+ ecore_evas_manual_render_set(e_comp->ee, 1);
+ }
+ else if(!strcmp("drm_tbm", name))
+ {
+ ecore_evas_manual_render_set(e_comp->ee, 1);
+ }
+ else if(!strcmp("gl_tbm", name))
+ {
+ ecore_evas_manual_render_set(e_comp->ee, 1);
+ }
+ else if(!strcmp("software_tbm", name))
+ {
+ ecore_evas_manual_render_set(e_comp->ee, 1);
+ }
+
+ target_hwc_window = E_NEW(E_Hwc_Window_Target, 1);
+ EINA_SAFETY_ON_NULL_GOTO(target_hwc_window, fail);
+
+ ((E_Hwc_Window *)target_hwc_window)->is_target = EINA_TRUE;
+ ((E_Hwc_Window *)target_hwc_window)->state = E_HWC_WINDOW_STATE_DEVICE;
+ ((E_Hwc_Window *)target_hwc_window)->output_hwc = output_hwc;
+
+ target_hwc_window->ee = e_comp->ee;
+ target_hwc_window->evas = ecore_evas_get(target_hwc_window->ee);
+ target_hwc_window->event_fd = eventfd(0, EFD_NONBLOCK);
+ target_hwc_window->event_hdlr =
+ ecore_main_fd_handler_add(target_hwc_window->event_fd, ECORE_FD_READ,
+ _e_hwc_window_target_window_render_finished_cb,
+ (void *)target_hwc_window, NULL, NULL);
+
+ ecore_evas_manual_render(target_hwc_window->ee);
+
+ target_hwc_window->queue = _get_tbm_surface_queue();
+
+ /* as evas_renderer has finished its work (to provide a composited buffer) it enqueues
+ * the result buffer into this queue and acquirable cb gets called; this cb does nothing
+ * except the writing into the event_fd object, this writing causes the new ecore_main loop
+ * iteration to be triggered ('cause we've registered ecore_main fd handler to check this writing);
+ * so it's just a way to inform E20's HWC that evas_renderer has done its work */
+ tbm_surface_queue_add_acquirable_cb(target_hwc_window->queue, _e_hwc_window_target_window_surface_queue_acquirable_cb, (void *)target_hwc_window);
+
+ /* TODO: we can use this call instead of an add_acquirable_cb and an add_dequeue_cb calls. */
+ tbm_surface_queue_add_trace_cb(target_hwc_window->queue, _e_hwc_window_target_window_surface_queue_trace_cb, (void *)target_hwc_window);
+
+ evas_event_callback_add(e_comp->evas, EVAS_CALLBACK_RENDER_FLUSH_POST, _e_hwc_window_target_window_render_flush_post_cb, target_hwc_window);
+
+ /* sorry..., current version of gcc requires an initializer to be evaluated at compile time */
+ ee_rendered_hw_list_key = (uintptr_t)&ee_rendered_hw_list_key;
+
+ return target_hwc_window;
+
+fail:
+ ecore_evas_manual_render_set(e_comp->ee, 0);
+
+ return NULL;
+}
+
+static E_Hwc_Window_Target *
+_e_hwc_window_target_window_get(E_Hwc_Window *hwc_window)
+{
+ E_Hwc_Window_Target *target_hwc_window;
+ E_Output_Hwc *output_hwc;
+
+ output_hwc = hwc_window->output_hwc;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+
+ target_hwc_window = output_hwc->target_hwc_window;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, NULL);
+
+ return target_hwc_window;
+}
+
+static Eina_Bool
+_e_hwc_window_target_window_clear(E_Hwc_Window_Target *target_hwc_window)
+{
+ tbm_surface_queue_h tqueue = NULL;
+ tbm_surface_h tsurface = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+ tqueue = target_hwc_window->queue;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, EINA_FALSE);
+
+ while ((tsurface = _e_hwc_window_target_window_surface_acquire(target_hwc_window)))
+ _e_hwc_window_target_window_surface_release(target_hwc_window, tsurface);
+
+ return EINA_TRUE;
+}
+
+static void
+_e_hwc_window_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
+{
+ E_Output *output;
+ E_Hwc_Window *hwc_window;
+ E_Zone *zone;
+
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ zone = ec->zone;
+ if (!zone)
+ {
+ ELOGF("HWC-WINS", "Try to create hwc_window, but it couldn't.(no zone)", ec->pixmap, ec);
+ return;
+ }
+
+ EINA_SAFETY_ON_NULL_RETURN(zone->output_id);
+
+ output = e_output_find(zone->output_id);
+ EINA_SAFETY_ON_NULL_RETURN(output);
+
+ /* If an e_client belongs to the e_output managed by hwc_plane policy,
+ * there's no need to deal with hwc_windows. */
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+ return;
+
+ hwc_window = e_hwc_window_new(output->output_hwc, ec, E_HWC_WINDOW_STATE_NONE);
+ EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+ /* set the hwc window to the e client */
+ ec->hwc_window = hwc_window;
+
+ return;
+}
+
+static void
+_e_hwc_window_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
+{
+ E_Output *output;
+ E_Zone *zone;
+
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ zone = ec->zone;
+ EINA_SAFETY_ON_NULL_RETURN(zone);
+ EINA_SAFETY_ON_NULL_RETURN(zone->output_id);
+
+ output = e_output_find(zone->output_id);
+ EINA_SAFETY_ON_NULL_RETURN(output);
+
+ /* If an e_client belongs to the e_output managed by hwc_plane policy,
+ * there's no need to deal with hwc_windows. */
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+ return;
+
+ if (!ec->hwc_window) return;
+
+ e_hwc_window_free(ec->hwc_window);
+ ec->hwc_window = NULL;
+}
+
+static Eina_Bool
+_e_hwc_window_client_cb_zone_set(void *data, int type, void *event)
+{
+ E_Event_Client *ev;
+ E_Client *ec;
+ E_Zone *zone;
+ E_Output *output;
+ E_Hwc_Window *hwc_window = NULL;
+
+ ev = event;
+ EINA_SAFETY_ON_NULL_GOTO(ev, end);
+
+ ec = ev->ec;
+ EINA_SAFETY_ON_NULL_GOTO(ec, end);
+
+ zone = ec->zone;
+ EINA_SAFETY_ON_NULL_GOTO(zone, end);
+ EINA_SAFETY_ON_NULL_GOTO(zone->output_id, end);
+
+ output = e_output_find(zone->output_id);
+ EINA_SAFETY_ON_NULL_GOTO(output, end);
+
+ /* If an e_client belongs to the e_output managed by hwc_plane policy,
+ * there's no need to deal with hwc_windows. */
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+ return ECORE_CALLBACK_PASS_ON;
+
+ if (ec->hwc_window)
+ {
+ /* we manage the video window in the video module */
+ if (e_hwc_window_is_video(ec->hwc_window)) goto end;
+ if (ec->hwc_window->output_hwc == output->output_hwc) goto end;
+
+ e_hwc_window_free(ec->hwc_window);
+ ec->hwc_window = NULL;
+ }
+
+ hwc_window = e_hwc_window_new(output->output_hwc, ec, E_HWC_WINDOW_STATE_NONE);
+ EINA_SAFETY_ON_NULL_GOTO(hwc_window, end);
+
+ /* set the hwc window to the e client */
+ ec->hwc_window = hwc_window;
+
+ ELOGF("HWC-WINS", "ehw:%p is set on eout:%p, zone_id:%d.",
+ hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, output, zone->id);
+
+end:
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static tbm_surface_h
+_e_hwc_window_client_surface_acquire(E_Hwc_Window *hwc_window)
+{
+ E_Comp_Wl_Buffer *buffer = _e_hwc_window_comp_wl_buffer_get(hwc_window);
+ E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
+ tbm_surface_h tsurface = NULL;
+
+ if (!buffer)
+ {
+ ELOGF("HWC-WINS", "[soolim] ehw:%p E_Comp_Wl_Buffer is null.",
+ hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec,
+ hwc_window);
+ return NULL;
+ }
+
+ tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
+ if (!tsurface)
+ {
+ ERR("fail to wayland_tbm_server_get_surface");
+ return NULL;
+ }
+
+ return tsurface;
+}
+
+
+static void
+_e_hwc_window_client_recover(E_Hwc_Window *hwc_window)
+{
+ E_Client *ec = hwc_window->ec;
+ E_Comp_Wl_Client_Data *cdata = NULL;
+ E_Comp_Wl_Buffer *buffer = NULL;
+ tbm_surface_h tsurface =NULL;
+
+ if (!ec) return;
+
+ cdata = ec->comp_data;
+ if (!cdata) return;
+
+ buffer = cdata->buffer_ref.buffer;
+
+ if (!buffer)
+ {
+ tsurface = e_hwc_window_displaying_surface_get(hwc_window);
+ if (!tsurface) return;
+
+ tbm_surface_internal_ref(tsurface);
+ buffer = e_comp_wl_tbm_buffer_get(tsurface);
+ if (!buffer)
+ {
+ tbm_surface_internal_unref(tsurface);
+ return;
+ }
+ }
+
+ /* force update */
+ e_pixmap_resource_set(ec->pixmap, buffer);
+ e_pixmap_dirty(ec->pixmap);
+ e_pixmap_refresh(ec->pixmap);
+
+ 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);
+
+ return;
+}
+
+static void
+_e_hwc_window_cursor_image_draw(E_Comp_Wl_Buffer *buffer, tbm_surface_info_s *tsurface_info, int rotation)
+{
+ int src_width, src_height, src_stride;
+ pixman_image_t *src_img = NULL, *dst_img = NULL;
+ pixman_transform_t t;
+ struct pixman_f_transform ft;
+ void *src_ptr = NULL, *dst_ptr = NULL;
+ int c = 0, s = 0, tx = 0, ty = 0;
+ int i, rotate;
+
+ src_width = wl_shm_buffer_get_width(buffer->shm_buffer);
+ src_height = wl_shm_buffer_get_height(buffer->shm_buffer);
+ src_stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
+ src_ptr = wl_shm_buffer_get_data(buffer->shm_buffer);
+
+ dst_ptr = tsurface_info->planes[0].ptr;
+ memset(dst_ptr, 0, tsurface_info->planes[0].stride * tsurface_info->height);
+
+ if (rotation)
+ {
+ src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, src_width, src_height, (uint32_t*)src_ptr, src_stride);
+ EINA_SAFETY_ON_NULL_GOTO(src_img, error);
+
+ dst_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, tsurface_info->width, tsurface_info->height,
+ (uint32_t*)dst_ptr, tsurface_info->planes[0].stride);
+ EINA_SAFETY_ON_NULL_GOTO(dst_img, error);
+
+ if (rotation == 90)
+ rotation = 270;
+ else if (rotation == 270)
+ rotation = 90;
+
+ rotate = (rotation + 360) / 90 % 4;
+ switch (rotate)
+ {
+ case 1:
+ c = 0, s = -1, tx = -tsurface_info->width;
+ break;
+ case 2:
+ c = -1, s = 0, tx = -tsurface_info->width, ty = -tsurface_info->height;
+ break;
+ case 3:
+ c = 0, s = 1, ty = -tsurface_info->width;
+ break;
+ }
+
+ pixman_f_transform_init_identity(&ft);
+ pixman_f_transform_translate(&ft, NULL, tx, ty);
+ pixman_f_transform_rotate(&ft, NULL, c, s);
+
+ pixman_transform_from_pixman_f_transform(&t, &ft);
+ pixman_image_set_transform(src_img, &t);
+
+ pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0,
+ tsurface_info->width, tsurface_info->height);
+ }
+ else
+ {
+ for (i = 0 ; i < src_height ; i++)
+ {
+ memcpy(dst_ptr, src_ptr, src_stride);
+ dst_ptr += tsurface_info->planes[0].stride;
+ src_ptr += src_stride;
+ }
+ }
+
+error:
+ if (src_img) pixman_image_unref(src_img);
+ if (dst_img) pixman_image_unref(dst_img);
+}
+
+static Eina_Bool
+_e_hwc_window_cursor_surface_refresh(E_Hwc_Window *hwc_window, E_Pointer *pointer)
+{
+ E_Output_Hwc *output_hwc = NULL;
+ E_Output *output = NULL;
+ int w, h, tw, th;
+ int tsurface_w, tsurface_h;
+ void *src_ptr = NULL;
+ tbm_surface_h tsurface = NULL;
+ E_Comp_Wl_Buffer *buffer = NULL;
+ tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE;
+ tbm_surface_info_s tsurface_info;
+ E_Client *ec;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ ec = hwc_window->ec;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ output_hwc = hwc_window->output_hwc;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+ output = output_hwc->output;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+ buffer = ec->comp_data->buffer_ref.buffer;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, EINA_FALSE);
+
+ if ((hwc_window->display_info.buffer_ref.buffer == buffer) &&
+ (hwc_window->cursor_tsurface) &&
+ (hwc_window->cursor_rotation == pointer->rotation))
+ return EINA_TRUE;
+
+ /* TODO: TBM TYPE, NATIVE_WL */
+ if (buffer->type == E_COMP_WL_BUFFER_TYPE_SHM)
+ {
+ src_ptr = wl_shm_buffer_get_data(buffer->shm_buffer);
+ if (!src_ptr)
+ {
+ ERR("Failed get data shm buffer");
+ return EINA_FALSE;
+ }
+ }
+ else
+ {
+ ERR("unkown buffer type:%d", ec->comp_data->buffer_ref.buffer->type);
+ return EINA_FALSE;
+ }
+
+ if (pointer->rotation == 90)
+ tw = ec->h, th = ec->w;
+ else if (pointer->rotation == 180)
+ tw = ec->w, th = ec->h;
+ else if (pointer->rotation == 270)
+ tw = ec->h, th = ec->w;
+ else
+ tw = ec->w, th = ec->h;
+
+ hwc_window->cursor_rotation = pointer->rotation;
+
+ w = (output->cursor_available.min_w > tw) ? output->cursor_available.min_w : tw;
+ h = (output->cursor_available.min_h > th) ? output->cursor_available.min_h : th;
+
+ if (e_comp->hwc_reuse_cursor_buffer)
+ {
+ if (hwc_window->cursor_tsurface)
+ {
+ tsurface_w = tbm_surface_get_width(hwc_window->cursor_tsurface);
+ tsurface_h = tbm_surface_get_height(hwc_window->cursor_tsurface);
+
+ if (w != tsurface_w || h != tsurface_h)
+ {
+ tbm_surface_destroy(hwc_window->cursor_tsurface);
+ hwc_window->cursor_tsurface = NULL;
+ }
+ }
+ }
+ else
+ {
+ if (hwc_window->cursor_tsurface)
+ {
+ tbm_surface_destroy(hwc_window->cursor_tsurface);
+ hwc_window->cursor_tsurface = NULL;
+ }
+ }
+
+ if (!hwc_window->cursor_tsurface)
+ {
+ /* Which tbm flags should be used? */
+ tsurface = tbm_surface_internal_create_with_flags(w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+ if (!tsurface) return EINA_FALSE;
+ }
+ else
+ {
+ tsurface = hwc_window->cursor_tsurface;
+ }
+
+ ret = tbm_surface_map(tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info);
+ if (ret != TBM_SURFACE_ERROR_NONE)
+ {
+ ERR("Failed to map tsurface");
+ tbm_surface_destroy(tsurface);
+ return EINA_FALSE;
+ }
+
+ _e_hwc_window_cursor_image_draw(buffer, &tsurface_info, pointer->rotation);
+
+ tbm_surface_unmap(tsurface);
+
+ hwc_window->cursor_tsurface = tsurface;
+
+ /* to set the hwc_window_cursor_tsurface to the hwc_window->tsurface */
+ e_comp_object_hwc_update_set(ec->frame, EINA_TRUE);
+
+ return EINA_TRUE;
+}
+
+static tbm_surface_h
+_e_hwc_window_cursor_surface_acquire(E_Hwc_Window *hwc_window)
+{
+ tbm_surface_h tsurface = NULL;
+ E_Client *ec = hwc_window->ec;
+ E_Comp_Wl_Buffer *buffer = NULL;
+ E_Pointer *pointer = NULL;
+
+ pointer = e_pointer_get(ec);
+ if (!pointer)
+ {
+ ELOGF("HWC-WINS", "[soolim] ehw:%p Pointer is null.(Cursor)",
+ hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec,
+ hwc_window);
+ return NULL;
+ }
+
+ buffer = ec->comp_data->buffer_ref.buffer;
+ if (!buffer)
+ {
+ ELOGF("HWC-WINS", "[soolim] ehw:%p E_Comp_Wl_Buffer is null.(Cursor)",
+ hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec,
+ hwc_window);
+ return NULL;
+ }
+#if 1
+ if (hwc_window->cursor_tsurface) return hwc_window->cursor_tsurface;
+#else
+ /* return the exist tsurface when there is no update on cursor image(pointer image) */
+ if (!e_comp_object_hwc_update_exists(ec->frame) && hwc_window->tsurface)
+ return hwc_window->tsurface;
+#endif
+
+ //e_comp_object_hwc_update_set(ec->frame, EINA_FALSE);
+
+ if (!_e_hwc_window_cursor_surface_refresh(hwc_window, pointer))
+ {
+ ERR("Failed to _e_hwc_window_cursor_surface_refresh");
+ return NULL;
+ }
+
+ tsurface = hwc_window->cursor_tsurface;
+
+ return tsurface;
+}
+
+static Eina_Bool
+_e_hwc_window_info_set(E_Hwc_Window *hwc_window, tbm_surface_h tsurface)
+{
+ E_Output_Hwc *output_hwc = hwc_window->output_hwc;
+ E_Output *output = output_hwc->output;
+ E_Client *ec = hwc_window->ec;
+ tbm_surface_info_s surf_info;
+ int size_w, size_h, src_x, src_y, src_w, src_h;
+ int dst_x, dst_y, dst_w, dst_h;
+ tbm_format format;
+ tdm_hwc_window_info hwc_win_info = {0};
+ tdm_error error;
+
+ if (e_hwc_window_is_video(hwc_window))
+ {
+ if (!e_comp_wl_video_hwc_window_info_get(hwc_window, &hwc_win_info))
+ {
+ ERR("Video window does not get the hwc_win_info.");
+ return EINA_FALSE;
+ }
+
+ error = tdm_hwc_window_set_info(hwc_window->thwc_window, &hwc_win_info);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+
+ return EINA_TRUE;
+ }
+
+ /* set hwc_window when the layer infomation is different from the previous one */
+ tbm_surface_get_info(tsurface, &surf_info);
+
+ format = surf_info.format;
+
+ size_w = _get_aligned_width(tsurface);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(size_w == 0, EINA_FALSE);
+
+ size_h = surf_info.height;
+
+ src_x = 0;
+ src_y = 0;
+ src_w = surf_info.width;
+ src_h = surf_info.height;
+
+ if (e_hwc_window_is_cursor(hwc_window))
+ {
+ E_Pointer *pointer = e_pointer_get(ec);
+ if (!pointer)
+ {
+ ERR("ec doesn't have E_Pointer");
+ return EINA_FALSE;
+ }
+
+ dst_x = pointer->x - pointer->hot.x;
+ dst_y = pointer->y - pointer->hot.y;
+ }
+ else
+ {
+ dst_x = ec->x;
+ dst_y = ec->y;
+ }
+
+ /* if output is transformed, the position of a buffer on screen should be also
+ * transformed.
+ */
+ if (output->config.rotation > 0)
+ {
+ int bw, bh;
+ e_pixmap_size_get(ec->pixmap, &bw, &bh);
+ e_comp_wl_rect_convert(ec->zone->w, ec->zone->h,
+ output->config.rotation / 90, 1,
+ dst_x, dst_y, bw, bh,
+ &dst_x, &dst_y, NULL, NULL);
+ }
+
+ dst_w = surf_info.width;
+ dst_h = surf_info.height;
+
+ if (hwc_window->info.src_config.size.h != size_w ||
+ hwc_window->info.src_config.size.v != size_h ||
+ hwc_window->info.src_config.pos.x != src_x ||
+ hwc_window->info.src_config.pos.y != src_y ||
+ hwc_window->info.src_config.pos.w != src_w ||
+ hwc_window->info.src_config.pos.h != src_h ||
+ hwc_window->info.src_config.format != format ||
+ hwc_window->info.dst_pos.x != dst_x ||
+ hwc_window->info.dst_pos.y != dst_y ||
+ hwc_window->info.dst_pos.w != dst_w ||
+ hwc_window->info.dst_pos.h != dst_h)
+ {
+ tdm_error error;
+
+ /* change the information at plane->info */
+ hwc_window->info.src_config.size.h = size_w;
+ hwc_window->info.src_config.size.v = size_h;
+ hwc_window->info.src_config.pos.x = src_x;
+ hwc_window->info.src_config.pos.y = src_y;
+ hwc_window->info.src_config.pos.w = src_w;
+ hwc_window->info.src_config.pos.h = src_h;
+ hwc_window->info.dst_pos.x = dst_x;
+ hwc_window->info.dst_pos.y = dst_y;
+ hwc_window->info.dst_pos.w = dst_w;
+ hwc_window->info.dst_pos.h = dst_h;
+ hwc_window->info.transform = TDM_TRANSFORM_NORMAL;
+ hwc_window->info.src_config.format = format;
+
+ error = tdm_hwc_window_set_info(hwc_window->thwc_window, &hwc_window->info);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+ }
+
+ return EINA_TRUE;
+}
+
+#if 0
+static Eina_Bool
+_e_hwc_window_correct_transformation_check(E_Hwc_Window *hwc_window)
+{
+ E_Client *ec;
+ int transform;
+ E_Output_Hwc *output_hwc = hwc_window->output_hwc;
+ E_Output *output = output_hwc->output;
+
+ /* do not check the transformation of the video window */
+ if (e_hwc_window_is_video(hwc_window)) return EINA_TRUE;
+
+ ec = hwc_window->ec;
+
+ transform = e_comp_wl_output_buffer_transform_get(ec);
+
+ /* request an ec to change its transformation if it doesn't fit the transformation */
+ if ((output->config.rotation / 90) != transform)
+ {
+ if (!e_config->screen_rotation_client_ignore && hwc_window->need_change_buffer_transform)
+ {
+ hwc_window->need_change_buffer_transform = EINA_FALSE;
+
+ /* TODO: why e_comp_wl_output_init() call ins't enough? why additional
+ * tizen_screen_rotation_send_ignore_output_transform() call is needed? */
+ e_comp_screen_rotation_ignore_output_transform_send(ec, EINA_FALSE);
+
+ ELOGF("HWC-WINS", " request {%25s} to change transformation to %d.",
+ ec->pixmap, ec, ec->icccm.title, output->config.rotation);
+ }
+
+ return EINA_FALSE;
+ }
+ else
+ hwc_window->need_change_buffer_transform = EINA_TRUE;
+
+ return EINA_TRUE;
+}
+#endif
+
+EINTERN Eina_Bool
+e_hwc_window_init(E_Output_Hwc *output_hwc)
+{
+ E_Hwc_Window_Target *target_hwc_window;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+ if (e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+ return EINA_FALSE;
+
+ client_hook_new = e_client_hook_add(E_CLIENT_HOOK_NEW_CLIENT,
+ _e_hwc_window_client_cb_new, NULL);
+ if (!client_hook_new)
+ {
+ ERR("fail to add the E_CLIENT_HOOK_NEW_CLIENT hook.");
+ return EINA_FALSE;
+ }
+ client_hook_del = e_client_hook_add(E_CLIENT_HOOK_DEL,
+ _e_hwc_window_client_cb_del, NULL);
+ if (!client_hook_del)
+ {
+ ERR("fail to add the E_CLIENT_HOOK_DEL hook.");
+ return EINA_FALSE;
+ }
+
+ zone_set_event_handler =
+ ecore_event_handler_add(E_EVENT_CLIENT_ZONE_SET, _e_hwc_window_client_cb_zone_set, NULL);
+ if (!zone_set_event_handler)
+ {
+ ERR("fail to add the E_EVENT_CLIENT_ZONE_SET event handler.");
+ return EINA_FALSE;
+ }
+
+ target_hwc_window = _e_hwc_window_target_new(output_hwc);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+ /* set the target_window to the output_hwc */
+ output_hwc->target_hwc_window = target_hwc_window;
+
+ output_hwc->hwc_windows = eina_list_append(output_hwc->hwc_windows, target_hwc_window);
+
+ return EINA_TRUE;
+}
+
+// TODO:
+EINTERN void
+e_hwc_window_deinit(E_Output_Hwc *output_hwc)
+{
+ EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+ // TODO:
+}
+
+EINTERN E_Hwc_Window *
+e_hwc_window_new(E_Output_Hwc *output_hwc, E_Client *ec, E_Hwc_Window_State state)
+{
+ E_Hwc_Window *hwc_window = NULL;
+ tdm_output *toutput;
+ tdm_error error;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc->output, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
+
+ toutput = output_hwc->output->toutput;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(toutput, EINA_FALSE);
+
+ hwc_window = E_NEW(E_Hwc_Window, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
+
+ hwc_window->output_hwc = output_hwc;
+ hwc_window->ec = ec;
+ hwc_window->state = state;
+ hwc_window->need_change_buffer_transform = EINA_TRUE;
+
+ if (state == E_HWC_WINDOW_STATE_VIDEO)
+ hwc_window->thwc_window = tdm_output_hwc_create_video_window(toutput, &error);
+ else
+ hwc_window->thwc_window = tdm_output_hwc_create_window(toutput, &error);
+ if (error != TDM_ERROR_NONE)
+ {
+ ERR("cannot create tdm_hwc_window for toutput(%p)", toutput);
+ E_FREE(hwc_window);
+ return NULL;
+ }
+
+ /* cursor window */
+ if (e_policy_client_is_cursor(ec))
+ hwc_window->is_cursor = EINA_TRUE;
+
+ /* video window */
+ if (state == E_HWC_WINDOW_STATE_VIDEO)
+ hwc_window->is_video = EINA_TRUE;
+
+ output_hwc->hwc_windows = eina_list_append(output_hwc->hwc_windows, hwc_window);
+
+ ELOGF("HWC-WINS", "ehw:%p is created on eout:%p, zone_id:%d",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, output_hwc->output, ec->zone->id);
+
+ return hwc_window;
+}
+
+EINTERN void
+e_hwc_window_free(E_Hwc_Window *hwc_window)
+{
+ E_Output_Hwc *output_hwc = NULL;
+ E_Output *output = NULL;
+ tdm_output *toutput = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+ EINA_SAFETY_ON_NULL_RETURN(hwc_window->output_hwc);
+
+ output_hwc = hwc_window->output_hwc;
+ EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+ output = output_hwc->output;
+ EINA_SAFETY_ON_NULL_RETURN(output_hwc->output);
+
+ toutput = output->toutput;
+ EINA_SAFETY_ON_NULL_RETURN(toutput);
+
+ /* we cannot remove the hwc_window because we need to release the commit_data */
+ if (e_hwc_window_displaying_surface_get(hwc_window))
+ {
+ ELOGF("HWC-WINS", "ehw:%p is destroyed on eout:%p. displaying surface.",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, output_hwc->output);
+
+ /* mark as deleted and delete when commit_data will be released */
+ hwc_window->is_deleted = EINA_TRUE;
+ hwc_window->ec = NULL;
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+ return;
+ }
+ else
+ ELOGF("HWC-WINS", "ehw:%p is destroyed on eout:%p",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, output_hwc->output);
+
+ if (hwc_window->thwc_window)
+ tdm_output_hwc_destroy_window(toutput, hwc_window->thwc_window);
+
+ output_hwc->hwc_windows = eina_list_remove(output_hwc->hwc_windows, hwc_window);
+
+ free(hwc_window);
+}
+
+EINTERN Eina_Bool
+e_hwc_window_zpos_set(E_Hwc_Window *hwc_window, int zpos)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (hwc_window->zpos != zpos) hwc_window->zpos = zpos;
+
+ return EINA_TRUE;
+}
+
+EINTERN int
+e_hwc_window_zpos_get(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) return -999;
+
+ return hwc_window->zpos;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_compsition_update(E_Hwc_Window *hwc_window)
+{
+ tdm_hwc_window *thwc_window;
+ tdm_hwc_window_composition composition_type;
+ tdm_error error;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (e_hwc_window_is_target(hwc_window))
+ {
+ ERR("HWC-WINS: target window cannot update at e_hwc_window_compsition_update.");
+ return EINA_FALSE;
+ }
+
+ thwc_window = hwc_window->thwc_window;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(thwc_window, EINA_FALSE);
+
+ /* set composition type */
+ composition_type = _get_composition_type(hwc_window->state);
+ error = tdm_hwc_window_set_composition_type(hwc_window->thwc_window, composition_type);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_buffer_update(E_Hwc_Window *hwc_window)
+{
+ tbm_surface_h tsurface = NULL;
+ tdm_hwc_window *thwc_window;
+ tdm_error error;
+ Eina_Bool result;
+
+ thwc_window = hwc_window->thwc_window;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(thwc_window, EINA_FALSE);
+
+ tsurface = hwc_window->tsurface;
+ if (tsurface)
+ {
+ /* set window info */
+ result = _e_hwc_window_info_set(hwc_window, tsurface);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(result != EINA_TRUE, EINA_FALSE);
+ }
+
+ /* set buffer */
+ error = tdm_hwc_window_set_buffer(thwc_window, hwc_window->tsurface);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_target(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ return hwc_window->is_target;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_video(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ return hwc_window->is_video;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_cursor(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ return hwc_window->is_cursor;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_buffer_fetch(E_Hwc_Window *hwc_window)
+{
+ tbm_surface_h tsurface = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+ if (hwc_window->is_deleted)
+ {
+ hwc_window->tsurface = NULL;
+ hwc_window->update_exist = EINA_TRUE;
+ return EINA_TRUE;
+ }
+
+ /* set the buffer to be null */
+ if (hwc_window->state == E_HWC_WINDOW_STATE_NONE)
+ {
+ if (hwc_window->cursor_tsurface)
+ {
+ tbm_surface_destroy(hwc_window->cursor_tsurface);
+ hwc_window->cursor_tsurface = NULL;
+ }
+
+ if (hwc_window->tsurface == NULL) return EINA_FALSE;
+
+ hwc_window->update_exist = EINA_TRUE;
+ hwc_window->tsurface = NULL;
+ }
+ else
+ {
+ /* for video we set buffer in the video module */
+ if (e_hwc_window_is_video(hwc_window))
+ {
+ tsurface = e_comp_wl_video_hwc_widow_surface_get(hwc_window);
+ if (!tsurface)
+ {
+ ELOGF("HWC-WINS", " ehw:%p no video buffer yet -- {%25s}, state:%s, zpos:%d, deleted:%s (Video)",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+ e_hwc_window_state_string_get(hwc_window->state),
+ hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+ return EINA_FALSE;
+ }
+ hwc_window->update_exist = EINA_TRUE;
+
+ ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s, zpos:%d, deleted:%s (Video)",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, tsurface, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+ e_hwc_window_state_string_get(hwc_window->state),
+ hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+ }
+ else if (e_hwc_window_is_cursor(hwc_window))
+ {
+ tsurface = _e_hwc_window_cursor_surface_acquire(hwc_window);
+ if (!tsurface)
+ {
+ ELOGF("HWC-WINS", " ehw:%10p cursor buffer is null.",
+ hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec, hwc_window);
+ return EINA_FALSE;
+ }
+ if (!e_comp_object_hwc_update_exists(hwc_window->ec->frame)) return EINA_FALSE;
+
+ e_comp_object_hwc_update_set(hwc_window->ec->frame, EINA_FALSE);
+ hwc_window->update_exist = EINA_TRUE;
+
+ ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s, zpos:%d, deleted:%s (Cusor)",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, tsurface, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+ e_hwc_window_state_string_get(hwc_window->state),
+ hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+ }
+ else
+ {
+ /* acquire the surface */
+ tsurface = _e_hwc_window_client_surface_acquire(hwc_window);
+ if (!tsurface)
+ {
+ ELOGF("HWC-WINS", " ehw:%p client buffer is null.",
+ hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec, hwc_window);
+ return EINA_FALSE;
+ }
+ if (tsurface == hwc_window->tsurface) return EINA_FALSE;
+
+ hwc_window->update_exist = EINA_TRUE;
+
+ ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s, zpos:%d, deleted:%s (Window)",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, tsurface, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+ e_hwc_window_state_string_get(hwc_window->state),
+ hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+ }
+ }
+
+ /* exist tsurface for update hwc_window */
+ hwc_window->tsurface = tsurface;
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_commit_data_aquire(E_Hwc_Window *hwc_window)
+{
+ E_Hwc_Window_Commit_Data *commit_data = NULL;
+
+
+ if (hwc_window->update_exist == EINA_FALSE) return EINA_FALSE;
+
+#if 0
+ if (!e_hwc_window_is_on_hw_overlay(hwc_window))
+ {
+ hwc_window->update_exist = EINA_FALSE;
+
+ /* right after an hwc_window's type has been changed from DEVICE to CLIENT
+ * we have to wait till hwc_window's buffer being composited to target_buffer
+ * and this target_buffer gets scheduled and only after this we can issue
+ * a 'fake commit_data' request to allow tdm_commit() to be called to unset
+ * an underlying hw overlay;
+ * target_wnd's hwc can't ever be at target_wnd :), so we pass it immediately */
+ if (e_hwc_window_displaying_surface_get(hwc_window) &&
+ !_e_hwc_window_is_device_to_client_transition(hwc_window))
+ {
+ commit_data = E_NEW(E_Hwc_Window_Commit_Data, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(commit_data, EINA_FALSE);
+
+ hwc_window->commit_data = commit_data;
+ hwc_window->is_device_to_client_transition = EINA_FALSE;
+
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+ }
+
+ /* If there are not updates and there is not displaying surface, it means the
+ * hwc_window's composition type just became TDM_COMPOSITION_DEVICE. Buffer
+ * for this hwc_window was set in the previous e_hwc_window_buffer_fetch but ref for
+ * buffer didn't happen because hwc_window had TDM_COMPOSITION_CLIENT type.
+ * So e20 needs to make ref for the current buffer which is set on the hwc_window.
+ */
+ if (!hwc_window->update_exist && e_hwc_window_displaying_surface_get(hwc_window))
+ {
+ return EINA_FALSE;
+ }
+#endif
+
+ commit_data = E_NEW(E_Hwc_Window_Commit_Data, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(commit_data, EINA_FALSE);
+
+ /* fake commit data for free the e_hwc_window resource */
+ if (hwc_window->is_deleted) goto done;
+
+ if (e_hwc_window_is_target(hwc_window) ||
+ e_hwc_window_is_video(hwc_window))
+ {
+ commit_data->tsurface = hwc_window->tsurface;
+ tbm_surface_internal_ref(commit_data->tsurface);
+ }
+ else
+ {
+ commit_data->tsurface = hwc_window->tsurface;
+ tbm_surface_internal_ref(commit_data->tsurface);
+
+ e_comp_wl_buffer_reference(&commit_data->buffer_ref, _e_hwc_window_comp_wl_buffer_get(hwc_window));
+ }
+
+done:
+ hwc_window->commit_data = commit_data;
+ hwc_window->update_exist = EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_commit_data_release(E_Hwc_Window *hwc_window)
+{
+ tbm_surface_h tsurface = NULL;
+ tbm_surface_h displaying_surface;
+
+ /* we don't have data to release */
+ if (!hwc_window->commit_data) return EINA_FALSE;
+
+ if (hwc_window->is_deleted)
+ {
+ displaying_surface = e_hwc_window_displaying_surface_get(hwc_window);
+ if (displaying_surface) tbm_surface_internal_unref(displaying_surface);
+ hwc_window->display_info.tsurface = NULL;
+
+ free(hwc_window->commit_data);
+ e_hwc_window_free(hwc_window);
+ }
+ else
+ {
+ tsurface = hwc_window->commit_data->tsurface;
+
+ if (!tsurface)
+ {
+ e_comp_wl_buffer_reference(&hwc_window->display_info.buffer_ref, NULL);
+ }
+ else if (e_hwc_window_is_target(hwc_window) || e_hwc_window_is_video(hwc_window))
+ {
+ e_comp_wl_buffer_reference(&hwc_window->display_info.buffer_ref, NULL);
+ }
+ else
+ {
+ e_comp_wl_buffer_reference(&hwc_window->display_info.buffer_ref, hwc_window->commit_data->buffer_ref.buffer);
+ }
+
+ e_comp_wl_buffer_reference(&hwc_window->commit_data->buffer_ref, NULL);
+
+ /* release and unreference the previous surface */
+ displaying_surface = e_hwc_window_displaying_surface_get(hwc_window);
+ if (displaying_surface)
+ {
+ if (e_hwc_window_is_target(hwc_window))
+ {
+ _e_hwc_window_target_window_surface_release((E_Hwc_Window_Target *)hwc_window, displaying_surface);
+ }
+ tbm_surface_internal_unref(displaying_surface);
+ }
+
+ /* update hwc_window display info */
+ hwc_window->display_info.tsurface = tsurface;
+
+ free(hwc_window->commit_data);
+ hwc_window->commit_data = NULL;
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_target_surface_queue_can_dequeue(E_Hwc_Window_Target *target_hwc_window)
+{
+ tbm_surface_queue_h tqueue = NULL;
+ int num_free = 0;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+ tqueue = target_hwc_window->queue;
+ if (!tqueue)
+ {
+ WRN("tbm_surface_queue is NULL");
+ return EINA_FALSE;
+ }
+
+ num_free = tbm_surface_queue_can_dequeue(tqueue, 0);
+
+ if (num_free <= 0) return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_target_enabled(E_Hwc_Window_Target *target_hwc_window)
+{
+ E_Hwc_Window *hwc_window;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+ hwc_window = (E_Hwc_Window *)target_hwc_window;
+
+ if (hwc_window->state != E_HWC_WINDOW_STATE_DEVICE)
+ return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+/* set the tsurface to the target_window->tsurface according to the state.
+ * 1. try to set the tsurface to the target_window at E_HWC_WINDOW_STATE_DEVICE.
+ * 2. try to set NULL and release(clear) tsurface_queue of the target_window at E_HWC_WINDOW_STATE_NONE.
+ * Returing EINA_FALSE means that there is no update for the target_window->tsurface.
+ **/
+EINTERN Eina_Bool
+e_hwc_window_target_buffer_fetch(E_Hwc_Window_Target *target_hwc_window)
+{
+ E_Output *output;
+ E_Output_Hwc *output_hwc;
+ E_Hwc_Window *hwc_window, *hw;
+ tbm_surface_h tsurface;
+ tdm_hwc_region fb_damage;
+ Eina_List *ee_rendered_hw_list = NULL;
+ uint32_t n_thw = 0;
+ const Eina_List *l;
+ int i;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+ hwc_window = (E_Hwc_Window *)target_hwc_window;
+
+ hwc_window->update_exist = EINA_FALSE;
+
+ if (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE)
+ {
+ /* acquire the surface */
+ tsurface = _e_hwc_window_target_window_surface_acquire((E_Hwc_Window_Target *)hwc_window);
+ if (!tsurface)
+ {
+ //ELOGF("HWC-WINS", " the surface of target is null.(E_HWC_WINDOW_STATE_DEVICE)", NULL, NULL);
+ return EINA_FALSE;
+ }
+ if (tsurface == hwc_window->tsurface)
+ {
+ //ELOGF("HWC-WINS", " aquired buffer is same.(ts:%p)(E_HWC_WINDOW_STATE_DEVICE)", NULL, NULL, hwc_window->tsurface);
+ return EINA_FALSE;
+ }
+
+ hwc_window->tsurface = tsurface;
+
+ output_hwc = hwc_window->output_hwc;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+ output = output_hwc->output;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+ /* the damage isn't supported by hwc extension yet */
+ memset(&fb_damage, 0, sizeof(fb_damage));
+
+ tdm_output_hwc_set_client_target_buffer(output->toutput, hwc_window->tsurface, fb_damage);
+
+ ee_rendered_hw_list = e_hwc_window_target_window_ee_rendered_hw_list_get(target_hwc_window);
+ n_thw = eina_list_count(ee_rendered_hw_list);
+ if (n_thw)
+ {
+ ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s",
+ NULL, NULL, hwc_window, hwc_window->tsurface, "@TARGET WINDOW@",
+ e_hwc_window_state_string_get(hwc_window->state));
+
+ i = 0;
+ EINA_LIST_FOREACH(ee_rendered_hw_list, l, hw)
+ {
+ ELOGF("HWC-WINS", " (%d) with ehw:%p, ts:%10p ------- {%25s}, state:%s, zpos:%d, deleted:%s",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ i++, hw, hw->tsurface, hw->ec ? hw->ec->icccm.title : "UNKNOWN",
+ e_hwc_window_state_string_get(hw->state),
+ hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+ }
+ }
+ else
+ ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s, zpos:%d no hwc_windows to render.",
+ NULL, NULL, hwc_window, hwc_window->tsurface, "@TARGET WINDOW@",
+ e_hwc_window_state_string_get(hwc_window->state), hwc_window->zpos);
+ }
+ else
+ {
+ if (hwc_window->tsurface == NULL)
+ {
+ //ELOGF("HWC-WINS", " the surface of target is null.(E_HWC_WINDOW_STATE_NONE)", NULL, NULL);
+ return EINA_FALSE;
+ }
+
+ if (hwc_window->tsurface)
+ _e_hwc_window_target_window_surface_release((E_Hwc_Window_Target *)hwc_window, hwc_window->tsurface);
+
+ if (!_e_hwc_window_target_window_clear((E_Hwc_Window_Target *)hwc_window))
+ ERR("fail to _e_hwc_window_target_window_clear");
+
+ hwc_window->tsurface = NULL;
+
+ //TODO: Do we set the target_buffer to be NULL?
+
+ ELOGF("HWC-WINS", " ehw:%p sets ts:%10p ------- {%25s}, state:%s",
+ NULL, NULL, hwc_window, hwc_window->tsurface, "@TARGET WINDOW@",
+ e_hwc_window_state_string_get(hwc_window->state));
+ }
+
+ hwc_window->update_exist = EINA_TRUE;
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_List *
+e_hwc_window_target_window_ee_rendered_hw_list_get(E_Hwc_Window_Target *target_window)
+{
+ Eina_List *ee_rendered_hw_list = NULL, *new_list = NULL;
+ E_Hwc_Window *hw1, *hw2;
+ const Eina_List *l, *ll;
+ E_Output_Hwc *output_hwc;
+ tbm_surface_h target_tsurface;
+
+ output_hwc = target_window->hwc_window.output_hwc;
+
+ target_tsurface = target_window->hwc_window.tsurface;
+ tbm_surface_internal_get_user_data(target_tsurface, ee_rendered_hw_list_key, (void**)&ee_rendered_hw_list);
+
+ /* refresh list of composited e_thwc_windows according to existed ones */
+ EINA_LIST_FOREACH(ee_rendered_hw_list, l, hw1)
+ EINA_LIST_FOREACH(output_hwc->hwc_windows, ll, hw2)
+ if (hw1 == hw2) new_list = eina_list_append(new_list, hw1);
+
+ return new_list;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_activate(E_Hwc_Window *hwc_window)
+{
+ struct wayland_tbm_client_queue *cqueue = NULL;
+ E_Client *ec;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (hwc_window->activation_state == E_HWC_WINDOW_ACTIVATION_STATE_ACTIVATED)
+ return EINA_TRUE;
+
+ ec = hwc_window->ec;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ /* set the redirected to FALSE */
+ e_client_redirected_set(ec, EINA_FALSE);
+
+ cqueue = _get_wayland_tbm_client_queue(ec);
+
+ if (cqueue)
+ wayland_tbm_server_client_queue_activate(cqueue, 0, 0, 0);
+
+ if (e_hwc_window_is_cursor(hwc_window))
+ {
+ E_Pointer *pointer = NULL;
+
+ pointer = e_pointer_get(ec);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(pointer, EINA_FALSE);
+
+ e_pointer_hwc_set(pointer, EINA_TRUE);
+ }
+
+ hwc_window->activation_state = E_HWC_WINDOW_ACTIVATION_STATE_ACTIVATED;
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_deactivate(E_Hwc_Window *hwc_window)
+{
+ struct wayland_tbm_client_queue * cqueue = NULL;
+ E_Client *ec = NULL;
+ int transform;
+ E_Output *output = NULL;
+ E_Output_Hwc *output_hwc = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (hwc_window->activation_state == E_HWC_WINDOW_ACTIVATION_STATE_DEACTIVATED)
+ return EINA_TRUE;
+
+ ec = hwc_window->ec;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ /* set the redirected to TRUE */
+ e_client_redirected_set(ec, EINA_TRUE);
+
+ cqueue = _get_wayland_tbm_client_queue(ec);
+ if (cqueue)
+ /* TODO: do we have to immediately inform a wayland client
+ * that an e_client got redirected or wait till it's being composited
+ * on the fb_target and a hw overlay owned by it gets free? */
+ wayland_tbm_server_client_queue_deactivate(cqueue);
+
+ output_hwc = hwc_window->output_hwc;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+ output = output_hwc->output;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+
+ transform = e_comp_wl_output_buffer_transform_get(ec);
+
+ if (output->config.rotation != 0 && (output->config.rotation / 90) == transform)
+ e_comp_screen_rotation_ignore_output_transform_send(ec, EINA_TRUE);
+
+ _e_hwc_window_client_recover(hwc_window);
+
+ if (e_hwc_window_is_cursor(hwc_window))
+ {
+ E_Pointer *pointer = NULL;
+
+ pointer = e_pointer_get(ec);
+ if (pointer)
+ e_pointer_hwc_set(pointer, EINA_FALSE);
+ }
+
+ hwc_window->activation_state = E_HWC_WINDOW_ACTIVATION_STATE_DEACTIVATED;
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_on_hw_overlay(E_Hwc_Window *hwc_window)
+{
+ E_Hwc_Window_State state = E_HWC_WINDOW_STATE_NONE;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ state = e_hwc_window_state_get(hwc_window);
+
+ if (state == E_HWC_WINDOW_STATE_DEVICE) return EINA_TRUE;
+ if (state == E_HWC_WINDOW_STATE_CURSOR) return EINA_TRUE;
+ if (state == E_HWC_WINDOW_STATE_VIDEO) return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
+EINTERN tbm_surface_h
+e_hwc_window_displaying_surface_get(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
+
+ return hwc_window->display_info.tsurface;
+}
+
+EINTERN Eina_Bool
+e_hwc_window_state_set(E_Hwc_Window *hwc_window, E_Hwc_Window_State state)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ if (hwc_window->state != state) hwc_window->state = state;
+
+ /* zpos is -999 at state none */
+ if (state == E_HWC_WINDOW_STATE_NONE)
+ e_hwc_window_zpos_set(hwc_window, -999);
+
+ return EINA_TRUE;
+}
+
+EINTERN E_Hwc_Window_State
+e_hwc_window_state_get(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, E_HWC_WINDOW_STATE_NONE);
+
+ return hwc_window->state;
+}
+
+EINTERN void
+e_hwc_window_prev_state_update(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+ if (hwc_window->uncompleted_transition != E_HWC_WINDOW_TRANSITION_NONE_TO_NONE)
+ return;
+
+ hwc_window->prev_state = hwc_window->state;
+}
+
+EINTERN E_Hwc_Window_State
+e_hwc_window_prev_state_get(E_Hwc_Window *hwc_window)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, E_HWC_WINDOW_STATE_NONE);
+
+ return hwc_window->prev_state;
+}
+
+// add hwc_window to the render_list
+EINTERN void
+e_hwc_window_render_list_add(E_Hwc_Window *hwc_window)
+{
+ E_Hwc_Window_Target *target_hwc_window;
+ E_Client *ec;
+
+ EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+ ec = hwc_window->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ target_hwc_window = _e_hwc_window_target_window_get(hwc_window);
+ EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
+
+ target_hwc_window->ee_rendered_hw_list =
+ eina_list_append(target_hwc_window->ee_rendered_hw_list, hwc_window);
+
+ ELOGF("HWC-WINS", " added the render_list -- ehw:%p -- {%25s}.", ec->pixmap, ec, hwc_window, ec->icccm.title);
+}
+
+EINTERN Eina_Bool
+e_hwc_window_is_on_target_window(E_Hwc_Window *hwc_window)
+{
+ Eina_List *ee_rendered_hw_list = NULL;
+ E_Hwc_Window_Target *target_hwc_window;
+ E_Hwc_Window *target_window;
+ E_Hwc_Window *hw;
+ const Eina_List *l;
+ tbm_surface_h target_tsurface;
+
+ target_hwc_window = _e_hwc_window_target_window_get(hwc_window);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
+
+ target_window = (E_Hwc_Window *)target_hwc_window;
+ if (e_hwc_window_state_get(target_window) != E_HWC_WINDOW_STATE_DEVICE) return EINA_FALSE;
+
+ target_tsurface = target_hwc_window->hwc_window.tsurface;
+
+ tbm_surface_internal_get_user_data(target_tsurface, ee_rendered_hw_list_key, (void**)&ee_rendered_hw_list);
+
+ EINA_LIST_FOREACH(ee_rendered_hw_list, l, hw)
+ if (hw == hwc_window) return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
+
+EINTERN const char*
+e_hwc_window_state_string_get(E_Hwc_Window_State hwc_window_state)
+{
+ switch (hwc_window_state)
+ {
+ case E_HWC_WINDOW_STATE_NONE:
+ return "NO"; // None
+ case E_HWC_WINDOW_STATE_CLIENT:
+ return "CL"; // Client
+ case E_HWC_WINDOW_STATE_DEVICE:
+ return "DV"; // Deivce
+ case E_HWC_WINDOW_STATE_VIDEO:
+ return "VD"; // Video
+ case E_HWC_WINDOW_STATE_DEVICE_CANDIDATE:
+ return "DC"; // Deivce Candidate
+ case E_HWC_WINDOW_STATE_CURSOR:
+ return "CS"; // Cursor
+ default:
+ return "UNKNOWN";
+ }
+}
--- /dev/null
+#ifdef E_TYPEDEFS
+
+typedef struct _E_Hwc_Window E_Hwc_Window;
+typedef struct _E_Hwc_Window_Target E_Hwc_Window_Target;
+typedef struct _E_Hwc_Window_Commit_Data E_Hwc_Window_Commit_Data;
+
+#else
+#ifndef E_HWC_WINDOW_H
+#define E_HWC_WINDOW_H
+
+typedef enum _E_Hwc_Window_State
+{
+ E_HWC_WINDOW_STATE_NONE,
+ E_HWC_WINDOW_STATE_CLIENT,
+ E_HWC_WINDOW_STATE_DEVICE,
+ E_HWC_WINDOW_STATE_VIDEO,
+ E_HWC_WINDOW_STATE_DEVICE_CANDIDATE,
+ E_HWC_WINDOW_STATE_CURSOR
+} E_Hwc_Window_State;
+
+typedef enum _E_Hwc_Window_Transition
+{
+ E_HWC_WINDOW_TRANSITION_NONE_TO_NONE,
+ E_HWC_WINDOW_TRANSITION_NONE_TO_CLIENT,
+ E_HWC_WINDOW_TRANSITION_NONE_TO_DEVICE,
+ E_HWC_WINDOW_TRANSITION_NONE_TO_CURSOR,
+ E_HWC_WINDOW_TRANSITION_CLIENT_TO_NONE,
+ E_HWC_WINDOW_TRANSITION_CLIENT_TO_CLIENT,
+ E_HWC_WINDOW_TRANSITION_CLIENT_TO_DEVICE,
+ E_HWC_WINDOW_TRANSITION_CLIENT_TO_CURSOR,
+ E_HWC_WINDOW_TRANSITION_DEVICE_TO_NONE,
+ E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT,
+ E_HWC_WINDOW_TRANSITION_DEVICE_TO_DEVICE,
+ E_HWC_WINDOW_TRANSITION_CURSOR_TO_NONE,
+ E_HWC_WINDOW_TRANSITION_CURSOR_TO_CLIENT,
+ E_HWC_WINDOW_TRANSITION_CURSOR_TO_CURSOR
+} E_Hwc_Window_Transition;
+
+typedef enum _E_Hwc_Window_Activation_State
+{
+ E_HWC_WINDOW_ACTIVATION_STATE_NONE = 0,
+ E_HWC_WINDOW_ACTIVATION_STATE_ACTIVATED,
+ E_HWC_WINDOW_ACTIVATION_STATE_DEACTIVATED,
+} E_Hwc_Window_Activation_State;
+
+struct _E_Hwc_Window
+{
+ E_Client *ec;
+ E_Output_Hwc *output_hwc;
+ tdm_hwc_window *thwc_window;
+ int zpos;
+ Eina_Bool is_target;
+ Eina_Bool is_video;
+ Eina_Bool is_cursor;
+ Eina_Bool is_deleted;
+ Eina_Bool update_exist;
+ tbm_surface_h tsurface;
+ E_Hwc_Window_Activation_State activation_state; /* hwc_window has occupied the hw layer or not */
+ tdm_hwc_window_info info;
+
+ E_Hwc_Window_State state;
+ E_Hwc_Window_State prev_state;
+ E_Hwc_Window_Transition transition;
+ E_Hwc_Window_Transition uncompleted_transition;
+
+ /* current display information */
+ struct
+ {
+ E_Comp_Wl_Buffer_Ref buffer_ref;
+ tbm_surface_h tsurface;
+ } display_info;
+
+ E_Hwc_Window_Commit_Data *commit_data;
+
+ Eina_Bool hwc_acceptable;
+ Eina_Bool need_change_buffer_transform;
+
+ tbm_surface_h cursor_tsurface;
+ int cursor_rotation;
+
+ Eina_Bool is_device_to_client_transition;
+};
+
+struct _E_Hwc_Window_Target
+{
+ E_Hwc_Window hwc_window; /* don't move this field */
+
+ Ecore_Evas *ee;
+ Evas *evas;
+ int event_fd;
+ Ecore_Fd_Handler *event_hdlr;
+
+ tbm_surface_queue_h queue;
+
+ /* a surface the rendering is currently performing at */
+ tbm_surface_h dequeued_tsurface;
+ Eina_List *ee_rendered_hw_list;
+
+ Eina_Bool skip_surface_set;
+};
+
+struct _E_Hwc_Window_Commit_Data {
+ E_Comp_Wl_Buffer_Ref buffer_ref;
+ tbm_surface_h tsurface;
+};
+
+EINTERN Eina_Bool e_hwc_window_init(E_Output_Hwc *output_hwc);
+EINTERN void e_hwc_window_deinit(E_Output_Hwc *output_hwc); // TODO:
+
+EINTERN E_Hwc_Window *e_hwc_window_new(E_Output_Hwc *output_hwc, E_Client *ec, E_Hwc_Window_State state);
+EINTERN void e_hwc_window_free(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool e_hwc_window_zpos_set(E_Hwc_Window *hwc_window, int zpos);
+EINTERN int e_hwc_window_zpos_get(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_compsition_update(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_buffer_update(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_is_target(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_is_video(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_is_cursor(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_buffer_fetch(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool e_hwc_window_commit_data_aquire(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_commit_data_release(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool e_hwc_window_target_surface_queue_can_dequeue(E_Hwc_Window_Target *target_hwc_window);
+EINTERN Eina_Bool e_hwc_window_target_enabled(E_Hwc_Window_Target *target_hwc_window);
+EINTERN Eina_Bool e_hwc_window_target_buffer_fetch(E_Hwc_Window_Target *target_hwc_window);
+EINTERN Eina_List *e_hwc_window_target_window_ee_rendered_hw_list_get(E_Hwc_Window_Target *target_window);
+
+EINTERN Eina_Bool e_hwc_window_activate(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_deactivate(E_Hwc_Window *hwc_window);
+EINTERN Eina_Bool e_hwc_window_is_on_hw_overlay(E_Hwc_Window *hwc_window);
+EINTERN tbm_surface_h e_hwc_window_displaying_surface_get(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool e_hwc_window_state_set(E_Hwc_Window *hwc_window, E_Hwc_Window_State state);
+EINTERN E_Hwc_Window_State e_hwc_window_state_get(E_Hwc_Window *hwc_window);
+EINTERN void e_hwc_window_prev_state_update(E_Hwc_Window *hwc_window);
+EINTERN E_Hwc_Window_State e_hwc_window_prev_state_get(E_Hwc_Window *hwc_window);
+
+EINTERN void e_hwc_window_render_list_add(E_Hwc_Window *hwc_window);
+
+EINTERN Eina_Bool e_hwc_window_is_on_target_window(E_Hwc_Window *hwc_window);
+
+EINTERN const char *e_hwc_window_state_string_get(E_Hwc_Window_State hwc_window_state);
+
+#endif // E_HWC_WINDOW_H
+#endif
#include "e_output.h"
#include "e_output_hwc.h"
#include "e_output_hwc_planes.h"
+#include "e_output_hwc_windows.h"
+#include "e_hwc_window.h"
#include "e_comp_wl.h"
#include "e_comp_wl_data.h"
#include "e_comp_wl_input.h"
Eldbus_Object *obj;
/* topvwins */
- int use_gl, use_hwc, use_multi_layer, hwc;
+ int use_gl, use_hwc, use_multi_layer, hwc, hwc_windows;
int use_buffer_flush, deiconify_approve;
const char *engine;
Eina_List *win_list;
res = eldbus_message_error_get(msg, &name, &text);
EINA_SAFETY_ON_TRUE_GOTO(res, finish);
- res = eldbus_message_arguments_get(msg, "iiiisiia("VALUE_TYPE_FOR_TOPVWINS")",
+ res = eldbus_message_arguments_get(msg, "iiiiisiia("VALUE_TYPE_FOR_TOPVWINS")",
&e_info_client.use_gl, &e_info_client.use_hwc, &e_info_client.use_multi_layer,
- &e_info_client.hwc, &engine,
+ &e_info_client.hwc, &e_info_client.hwc_windows, &engine,
&e_info_client.use_buffer_flush, &e_info_client.deiconify_approve,
&array);
EINA_SAFETY_ON_FALSE_GOTO(res, finish);
printf("ENG: %s\n", e_info_client.engine);
if (e_info_client.use_hwc)
{
- printf("HWC: %s\n", e_info_client.hwc ? "on":"off");
- printf("Multi Plane: %s\n", e_info_client.use_multi_layer ? "on":"off");
+ if (e_info_client.hwc)
+ {
+ printf("HWC: ");
+ if (e_info_client.hwc_windows)
+ printf("hwc windows policy\n");
+ else
+ printf("hwc planes policy and multiple plane is %s\n", e_info_client.use_multi_layer ? "on":"off");
+ }
+ else
+ printf("HWC: off");
}
+ else
+ printf("HWC: configuration is off");
+
printf("Buffer flush: %s\n", e_info_client.use_buffer_flush ? "on":"off");
if (e_info_client.use_buffer_flush)
printf("Deiconify Approve: %s\n", "auto on");
{
if ((!win->iconic) && (win->frame_visible))
{
- if (win->hwc) snprintf(tmp, sizeof(tmp), "hwc@%i", win->pl_zpos);
- else snprintf(tmp, sizeof(tmp), "comp@%i", win->pl_zpos);
+ if (win->pl_zpos == -999)
+ snprintf(tmp, sizeof(tmp), " - ");
+ else
+ {
+ if (win->hwc) snprintf(tmp, sizeof(tmp), "hwc@%i", win->pl_zpos);
+ else snprintf(tmp, sizeof(tmp), "comp@%i", win->pl_zpos);
+ }
}
else
snprintf(tmp, sizeof(tmp), " - ");
{
if ((!win->iconic) && (win->frame_visible))
{
- if (win->hwc) snprintf(tmp, sizeof(tmp), "hwc@%i", win->pl_zpos);
- else snprintf(tmp, sizeof(tmp), "comp@%i", win->pl_zpos);
+ if (win->pl_zpos == -999)
+ snprintf(tmp, sizeof(tmp), " - ");
+ else
+ {
+ if (win->hwc) snprintf(tmp, sizeof(tmp), "hwc@%i", win->pl_zpos);
+ else snprintf(tmp, sizeof(tmp), "comp@%i", win->pl_zpos);
+ }
}
else
snprintf(tmp, sizeof(tmp), " - ");
{
if ((!iconic) && (frame_visible))
{
- if (hwc) printf(" hwc@%i\n", pl_zpos);
- else printf(" comp@%i\n", pl_zpos);
+ if (pl_zpos == -999)
+ printf(" - ");
+ else
+ {
+ if (hwc) printf(" hwc@%i\n", pl_zpos);
+ else printf(" comp@%i\n", pl_zpos);
+ }
}
else
printf(" - \n");
else
printf("0x%lx \"%s\":", (unsigned long)child_win, child_name);
printf (" %dx%d+%d+%d", w, h, x, y);
- if (hwc > 0) printf(" hwc@%i", pl_zpos);
- else if (!hwc) printf(" comp@%i", pl_zpos);
+ if (pl_zpos == -999)
+ printf(" - ");
+ else
+ {
+ if (hwc > 0) printf(" hwc@%i", pl_zpos);
+ else if (!hwc) printf(" comp@%i", pl_zpos);
+ }
printf("\n");
if (num_children > 0)
{
Eina_List *l;
E_Output *eout;
E_Plane *ep;
+ E_Hwc_Window *hwc_window = NULL;
*hwc = -1;
*pl_zpos = -999;
eout = e_output_find(ec->zone->output_id);
if (!eout) return;
- EINA_LIST_FOREACH(eout->planes, l, ep)
- {
- if (e_plane_is_fb_target(ep))
- *pl_zpos = ep->zpos;
- if (ep->ec == ec)
+ if (e_output_hwc_policy_get(eout->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+ {
+ EINA_LIST_FOREACH(eout->planes, l, ep)
{
- *hwc = 1;
- *pl_zpos = ep->zpos;
- break;
+ if (e_plane_is_fb_target(ep))
+ *pl_zpos = ep->zpos;
+
+ if (ep->ec == ec)
+ {
+ *hwc = 1;
+ *pl_zpos = ep->zpos;
+ break;
+ }
}
}
+ else
+ {
+ if (!ec->hwc_window) return;
+ hwc_window = ec->hwc_window;
+ if (e_hwc_window_is_on_hw_overlay(hwc_window))
+ *hwc = 1;
+
+ *pl_zpos = e_hwc_window_zpos_get(hwc_window);
+ }
}
static void
eldbus_message_iter_container_close(iter, array_of_ec);
}
+static int
+_e_info_server_is_hwc_windows()
+{
+ E_Output *primary_output;
+
+ primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+ if (!primary_output)
+ return 0;
+
+ if (e_output_hwc_policy_get(primary_output->output_hwc) == E_OUTPUT_HWC_POLICY_WINDOWS)
+ return 1;
+
+ return 0;
+}
+
/* Method Handlers */
static Eldbus_Message *
_e_info_server_cb_window_info_get(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
eldbus_message_iter_basic_append(iter, 'i', e_comp_config_get()->hwc);
eldbus_message_iter_basic_append(iter, 'i', e_comp_config_get()->hwc_use_multi_plane);
eldbus_message_iter_basic_append(iter, 'i', e_comp->hwc);
+ eldbus_message_iter_basic_append(iter, 'i', _e_info_server_is_hwc_windows());
eldbus_message_iter_basic_append(iter, 's', ecore_evas_engine_name_get(e_comp->ee));
eldbus_message_iter_basic_append(iter, 'i', e_config->use_buffer_flush);
eldbus_message_iter_basic_append(iter, 'i', e_config->deiconify_approve);
//{ "method_name", arguments_from_client, return_values_to_client, _method_cb, ELDBUS_METHOD_FLAG },
static const Eldbus_Method methods[] = {
- { "get_window_info", NULL, ELDBUS_ARGS({"iiiisa("VALUE_TYPE_FOR_TOPVWINS")", "array of ec"}), _e_info_server_cb_window_info_get, 0 },
+ { "get_window_info", NULL, ELDBUS_ARGS({"iiiiisa("VALUE_TYPE_FOR_TOPVWINS")", "array of ec"}), _e_info_server_cb_window_info_get, 0 },
{ "get_all_window_info", NULL, ELDBUS_ARGS({"a("VALUE_TYPE_FOR_TOPVWINS")", "array of ec"}), _e_info_server_cb_all_window_info_get, 0 },
{ "compobjs", NULL, ELDBUS_ARGS({"a("SIGNATURE_COMPOBJS_CLIENT")", "array of comp objs"}), _e_info_server_cb_compobjs, 0 },
{ "subsurface", NULL, ELDBUS_ARGS({"a("SIGNATURE_SUBSURFACE")", "array of ec"}), _e_info_server_cb_subsurface, 0 },
DBG("zoom_rect rotate(x:%d,y:%d) (w:%d,h:%d)",
output->zoom_conf.rect.x, output->zoom_conf.rect.y, output->zoom_conf.rect.w, output->zoom_conf.rect.h);
- EINA_LIST_FOREACH(output->planes, l, ep)
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
{
- if (!e_plane_is_fb_target(ep)) continue;
+ EINA_LIST_FOREACH(output->planes, l, ep)
+ {
+ if (!e_plane_is_fb_target(ep)) continue;
- e_plane_zoom_set(ep, &output->zoom_conf.rect);
- break;
+ e_plane_zoom_set(ep, &output->zoom_conf.rect);
+ break;
+ }
+
+ if (!_e_output_zoom_touch_set(output))
+ ERR("fail _e_output_zoom_touch_set");
+
+ /* update the ecore_evas */
+ if (e_plane_pp_commit_possible_check(ep))
+ _e_output_render_update(output);
}
+ else
+ {
+ e_output_hwc_windows_zoom_set(output->output_hwc, &output->zoom_conf.rect);
- if (!_e_output_zoom_touch_set(output))
- ERR("fail _e_output_zoom_touch_set");
+ if (!_e_output_zoom_touch_set(output))
+ ERR("fail _e_output_zoom_touch_set");
- /* update the ecore_evas */
- if (e_plane_pp_commit_possible_check(ep))
- _e_output_render_update(output);
+ /* update the ecore_evas */
+ if (e_output_hwc_windows_pp_commit_possible_check(output->output_hwc))
+ _e_output_render_update(output);
+ }
}
EINTERN void
output->output_hwc = output_hwc;
}
- /* ecore evas engine setup */
- EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
{
- if (plane->is_fb)
+ /* ecore evas engine setup */
+ EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
{
- if (!e_plane_setup(plane)) return EINA_FALSE;
- else return EINA_TRUE;
+ if (plane->is_fb)
+ {
+ if (!e_plane_setup(plane)) return EINA_FALSE;
+ else return EINA_TRUE;
+ }
}
}
+ else
+ {
+#if 0
+ Evas_Object *canvas_bg = NULL;
+ unsigned int r, g, b, a;
+
+ /* set the color of the canvas_gb object */
+ r = 0; g = 0; b = 0; a = 1;
+ canvas_bg = e_comp->bg_blank_object;
+ evas_object_color_set(canvas_bg, r, g, b, a);
+#endif
+ return EINA_TRUE;
+ }
return EINA_FALSE;
}
EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
- EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
{
- if (!e_plane_render(plane))
- {
- ERR("fail to e_plane_render.");
- return EINA_FALSE;
- }
+ EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
+ {
+ if (!e_plane_render(plane))
+ {
+ ERR("fail to e_plane_render.");
+ return EINA_FALSE;
+ }
+ }
+ }
+ else
+ {
+ if (!e_output_hwc_windows_render(output->output_hwc))
+ {
+ ERR("fail to e_output_hwc_windows_render.");
+ return EINA_FALSE;
+ }
}
return EINA_TRUE;
output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
- if (output == output_primary)
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
{
- if (!_e_output_planes_commit(output))
+ if (output == output_primary)
{
- ERR("fail _e_output_planes_commit");
- return EINA_FALSE;
+ if (!_e_output_planes_commit(output))
+ {
+ ERR("fail to _e_output_commit.");
+ return EINA_FALSE;
+ }
+ }
+ else
+ {
+ if (!_e_output_external_commit(output))
+ {
+ ERR("fail _e_output_external_commit");
+ return EINA_FALSE;
+ }
}
}
else
{
- if (!_e_output_external_commit(output))
+ if (!e_output_hwc_windows_commit(output->output_hwc))
{
- ERR("fail _e_output_external_commit");
return EINA_FALSE;
}
}
if (!output || !output->planes) continue;
- fprintf(stderr, "HWC in %s .. \n", output->id);
- fprintf(stderr, "HWC \tzPos \t on_plane \t\t\t\t on_prepare \t \n");
-
- EINA_LIST_REVERSE_FOREACH(output->planes, p_l, plane)
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
{
- ec = plane->ec;
- if (ec) fprintf(stderr, "HWC \t[%d]%s\t %s (0x%08x)",
- plane->zpos,
- plane->is_primary ? "--" : " ",
- ec->icccm.title, (unsigned int)ec->frame);
+ fprintf(stderr, "HWC in %s .. \n", output->id);
+ fprintf(stderr, "HWC \tzPos \t on_plane \t\t\t\t on_prepare \t \n");
- ec = plane->prepare_ec;
- if (ec) fprintf(stderr, "\t\t\t %s (0x%08x)",
- ec->icccm.title, (unsigned int)ec->frame);
+ EINA_LIST_REVERSE_FOREACH(output->planes, p_l, plane)
+ {
+ ec = plane->ec;
+ if (ec) fprintf(stderr, "HWC \t[%d]%s\t %s (0x%08x)",
+ plane->zpos,
+ plane->is_primary ? "--" : " ",
+ ec->icccm.title, (unsigned int)ec->frame);
+
+ ec = plane->prepare_ec;
+ if (ec) fprintf(stderr, "\t\t\t %s (0x%08x)",
+ ec->icccm.title, (unsigned int)ec->frame);
+ fputc('\n', stderr);
+ }
fputc('\n', stderr);
}
- fputc('\n', stderr);
}
}
_e_output_zoom_coordinate_cal(output);
_e_output_zoom_touch_rect_get(output);
- ep = e_output_fb_target_get(output);
- EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
-
- if (!output->zoom_set)
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
{
- if (_e_output_fb_over_plane_check(output))
- output->zoom_conf.unset_skip = EINA_TRUE;
- }
+ ep = e_output_fb_target_get(output);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
- e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_FALSE);
+ if (!output->zoom_set)
+ {
+ if (_e_output_fb_over_plane_check(output))
+ output->zoom_conf.unset_skip = EINA_TRUE;
+ }
- if (!e_plane_zoom_set(ep, &output->zoom_conf.rect))
- {
- ERR("e_plane_zoom_set failed.");
- output->zoom_conf.unset_skip = EINA_FALSE;
- e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_TRUE);
+ e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_FALSE);
- return EINA_FALSE;
+ if (!e_plane_zoom_set(ep, &output->zoom_conf.rect))
+ {
+ ERR("e_plane_zoom_set failed.");
+ output->zoom_conf.unset_skip = EINA_FALSE;
+ e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_TRUE);
+
+ return EINA_FALSE;
+ }
+
+ /* update the ecore_evas */
+ if (e_plane_pp_commit_possible_check(ep))
+ _e_output_render_update(output);
}
+ else
+ {
+ if (!e_output_hwc_windows_zoom_set(output->output_hwc, &output->zoom_conf.rect))
+ {
+ ERR("e_output_hwc_windows_zoom_set failed.");
+ return EINA_FALSE;
+ }
- /* update the ecore_evas */
- if (e_plane_pp_commit_possible_check(ep))
- _e_output_render_update(output);
+ /* update the ecore_evas */
+ if (e_output_hwc_windows_pp_commit_possible_check(output->output_hwc))
+ _e_output_render_update(output);
+ }
if (!_e_output_zoom_touch_set(output))
ERR("fail _e_output_zoom_touch_set");
if (!_e_output_zoom_touch_unset(output))
ERR("fail _e_output_zoom_touch_unset");
- ep = e_output_fb_target_get(output);
- if (ep) e_plane_zoom_unset(ep);
+ if (e_output_hwc_policy_get(output->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+ {
+ ep = e_output_fb_target_get(output);
+ if (ep) e_plane_zoom_unset(ep);
- e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_TRUE);
+ e_output_hwc_planes_multi_plane_set(output->output_hwc, EINA_TRUE);
+ }
+ else
+ {
+ e_output_hwc_windows_zoom_unset(output->output_hwc);
+ }
output->zoom_conf.zoomx = 0;
output->zoom_conf.zoomy = 0;
_e_output_external_rect_get(output_primary, p_w, p_h, w, h, &output->zoom_conf.rect);
e_output_hwc_planes_multi_plane_set(output_primary->output_hwc, EINA_FALSE);
+ e_output_hwc_deactive_set(output_primary->output_hwc, EINA_TRUE);
ep->output_primary = output_primary;
if (!e_plane_external_set(ep, &output->zoom_conf.rect, state))
{
ERR("e_plane_mirror_set failed.");
e_output_hwc_planes_multi_plane_set(output_primary->output_hwc, EINA_TRUE);
+ e_output_hwc_deactive_set(output_primary->output_hwc, EINA_FALSE);
return EINA_FALSE;
}
INF("Output uses the HWC PLANES Policy.");
}
else
- output_hwc->hwc_policy = E_OUTPUT_HWC_POLICY_WINDOWS;
+ {
+ output_hwc->hwc_policy = E_OUTPUT_HWC_POLICY_WINDOWS;
+
+ if (!e_output_hwc_windows_init(output_hwc))
+ {
+ ERR("hwc_opt: e_output_hwc_windows_init failed");
+ goto fail;
+ }
+
+ if (!e_hwc_window_init(output_hwc))
+ {
+ ERR("hwc_opt: E_Hwc_Window init failed");
+ goto fail;
+ }
+
+ /* turn on sw compositor at the start */
+ ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
+
+ INF("Output uses the HWC WINDOWS Policy.");
+ }
return output_hwc;
if (output_hwc->hwc_policy == E_OUTPUT_HWC_POLICY_PLANES)
e_output_hwc_planes_deinit();
+ else
+ {
+ e_hwc_window_deinit(output_hwc);
+ e_output_hwc_windows_deinit();
+ }
E_FREE(output_hwc);
}
{
EINA_SAFETY_ON_NULL_RETURN(output_hwc);
EINA_SAFETY_ON_NULL_RETURN(output_hwc->output);
- if (e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_NONE) return;
+ if (e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_NONE ||
+ e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_WINDOWS) return;
- if (e_output_hwc_policy_get(output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+ if (e_output_hwc_deactive_get(output_hwc))
{
- if (e_output_hwc_deactive_get(output_hwc))
- {
- if (output_hwc->hwc_mode != E_OUTPUT_HWC_MODE_NONE)
- e_output_hwc_planes_end(output_hwc, "deactive set.");
- return;
- }
-
- if (!e_output_hwc_planes_usable(output_hwc))
- {
- e_output_hwc_planes_end(output_hwc, __FUNCTION__);
- return;
- }
+ if (output_hwc->hwc_mode != E_OUTPUT_HWC_MODE_NONE)
+ e_output_hwc_planes_end(output_hwc, "deactive set.");
+ return;
+ }
- if (output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_NONE)
- e_output_hwc_planes_begin(output_hwc);
- else
- e_output_hwc_planes_changed(output_hwc);
+ if (!e_output_hwc_planes_usable(output_hwc))
+ {
+ e_output_hwc_planes_end(output_hwc, __FUNCTION__);
+ return;
}
+
+ if (output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+ e_output_hwc_planes_begin(output_hwc);
+ else
+ e_output_hwc_planes_changed(output_hwc);
}
EINTERN E_Output_Hwc_Mode
EINTERN E_Output_Hwc_Policy
e_output_hwc_policy_get(E_Output_Hwc *output_hwc)
{
- EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, E_OUTPUT_HWC_MODE_NONE);
return output_hwc->hwc_policy;
}
EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
return output_hwc->hwc_deactive;
-}
\ No newline at end of file
+}
/* variables for hwc_planes polic */
Eina_Bool hwc_use_multi_plane;
+
+ /* variables for hwc_windows policy */
+ Eina_Bool hwc_wins;
+ Eina_List *hwc_windows;
+ E_Hwc_Window_Target *target_hwc_window;
+ Eina_Bool wait_commit;
+ int num_visible_windows;
+
+ /* variables for pp at hwc_windows policy */
+ tdm_pp *tpp;
+ Eina_List *pp_hwc_window_list;
+ Eina_List *pending_pp_hwc_window_list;
+ Eina_List *pending_pp_commit_data_list;
+ tbm_surface_queue_h pp_tqueue;
+ tbm_surface_h pp_tsurface;
+ Eina_Bool pp_set_info;
+ Eina_Bool pp_set;
+ Eina_Bool pp_commit;
+ Eina_Bool pp_output_commit;
+ E_Hwc_Window_Commit_Data *pp_output_commit_data;
+ Eina_Rectangle pp_rect;
};
EINTERN E_Output_Hwc *e_output_hwc_new(E_Output *output);
--- /dev/null
+#include "e.h"
+#include "services/e_service_quickpanel.h"
+
+#define DBG_EVALUATE 1
+
+#define ZPOS_NONE -999
+
+static Eina_Bool _e_output_hwc_windows_pp_output_data_commit(E_Output_Hwc *output_hwc, E_Hwc_Window_Commit_Data *data);
+static Eina_Bool _e_output_hwc_windows_pp_window_commit(E_Output_Hwc *output_hwc, E_Hwc_Window *hwc_window);
+
+// if ec has invalid buffer or scaled( transformed ) or forced composite(never_hwc)
+static Eina_Bool
+_e_output_hwc_windows_device_state_check(E_Client *ec)
+{
+ E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
+ E_Output *eout;
+ int minw = 0, minh = 0;
+ int transform;
+
+ if ((!cdata) || (!cdata->buffer_ref.buffer))
+ {
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is forced to set CL state.(null cdata or buffer)",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+ return EINA_FALSE;
+ }
+
+ if ((cdata->width_from_buffer != cdata->width_from_viewport) ||
+ (cdata->height_from_buffer != cdata->height_from_viewport))
+ {
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is forced to set CL state.(size_from_viewport)",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+ return EINA_FALSE;
+ }
+
+ if (cdata->never_hwc)
+ {
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is forced to set CL state.(never_hwc)",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+ return EINA_FALSE;
+ }
+
+ if (e_client_transform_core_enable_get(ec))
+ {
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is forced to set CL state.(transfrom_core)",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+ return EINA_FALSE;
+ }
+
+ switch (cdata->buffer_ref.buffer->type)
+ {
+ case E_COMP_WL_BUFFER_TYPE_NATIVE:
+ break;
+ case E_COMP_WL_BUFFER_TYPE_TBM:
+ if (cdata->buffer_ref.buffer->resource)
+ break;
+ case E_COMP_WL_BUFFER_TYPE_SHM:
+ if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role))
+ break;
+ default:
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is forced to set CL state.(buffer_type)",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+ return EINA_FALSE;
+ }
+
+ eout = e_output_find(ec->zone->output_id);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(eout, EINA_FALSE);
+
+ tdm_output_get_available_size(eout->toutput, &minw, &minh, NULL, NULL, NULL);
+
+ if ((minw > 0) && (minw > cdata->buffer_ref.buffer->w))
+ {
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is forced to set CL state.(minw:%d > buffer->w:%d)",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title, minw, cdata->buffer_ref.buffer->w);
+ return EINA_FALSE;
+ }
+
+ if ((minh > 0) && (minh > cdata->buffer_ref.buffer->h))
+ {
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is forced to set CL state.(minh:%d > buffer->h:%d)",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title, minh, cdata->buffer_ref.buffer->h);
+ return EINA_FALSE;
+ }
+
+ transform = e_comp_wl_output_buffer_transform_get(ec);
+
+ /* If a client doesn't watch the ignore_output_transform events, we can't show
+ * a client buffer to HW overlay directly when the buffer transform is not same
+ * with output transform. If a client watch the ignore_output_transform events,
+ * we can control client's buffer transform. In this case, we don't need to
+ * check client's buffer transform here.
+ */
+ if (!e_comp_screen_rotation_ignore_output_transform_watch(ec))
+ {
+ if ((eout->config.rotation / 90) != transform)
+ {
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is forced to set CL state.(no igrore_transfrom)",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+ return EINA_FALSE;
+ }
+ }
+
+ return EINA_TRUE;
+}
+
+static E_Output_Hwc_Mode
+_e_output_hwc_windows_hwc_mode_get(E_Output_Hwc *output_hwc)
+{
+ Eina_List *l;
+ E_Hwc_Window *hwc_window;
+ E_Output_Hwc_Mode hwc_mode = E_OUTPUT_HWC_MODE_NONE;
+ int num_visible = 0;
+ int num_visible_client = 0;
+
+ EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+ {
+ if (e_hwc_window_is_target(hwc_window)) continue;
+
+ if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) continue;
+ if (hwc_window->state == E_HWC_WINDOW_STATE_VIDEO) continue;
+
+ if (hwc_window->state == E_HWC_WINDOW_STATE_CLIENT)
+ num_visible_client++;
+
+ num_visible++;
+ }
+
+ if (!num_visible)
+ hwc_mode = E_OUTPUT_HWC_MODE_NONE;
+ else if (num_visible_client > 0)
+ hwc_mode = E_OUTPUT_HWC_MODE_HYBRID;
+ else
+ hwc_mode = E_OUTPUT_HWC_MODE_FULL;
+
+ return hwc_mode;
+}
+
+static int
+_e_output_hwc_windows_sort_cb(const void *d1, const void *d2)
+{
+ E_Hwc_Window *hwc_window_1 = (E_Hwc_Window *)d1;
+ E_Hwc_Window *hwc_window_2 = (E_Hwc_Window *)d2;
+
+ if (!hwc_window_1) return(-1);
+ if (!hwc_window_2) return(1);
+
+ return (hwc_window_2->zpos - hwc_window_1->zpos);
+}
+
+static unsigned int
+_e_output_hwc_windows_aligned_width_get(tbm_surface_h tsurface)
+{
+ unsigned int aligned_width = 0;
+ tbm_surface_info_s surf_info;
+
+ tbm_surface_get_info(tsurface, &surf_info);
+
+ switch (surf_info.format)
+ {
+ case TBM_FORMAT_YUV420:
+ case TBM_FORMAT_YVU420:
+ case TBM_FORMAT_YUV422:
+ case TBM_FORMAT_YVU422:
+ case TBM_FORMAT_NV12:
+ case TBM_FORMAT_NV21:
+ aligned_width = surf_info.planes[0].stride;
+ break;
+ case TBM_FORMAT_YUYV:
+ case TBM_FORMAT_UYVY:
+ aligned_width = surf_info.planes[0].stride >> 1;
+ break;
+ case TBM_FORMAT_ARGB8888:
+ case TBM_FORMAT_XRGB8888:
+ aligned_width = surf_info.planes[0].stride >> 2;
+ break;
+ default:
+ ERR("not supported format: %x", surf_info.format);
+ }
+
+ return aligned_width;
+}
+
+
+
+static void
+_e_output_hwc_windows_commit_handler(tdm_output *toutput, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_data)
+{
+ const Eina_List *l;
+ E_Hwc_Window *hwc_window;
+ E_Output_Hwc *output_hwc = (E_Output_Hwc *)user_data;
+
+ EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+ if (output_hwc->pp_tsurface && !output_hwc->output->zoom_set)
+ {
+ tbm_surface_internal_unref(output_hwc->pp_tsurface);
+ output_hwc->pp_tsurface = NULL;
+ }
+
+ ELOGF("HWC-WINS", "!!!!!!!! Output Commit Handler !!!!!!!!", NULL, NULL);
+
+ EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, hwc_window)
+ {
+ if (!e_hwc_window_commit_data_release(hwc_window)) continue;
+ if (e_hwc_window_is_video(hwc_window))
+ {
+ ELOGF("HWC-WINS", "!!!!!!!! Output Commit Handler (VIDEO)!!!!!!!!", NULL, NULL);
+ e_comp_wl_video_hwc_window_commit_data_release(hwc_window, sequence, tv_sec, tv_usec);
+ }
+ }
+
+ /* 'wait_commit' is mechanism to make 'fetch and commit' no more than one time per a frame;
+ * a 'page flip' happened so it's time to allow to make 'fetch and commit' for the e_output */
+ output_hwc->wait_commit = EINA_FALSE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_prepare_commit(E_Output *output, E_Hwc_Window *hwc_window)
+{
+ if (!e_hwc_window_commit_data_aquire(hwc_window))
+ return EINA_FALSE;
+
+ /* send frame event enlightenment dosen't send frame evnet in nocomp */
+ if (hwc_window->ec)
+ e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_offscreen_commit(E_Output *output, E_Hwc_Window *hwc_window)
+{
+ if (!e_hwc_window_commit_data_aquire(hwc_window))
+ return EINA_FALSE;
+
+ /* send frame event enlightenment doesn't send frame event in nocomp */
+ if (hwc_window->ec)
+ e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
+
+ e_hwc_window_commit_data_release(hwc_window);
+
+ return EINA_TRUE;
+}
+
+static E_Hwc_Window *
+_e_output_hwc_windows_pp_window_get(E_Output_Hwc *output_hwc, tbm_surface_h tsurface)
+{
+ Eina_List *l;
+ E_Hwc_Window *hwc_window = NULL;
+
+ EINA_LIST_FOREACH(output_hwc->pp_hwc_window_list, l, hwc_window)
+ {
+ if (!hwc_window) continue;
+ if (!hwc_window->commit_data) continue;
+
+ if (hwc_window->commit_data->tsurface == tsurface)
+ return hwc_window;
+ }
+
+ return NULL;
+}
+
+static void
+_e_output_hwc_windows_pp_pending_data_remove(E_Output_Hwc *output_hwc)
+{
+ E_Hwc_Window_Commit_Data *data = NULL;
+ Eina_List *l = NULL, *ll = NULL;
+
+ if (eina_list_count(output_hwc->pending_pp_commit_data_list) != 0)
+ {
+ EINA_LIST_FOREACH_SAFE(output_hwc->pending_pp_commit_data_list, l, ll, data)
+ {
+ if (!data) continue;
+ output_hwc->pending_pp_commit_data_list = eina_list_remove_list(output_hwc->pending_pp_commit_data_list, l);
+ tbm_surface_queue_release(output_hwc->pp_tqueue, data->tsurface);
+ tbm_surface_internal_unref(data->tsurface);
+ E_FREE(data);
+ }
+ }
+ eina_list_free(output_hwc->pending_pp_commit_data_list);
+ output_hwc->pending_pp_commit_data_list = NULL;
+
+ if (eina_list_count(output_hwc->pending_pp_hwc_window_list) != 0)
+ {
+ E_Hwc_Window *hwc_window;
+ EINA_LIST_FOREACH_SAFE(output_hwc->pending_pp_hwc_window_list, l, ll, hwc_window)
+ {
+ if (!hwc_window) continue;
+ output_hwc->pending_pp_hwc_window_list = eina_list_remove_list(output_hwc->pending_pp_hwc_window_list, l);
+
+ if (hwc_window->ec) e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
+ e_hwc_window_commit_data_release(hwc_window);
+ }
+ }
+ eina_list_free(output_hwc->pending_pp_hwc_window_list);
+ output_hwc->pending_pp_hwc_window_list = NULL;
+}
+
+static void
+_e_output_hwc_windows_pp_output_commit_handler(tdm_output *toutput, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_data)
+{
+ E_Output_Hwc *output_hwc;
+ E_Hwc_Window_Commit_Data *data = NULL;
+ E_Output *output = NULL;
+ const Eina_List *l;
+ E_Hwc_Window *window;
+
+ EINA_SAFETY_ON_NULL_RETURN(user_data);
+
+ output_hwc = user_data;
+
+ output_hwc->pp_output_commit = EINA_FALSE;
+
+ EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, window)
+ {
+ if (window->commit_data && !window->commit_data->tsurface)
+ e_hwc_window_commit_data_release(window);
+ }
+
+ /* layer already resetted */
+ if (output_hwc->pp_output_commit_data)
+ {
+ data = output_hwc->pp_output_commit_data;
+ output_hwc->pp_output_commit_data = NULL;
+
+ /* if pp_set is false, do not deal with pending list */
+ if (!output_hwc->pp_set)
+ {
+ if (output_hwc->pp_tsurface)
+ tbm_surface_internal_unref(output_hwc->pp_tsurface);
+
+ output_hwc->pp_tsurface = data->tsurface;
+ output_hwc->wait_commit = EINA_FALSE;
+
+ E_FREE(data);
+
+ return;
+ }
+
+ if (output_hwc->pp_tqueue && output_hwc->pp_tsurface)
+ {
+ /* release and unref the current pp surface on the plane */
+ tbm_surface_queue_release(output_hwc->pp_tqueue, output_hwc->pp_tsurface);
+ tbm_surface_internal_unref(output_hwc->pp_tsurface);
+ }
+
+ /* set the new pp surface to the plane */
+ output_hwc->pp_tsurface = data->tsurface;
+
+ E_FREE(data);
+ }
+
+ ELOGF("HWC-WINS", "PP Output Commit Handler Output_Hwc(%p)", NULL, NULL, output_hwc);
+
+ output = output_hwc->output;
+ if (e_output_dpms_get(output))
+ {
+ _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+ return;
+ }
+
+ /* deal with the pending layer commit */
+ if (eina_list_count(output_hwc->pending_pp_commit_data_list) != 0)
+ {
+ data = eina_list_nth(output_hwc->pending_pp_commit_data_list, 0);
+ if (data)
+ {
+ output_hwc->pending_pp_commit_data_list = eina_list_remove(output_hwc->pending_pp_commit_data_list, data);
+
+ ELOGF("HWC-WINS", "PP Output Commit Handler start pending commit data(%p) tsurface(%p)", NULL, NULL, data, data->tsurface);
+
+ if (!_e_output_hwc_windows_pp_output_data_commit(output_hwc, data))
+ {
+ ERR("fail to _e_output_hwc_windows_pp_output_data_commit");
+ return;
+ }
+ }
+ }
+
+ /* deal with the pending pp commit */
+ if (eina_list_count(output_hwc->pending_pp_hwc_window_list) != 0)
+ {
+ E_Hwc_Window *hwc_window;
+
+ hwc_window = eina_list_nth(output_hwc->pending_pp_hwc_window_list, 0);
+ if (hwc_window)
+ {
+ if (!tbm_surface_queue_can_dequeue(output_hwc->pp_tqueue, 0))
+ return;
+
+ output_hwc->pending_pp_hwc_window_list = eina_list_remove(output_hwc->pending_pp_hwc_window_list, hwc_window);
+
+ if (data)
+ ELOGF("HWC-WINS", "PP Layer Commit Handler start pending pp data(%p) tsurface(%p)", NULL, NULL, data, data->tsurface);
+ else
+ ELOGF("HWC-WINS", "PP Layer Commit Handler start pending pp data(%p) tsurface(%p)", NULL, NULL, NULL, NULL);
+
+ if (!_e_output_hwc_windows_pp_window_commit(output_hwc, hwc_window))
+ {
+ ERR("fail _e_output_hwc_windows_pp_data_commit");
+ e_hwc_window_commit_data_release(hwc_window);
+ return;
+ }
+ }
+ }
+}
+
+static Eina_Bool
+_e_output_hwc_windows_pp_output_data_commit(E_Output_Hwc *output_hwc, E_Hwc_Window_Commit_Data *data)
+{
+ E_Output *output = NULL;
+ tdm_layer *toutput = NULL;
+ tdm_error terror;
+ tdm_hwc_region fb_damage;
+
+ /* the damage isn't supported by hwc extension yet */
+ memset(&fb_damage, 0, sizeof(fb_damage));
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
+
+ output = output_hwc->output;
+ toutput = output->toutput;
+
+ if (e_output_dpms_get(output))
+ {
+ _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+ goto fail;
+ }
+
+ /* no need to pass composited_wnds list because smooth transition isn't
+ * used is this case */
+ terror = tdm_output_hwc_set_client_target_buffer(toutput, data->tsurface, fb_damage);
+ if (terror != TDM_ERROR_NONE)
+ {
+ ERR("fail to tdm_output_hwc_set_client_target_buffer");
+ goto fail;
+ }
+
+ terror = tdm_output_commit(toutput, 0, _e_output_hwc_windows_pp_output_commit_handler, output_hwc);
+
+ if (terror != TDM_ERROR_NONE)
+ {
+ ERR("fail to tdm_output_commit output_hwc:%p", output_hwc);
+ goto fail;
+ }
+
+ output_hwc->pp_output_commit = EINA_TRUE;
+ output_hwc->pp_output_commit_data = data;
+
+ return EINA_TRUE;
+
+fail:
+ tbm_surface_internal_unref(data->tsurface);
+ tbm_surface_queue_release(output_hwc->pp_tqueue, data->tsurface);
+ E_FREE(data);
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_pp_output_commit(E_Output_Hwc *output_hwc, tbm_surface_h tsurface)
+{
+ tbm_surface_h pp_tsurface = NULL;
+ tbm_error_e tbm_err;
+ E_Hwc_Window_Commit_Data *data = NULL;
+
+ ELOGF("HWC-WINS", "PP Layer Commit output_hwc(%p) pp_tsurface(%p)", NULL, NULL, output_hwc, tsurface);
+
+ tbm_err = tbm_surface_queue_enqueue(output_hwc->pp_tqueue, tsurface);
+ if (tbm_err != TBM_ERROR_NONE)
+ {
+ ERR("fail tbm_surface_queue_enqueue");
+ goto fail;
+ }
+
+ tbm_err = tbm_surface_queue_acquire(output_hwc->pp_tqueue, &pp_tsurface);
+ if (tbm_err != TBM_ERROR_NONE)
+ {
+ ERR("fail tbm_surface_queue_acquire");
+ goto fail;
+ }
+
+ data = E_NEW(E_Hwc_Window_Commit_Data, 1);
+ if (!data) goto fail;
+ data->tsurface = pp_tsurface;
+ tbm_surface_internal_ref(data->tsurface);
+
+ if (output_hwc->pp_output_commit)
+ {
+ output_hwc->pending_pp_commit_data_list = eina_list_append(output_hwc->pending_pp_commit_data_list, data);
+ return EINA_TRUE;
+ }
+
+ if (!_e_output_hwc_windows_pp_output_data_commit(output_hwc, data))
+ {
+ ERR("fail to _e_output_hwc_windows_pp_output_data_commit");
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+
+fail:
+ tbm_surface_queue_release(output_hwc->pp_tqueue, tsurface);
+ if (pp_tsurface && pp_tsurface != tsurface)
+ tbm_surface_queue_release(output_hwc->pp_tqueue, pp_tsurface);
+
+ return EINA_FALSE;
+}
+
+static void
+_e_output_hwc_windows_pp_commit_handler(tdm_pp *pp, tbm_surface_h tsurface_src, tbm_surface_h tsurface_dst, void *user_data)
+{
+ E_Output *output = NULL;
+ E_Output_Hwc *output_hwc = NULL;
+ E_Hwc_Window *hwc_window = NULL;
+
+ output_hwc = (E_Output_Hwc *)user_data;
+ EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+ hwc_window = _e_output_hwc_windows_pp_window_get(output_hwc, tsurface_src);
+ EINA_SAFETY_ON_NULL_RETURN(hwc_window);
+
+ output_hwc->pp_hwc_window_list = eina_list_remove(output_hwc->pp_hwc_window_list, hwc_window);
+
+ if (hwc_window->ec) e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
+ e_hwc_window_commit_data_release(hwc_window);
+
+ if (eina_list_count(output_hwc->pending_pp_hwc_window_list) == 0)
+ {
+ output_hwc->wait_commit = EINA_FALSE;
+ output_hwc->pp_commit = EINA_FALSE;
+ }
+
+ ELOGF("HWC-WINS", "PP Commit Handler output_hwc(%p) tsurface src(%p) dst(%p)",
+ NULL, NULL, output_hwc, tsurface_src, tsurface_dst);
+
+ /* if pp_set is false, skip the commit */
+ if (!output_hwc->pp_set)
+ {
+ if (output_hwc->tpp)
+ {
+ tdm_pp_destroy(output_hwc->tpp);
+ output_hwc->tpp = NULL;
+ }
+ goto done;
+ }
+
+ output = output_hwc->output;
+ if (e_output_dpms_get(output))
+ {
+ _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+ tbm_surface_queue_release(output_hwc->pp_tqueue, tsurface_dst);
+
+ goto done;
+ }
+
+ if (!_e_output_hwc_windows_pp_output_commit(output_hwc, tsurface_dst))
+ ERR("fail to _e_output_hwc_windows_pp_output_commit");
+
+done:
+ tbm_surface_internal_unref(tsurface_src);
+ tbm_surface_internal_unref(tsurface_dst);
+}
+
+static Eina_Bool
+_e_output_hwc_pp_windows_info_set(E_Output_Hwc *output_hwc, E_Hwc_Window *hwc_window,
+ tbm_surface_h dst_tsurface)
+{
+ tdm_info_pp pp_info;
+ tdm_error ret = TDM_ERROR_NONE;
+ unsigned int aligned_width_src = 0, aligned_width_dst = 0;
+ tbm_surface_info_s surf_info_src, surf_info_dst;
+ tbm_surface_h src_tsurface = hwc_window->commit_data->tsurface;
+
+ /* when the pp_set_info is true, change the pp set_info */
+ if (!output_hwc->pp_set_info) return EINA_TRUE;
+ output_hwc->pp_set_info = EINA_FALSE;
+
+ tbm_surface_get_info(src_tsurface, &surf_info_src);
+
+ aligned_width_src = _e_output_hwc_windows_aligned_width_get(src_tsurface);
+ if (aligned_width_src == 0) return EINA_FALSE;
+
+ tbm_surface_get_info(dst_tsurface, &surf_info_dst);
+
+ aligned_width_dst = _e_output_hwc_windows_aligned_width_get(dst_tsurface);
+ if (aligned_width_dst == 0) return EINA_FALSE;
+
+ pp_info.src_config.size.h = aligned_width_src;
+ pp_info.src_config.size.v = surf_info_src.height;
+ pp_info.src_config.format = surf_info_src.format;
+
+ pp_info.dst_config.size.h = aligned_width_dst;
+ pp_info.dst_config.size.v = surf_info_dst.height;
+ pp_info.dst_config.format = surf_info_dst.format;
+
+ pp_info.transform = TDM_TRANSFORM_NORMAL;
+ pp_info.sync = 0;
+ pp_info.flags = 0;
+
+ pp_info.src_config.pos.x = output_hwc->pp_rect.x;
+ pp_info.src_config.pos.y = output_hwc->pp_rect.y;
+ pp_info.src_config.pos.w = output_hwc->pp_rect.w;
+ pp_info.src_config.pos.h = output_hwc->pp_rect.h;
+ pp_info.dst_config.pos.x = 0;
+ pp_info.dst_config.pos.y = 0;
+ pp_info.dst_config.pos.w = surf_info_dst.width;
+ pp_info.dst_config.pos.h = surf_info_dst.height;
+
+ ret = tdm_pp_set_info(output_hwc->tpp, &pp_info);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
+
+ ELOGF("HWC-WINS", "PP Info Output_Hwc(%p) src_rect(%d,%d),(%d,%d), dst_rect(%d,%d),(%d,%d)",
+ NULL, NULL, output_hwc,
+ pp_info.src_config.pos.x, pp_info.src_config.pos.y, pp_info.src_config.pos.w, pp_info.src_config.pos.h,
+ pp_info.dst_config.pos.x, pp_info.dst_config.pos.y, pp_info.dst_config.pos.w, pp_info.dst_config.pos.h);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_pp_window_commit(E_Output_Hwc *output_hwc, E_Hwc_Window *hwc_window)
+{
+ E_Output *output = NULL;
+ tbm_surface_h pp_tsurface = NULL;
+ tbm_error_e tbm_err = TBM_ERROR_NONE;
+ tdm_error terror = TDM_ERROR_NONE;
+ E_Hwc_Window_Commit_Data *commit_data = hwc_window->commit_data;
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(commit_data, EINA_FALSE);
+
+ tbm_surface_h tsurface = commit_data->tsurface;
+
+ ELOGF("HWC-WINS", "PP Commit Output_Hwc(%p) tsurface(%p) tqueue(%p) wl_buffer(%p) data(%p)",
+ NULL, NULL, output_hwc, commit_data->tsurface, output_hwc->pp_tqueue,
+ commit_data->buffer_ref.buffer ? commit_data->buffer_ref.buffer->resource : NULL, commit_data);
+
+ output = output_hwc->output;
+ if (e_output_dpms_get(output))
+ {
+ _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+ return EINA_FALSE;
+ }
+
+ tbm_err = tbm_surface_queue_dequeue(output_hwc->pp_tqueue, &pp_tsurface);
+ if (tbm_err != TBM_ERROR_NONE)
+ {
+ ERR("fail tbm_surface_queue_dequeue");
+ return EINA_FALSE;
+ }
+
+ if (!_e_output_hwc_pp_windows_info_set(output_hwc, hwc_window, pp_tsurface))
+ {
+ ERR("fail _e_output_hwc_windows_info_set");
+ goto pp_fail;
+ }
+
+ terror = tdm_pp_set_done_handler(output_hwc->tpp, _e_output_hwc_windows_pp_commit_handler, output_hwc);
+ EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, pp_fail);
+
+ tbm_surface_internal_ref(pp_tsurface);
+ tbm_surface_internal_ref(commit_data->tsurface);
+ terror = tdm_pp_attach(output_hwc->tpp, commit_data->tsurface, pp_tsurface);
+ EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, attach_fail);
+
+ output_hwc->pp_hwc_window_list = eina_list_append(output_hwc->pp_hwc_window_list, hwc_window);
+
+ terror = tdm_pp_commit(output_hwc->tpp);
+ EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, commit_fail);
+
+ output_hwc->wait_commit = EINA_TRUE;
+ output_hwc->pp_commit = EINA_TRUE;
+
+ return EINA_TRUE;
+
+commit_fail:
+ output_hwc->pp_hwc_window_list = eina_list_remove(output_hwc->pp_hwc_window_list, hwc_window);
+attach_fail:
+ tbm_surface_internal_unref(pp_tsurface);
+ tbm_surface_internal_unref(tsurface);
+pp_fail:
+ tbm_surface_queue_release(output_hwc->pp_tqueue, pp_tsurface);
+
+ ERR("failed _e_output_hwc_windows_pp_data_commit");
+
+ return EINA_FALSE;
+}
+
+static E_Hwc_Window *
+_e_output_hwc_windows_pp_get_hwc_window_for_zoom(E_Output_Hwc *output_hwc)
+{
+ const Eina_List *hwc_windows, *l;
+ E_Hwc_Window *hwc_window = NULL;
+ E_Hwc_Window *hwc_window_for_zoom = NULL;
+ int num = 0;
+ int w, h;
+
+ e_output_size_get(output_hwc->output, &w, &h);
+
+ hwc_windows = e_output_hwc_windows_get(output_hwc);
+ EINA_LIST_FOREACH(hwc_windows, l, hwc_window)
+ {
+ if (!e_hwc_window_is_on_hw_overlay(hwc_window)) continue;
+
+ hwc_window_for_zoom = hwc_window;
+ num++;
+ }
+
+ if (num != 1) return NULL;
+ if (!hwc_window_for_zoom->tsurface) return NULL;
+ if (tbm_surface_get_width(hwc_window_for_zoom->tsurface) != w ||
+ tbm_surface_get_height(hwc_window_for_zoom->tsurface) != h)
+ return NULL;
+
+ return hwc_window_for_zoom;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_pp_commit(E_Output_Hwc *output_hwc)
+{
+ E_Hwc_Window_Commit_Data *commit_data = NULL;
+ E_Hwc_Window *hwc_window = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc->pp_tqueue, EINA_FALSE);
+
+ hwc_window = _e_output_hwc_windows_pp_get_hwc_window_for_zoom(output_hwc);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
+
+ commit_data = hwc_window->commit_data;
+ if (!commit_data) return EINA_TRUE;
+ if (!commit_data->tsurface) return EINA_TRUE;
+
+ if (!tbm_surface_queue_can_dequeue(output_hwc->pp_tqueue, 0))
+ {
+ ELOGF("HWC-WINS", "PP Commit Can Dequeue failed Output_Hwc(%p) tsurface(%p) tqueue(%p) wl_buffer(%p) data(%p)",
+ NULL, NULL, output_hwc, commit_data->tsurface, output_hwc->pp_tqueue,
+ commit_data->buffer_ref.buffer ? commit_data->buffer_ref.buffer->resource : NULL, commit_data);
+ output_hwc->pending_pp_hwc_window_list = eina_list_append(output_hwc->pending_pp_hwc_window_list, hwc_window);
+
+ output_hwc->wait_commit = EINA_TRUE;
+
+ return EINA_TRUE;
+ }
+
+ if (eina_list_count(output_hwc->pending_pp_hwc_window_list) != 0)
+ {
+ ELOGF("HWC-WINS", "PP Commit Pending pp data remained Output_Hwc(%p) tsurface(%p) tqueue(%p) wl_buffer(%p) data(%p)",
+ NULL, NULL, output_hwc, commit_data->tsurface, output_hwc->pp_tqueue,
+ commit_data->buffer_ref.buffer ? commit_data->buffer_ref.buffer->resource : NULL, commit_data);
+ output_hwc->pending_pp_hwc_window_list = eina_list_append(output_hwc->pending_pp_hwc_window_list, hwc_window);
+
+ output_hwc->wait_commit = EINA_TRUE;
+
+ return EINA_TRUE;
+ }
+
+ if (!_e_output_hwc_windows_pp_window_commit(output_hwc, hwc_window))
+ {
+ ERR("fail _e_output_hwc_windows_pp_data_commit");
+ e_hwc_window_commit_data_release(hwc_window);
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_e_output_hwc_windows_status_print(E_Output_Hwc *output_hwc, Eina_Bool with_target)
+{
+ const Eina_List *l;
+ Eina_List *sort_wnds;
+ E_Hwc_Window *hwc_window;
+
+ sort_wnds = eina_list_clone(output_hwc->hwc_windows);
+ sort_wnds = eina_list_sort(sort_wnds, eina_list_count(sort_wnds), _e_output_hwc_windows_sort_cb);
+
+ EINA_LIST_FOREACH(sort_wnds, l, hwc_window)
+ {
+ if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) continue;
+
+ if (e_hwc_window_is_target(hwc_window))
+ {
+ if (!with_target) continue;
+
+ ELOGF("HWC-WINS", " ehw:%p ts:%p -- {%25s}, state:%s",
+ NULL, NULL, hwc_window, hwc_window->tsurface, "@TARGET WINDOW@",
+ e_hwc_window_state_string_get(hwc_window->state));
+ continue;
+ }
+
+ ELOGF("HWC-WINS", " ehw:%p ts:%p -- {%25s}, state:%s, zpos:%d, deleted:%s",
+ hwc_window->ec ? hwc_window->ec->pixmap : NULL, hwc_window->ec,
+ hwc_window, hwc_window->tsurface, hwc_window->ec ? hwc_window->ec->icccm.title : "UNKNOWN",
+ e_hwc_window_state_string_get(hwc_window->state),
+ hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no");
+ }
+
+ eina_list_free(sort_wnds);
+}
+
+static void
+_e_output_hwc_windows_ouput_commit_dump(E_Output_Hwc *output_hwc)
+{
+ const Eina_List *l;
+ Eina_List *sort_wnds;
+ E_Hwc_Window *hwc_window;
+ char fname[PATH_MAX];
+ Ecore_Window ec_win;
+ int i = 0;
+
+ sort_wnds = eina_list_clone(output_hwc->hwc_windows);
+ sort_wnds = eina_list_sort(sort_wnds, eina_list_count(sort_wnds), _e_output_hwc_windows_sort_cb);
+
+ EINA_LIST_FOREACH(sort_wnds, l, hwc_window)
+ {
+ if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) continue;
+
+ ec_win = e_client_util_win_get(hwc_window->ec);
+
+ if (e_hwc_window_is_target(hwc_window))
+ snprintf(fname, sizeof(fname), "(%d)_output_commit_0x%08x_%s", i++, ec_win, e_hwc_window_state_string_get(hwc_window->state));
+ else
+ snprintf(fname, sizeof(fname), "(%d)_output_commit_0x%08x_%s_%d", i++, ec_win, e_hwc_window_state_string_get(hwc_window->state), hwc_window->zpos);
+
+ tbm_surface_internal_dump_buffer(hwc_window->tsurface, fname);
+ }
+
+ eina_list_free(sort_wnds);
+}
+
+static E_Hwc_Window *
+_e_output_hwc_windows_window_find_by_twin(E_Output_Hwc *output_hwc, tdm_hwc_window *hwc_win)
+{
+ Eina_List *l;
+ E_Hwc_Window *hwc_window;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_win, NULL);
+
+ EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+ {
+ if (hwc_window->thwc_window == hwc_win) return hwc_window;
+ }
+
+ return NULL;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_compsitions_update(E_Output_Hwc *output_hwc)
+{
+ const Eina_List *l;
+ E_Hwc_Window *hwc_window;
+
+ EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, hwc_window)
+ {
+ if (e_hwc_window_is_target(hwc_window)) continue;
+
+ if (!e_hwc_window_compsition_update(hwc_window))
+ {
+ ERR("HWC-WINS: cannot update E_Hwc_Window(%p)", hwc_window);
+ return EINA_FALSE;
+ }
+ }
+
+#if DBG_EVALUATE
+ ELOGF("HWC-WINS", " Request HWC Validation to TDM HWC:", NULL, NULL);
+ _e_output_hwc_windows_status_print(output_hwc, EINA_FALSE);
+#endif
+
+ return EINA_TRUE;
+}
+
+static E_Hwc_Window_State
+_e_output_hwc_windows_window_state_get(tdm_hwc_window_composition composition_type)
+{
+ E_Hwc_Window_State state = E_HWC_WINDOW_STATE_NONE;
+
+ switch (composition_type)
+ {
+ case TDM_COMPOSITION_NONE:
+ state = E_HWC_WINDOW_STATE_NONE;
+ break;
+ case TDM_COMPOSITION_CLIENT:
+ state = E_HWC_WINDOW_STATE_CLIENT;
+ break;
+ case TDM_COMPOSITION_DEVICE:
+ state = E_HWC_WINDOW_STATE_DEVICE;
+ break;
+ case TDM_COMPOSITION_DEVICE_CANDIDATE:
+ state = E_HWC_WINDOW_STATE_DEVICE_CANDIDATE;
+ break;
+ case TDM_COMPOSITION_CURSOR:
+ state = E_HWC_WINDOW_STATE_CURSOR;
+ break;
+ case TDM_COMPOSITION_VIDEO:
+ state = E_HWC_WINDOW_STATE_VIDEO;
+ break;
+ default:
+ state = E_HWC_WINDOW_STATE_NONE;
+ ERR("HWC-WINS: unknown state of hwc_window.");
+ }
+
+ return state;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_accept(E_Output_Hwc *output_hwc, uint32_t num_changes)
+{
+ E_Output *output = output_hwc->output;
+ E_Hwc_Window *hwc_window;
+ E_Hwc_Window_State state;
+ tdm_error terror;
+ tdm_output *toutput = output->toutput;
+ tdm_hwc_window **changed_hwc_window = NULL;
+ tdm_hwc_window_composition *composition_types = NULL;
+ Eina_Bool accept_changes = EINA_TRUE;
+ int i;
+
+ changed_hwc_window = E_NEW(tdm_hwc_window *, num_changes);
+ EINA_SAFETY_ON_NULL_GOTO(changed_hwc_window, fail);
+
+ composition_types = E_NEW(tdm_hwc_window_composition, num_changes);
+ EINA_SAFETY_ON_NULL_GOTO(composition_types, fail);
+
+ terror = tdm_output_hwc_get_changed_composition_types(toutput,
+ &num_changes, changed_hwc_window,
+ composition_types);
+ if (terror != TDM_ERROR_NONE)
+ {
+ ERR("HWC-WINS: failed to get changed composition types");
+ goto fail;
+ }
+
+ ELOGF("HWC-WINS", " Accept Changes NUM : %d", NULL, NULL, num_changes);
+
+ for (i = 0; i < num_changes; ++i)
+ {
+ hwc_window = _e_output_hwc_windows_window_find_by_twin(output_hwc, changed_hwc_window[i]);
+ if (!hwc_window)
+ {
+ ERR("HWC-WINS: cannot find the E_Hwc_Window by hwc hwc_window");
+ goto fail;
+ }
+
+ /* accept_changes failed at DEVICE to CLIENT transition */
+ if (hwc_window->prev_state == E_HWC_WINDOW_STATE_DEVICE &&
+ composition_types[i] == TDM_COMPOSITION_CLIENT)
+ {
+ if (!e_hwc_window_is_on_target_window(hwc_window))
+ {
+ hwc_window->uncompleted_transition = E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT;
+ accept_changes = EINA_FALSE;
+
+ ELOGF("HWC-WINS", " E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT is set.(Accept_Changes)",
+ hwc_window->ec ? ec->pixmap : NULL, hwc_window->ec);
+ }
+ }
+
+ /* update the state with the changed compsition */
+ state = _e_output_hwc_windows_window_state_get(composition_types[i]);
+ e_hwc_window_state_set(hwc_window, state);
+ }
+
+#if DBG_EVALUATE
+ ELOGF("HWC-WINS", " Modified after HWC Validation:", NULL, NULL);
+ _e_output_hwc_windows_status_print(output_hwc, EINA_FALSE);
+#endif
+
+ /* re-validate when there is a DEVICE_TO_CLIENT transition */
+ if (!accept_changes) goto fail;
+
+ /* accept changes */
+ terror = tdm_output_hwc_accept_changes(toutput);
+ if (terror != TDM_ERROR_NONE)
+ {
+ ERR("HWC-WINS: failed to accept changes required by the hwc extension");
+ goto fail;
+ }
+
+ free(changed_hwc_window);
+ free(composition_types);
+
+ return EINA_TRUE;
+
+fail:
+ if (changed_hwc_window) free(changed_hwc_window);
+ if (composition_types) free(composition_types);
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_validate(E_Output_Hwc *output_hwc, Eina_List *visible_windows_list, uint32_t *num_changes)
+{
+ E_Output *output = output_hwc->output;
+ tdm_error terror;
+ tdm_output *toutput = output->toutput;
+ tdm_hwc_window **thwc_windows = NULL;
+ int i, n_thw;
+ E_Hwc_Window *hwc_window;
+ const Eina_List *l;
+
+ n_thw = eina_list_count(visible_windows_list);
+ if (n_thw)
+ {
+ thwc_windows = E_NEW(tdm_hwc_window *, n_thw);
+ EINA_SAFETY_ON_NULL_GOTO(thwc_windows, error);
+
+ i = 0;
+ EINA_LIST_FOREACH(visible_windows_list, l, hwc_window)
+ thwc_windows[i++] = hwc_window->thwc_window;
+ }
+
+ /* make hwc extension choose which clients will own hw overlays */
+ terror = tdm_output_hwc_validate(toutput, thwc_windows, n_thw, num_changes);
+ if (terror != TDM_ERROR_NONE) goto error;
+
+ E_FREE(thwc_windows);
+
+ return EINA_TRUE;
+
+error:
+ ERR("HWC-WINS: failed to validate the output(%p)", toutput);
+ E_FREE(thwc_windows);
+
+ return EINA_FALSE;
+}
+
+static void
+_e_output_hwc_windows_activation_states_update(E_Output_Hwc *output_hwc)
+{
+ E_Hwc_Window *hwc_window;
+ const Eina_List *l;
+
+ /* mark the active/deactive on hwc_window */
+ EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, hwc_window)
+ {
+ if (hwc_window->is_deleted) continue;
+ if (e_hwc_window_is_target(hwc_window)) continue;
+
+ if (e_hwc_window_is_on_hw_overlay(hwc_window))
+ /* notify the hwc_window that it will be displayed on hw layer */
+ e_hwc_window_activate(hwc_window);
+ else
+ /* notify the hwc_window that it will be composite on the target buffer */
+ e_hwc_window_deactivate(hwc_window);
+ }
+}
+
+static Eina_Bool
+_e_output_hwc_windows_target_window_render(E_Output *output, E_Hwc_Window_Target *target_hwc_window)
+{
+ if (target_hwc_window->hwc_window.state == E_HWC_WINDOW_STATE_NONE) return EINA_TRUE;
+
+ if (e_comp_canvas_norender_get() > 0)
+ {
+ ELOGF("HWC-WINS", " NoRender get. Do not ecore_evas_manual_render.", NULL, NULL);
+ return EINA_TRUE;
+ }
+
+ /* render the ecore_evas and
+ update_ee is to be true at post_render_cb when the render is successful. */
+ TRACE_DS_BEGIN(MANUAL RENDER);
+
+ if (e_hwc_window_target_surface_queue_can_dequeue(target_hwc_window))
+ {
+ ELOGF("HWC-WINS", "###### Render target window(ecore_evas_manual_render))", NULL, NULL);
+ ecore_evas_manual_render(target_hwc_window->ee);
+ }
+
+ TRACE_DS_END();
+
+ return EINA_TRUE;
+}
+
+static Eina_List *
+_e_output_hwc_windows_visible_windows_list_get(E_Output_Hwc *output_hwc)
+{
+ Eina_List *windows_list = NULL;
+ Eina_List *l;
+ E_Hwc_Window *hwc_window;
+ E_Client *ec;
+ Evas_Object *o;
+ int scr_w, scr_h;
+ int zpos = 0;
+ E_Comp_Wl_Client_Data *cdata = NULL;
+
+ for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
+ {
+ ec = evas_object_data_get(o, "E_Client");
+ if (!ec) continue;
+ if (!ec->hwc_window) continue;
+ if (e_object_is_del(E_OBJECT(ec))) continue;
+
+ hwc_window = ec->hwc_window;
+
+ // check clients to skip composite
+ if (e_client_util_ignored_get(ec) || (!evas_object_visible_get(ec->frame)))
+ {
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+ continue;
+ }
+
+ // check geometry if located out of screen such as quick panel
+ ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &scr_w, &scr_h);
+ if (!E_INTERSECTS(0, 0, scr_w, scr_h, ec->client.x, ec->client.y, ec->client.w, ec->client.h))
+ {
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+ e_hwc_window_zpos_set(hwc_window, ZPOS_NONE);
+ continue;
+ }
+
+ if (evas_object_data_get(ec->frame, "comp_skip"))
+ {
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+ continue;
+ }
+
+ /* skip all small clients except the video clients */
+ if ((ec->w == 1 || ec->h == 1) && !e_hwc_window_is_video(hwc_window))
+ {
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+ continue;
+ }
+
+ /* skip the cdata is null */
+ cdata = (E_Comp_Wl_Client_Data*)ec->comp_data;
+ if (!cdata)
+ {
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} cdata is NULL. Set E_HWC_WINDOW_STATE_NONE.",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+ continue;
+ }
+
+ /* skip the cdata->buffer_ref.buffer is null */
+ if (!cdata->buffer_ref.buffer)
+ {
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE);
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} cdata->buffer_ref.buffer is NULL. Set E_HWC_WINDOW_STATE_NONE.",
+ ec->pixmap, ec, ec->hwc_window, ec->icccm.title);
+ continue;
+ }
+
+ if (e_hwc_window_is_video(hwc_window))
+ {
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_VIDEO);
+ continue;
+ }
+
+ windows_list = eina_list_append(windows_list, hwc_window);
+ }
+
+ /* assign zpos */
+ EINA_LIST_REVERSE_FOREACH(windows_list, l, hwc_window)
+ e_hwc_window_zpos_set(hwc_window, zpos++);
+
+ output_hwc->num_visible_windows = eina_list_count(windows_list);
+
+#if DBG_EVALUATE
+ ELOGF("HWC-WINS", " The number of visible clients:%d.", NULL, NULL, output_hwc->num_visible_windows);
+#endif
+ return windows_list;
+}
+
+static Eina_Bool
+_e_output_hwc_windows_full_gl_composite_check(E_Output_Hwc *output_hwc, Eina_List *visible_windows_list)
+{
+ Eina_List *l;
+ E_Client *ec;
+ E_Hwc_Window *hwc_window = NULL;
+
+ /* make the full_gl_composite when the zoom is enabled */
+ if (output_hwc->output->zoom_set) goto full_gl_composite;
+
+ /* full composite is forced to be set */
+ if (e_output_hwc_deactive_get(output_hwc)) goto full_gl_composite;
+
+ /* hwc_window manager required full GLES composition */
+ if (e_comp->nocomp_override > 0)
+ {
+ ELOGF("HWC-WINS", " HWC_MODE_HYBRID due to nocomp_override > 0.", NULL, NULL);
+ goto full_gl_composite;
+ }
+
+ EINA_LIST_FOREACH(visible_windows_list, l, hwc_window)
+ {
+ ec = hwc_window->ec;
+
+ // if there is a ec which is lower than quickpanel and quickpanel is opened.
+ if (E_POLICY_QUICKPANEL_LAYER >= evas_object_layer_get(ec->frame))
+ {
+ // check whether quickpanel is open than break
+ if (e_qp_visible_get())
+ {
+ ELOGF("HWC-WINS", " HWC_MODE_NONE due to quickpanel is opened.{%25s}.",
+ ec->pixmap, ec, ec->icccm.title);
+ goto full_gl_composite;
+ }
+ }
+
+ // if ec->frame is not for client buffer (e.g. launchscreen)
+ if (e_comp_object_content_type_get(ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
+ {
+ ELOGF("HWC-WINS", " HWC_MODE_NONE due to E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE{%25s}.",
+ ec->pixmap, ec, ec->icccm.title);
+ goto full_gl_composite;
+ }
+
+ // if there is UI subfrace, it means need to composite
+ if (e_client_normal_client_has(ec))
+ {
+ ELOGF("HWC-WINS", " HWC_MODE_NONE due to UI subfrace{%25s}.",
+ ec->pixmap, ec, ec->icccm.title);
+ goto full_gl_composite;
+ }
+ }
+
+ return EINA_FALSE;
+
+full_gl_composite:
+ EINA_LIST_FOREACH(visible_windows_list, l, hwc_window)
+ {
+ /* The video window is not composited by gl compositor */
+ if (e_hwc_window_is_video(hwc_window)) continue;
+
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CLIENT);
+
+ ELOGF("HWC-WINS", " ehw:%p -- {%25s} is NOT hwc_acceptable.",
+ hwc_window->ec->pixmap, hwc_window->ec, hwc_window, hwc_window->ec->icccm.title);
+ }
+ return EINA_TRUE;
+}
+
+/* filter visible clients by the hwc_window manager
+ *
+ * returns list of clients which are acceptable to be composited by hw,
+ * it's a caller responsibility to free it
+ *
+ * for optimized hwc the returned list contains ALL clients
+ */
+static void
+_e_output_hwc_windows_hwc_acceptable_check(Eina_List *visible_windows_list)
+{
+ Eina_List *l;
+ E_Hwc_Window *hwc_window = NULL;
+
+ EINA_LIST_FOREACH(visible_windows_list, l, hwc_window)
+ {
+ /* The video window is not composited by gl compositor */
+ if (e_hwc_window_is_video(hwc_window)) continue;
+
+ // check clients are able to use hwc
+ if (_e_output_hwc_windows_device_state_check(hwc_window->ec))
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_DEVICE);
+ else
+ e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CLIENT);
+ }
+}
+
+static Eina_Bool
+_e_output_hwc_windows_composition_evaulate(E_Output_Hwc *output_hwc, Eina_List *visible_windows_list)
+{
+ Eina_Bool ret = EINA_FALSE;
+ uint32_t num_changes;
+
+ /* evaluate the transition */
+ if (!_e_output_hwc_windows_compsitions_update(output_hwc))
+ {
+ ERR("HWC-WINS: _e_output_hwc_windows_compsitions_update failed.");
+ ret = EINA_FALSE;
+ goto done;
+ }
+
+ /* validate the updated hwc_windows by asking tdm_hwc_output */
+ if (!_e_output_hwc_windows_validate(output_hwc, visible_windows_list, &num_changes))
+ {
+ ERR("HWC-WINS: _e_output_hwc_windows_validate failed.");
+ ret = EINA_FALSE;
+ goto done;
+ }
+
+ if (num_changes > 0)
+ {
+ if (_e_output_hwc_windows_accept(output_hwc, num_changes))
+ ret = EINA_TRUE;
+ else
+ ret = EINA_FALSE;
+ }
+ else
+ ret = EINA_TRUE;
+
+done:
+
+ return ret;
+}
+
+static Eina_List *
+_e_output_hwc_windows_states_evaluate(E_Output_Hwc *output_hwc)
+{
+ Eina_List *visible_windows_list = NULL;
+
+ /* get the visible ecs */
+ visible_windows_list = _e_output_hwc_windows_visible_windows_list_get(output_hwc);
+
+ /* check the gles composite with all hwc_windows. */
+ if (!_e_output_hwc_windows_full_gl_composite_check(output_hwc, visible_windows_list))
+ {
+ /* by demand of hwc_window manager to prevent some e_clients to be shown by hw directly */
+ _e_output_hwc_windows_hwc_acceptable_check(visible_windows_list);
+ }
+
+ return visible_windows_list;
+}
+
+/* evaluate the hwc_windows */
+static Eina_Bool
+_e_output_hwc_windows_evaluate(E_Output_Hwc *output_hwc, Eina_List *visible_windows_list)
+{
+ E_Output_Hwc_Mode hwc_mode = E_OUTPUT_HWC_MODE_NONE;
+ E_Hwc_Window *target_window = (E_Hwc_Window *)output_hwc->target_hwc_window;
+
+ ELOGF("HWC-WINS", "====================== Output HWC Apply (evaluate) ======================", NULL, NULL);
+
+ /* evaulate the compositions with the states*/
+ if (_e_output_hwc_windows_composition_evaulate(output_hwc, visible_windows_list))
+ ELOGF("HWC-WINS", " Succeed the compsition_evaulation.", NULL, NULL);
+ else
+ ELOGF("HWC-WINS", " Need the comopsition re-evaulation.", NULL, NULL);
+
+ /* update the activate/decativate state */
+ _e_output_hwc_windows_activation_states_update(output_hwc);
+
+ /* decide the E_OUTPUT_HWC_MODE */
+ hwc_mode = _e_output_hwc_windows_hwc_mode_get(output_hwc);
+ if (output_hwc->hwc_mode != hwc_mode)
+ {
+ if (hwc_mode == E_OUTPUT_HWC_MODE_HYBRID || hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+ ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
+ else
+ ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
+
+ output_hwc->hwc_mode = hwc_mode;
+ }
+
+#if DBG_EVALUATE
+ if (hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+ ELOGF("HWC-WINS", " HWC_MODE is NONE composition.", NULL, NULL);
+ else if (hwc_mode == E_OUTPUT_HWC_MODE_HYBRID)
+ ELOGF("HWC-WINS", " HWC_MODE is HYBRID composition.", NULL, NULL);
+ else
+ ELOGF("HWC-WINS", " HWC_MODE is FULL HW composition.", NULL, NULL);
+#endif
+
+ /* set the state of the target_window */
+ if (hwc_mode == E_OUTPUT_HWC_MODE_HYBRID || hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+ e_hwc_window_state_set(target_window, E_HWC_WINDOW_STATE_DEVICE);
+ else
+ e_hwc_window_state_set(target_window, E_HWC_WINDOW_STATE_NONE);
+
+ /* target state is DEVICE and no surface, then return false */
+ if (e_hwc_window_state_get(target_window) == E_HWC_WINDOW_STATE_DEVICE &&
+ target_window->tsurface == NULL)
+ {
+ ELOGF("HWC-WINS", "Need target_window buffer.", NULL, NULL);
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_e_output_hwc_windows_prev_states_update(E_Output_Hwc *output_hwc)
+{
+ E_Hwc_Window *hwc_window = NULL;
+ Eina_List *l;
+
+ EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+ e_hwc_window_prev_state_update(hwc_window);
+}
+
+/* check if there is a need to update the output */
+static Eina_Bool
+_e_output_hwc_windows_update_changes(E_Output_Hwc *output_hwc)
+{
+ const Eina_List *l;
+ E_Hwc_Window *hwc_window;
+ Eina_Bool update_changes = EINA_FALSE;
+
+ /* fetch the target buffer */
+ if (e_hwc_window_target_buffer_fetch(output_hwc->target_hwc_window)) // try aquire
+ update_changes = EINA_TRUE;
+
+ /* fetch the windows buffers */
+ EINA_LIST_FOREACH(e_output_hwc_windows_get(output_hwc), l, hwc_window)
+ {
+ if (e_hwc_window_is_target(hwc_window)) continue;
+
+ if (!e_hwc_window_buffer_fetch(hwc_window))
+ continue;
+
+ if (!e_hwc_window_buffer_update(hwc_window))
+ {
+ ERR("HWC-WINS: cannot update E_Hwc_Window(%p)", hwc_window);
+ continue;
+ }
+
+ update_changes = EINA_TRUE;
+ }
+
+ return update_changes;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_init(E_Output_Hwc *output_hwc)
+{
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_output_hwc_windows_deinit(void)
+{
+ // TDOO:
+ ;;;
+}
+
+EINTERN const Eina_List *
+e_output_hwc_windows_get(E_Output_Hwc *output_hwc)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, NULL);
+
+ return output_hwc->hwc_windows;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_render(E_Output_Hwc *output_hwc)
+{
+ E_Output *output = output_hwc->output;
+ E_Hwc_Window_Target *target_hwc_window;
+
+ target_hwc_window = output_hwc->target_hwc_window;
+ if (!target_hwc_window)
+ {
+ ERR("fail to get target hwc_window for output(%p).", output);
+ return EINA_FALSE;
+ }
+
+ if (!_e_output_hwc_windows_target_window_render(output, target_hwc_window))
+ ERR("fail to render output(%p).", output);
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_commit(E_Output_Hwc *output_hwc)
+{
+ E_Hwc_Window *hwc_window = NULL;
+ Eina_List *l;
+ E_Output *output = NULL;
+ tdm_error error = TDM_ERROR_NONE;
+ Eina_List *visible_windows_list = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+ output = output_hwc->output;
+
+ if (output_hwc->wait_commit)
+ {
+ ELOGF("HWC-WINS", "!!!!!!!! Didn't get Output Commit Handler Yet !!!!!!!!", NULL, NULL);
+ return EINA_TRUE;
+ }
+
+ if (e_comp_canvas_norender_get() > 0)
+ {
+ ELOGF("HWC-WINS", " Block Display... NoRender get.", NULL, NULL);
+ return EINA_TRUE;
+ }
+
+ if (output->dpms == E_OUTPUT_DPMS_OFF)
+ {
+ EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+ _e_output_hwc_windows_offscreen_commit(output, hwc_window);
+
+ return EINA_TRUE;
+ }
+
+ /* evaulate the current states */
+ visible_windows_list = _e_output_hwc_windows_states_evaluate(output_hwc);
+
+ if (_e_output_hwc_windows_update_changes(output_hwc) ||
+ output_hwc->hwc_mode == E_OUTPUT_HWC_MODE_NONE)
+ {
+ if (!_e_output_hwc_windows_evaluate(output_hwc, visible_windows_list))
+ {
+ ELOGF("HWC-WINS", "Evaluation is not completed. No Commit at this time.", NULL, NULL);
+ /* update the previous states. */
+ _e_output_hwc_windows_prev_states_update(output_hwc);
+ goto fail;
+ }
+
+ EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+ _e_output_hwc_windows_prepare_commit(output, hwc_window);
+
+ if (output->zoom_set)
+ {
+ e_output_zoom_rotating_check(output);
+ ELOGF("HWC-WINS", "###### PP Commit", NULL, NULL);
+ if (!_e_output_hwc_windows_pp_commit(output_hwc))
+ {
+ ERR("_e_output_hwc_windows_pp_commit failed.");
+ goto fail;
+ }
+ }
+ else
+ {
+ ELOGF("HWC-WINS", "!!!!!!!! Output Commit !!!!!!!!", NULL, NULL);
+ ELOGF("HWC-WINS", " The number of visible clients:%d.", NULL, NULL, output_hwc->num_visible_windows);
+ _e_output_hwc_windows_status_print(output_hwc, EINA_TRUE);
+ _e_output_hwc_windows_ouput_commit_dump(output_hwc);
+
+ error = tdm_output_commit(output->toutput, 0, _e_output_hwc_windows_commit_handler, output_hwc);
+ if (error != TDM_ERROR_NONE)
+ {
+ ERR("tdm_output_commit failed.");
+ _e_output_hwc_windows_commit_handler(output->toutput, 0, 0, 0, output_hwc);
+ goto fail;
+ }
+
+ output_hwc->wait_commit = EINA_TRUE;
+ }
+
+ /* update the previous states. */
+ _e_output_hwc_windows_prev_states_update(output_hwc);
+ }
+
+ if (visible_windows_list)
+ eina_list_free(visible_windows_list);
+
+ return EINA_TRUE;
+
+fail:
+
+ if (visible_windows_list)
+ eina_list_free(visible_windows_list);
+
+ return EINA_FALSE;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_pp_commit_possible_check(E_Output_Hwc *output_hwc)
+{
+ if (!output_hwc->pp_set) return EINA_FALSE;
+
+ if (output_hwc->pp_tqueue)
+ {
+ if (!tbm_surface_queue_can_dequeue(output_hwc->pp_tqueue, 0))
+ return EINA_FALSE;
+ }
+
+ if (output_hwc->pending_pp_hwc_window_list)
+ {
+ if (eina_list_count(output_hwc->pending_pp_hwc_window_list) != 0)
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_output_hwc_windows_zoom_set(E_Output_Hwc *output_hwc, Eina_Rectangle *rect)
+{
+ E_Comp_Screen *e_comp_screen = NULL;
+ tdm_error ret = TDM_ERROR_NONE;
+ int w, h;
+ Eina_List *l;
+ E_Hwc_Window *hwc_window;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output_hwc, EINA_FALSE);
+
+ if ((output_hwc->pp_rect.x == rect->x) &&
+ (output_hwc->pp_rect.y == rect->y) &&
+ (output_hwc->pp_rect.w == rect->w) &&
+ (output_hwc->pp_rect.h == rect->h))
+ return EINA_TRUE;
+
+ e_comp_screen = e_comp->e_comp_screen;
+ e_output_size_get(output_hwc->output, &w, &h);
+
+ if (!output_hwc->tpp)
+ {
+ output_hwc->tpp = tdm_display_create_pp(e_comp_screen->tdisplay, &ret);
+ if (ret != TDM_ERROR_NONE)
+ {
+ ERR("fail tdm pp create");
+ goto fail;
+ }
+ }
+
+ if (!output_hwc->pp_tqueue)
+ {
+ //TODO: Does e20 get the buffer flags from the tdm backend?
+ output_hwc->pp_tqueue = tbm_surface_queue_create(3, w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+ if (!output_hwc->pp_tqueue)
+ {
+ ERR("fail tbm_surface_queue_create");
+ goto fail;
+ }
+ }
+
+ output_hwc->pp_rect.x = rect->x;
+ output_hwc->pp_rect.y = rect->y;
+ output_hwc->pp_rect.w = rect->w;
+ output_hwc->pp_rect.h = rect->h;
+
+ output_hwc->pp_set = EINA_TRUE;
+ output_hwc->target_hwc_window->skip_surface_set = EINA_TRUE;
+ output_hwc->pp_set_info = EINA_TRUE;
+
+ EINA_LIST_FOREACH(output_hwc->hwc_windows, l, hwc_window)
+ {
+ if (e_hwc_window_state_get(hwc_window) ==E_HWC_WINDOW_STATE_NONE) continue;
+ if (e_hwc_window_is_target(hwc_window)) continue;
+ if (e_hwc_window_is_video(hwc_window)) continue;
+
+ hwc_window->update_exist = EINA_TRUE;
+ }
+
+ /* to wake up main loop */
+ uint64_t value = 1;
+ if (write(output_hwc->target_hwc_window->event_fd, &value, sizeof(value)) < 0)
+ ERR("failed to wake up main loop:%m");
+
+ return EINA_TRUE;
+
+fail:
+ if (output_hwc->tpp)
+ {
+ tdm_pp_destroy(output_hwc->tpp);
+ output_hwc->tpp = NULL;
+ }
+
+ return EINA_FALSE;
+}
+
+EINTERN void
+e_output_hwc_windows_zoom_unset(E_Output_Hwc *output_hwc)
+{
+ EINA_SAFETY_ON_NULL_RETURN(output_hwc);
+
+ output_hwc->pp_set_info = EINA_FALSE;
+ output_hwc->target_hwc_window->skip_surface_set = EINA_FALSE;
+ output_hwc->pp_set = EINA_FALSE;
+
+ output_hwc->pp_rect.x = 0;
+ output_hwc->pp_rect.y = 0;
+ output_hwc->pp_rect.w = 0;
+ output_hwc->pp_rect.h = 0;
+
+ _e_output_hwc_windows_pp_pending_data_remove(output_hwc);
+
+ if (output_hwc->pp_tsurface)
+ tbm_surface_queue_release(output_hwc->pp_tqueue, output_hwc->pp_tsurface);
+
+ if (output_hwc->pp_tqueue)
+ {
+ tbm_surface_queue_destroy(output_hwc->pp_tqueue);
+ output_hwc->pp_tqueue = NULL;
+ }
+
+ if (!output_hwc->pp_commit)
+ {
+ if (output_hwc->tpp)
+ {
+ tdm_pp_destroy(output_hwc->tpp);
+ output_hwc->tpp = NULL;
+ }
+ }
+
+ if (output_hwc->pp_output_commit_data)
+ output_hwc->wait_commit = EINA_TRUE;
+
+ /* to wake up main loop */
+ uint64_t value = 1;
+ if (write(output_hwc->target_hwc_window->event_fd, &value, sizeof(value)) < 0)
+ ERR("failed to wake up main loop:%m");
+}
+
--- /dev/null
+#ifdef E_TYPEDEFS
+#else
+#ifndef E_OUTPUT_HWC_WINDOWS_H
+#define E_OUTPUT_HWC_WINDOWS_H
+
+EINTERN Eina_Bool e_output_hwc_windows_init(E_Output_Hwc *output_hwc);
+EINTERN void e_output_hwc_windows_deinit(void);
+
+EINTERN const Eina_List *e_output_hwc_windows_get(E_Output_Hwc *output_hwc);
+EINTERN Eina_Bool e_output_hwc_windows_render(E_Output_Hwc *output_hwc);
+EINTERN Eina_Bool e_output_hwc_windows_commit(E_Output_Hwc *output_hwc);
+
+EINTERN Eina_Bool e_output_hwc_windows_pp_commit_possible_check(E_Output_Hwc *output_hwc);
+EINTERN Eina_Bool e_output_hwc_windows_zoom_set(E_Output_Hwc *output_hwc, Eina_Rectangle *rect);
+EINTERN void e_output_hwc_windows_zoom_unset(E_Output_Hwc *output_hwc);
+
+#endif
+#endif
tdm_error ret = TDM_ERROR_NONE;
E_Plane *plane_primary_output_fb = NULL;
- plane_primary_output_fb = e_output_fb_target_get(plane->output_primary);
- EINA_SAFETY_ON_NULL_RETURN_VAL(plane_primary_output_fb, NULL);
-
if (plane->ext_state == E_OUTPUT_EXT_MIRROR)
{
- if ((plane->pp_rect.x != plane->mirror_rect.x) ||
- (plane->pp_rect.y != plane->mirror_rect.y) ||
- (plane->pp_rect.w != plane->mirror_rect.w) ||
- (plane->pp_rect.h != plane->mirror_rect.h))
- e_plane_zoom_set(plane, &plane->mirror_rect);
+ if (e_output_hwc_policy_get(plane->output_primary->output_hwc) == E_OUTPUT_HWC_POLICY_PLANES)
+ {
+ plane_primary_output_fb = e_output_fb_target_get(plane->output_primary);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(plane_primary_output_fb, NULL);
- tsurface = tdm_layer_get_displaying_buffer(plane_primary_output_fb->tlayer, &ret);
- EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, NULL);
+ if ((plane->pp_rect.x != plane->mirror_rect.x) ||
+ (plane->pp_rect.y != plane->mirror_rect.y) ||
+ (plane->pp_rect.w != plane->mirror_rect.w) ||
+ (plane->pp_rect.h != plane->mirror_rect.h))
+ e_plane_zoom_set(plane, &plane->mirror_rect);
+
+ tsurface = tdm_layer_get_displaying_buffer(plane_primary_output_fb->tlayer, &ret);
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, NULL);
+ }
+ else
+ {
+ tsurface = plane->output_primary->output_hwc->target_hwc_window->hwc_window.tsurface;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, NULL);
+ }
}
else if (plane->ext_state == E_OUTPUT_EXT_PRESENTATION)
{