#define IS_RGB(f) ((f) == TBM_FORMAT_XRGB8888 || (f) == TBM_FORMAT_ARGB8888)
-EINTERN void
-e_video_hwc_input_buffer_valid(E_Video_Hwc *evh, E_Comp_Wl_Buffer *comp_buffer)
+static void _e_video_hwc_render(E_Video_Hwc *evh, const char *func);
+
+static void
+_e_video_hwc_input_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
{
- E_Comp_Wl_Video_Buf *vbuf;
- Eina_List *l;
+ E_Video_Hwc *evh = data;
+ Eina_Bool need_hide = EINA_FALSE;
- EINA_LIST_FOREACH(evh->input_buffer_list, l, vbuf)
+ DBG("Buffer(%p) to be free, refcnt(%d)", vbuf, vbuf->ref_cnt);
+
+ evh->input_buffer_list = eina_list_remove(evh->input_buffer_list, vbuf);
+
+ if (vbuf->comp_buffer)
+ e_comp_wl_buffer_reference(&vbuf->buffer_ref, NULL);
+
+ if (evh->current_fb == vbuf)
{
- tbm_surface_h tbm_surf;
- tbm_bo bo;
- uint32_t size = 0, offset = 0, pitch = 0;
+ VIN("current fb destroyed", evh->ec);
+ e_comp_wl_video_buffer_set_use(evh->current_fb, EINA_FALSE);
+ evh->current_fb = NULL;
+ need_hide = EINA_TRUE;
+ }
- if (!vbuf->comp_buffer) continue;
- if (vbuf->resource == comp_buffer->resource)
- {
- WRN("got wl_buffer@%d twice", wl_resource_get_id(comp_buffer->resource));
- return;
- }
+ if (eina_list_data_find(evh->committed_list, vbuf))
+ {
+ VIN("committed fb destroyed", evh->ec);
+ evh->committed_list = eina_list_remove(evh->committed_list, vbuf);
+ e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+ need_hide = EINA_TRUE;
+ }
- tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
- bo = tbm_surface_internal_get_bo(tbm_surf, 0);
- tbm_surface_internal_get_plane_data(tbm_surf, 0, &size, &offset, &pitch);
+ if (eina_list_data_find(evh->waiting_list, vbuf))
+ {
+ VIN("waiting fb destroyed", evh->ec);
+ evh->waiting_list = eina_list_remove(evh->waiting_list, vbuf);
+ }
- if (vbuf->names[0] == tbm_bo_export(bo) && vbuf->offsets[0] == offset)
- {
- WRN("can tearing: wl_buffer@%d, wl_buffer@%d are same. gem_name(%d)",
- wl_resource_get_id(vbuf->resource),
- wl_resource_get_id(comp_buffer->resource), vbuf->names[0]);
- return;
- }
+ if (need_hide)
+ {
+ if (evh->hwc_policy == E_HWC_POLICY_PLANES)
+ e_video_hwc_planes_frame_buffer_show(evh, NULL);
+ else
+ e_video_hwc_windows_frame_buffer_show(evh, NULL);
}
}
-EINTERN E_Comp_Wl_Video_Buf *
-e_video_hwc_input_buffer_copy(E_Video_Hwc *evh, E_Comp_Wl_Buffer *comp_buf, E_Comp_Wl_Video_Buf *vbuf, Eina_Bool scanout)
+static E_Comp_Wl_Video_Buf *
+_e_video_hwc_input_buffer_copy(E_Video_Hwc *evh, E_Comp_Wl_Buffer *comp_buf, E_Comp_Wl_Video_Buf *vbuf, Eina_Bool scanout)
{
E_Comp_Wl_Video_Buf *temp = NULL;
int aligned_width = ROUNDUP(vbuf->width_from_pitch, evh->pp_align);
return temp;
}
-EINTERN Eina_Bool
-e_video_hwc_video_buffer_scanout_check(E_Comp_Wl_Video_Buf *vbuf)
+static E_Comp_Wl_Video_Buf *
+_e_video_hwc_vbuf_find_with_comp_buffer(Eina_List *list, E_Comp_Wl_Buffer *comp_buffer)
+{
+ E_Comp_Wl_Video_Buf *vbuf;
+ Eina_List *l = NULL;
+
+ EINA_LIST_FOREACH(list, l, vbuf)
+ {
+ if (vbuf->comp_buffer == comp_buffer)
+ return vbuf;
+ }
+
+ return NULL;
+}
+
+static Eina_Bool
+_e_video_hwc_video_buffer_scanout_check(E_Comp_Wl_Video_Buf *vbuf)
{
tbm_surface_h tbm_surface = NULL;
tbm_bo bo = NULL;
return EINA_FALSE;
}
-EINTERN Eina_Bool
-e_video_hwc_can_commit(E_Video_Hwc *evh)
-{
- if (e_output_dpms_get(evh->e_output))
- return EINA_FALSE;
-
- return e_video_hwc_client_visible_get(evh->ec);
-}
-
-static void
-_e_video_hwc_pp_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
-{
- E_Video_Hwc *evh = data;
-
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-
- if (evh->current_fb == vbuf)
- evh->current_fb = NULL;
-
- evh->committed_list = eina_list_remove(evh->committed_list, vbuf);
-
- evh->waiting_list = eina_list_remove(evh->waiting_list, vbuf);
-
- evh->pp_buffer_list = eina_list_remove(evh->pp_buffer_list, vbuf);
-}
-
-EINTERN E_Comp_Wl_Video_Buf *
-e_video_hwc_pp_buffer_get(E_Video_Hwc *evh, int width, int height)
+static E_Comp_Wl_Video_Buf *
+_e_video_hwc_input_buffer_get(E_Video_Hwc *evh, E_Comp_Wl_Buffer *comp_buffer, Eina_Bool scanout)
{
E_Comp_Wl_Video_Buf *vbuf;
- Eina_List *l;
- int i = 0;
- int aligned_width;
+ Eina_Bool need_pp_scanout = EINA_FALSE;
- if (evh->video_align != -1)
- aligned_width = ROUNDUP(width, evh->video_align);
- else
- aligned_width = width;
+ vbuf = _e_video_hwc_vbuf_find_with_comp_buffer(evh->input_buffer_list, comp_buffer);
+ if (vbuf)
+ {
+ vbuf->content_r = evh->geo.input_r;
+ return vbuf;
+ }
- if (evh->pp_buffer_list)
+ vbuf = e_comp_wl_video_buffer_create_comp(comp_buffer);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+
+ if (evh->pp_scanout)
{
- vbuf = eina_list_data_get(evh->pp_buffer_list);
- EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+ Eina_Bool input_buffer_scanout = EINA_FALSE;
+ input_buffer_scanout = _e_video_hwc_video_buffer_scanout_check(vbuf);
+ if (!input_buffer_scanout) need_pp_scanout = EINA_TRUE;
+ }
- /* if we need bigger pp_buffers, destroy all pp_buffers and create */
- if (aligned_width > vbuf->width_from_pitch || height != vbuf->height)
+ if (evh->pp)
+ {
+ if ((evh->pp_align != -1 && (vbuf->width_from_pitch % evh->pp_align)) ||
+ need_pp_scanout)
{
- Eina_List *ll;
+ E_Comp_Wl_Video_Buf *temp;
- VIN("pp buffer changed: %dx%d => %dx%d", evh->ec,
- vbuf->width_from_pitch, vbuf->height,
- aligned_width, height);
-
- EINA_LIST_FOREACH_SAFE(evh->pp_buffer_list, l, ll, vbuf)
+ if (need_pp_scanout)
+ temp = _e_video_hwc_input_buffer_copy((E_Video_Hwc *)evh, comp_buffer, vbuf, EINA_TRUE);
+ else
+ temp = _e_video_hwc_input_buffer_copy((E_Video_Hwc *)evh, comp_buffer, vbuf, scanout);
+ if (!temp)
{
- /* free forcely */
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
e_comp_wl_video_buffer_unref(vbuf);
+ return NULL;
}
- if (evh->pp_buffer_list)
- NEVER_GET_HERE();
-
- if (evh->waiting_list)
- NEVER_GET_HERE();
+ vbuf = temp;
}
}
- if (!evh->pp_buffer_list)
- {
- for (i = 0; i < BUFFER_MAX_COUNT; i++)
- {
- vbuf = e_comp_wl_video_buffer_alloc(aligned_width, height, evh->pp_tbmfmt, EINA_TRUE);
- EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
-
- e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_hwc_pp_buffer_cb_free, evh);
- evh->pp_buffer_list = eina_list_append(evh->pp_buffer_list, vbuf);
+ vbuf->content_r = evh->geo.input_r;
- }
+ evh->input_buffer_list = eina_list_append(evh->input_buffer_list, vbuf);
+ e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_hwc_input_buffer_cb_free, evh);
- VIN("pp buffer created: %dx%d, %c%c%c%c", evh->ec,
- vbuf->width_from_pitch, height, FOURCC_STR(evh->pp_tbmfmt));
+ DBG("Client(%s):PID(%d) RscID(%d), Buffer(%p) created, refcnt:%d"
+ " scanout=%d", e_client_util_name_get(evh->ec) ?: "No Name" ,
+ evh->ec->netwm.pid, wl_resource_get_id(evh->ec->comp_data->surface), vbuf,
+ vbuf->ref_cnt, scanout);
- evh->next_buffer = evh->pp_buffer_list;
- }
+ return vbuf;
+}
- EINA_SAFETY_ON_NULL_RETURN_VAL(evh->pp_buffer_list, NULL);
- EINA_SAFETY_ON_NULL_RETURN_VAL(evh->next_buffer, NULL);
+static void
+_e_video_hwc_hide(E_Video_Hwc *evh)
+{
+ E_Comp_Wl_Video_Buf *vbuf;
- l = evh->next_buffer;
- while ((vbuf = evh->next_buffer->data))
+ if (evh->current_fb || evh->committed_list)
{
- evh->next_buffer = (evh->next_buffer->next) ? evh->next_buffer->next : evh->pp_buffer_list;
-
- if (!vbuf->in_use)
- return vbuf;
-
- if (l == evh->next_buffer)
- {
- VWR("all video framebuffers in use (max:%d)", evh->ec, BUFFER_MAX_COUNT);
- return NULL;
- }
+ if (evh->hwc_policy == E_HWC_POLICY_PLANES)
+ e_video_hwc_planes_frame_buffer_show(evh, NULL);
+ else
+ e_video_hwc_windows_frame_buffer_show(evh, NULL);
}
- return NULL;
-}
-
-
+ if (evh->current_fb)
+ {
+ e_comp_wl_video_buffer_set_use(evh->current_fb, EINA_FALSE);
+ evh->current_fb = NULL;
+ }
-EINTERN tbm_format
-e_video_hwc_comp_buffer_tbm_format_get(E_Comp_Wl_Buffer *comp_buffer)
-{
- tbm_surface_h tbm_surf;
+ if (evh->old_comp_buffer)
+ evh->old_comp_buffer = NULL;
- tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
- EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surf, 0);
+ EINA_LIST_FREE(evh->committed_list, vbuf)
+ e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
- return tbm_surface_get_format(tbm_surf);
+ EINA_LIST_FREE(evh->waiting_list, vbuf)
+ e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
}
-EINTERN Eina_Bool
-e_video_hwc_client_parent_viewable_get(E_Client *ec)
+static void
+_e_video_hwc_geometry_tdm_config_update(E_Client *ec, E_Video_Hwc_Geometry *out)
{
- E_Client *topmost_parent;
-
- if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
+ E_Zone *zone;
+ E_Comp_Wl_Output *output;
+ E_Client *topmost;
+ int tran, flip;
+ int transform;
- topmost_parent = e_comp_wl_topmost_parent_get(ec);
+ topmost = e_comp_wl_topmost_parent_get(ec);
+ EINA_SAFETY_ON_NULL_GOTO(topmost, normal);
- if (!topmost_parent)
- return EINA_FALSE;
+ output = e_comp_wl_output_find(topmost);
+ EINA_SAFETY_ON_NULL_GOTO(output, normal);
- if (topmost_parent == ec)
- {
- VDB("There is no video parent surface", ec);
- return EINA_FALSE;
- }
+ zone = e_comp_zone_xy_get(topmost->x, topmost->y);
+ EINA_SAFETY_ON_NULL_GOTO(zone, normal);
- if (!topmost_parent->visible)
+ tran = out->transform & 0x3;
+ flip = out->transform & 0x4;
+ transform = flip + (tran + output->transform) % 4;
+ switch(transform)
{
- VDB("parent(0x%08"PRIxPTR") not viewable", ec,
- (Ecore_Window)e_client_util_win_get(topmost_parent));
- return EINA_FALSE;
+ case WL_OUTPUT_TRANSFORM_90:
+ out->tdm.transform = TDM_TRANSFORM_270;
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ out->tdm.transform = TDM_TRANSFORM_180;
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ out->tdm.transform = TDM_TRANSFORM_90;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ out->tdm.transform = TDM_TRANSFORM_FLIPPED;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ out->tdm.transform = TDM_TRANSFORM_FLIPPED_270;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ out->tdm.transform = TDM_TRANSFORM_FLIPPED_180;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ out->tdm.transform = TDM_TRANSFORM_FLIPPED_90;
+ break;
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ default:
+ out->tdm.transform = TDM_TRANSFORM_NORMAL;
+ break;
}
- if (!e_pixmap_resource_get(topmost_parent->pixmap))
+ if (output->transform % 2)
{
- VDB("parent(0x%08"PRIxPTR") no comp buffer", ec,
- (Ecore_Window)e_client_util_win_get(topmost_parent));
- return EINA_FALSE;
+ if (out->tdm.transform == TDM_TRANSFORM_FLIPPED)
+ out->tdm.transform = TDM_TRANSFORM_FLIPPED_180;
+ else if (out->tdm.transform == TDM_TRANSFORM_FLIPPED_90)
+ out->tdm.transform = TDM_TRANSFORM_FLIPPED_270;
+ else if (out->tdm.transform == TDM_TRANSFORM_FLIPPED_180)
+ out->tdm.transform = TDM_TRANSFORM_FLIPPED;
+ else if (out->tdm.transform == TDM_TRANSFORM_FLIPPED_270)
+ out->tdm.transform = TDM_TRANSFORM_FLIPPED_90;
}
- return EINA_TRUE;
-}
-
-EINTERN E_Comp_Wl_Video_Buf *
-e_video_hwc_vbuf_find(Eina_List *list, tbm_surface_h buffer)
-{
- E_Comp_Wl_Video_Buf *vbuf;
- Eina_List *l = NULL;
+ if (output->transform == 0)
+ out->tdm.output_r = out->output_r;
+ else
+ e_comp_wl_rect_convert(zone->w, zone->h, output->transform, 1,
+ out->output_r.x, out->output_r.y,
+ out->output_r.w, out->output_r.h,
+ &out->tdm.output_r.x, &out->tdm.output_r.y,
+ &out->tdm.output_r.w, &out->tdm.output_r.h);
- EINA_LIST_FOREACH(list, l, vbuf)
- {
- if (vbuf->tbm_surface == buffer)
- return vbuf;
- }
+ VDB("geomtry: screen(%d,%d %dx%d | %d) => %d => physical(%d,%d %dx%d | %d)",
+ ec, EINA_RECTANGLE_ARGS(&out->output_r), out->transform, transform,
+ EINA_RECTANGLE_ARGS(&out->tdm.output_r), out->tdm.transform);
- return NULL;
+ return;
+normal:
+ out->tdm.output_r = out->output_r;
+ out->tdm.transform = out->transform;
}
-EINTERN E_Comp_Wl_Video_Buf *
-e_video_hwc_vbuf_find_with_comp_buffer(Eina_List *list, E_Comp_Wl_Buffer *comp_buffer)
+static Eina_Bool
+_e_video_hwc_geometry_map_apply(E_Client *ec, E_Video_Hwc_Geometry *out)
{
- E_Comp_Wl_Video_Buf *vbuf;
- Eina_List *l = NULL;
+ const Evas_Map *m;
+ Evas_Coord x1, x2, y1, y2;
+ Eina_Rectangle output_r;
- EINA_LIST_FOREACH(list, l, vbuf)
- {
- if (vbuf->comp_buffer == comp_buffer)
- return vbuf;
- }
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
- return NULL;
+ m = evas_object_map_get(ec->frame);
+ if (!m) return EINA_TRUE;
+
+ /* If frame has map, it means that ec's geometry is decided by map's geometry.
+ * ec->x,y,w,h and ec->client.x,y,w,h is not useful.
+ */
+
+ evas_map_point_coord_get(m, 0, &x1, &y1, NULL);
+ evas_map_point_coord_get(m, 2, &x2, &y2, NULL);
+
+ output_r.x = x1;
+ output_r.y = y1;
+ output_r.w = x2 - x1;
+ output_r.w = (output_r.w + 1) & ~1;
+ output_r.h = y2 - y1;
+ output_r.h = (output_r.h + 1) & ~1;
+
+ if (!memcmp(&out->output_r, &output_r, sizeof(Eina_Rectangle)))
+ return EINA_FALSE;
+
+ VDB("frame(%p) m(%p) output(%d,%d %dx%d) => (%d,%d %dx%d)", ec, ec->frame, m,
+ EINA_RECTANGLE_ARGS(&out->output_r), EINA_RECTANGLE_ARGS(&output_r));
+
+ out->output_r = output_r;
+
+ _e_video_hwc_geometry_tdm_config_update(ec, out);
+
+ return EINA_TRUE;
}
-EINTERN E_Client *
-e_video_hwc_client_offscreen_parent_get(E_Client *ec)
+static void
+_e_video_hwc_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
- E_Client *parent = NULL;
+ E_Video_Hwc *evh = data;
- if (!ec->comp_data || !ec->comp_data->sub.data)
- return NULL;
+ if (_e_video_hwc_geometry_map_apply(evh->ec, &evh->geo))
+ _e_video_hwc_render(evh, __FUNCTION__);
+}
- parent = ec->comp_data->sub.data->parent;
- while (parent)
- {
- if (!parent->comp_data || !parent->comp_data->sub.data)
- return NULL;
+static void
+_e_video_hwc_cb_evas_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ E_Video_Hwc *evh = data;
- if (parent->comp_data->sub.data->remote_surface.offscreen_parent)
- return parent->comp_data->sub.data->remote_surface.offscreen_parent;
+ if (_e_video_hwc_geometry_map_apply(evh->ec, &evh->geo))
+ _e_video_hwc_render(evh, __FUNCTION__);
+}
- parent = parent->comp_data->sub.data->parent;
+static E_Comp_Wl_Video_Buf *
+_e_video_hwc_vbuf_find(Eina_List *list, tbm_surface_h buffer)
+{
+ E_Comp_Wl_Video_Buf *vbuf;
+ Eina_List *l = NULL;
+
+ EINA_LIST_FOREACH(list, l, vbuf)
+ {
+ if (vbuf->tbm_surface == buffer)
+ return vbuf;
}
return NULL;
}
-EINTERN Eina_Bool
-e_video_hwc_client_visible_get(E_Client *ec)
+static Eina_Bool
+_e_video_hwc_client_visible_get(E_Client *ec)
{
E_Client *offscreen_parent;
return EINA_TRUE;
}
-EINTERN E_Client *
-e_video_hwc_child_client_get(E_Client *ec)
+static void
+_e_video_hwc_pp_cb_done(tdm_pp *pp, tbm_surface_h sb, tbm_surface_h db, void *user_data)
{
- E_Client *subc = NULL;
- Eina_List *l;
- if (!ec) return NULL;
- if (e_object_is_del(E_OBJECT(ec))) return NULL;
- if (!ec->comp_data) return NULL;
+ E_Video_Hwc *evh = (E_Video_Hwc *)user_data;
+ E_Comp_Wl_Video_Buf *input_buffer, *pp_buffer;
- if (ec->comp_data->video_client) return ec;
+ input_buffer = _e_video_hwc_vbuf_find(evh->input_buffer_list, sb);
+ if (input_buffer)
+ e_comp_wl_video_buffer_unref(input_buffer);
- EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
+ pp_buffer = _e_video_hwc_vbuf_find(evh->pp_buffer_list, db);
+ if (pp_buffer)
{
- E_Client *temp= NULL;
- if (!subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
- temp = e_video_hwc_child_client_get(subc);
- if(temp) return temp;
+ e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
+ if (!_e_video_hwc_client_visible_get(evh->ec)) return;
+
+ if (evh->hwc_policy == E_HWC_POLICY_PLANES)
+ e_video_hwc_planes_buffer_show(evh, pp_buffer, 0);
+ else
+ e_video_hwc_windows_buffer_show(evh, pp_buffer, 0);
+ }
+ else
+ {
+ VER("There is no pp_buffer", evh->ec);
+ // there is no way to set in_use flag.
+ // This will cause issue when server get available pp_buffer.
}
+}
- return NULL;
+static void
+_e_video_hwc_input_buffer_valid(E_Video_Hwc *evh, E_Comp_Wl_Buffer *comp_buffer)
+{
+ E_Comp_Wl_Video_Buf *vbuf;
+ Eina_List *l;
+
+ EINA_LIST_FOREACH(evh->input_buffer_list, l, vbuf)
+ {
+ tbm_surface_h tbm_surf;
+ tbm_bo bo;
+ uint32_t size = 0, offset = 0, pitch = 0;
+
+ if (!vbuf->comp_buffer) continue;
+ if (vbuf->resource == comp_buffer->resource)
+ {
+ WRN("got wl_buffer@%d twice", wl_resource_get_id(comp_buffer->resource));
+ return;
+ }
+
+ tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
+ bo = tbm_surface_internal_get_bo(tbm_surf, 0);
+ tbm_surface_internal_get_plane_data(tbm_surf, 0, &size, &offset, &pitch);
+
+ if (vbuf->names[0] == tbm_bo_export(bo) && vbuf->offsets[0] == offset)
+ {
+ WRN("can tearing: wl_buffer@%d, wl_buffer@%d are same. gem_name(%d)",
+ wl_resource_get_id(vbuf->resource),
+ wl_resource_get_id(comp_buffer->resource), vbuf->names[0]);
+ return;
+ }
+ }
+}
+
+static tbm_format
+_e_video_hwc_comp_buffer_tbm_format_get(E_Comp_Wl_Buffer *comp_buffer)
+{
+ tbm_surface_h tbm_surf;
+
+ tbm_surf = wayland_tbm_server_get_surface(e_comp->wl_comp_data->tbm.server, comp_buffer->resource);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surf, 0);
+
+ return tbm_surface_get_format(tbm_surf);
}
static tbm_surface_h
return tbmsurf;
}
-static E_Comp_Wl_Subsurf_Data *
-_e_video_hwc_client_subsurface_data_get(E_Client *ec)
-{
- if (ec->comp_data && ec->comp_data->sub.data)
- return ec->comp_data->sub.data;
-
- return NULL;
-}
-
static void
_e_video_hwc_buffer_size_get(tbm_surface_h tbm_surf, int *w, int *h)
{
out->h = (ty1 <= ty2) ? ty2 - ty1 : ty1 - ty2;
}
+static E_Comp_Wl_Subsurf_Data *
+_e_video_hwc_client_subsurface_data_get(E_Client *ec)
+{
+ if (ec->comp_data && ec->comp_data->sub.data)
+ return ec->comp_data->sub.data;
+
+ return NULL;
+}
+
static void
_e_video_hwc_geometry_output_rect_get(E_Client *ec, Eina_Rectangle *out)
{
}
/* convert from logical screen to physical output */
-static void
-_e_video_hwc_geometry_tdm_config_update(E_Client *ec, E_Video_Hwc_Geometry *out)
-{
- E_Zone *zone;
- E_Comp_Wl_Output *output;
- E_Client *topmost;
- int tran, flip;
- int transform;
-
- topmost = e_comp_wl_topmost_parent_get(ec);
- EINA_SAFETY_ON_NULL_GOTO(topmost, normal);
-
- output = e_comp_wl_output_find(topmost);
- EINA_SAFETY_ON_NULL_GOTO(output, normal);
-
- zone = e_comp_zone_xy_get(topmost->x, topmost->y);
- EINA_SAFETY_ON_NULL_GOTO(zone, normal);
-
- tran = out->transform & 0x3;
- flip = out->transform & 0x4;
- transform = flip + (tran + output->transform) % 4;
- switch(transform)
- {
- case WL_OUTPUT_TRANSFORM_90:
- out->tdm.transform = TDM_TRANSFORM_270;
- break;
- case WL_OUTPUT_TRANSFORM_180:
- out->tdm.transform = TDM_TRANSFORM_180;
- break;
- case WL_OUTPUT_TRANSFORM_270:
- out->tdm.transform = TDM_TRANSFORM_90;
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED:
- out->tdm.transform = TDM_TRANSFORM_FLIPPED;
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_90:
- out->tdm.transform = TDM_TRANSFORM_FLIPPED_270;
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_180:
- out->tdm.transform = TDM_TRANSFORM_FLIPPED_180;
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_270:
- out->tdm.transform = TDM_TRANSFORM_FLIPPED_90;
- break;
- case WL_OUTPUT_TRANSFORM_NORMAL:
- default:
- out->tdm.transform = TDM_TRANSFORM_NORMAL;
- break;
- }
-
- if (output->transform % 2)
- {
- if (out->tdm.transform == TDM_TRANSFORM_FLIPPED)
- out->tdm.transform = TDM_TRANSFORM_FLIPPED_180;
- else if (out->tdm.transform == TDM_TRANSFORM_FLIPPED_90)
- out->tdm.transform = TDM_TRANSFORM_FLIPPED_270;
- else if (out->tdm.transform == TDM_TRANSFORM_FLIPPED_180)
- out->tdm.transform = TDM_TRANSFORM_FLIPPED;
- else if (out->tdm.transform == TDM_TRANSFORM_FLIPPED_270)
- out->tdm.transform = TDM_TRANSFORM_FLIPPED_90;
- }
-
- if (output->transform == 0)
- out->tdm.output_r = out->output_r;
- else
- e_comp_wl_rect_convert(zone->w, zone->h, output->transform, 1,
- out->output_r.x, out->output_r.y,
- out->output_r.w, out->output_r.h,
- &out->tdm.output_r.x, &out->tdm.output_r.y,
- &out->tdm.output_r.w, &out->tdm.output_r.h);
-
- VDB("geomtry: screen(%d,%d %dx%d | %d) => %d => physical(%d,%d %dx%d | %d)",
- ec, EINA_RECTANGLE_ARGS(&out->output_r), out->transform, transform,
- EINA_RECTANGLE_ARGS(&out->tdm.output_r), out->tdm.transform);
-
- return;
-normal:
- out->tdm.output_r = out->output_r;
- out->tdm.transform = out->transform;
-}
-
static Eina_Bool
_e_video_hwc_geometry_viewport_apply(E_Client *ec, E_Video_Hwc_Geometry *out)
{
return EINA_TRUE;
}
-EINTERN Eina_Bool
-e_video_hwc_geometry_map_apply(E_Client *ec, E_Video_Hwc_Geometry *out)
+static void
+_e_video_hwc_geometry_cal_to_input(int output_w, int output_h, int input_w, int input_h,
+ uint32_t trasnform, int ox, int oy, int *ix, int *iy)
{
- const Evas_Map *m;
- Evas_Coord x1, x2, y1, y2;
- Eina_Rectangle output_r;
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
- EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
- EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
-
- m = evas_object_map_get(ec->frame);
- if (!m) return EINA_TRUE;
-
- /* If frame has map, it means that ec's geometry is decided by map's geometry.
- * ec->x,y,w,h and ec->client.x,y,w,h is not useful.
- */
-
- evas_map_point_coord_get(m, 0, &x1, &y1, NULL);
- evas_map_point_coord_get(m, 2, &x2, &y2, NULL);
-
- output_r.x = x1;
- output_r.y = y1;
- output_r.w = x2 - x1;
- output_r.w = (output_r.w + 1) & ~1;
- output_r.h = y2 - y1;
- output_r.h = (output_r.h + 1) & ~1;
-
- if (!memcmp(&out->output_r, &output_r, sizeof(Eina_Rectangle)))
- return EINA_FALSE;
-
- VDB("frame(%p) m(%p) output(%d,%d %dx%d) => (%d,%d %dx%d)", ec, ec->frame, m,
- EINA_RECTANGLE_ARGS(&out->output_r), EINA_RECTANGLE_ARGS(&output_r));
-
- out->output_r = output_r;
-
- _e_video_hwc_geometry_tdm_config_update(ec, out);
-
- return EINA_TRUE;
-}
-
-static void
-_e_video_hwc_geometry_cal_to_input(int output_w, int output_h, int input_w, int input_h,
- uint32_t trasnform, int ox, int oy, int *ix, int *iy)
-{
- float ratio_w, ratio_h;
+ float ratio_w, ratio_h;
switch(trasnform)
{
drect->h = MAX(yf1, yf2) - drect->y;
}
-EINTERN Eina_Bool
-e_video_hwc_geometry_get(E_Client *ec, E_Video_Hwc_Geometry *out)
+static Eina_Bool
+_e_video_hwc_geometry_get(E_Client *ec, E_Video_Hwc_Geometry *out)
{
E_Zone *zone;
E_Client *topmost;
if (!_e_video_hwc_geometry_viewport_apply(ec, out))
return EINA_FALSE;
- e_video_hwc_geometry_map_apply(ec, out);
+ _e_video_hwc_geometry_map_apply(ec, out);
topmost = e_comp_wl_topmost_parent_get(ec);
EINA_SAFETY_ON_NULL_RETURN_VAL(topmost, EINA_FALSE);
return EINA_TRUE;
}
+static Eina_Bool
+_e_video_hwc_client_parent_viewable_get(E_Client *ec)
+{
+ E_Client *topmost_parent;
+
+ if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
+
+ topmost_parent = e_comp_wl_topmost_parent_get(ec);
+
+ if (!topmost_parent)
+ return EINA_FALSE;
+
+ if (topmost_parent == ec)
+ {
+ VDB("There is no video parent surface", ec);
+ return EINA_FALSE;
+ }
+
+ if (!topmost_parent->visible)
+ {
+ VDB("parent(0x%08"PRIxPTR") not viewable", ec,
+ (Ecore_Window)e_client_util_win_get(topmost_parent));
+ return EINA_FALSE;
+ }
+
+ if (!e_pixmap_resource_get(topmost_parent->pixmap))
+ {
+ VDB("parent(0x%08"PRIxPTR") no comp buffer", ec,
+ (Ecore_Window)e_client_util_win_get(topmost_parent));
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_e_video_hwc_pp_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
+{
+ E_Video_Hwc *evh = data;
+
+ e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+
+ if (evh->current_fb == vbuf)
+ evh->current_fb = NULL;
+
+ evh->committed_list = eina_list_remove(evh->committed_list, vbuf);
+
+ evh->waiting_list = eina_list_remove(evh->waiting_list, vbuf);
+
+ evh->pp_buffer_list = eina_list_remove(evh->pp_buffer_list, vbuf);
+}
+
+static E_Comp_Wl_Video_Buf *
+_e_video_hwc_pp_buffer_get(E_Video_Hwc *evh, int width, int height)
+{
+ E_Comp_Wl_Video_Buf *vbuf;
+ Eina_List *l;
+ int i = 0;
+ int aligned_width;
+
+ if (evh->video_align != -1)
+ aligned_width = ROUNDUP(width, evh->video_align);
+ else
+ aligned_width = width;
+
+ if (evh->pp_buffer_list)
+ {
+ vbuf = eina_list_data_get(evh->pp_buffer_list);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+
+ /* if we need bigger pp_buffers, destroy all pp_buffers and create */
+ if (aligned_width > vbuf->width_from_pitch || height != vbuf->height)
+ {
+ Eina_List *ll;
+
+ VIN("pp buffer changed: %dx%d => %dx%d", evh->ec,
+ vbuf->width_from_pitch, vbuf->height,
+ aligned_width, height);
+
+ EINA_LIST_FOREACH_SAFE(evh->pp_buffer_list, l, ll, vbuf)
+ {
+ /* free forcely */
+ e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+ e_comp_wl_video_buffer_unref(vbuf);
+ }
+ if (evh->pp_buffer_list)
+ NEVER_GET_HERE();
+
+ if (evh->waiting_list)
+ NEVER_GET_HERE();
+ }
+ }
+
+ if (!evh->pp_buffer_list)
+ {
+ for (i = 0; i < BUFFER_MAX_COUNT; i++)
+ {
+ vbuf = e_comp_wl_video_buffer_alloc(aligned_width, height, evh->pp_tbmfmt, EINA_TRUE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
+
+ e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_hwc_pp_buffer_cb_free, evh);
+ evh->pp_buffer_list = eina_list_append(evh->pp_buffer_list, vbuf);
+
+ }
+
+ VIN("pp buffer created: %dx%d, %c%c%c%c", evh->ec,
+ vbuf->width_from_pitch, height, FOURCC_STR(evh->pp_tbmfmt));
+
+ evh->next_buffer = evh->pp_buffer_list;
+ }
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(evh->pp_buffer_list, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(evh->next_buffer, NULL);
+
+ l = evh->next_buffer;
+ while ((vbuf = evh->next_buffer->data))
+ {
+ evh->next_buffer = (evh->next_buffer->next) ? evh->next_buffer->next : evh->pp_buffer_list;
+
+ if (!vbuf->in_use)
+ return vbuf;
+
+ if (l == evh->next_buffer)
+ {
+ VWR("all video framebuffers in use (max:%d)", evh->ec, BUFFER_MAX_COUNT);
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+_e_video_hwc_render(E_Video_Hwc *evh, const char *func)
+{
+ E_Comp_Wl_Buffer *comp_buffer;
+ E_Comp_Wl_Video_Buf *pp_buffer = NULL;
+ E_Comp_Wl_Video_Buf *input_buffer = NULL;
+ E_Client *topmost;
+ Eina_Bool res;
+
+ EINA_SAFETY_ON_NULL_RETURN(evh->ec);
+
+ /* buffer can be NULL when camera/video's mode changed. Do nothing and
+ * keep previous frame in this case.
+ */
+ if (!evh->ec->pixmap)
+ return;
+
+ if (!_e_video_hwc_client_visible_get(evh->ec))
+ {
+ _e_video_hwc_hide(evh);
+ return;
+ }
+
+ comp_buffer = e_pixmap_resource_get(evh->ec->pixmap);
+ if (!comp_buffer) return;
+
+ evh->tbmfmt = _e_video_hwc_comp_buffer_tbm_format_get(comp_buffer);
+
+ topmost = e_comp_wl_topmost_parent_get(evh->ec);
+ EINA_SAFETY_ON_NULL_RETURN(topmost);
+
+ if(e_comp_wl_viewport_is_changed(topmost))
+ {
+ VIN("need update viewport: apply topmost", evh->ec);
+ e_comp_wl_viewport_apply(topmost);
+ }
+
+ if (!_e_video_hwc_geometry_get(evh->ec, &evh->geo))
+ {
+ if(!evh->need_force_render && !_e_video_hwc_client_parent_viewable_get(evh->ec))
+ {
+ VIN("need force render", evh->ec);
+ evh->need_force_render = EINA_TRUE;
+ }
+ return;
+ }
+
+ DBG("====================================== (%s)", func);
+ VDB("old: "GEO_FMT" buf(%p)", evh->ec, GEO_ARG(&evh->old_geo), evh->old_comp_buffer);
+ VDB("new: "GEO_FMT" buf(%p) %c%c%c%c", evh->ec, GEO_ARG(&evh->geo), comp_buffer, FOURCC_STR(evh->tbmfmt));
+
+ if (!memcmp(&evh->old_geo, &evh->geo, sizeof evh->geo) &&
+ evh->old_comp_buffer == comp_buffer)
+ return;
+
+ evh->need_force_render = EINA_FALSE;
+
+ _e_video_hwc_input_buffer_valid((E_Video_Hwc *)evh, comp_buffer);
+
+ if (evh->hwc_policy == E_HWC_POLICY_PLANES)
+ res = e_video_hwc_planes_check_if_pp_needed(evh);
+ else
+ res = e_video_hwc_windows_check_if_pp_needed(evh);
+
+ if (!res)
+ {
+ /* 1. non converting case */
+ input_buffer = _e_video_hwc_input_buffer_get(evh, comp_buffer, EINA_TRUE);
+ EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
+
+ if (evh->hwc_policy == E_HWC_POLICY_PLANES)
+ e_video_hwc_planes_buffer_show(evh, input_buffer, evh->geo.tdm.transform);
+ else
+ e_video_hwc_windows_buffer_show(evh, input_buffer, evh->geo.tdm.transform);
+
+ evh->old_geo = evh->geo;
+ evh->old_comp_buffer = comp_buffer;
+
+ goto done;
+ }
+
+ /* 2. converting case */
+ if (!evh->pp)
+ {
+ tdm_pp_capability pp_cap;
+ tdm_error error = TDM_ERROR_NONE;
+
+ evh->pp = tdm_display_create_pp(e_comp->e_comp_screen->tdisplay, NULL);
+ EINA_SAFETY_ON_NULL_GOTO(evh->pp, render_fail);
+
+ tdm_display_get_pp_available_size(e_comp->e_comp_screen->tdisplay, &evh->pp_minw, &evh->pp_minh,
+ &evh->pp_maxw, &evh->pp_maxh, &evh->pp_align);
+
+ error = tdm_display_get_pp_capabilities(e_comp->e_comp_screen->tdisplay, &pp_cap);
+ if (error == TDM_ERROR_NONE)
+ {
+ if (pp_cap & TDM_PP_CAPABILITY_SCANOUT)
+ evh->pp_scanout = EINA_TRUE;
+ }
+ }
+
+ if ((evh->pp_minw > 0 && (evh->geo.input_r.w < evh->pp_minw || evh->geo.tdm.output_r.w < evh->pp_minw)) ||
+ (evh->pp_minh > 0 && (evh->geo.input_r.h < evh->pp_minh || evh->geo.tdm.output_r.h < evh->pp_minh)) ||
+ (evh->pp_maxw > 0 && (evh->geo.input_r.w > evh->pp_maxw || evh->geo.tdm.output_r.w > evh->pp_maxw)) ||
+ (evh->pp_maxh > 0 && (evh->geo.input_r.h > evh->pp_maxh || evh->geo.tdm.output_r.h > evh->pp_maxh)))
+ {
+ INF("size(%dx%d, %dx%d) is out of PP range",
+ evh->geo.input_r.w, evh->geo.input_r.h, evh->geo.tdm.output_r.w, evh->geo.tdm.output_r.h);
+ goto done;
+ }
+
+ input_buffer = _e_video_hwc_input_buffer_get(evh, comp_buffer, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
+
+ pp_buffer = _e_video_hwc_pp_buffer_get((E_Video_Hwc *)evh, evh->geo.tdm.output_r.w, evh->geo.tdm.output_r.h);
+ EINA_SAFETY_ON_NULL_GOTO(pp_buffer, render_fail);
+
+ if (memcmp(&evh->old_geo, &evh->geo, sizeof evh->geo))
+ {
+ tdm_info_pp info;
+
+ CLEAR(info);
+ info.src_config.size.h = input_buffer->width_from_pitch;
+ info.src_config.size.v = input_buffer->height_from_size;
+ info.src_config.pos.x = evh->geo.input_r.x;
+ info.src_config.pos.y = evh->geo.input_r.y;
+ info.src_config.pos.w = evh->geo.input_r.w;
+ info.src_config.pos.h = evh->geo.input_r.h;
+ info.src_config.format = evh->tbmfmt;
+ info.dst_config.size.h = pp_buffer->width_from_pitch;
+ info.dst_config.size.v = pp_buffer->height_from_size;
+ info.dst_config.pos.w = evh->geo.tdm.output_r.w;
+ info.dst_config.pos.h = evh->geo.tdm.output_r.h;
+ info.dst_config.format = evh->pp_tbmfmt;
+ info.transform = evh->geo.tdm.transform;
+
+ if (tdm_pp_set_info(evh->pp, &info))
+ {
+ VER("tdm_pp_set_info() failed", evh->ec);
+ goto render_fail;
+ }
+
+ if (tdm_pp_set_done_handler(evh->pp, _e_video_hwc_pp_cb_done, evh))
+ {
+ VER("tdm_pp_set_done_handler() failed", evh->ec);
+ goto render_fail;
+ }
+
+ CLEAR(evh->pp_r);
+ evh->pp_r.w = info.dst_config.pos.w;
+ evh->pp_r.h = info.dst_config.pos.h;
+ }
+
+ pp_buffer->content_r = evh->pp_r;
+
+ if (tdm_pp_attach(evh->pp, input_buffer->tbm_surface, pp_buffer->tbm_surface))
+ {
+ VER("tdm_pp_attach() failed", evh->ec);
+ goto render_fail;
+ }
+
+ e_comp_wl_video_buffer_set_use(pp_buffer, EINA_TRUE);
+
+ e_comp_wl_buffer_reference(&input_buffer->buffer_ref, comp_buffer);
+
+ if (tdm_pp_commit(evh->pp))
+ {
+ VER("tdm_pp_commit() failed", evh->ec);
+ e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
+ goto render_fail;
+ }
+
+ evh->old_geo = evh->geo;
+ evh->old_comp_buffer = comp_buffer;
+
+ goto done;
+
+render_fail:
+ if (input_buffer)
+ e_comp_wl_video_buffer_unref(input_buffer);
+
+done:
+ if (!evh->cb_registered)
+ {
+ evas_object_event_callback_add(evh->ec->frame, EVAS_CALLBACK_RESIZE,
+ _e_video_hwc_cb_evas_resize, evh);
+ evas_object_event_callback_add(evh->ec->frame, EVAS_CALLBACK_MOVE,
+ _e_video_hwc_cb_evas_move, evh);
+ evh->cb_registered = EINA_TRUE;
+ }
+ DBG("======================================.");
+}
+
+EINTERN void
+e_video_hwc_render(E_Video_Hwc *evh, const char *func)
+{
+ _e_video_hwc_render(evh, func);
+}
+
+EINTERN Eina_Bool
+e_video_hwc_can_commit(E_Video_Hwc *evh)
+{
+ if (e_output_dpms_get(evh->e_output))
+ return EINA_FALSE;
+
+ return _e_video_hwc_client_visible_get(evh->ec);
+}
+
+EINTERN E_Client *
+e_video_hwc_client_offscreen_parent_get(E_Client *ec)
+{
+ E_Client *parent = NULL;
+
+ if (!ec->comp_data || !ec->comp_data->sub.data)
+ return NULL;
+
+ parent = ec->comp_data->sub.data->parent;
+ while (parent)
+ {
+ if (!parent->comp_data || !parent->comp_data->sub.data)
+ return NULL;
+
+ if (parent->comp_data->sub.data->remote_surface.offscreen_parent)
+ return parent->comp_data->sub.data->remote_surface.offscreen_parent;
+
+ parent = parent->comp_data->sub.data->parent;
+ }
+
+ return NULL;
+}
+
+EINTERN E_Client *
+e_video_hwc_child_client_get(E_Client *ec)
+{
+ E_Client *subc = NULL;
+ Eina_List *l;
+ if (!ec) return NULL;
+ if (e_object_is_del(E_OBJECT(ec))) return NULL;
+ if (!ec->comp_data) return NULL;
+
+ if (ec->comp_data->video_client) return ec;
+
+ EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
+ {
+ E_Client *temp= NULL;
+ if (!subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
+ temp = e_video_hwc_child_client_get(subc);
+ if(temp) return temp;
+ }
+
+ return NULL;
+}
+
static void
_e_video_hwc_iface_destroy(E_Video_Comp_Iface *iface)
{
IFACE_ENTRY;
+ _e_video_hwc_hide(evh);
+
+ if (evh->cb_registered)
+ {
+ evas_object_event_callback_del_full(evh->ec->frame, EVAS_CALLBACK_RESIZE,
+ _e_video_hwc_cb_evas_resize, evh);
+ evas_object_event_callback_del_full(evh->ec->frame, EVAS_CALLBACK_MOVE,
+ _e_video_hwc_cb_evas_move, evh);
+ }
+
+ EINA_LIST_FOREACH_SAFE(evh->input_buffer_list, l, ll, vbuf)
+ {
+ e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
+ e_comp_wl_video_buffer_unref(vbuf);
+ }
+
EINA_LIST_FOREACH_SAFE(evh->pp_buffer_list, l, ll, vbuf)
{
e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
e_comp_wl_video_buffer_unref(vbuf);
}
+ if (evh->input_buffer_list)
+ NEVER_GET_HERE();
if (evh->pp_buffer_list)
NEVER_GET_HERE();
+ /* destroy converter second */
+ if (evh->pp)
+ tdm_pp_destroy(evh->pp);
+
evh->backend.destroy(&evh->backend);
}
static Eina_Bool _e_video_set(E_Video_Hwc_Planes *evhp);
static void _e_video_destroy(E_Video_Hwc_Planes *evhp);
-static void _e_video_render(E_Video_Hwc_Planes *evhp, const char *func);
static Eina_Bool _e_video_frame_buffer_show(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Video_Buf *vbuf);
static void _e_video_video_set_hook(void *data, E_Plane *plane);
}
static void
-_e_video_input_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
-{
- E_Video_Hwc_Planes *evhp = data;
- Eina_Bool need_hide = EINA_FALSE;
-
- DBG("Buffer(%p) to be free, refcnt(%d)", vbuf, vbuf->ref_cnt);
-
- evhp->base.input_buffer_list = eina_list_remove(evhp->base.input_buffer_list, vbuf);
-
- if (vbuf->comp_buffer)
- e_comp_wl_buffer_reference(&vbuf->buffer_ref, NULL);
-
- if (evhp->base.current_fb == vbuf)
- {
- VIN("current fb destroyed", evhp->base.ec);
- e_comp_wl_video_buffer_set_use(evhp->base.current_fb, EINA_FALSE);
- evhp->base.current_fb = NULL;
- need_hide = EINA_TRUE;
- }
-
- if (eina_list_data_find(evhp->base.committed_list, vbuf))
- {
- VIN("committed fb destroyed", evhp->base.ec);
- evhp->base.committed_list = eina_list_remove(evhp->base.committed_list, vbuf);
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
- need_hide = EINA_TRUE;
- }
-
- if (eina_list_data_find(evhp->base.waiting_list, vbuf))
- {
- VIN("waiting fb destroyed", evhp->base.ec);
- evhp->base.waiting_list = eina_list_remove(evhp->base.waiting_list, vbuf);
- }
-
- if (need_hide && evhp->layer)
- _e_video_frame_buffer_show(evhp, NULL);
-}
-
-static E_Comp_Wl_Video_Buf *
-_e_video_input_buffer_get(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Buffer *comp_buffer, Eina_Bool scanout)
-{
- E_Comp_Wl_Video_Buf *vbuf;
- Eina_Bool need_pp_scanout = EINA_FALSE;
-
- vbuf = e_video_hwc_vbuf_find_with_comp_buffer(evhp->base.input_buffer_list, comp_buffer);
- if (vbuf)
- {
- vbuf->content_r = evhp->base.geo.input_r;
- return vbuf;
- }
-
- vbuf = e_comp_wl_video_buffer_create_comp(comp_buffer);
- EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
-
- if (evhp->base.pp_scanout)
- {
- Eina_Bool input_buffer_scanout = EINA_FALSE;
- input_buffer_scanout = e_video_hwc_video_buffer_scanout_check(vbuf);
- if (!input_buffer_scanout) need_pp_scanout = EINA_TRUE;
- }
-
- if (evhp->base.pp)
- {
- if ((evhp->base.pp_align != -1 && (vbuf->width_from_pitch % evhp->base.pp_align)) ||
- need_pp_scanout)
- {
- E_Comp_Wl_Video_Buf *temp;
-
- if (need_pp_scanout)
- temp = e_video_hwc_input_buffer_copy((E_Video_Hwc *)evhp, comp_buffer, vbuf, EINA_TRUE);
- else
- temp = e_video_hwc_input_buffer_copy((E_Video_Hwc *)evhp, comp_buffer, vbuf, scanout);
- if (!temp)
- {
- e_comp_wl_video_buffer_unref(vbuf);
- return NULL;
- }
- vbuf = temp;
- }
- }
-
- vbuf->content_r = evhp->base.geo.input_r;
-
- evhp->base.input_buffer_list = eina_list_append(evhp->base.input_buffer_list, vbuf);
- e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_input_buffer_cb_free, evhp);
-
- DBG("Client(%s):PID(%d) RscID(%d), Buffer(%p) created, refcnt:%d"
- " scanout=%d", e_client_util_name_get(evhp->base.ec) ?: "No Name" ,
- evhp->base.ec->netwm.pid, wl_resource_get_id(evhp->base.ec->comp_data->surface), vbuf,
- vbuf->ref_cnt, scanout);
-
- return vbuf;
-}
-
-static void
_e_video_commit_handler(tdm_layer *layer, unsigned int sequence,
unsigned int tv_sec, unsigned int tv_usec,
void *user_data)
return EINA_TRUE;
}
+EINTERN Eina_Bool
+e_video_hwc_planes_frame_buffer_show(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf)
+{
+ E_Video_Hwc_Planes *evhp;
+
+ evhp = (E_Video_Hwc_Planes *)evh;
+ return _e_video_frame_buffer_show(evhp, vbuf);
+}
+
static void
_e_video_buffer_show(E_Video_Hwc_Planes *evhp, E_Comp_Wl_Video_Buf *vbuf, unsigned int transform)
{
_e_video_commit_buffer(evhp, vbuf);
}
-static void
-_e_video_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
- E_Video_Hwc_Planes *evhp = data;
-
- if (e_video_hwc_geometry_map_apply(evhp->base.ec, &evhp->base.geo))
- _e_video_render(evhp, __FUNCTION__);
-}
-
-static void
-_e_video_cb_evas_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+EINTERN void
+e_video_hwc_planes_buffer_show(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf, unsigned int transform)
{
- E_Video_Hwc_Planes *evhp = data;
+ E_Video_Hwc_Planes *evhp;
- if (e_video_hwc_geometry_map_apply(evhp->base.ec, &evhp->base.geo))
- _e_video_render(evhp, __FUNCTION__);
+ evhp = (E_Video_Hwc_Planes *)evh;
+ _e_video_buffer_show(evhp, vbuf, transform);
}
static void
if (evhp->base.need_force_render)
{
VIN("video forcely rendering..", evhp->base.ec);
- _e_video_render(evhp, __FUNCTION__);
+ e_video_hwc_render((E_Video_Hwc *)evhp, __FUNCTION__);
}
/* if stand_alone is true, not show */
}
static void
-_e_video_hide(E_Video_Hwc_Planes *evhp)
-{
- E_Comp_Wl_Video_Buf *vbuf;
-
- if (evhp->base.current_fb || evhp->base.committed_list)
- _e_video_frame_buffer_show(evhp, NULL);
-
- if (evhp->base.current_fb)
- {
- e_comp_wl_video_buffer_set_use(evhp->base.current_fb, EINA_FALSE);
- evhp->base.current_fb = NULL;
- }
-
- if (evhp->base.old_comp_buffer)
- evhp->base.old_comp_buffer = NULL;
-
- EINA_LIST_FREE(evhp->base.committed_list, vbuf)
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-
- EINA_LIST_FREE(evhp->base.waiting_list, vbuf)
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-}
-
-static void
_e_video_destroy(E_Video_Hwc_Planes *evhp)
{
- E_Comp_Wl_Video_Buf *vbuf;
- Eina_List *l = NULL, *ll = NULL;
-
if (!evhp)
return;
VIN("destroy", evhp->base.ec);
- if (evhp->base.cb_registered)
- {
- evas_object_event_callback_del_full(evhp->base.ec->frame, EVAS_CALLBACK_RESIZE,
- _e_video_cb_evas_resize, evhp);
- evas_object_event_callback_del_full(evhp->base.ec->frame, EVAS_CALLBACK_MOVE,
- _e_video_cb_evas_move, evhp);
- }
-
- _e_video_hide(evhp);
-
- /* others */
- EINA_LIST_FOREACH_SAFE(evhp->base.input_buffer_list, l, ll, vbuf)
- {
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
- e_comp_wl_video_buffer_unref(vbuf);
- }
-
if(evhp->tdm_prop_list)
{
Tdm_Prop_Value *tdm_prop;
}
}
- if (evhp->base.input_buffer_list)
- NEVER_GET_HERE();
if (evhp->tdm_prop_list)
NEVER_GET_HERE();
if (evhp->late_tdm_prop_list)
NEVER_GET_HERE();
- /* destroy converter second */
- if (evhp->base.pp)
- tdm_pp_destroy(evhp->base.pp);
-
if (evhp->layer)
{
VIN("unset layer: destroy", evhp->base.ec);
#endif
}
-static Eina_Bool
-_e_video_check_if_pp_needed(E_Video_Hwc_Planes *evhp)
+EINTERN Eina_Bool
+e_video_hwc_planes_check_if_pp_needed(E_Video_Hwc *evh)
{
+ E_Video_Hwc_Planes *evhp;
int i, count = 0;
const tbm_format *formats;
Eina_Bool found = EINA_FALSE;
tdm_layer_capability capabilities = 0;
+ evhp = (E_Video_Hwc_Planes *)evh;
tdm_layer *layer = _e_video_tdm_video_layer_get(evhp->base.output);
return EINA_TRUE;
}
-static void
-_e_video_pp_cb_done(tdm_pp *pp, tbm_surface_h sb, tbm_surface_h db, void *user_data)
-{
- E_Video_Hwc_Planes *evhp = (E_Video_Hwc_Planes*)user_data;
- E_Comp_Wl_Video_Buf *input_buffer, *pp_buffer;
-
- input_buffer = e_video_hwc_vbuf_find(evhp->base.input_buffer_list, sb);
- if (input_buffer)
- e_comp_wl_video_buffer_unref(input_buffer);
-
- pp_buffer = e_video_hwc_vbuf_find(evhp->base.pp_buffer_list, db);
- if (pp_buffer)
- {
- e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
- if (!e_video_hwc_client_visible_get(evhp->base.ec)) return;
-
- _e_video_buffer_show(evhp, pp_buffer, 0);
- }
- else
- {
- VER("There is no pp_buffer", evhp->base.ec);
- // there is no way to set in_use flag.
- // This will cause issue when server get available pp_buffer.
- }
-}
-
-static void
-_e_video_render(E_Video_Hwc_Planes *evhp, const char *func)
-{
- E_Comp_Wl_Buffer *comp_buffer;
- E_Comp_Wl_Video_Buf *pp_buffer = NULL;
- E_Comp_Wl_Video_Buf *input_buffer = NULL;
- E_Client *topmost;
-
- EINA_SAFETY_ON_NULL_RETURN(evhp->base.ec);
-
- /* buffer can be NULL when camera/video's mode changed. Do nothing and
- * keep previous frame in this case.
- */
- if (!evhp->base.ec->pixmap)
- return;
-
- if (!e_video_hwc_client_visible_get(evhp->base.ec))
- {
- _e_video_hide(evhp);
- return;
- }
-
- comp_buffer = e_pixmap_resource_get(evhp->base.ec->pixmap);
- if (!comp_buffer) return;
-
- evhp->base.tbmfmt = e_video_hwc_comp_buffer_tbm_format_get(comp_buffer);
-
- topmost = e_comp_wl_topmost_parent_get(evhp->base.ec);
- EINA_SAFETY_ON_NULL_RETURN(topmost);
-
- if(e_comp_wl_viewport_is_changed(topmost))
- {
- VIN("need update viewport: apply topmost", evhp->base.ec);
- e_comp_wl_viewport_apply(topmost);
- }
-
- if (!e_video_hwc_geometry_get(evhp->base.ec, &evhp->base.geo))
- {
- if(!evhp->base.need_force_render && !e_video_hwc_client_parent_viewable_get(evhp->base.ec))
- {
- VIN("need force render", evhp->base.ec);
- evhp->base.need_force_render = EINA_TRUE;
- }
- return;
- }
-
- DBG("====================================== (%s)", func);
- VDB("old: "GEO_FMT" buf(%p)", evhp->base.ec, GEO_ARG(&evhp->base.old_geo), evhp->base.old_comp_buffer);
- VDB("new: "GEO_FMT" buf(%p) %c%c%c%c", evhp->base.ec, GEO_ARG(&evhp->base.geo), comp_buffer, FOURCC_STR(evhp->base.tbmfmt));
-
- if (!memcmp(&evhp->base.old_geo, &evhp->base.geo, sizeof evhp->base.geo) &&
- evhp->base.old_comp_buffer == comp_buffer)
- return;
-
- evhp->base.need_force_render = EINA_FALSE;
-
- e_video_hwc_input_buffer_valid((E_Video_Hwc *)evhp, comp_buffer);
-
- if (!_e_video_check_if_pp_needed(evhp))
- {
- /* 1. non converting case */
- input_buffer = _e_video_input_buffer_get(evhp, comp_buffer, EINA_TRUE);
- EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
-
- _e_video_buffer_show(evhp, input_buffer, evhp->base.geo.tdm.transform);
-
- evhp->base.old_geo = evhp->base.geo;
- evhp->base.old_comp_buffer = comp_buffer;
-
- goto done;
- }
-
- /* 2. converting case */
- if (!evhp->base.pp)
- {
- tdm_pp_capability pp_cap;
- tdm_error error = TDM_ERROR_NONE;
-
- evhp->base.pp = tdm_display_create_pp(e_comp->e_comp_screen->tdisplay, NULL);
- EINA_SAFETY_ON_NULL_GOTO(evhp->base.pp, render_fail);
-
- tdm_display_get_pp_available_size(e_comp->e_comp_screen->tdisplay, &evhp->base.pp_minw, &evhp->base.pp_minh,
- &evhp->base.pp_maxw, &evhp->base.pp_maxh, &evhp->base.pp_align);
-
- error = tdm_display_get_pp_capabilities(e_comp->e_comp_screen->tdisplay, &pp_cap);
- if (error == TDM_ERROR_NONE)
- {
- if (pp_cap & TDM_PP_CAPABILITY_SCANOUT)
- evhp->base.pp_scanout = EINA_TRUE;
- }
- }
-
- if ((evhp->base.pp_minw > 0 && (evhp->base.geo.input_r.w < evhp->base.pp_minw || evhp->base.geo.tdm.output_r.w < evhp->base.pp_minw)) ||
- (evhp->base.pp_minh > 0 && (evhp->base.geo.input_r.h < evhp->base.pp_minh || evhp->base.geo.tdm.output_r.h < evhp->base.pp_minh)) ||
- (evhp->base.pp_maxw > 0 && (evhp->base.geo.input_r.w > evhp->base.pp_maxw || evhp->base.geo.tdm.output_r.w > evhp->base.pp_maxw)) ||
- (evhp->base.pp_maxh > 0 && (evhp->base.geo.input_r.h > evhp->base.pp_maxh || evhp->base.geo.tdm.output_r.h > evhp->base.pp_maxh)))
- {
- INF("size(%dx%d, %dx%d) is out of PP range",
- evhp->base.geo.input_r.w, evhp->base.geo.input_r.h, evhp->base.geo.tdm.output_r.w, evhp->base.geo.tdm.output_r.h);
- goto done;
- }
-
- input_buffer = _e_video_input_buffer_get(evhp, comp_buffer, EINA_FALSE);
- EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
-
- pp_buffer = e_video_hwc_pp_buffer_get((E_Video_Hwc *)evhp, evhp->base.geo.tdm.output_r.w, evhp->base.geo.tdm.output_r.h);
- EINA_SAFETY_ON_NULL_GOTO(pp_buffer, render_fail);
-
- if (memcmp(&evhp->base.old_geo, &evhp->base.geo, sizeof evhp->base.geo))
- {
- tdm_info_pp info;
-
- CLEAR(info);
- info.src_config.size.h = input_buffer->width_from_pitch;
- info.src_config.size.v = input_buffer->height_from_size;
- info.src_config.pos.x = evhp->base.geo.input_r.x;
- info.src_config.pos.y = evhp->base.geo.input_r.y;
- info.src_config.pos.w = evhp->base.geo.input_r.w;
- info.src_config.pos.h = evhp->base.geo.input_r.h;
- info.src_config.format = evhp->base.tbmfmt;
- info.dst_config.size.h = pp_buffer->width_from_pitch;
- info.dst_config.size.v = pp_buffer->height_from_size;
- info.dst_config.pos.w = evhp->base.geo.tdm.output_r.w;
- info.dst_config.pos.h = evhp->base.geo.tdm.output_r.h;
- info.dst_config.format = evhp->base.pp_tbmfmt;
- info.transform = evhp->base.geo.tdm.transform;
-
- if (tdm_pp_set_info(evhp->base.pp, &info))
- {
- VER("tdm_pp_set_info() failed", evhp->base.ec);
- goto render_fail;
- }
-
- if (tdm_pp_set_done_handler(evhp->base.pp, _e_video_pp_cb_done, evhp))
- {
- VER("tdm_pp_set_done_handler() failed", evhp->base.ec);
- goto render_fail;
- }
-
- CLEAR(evhp->base.pp_r);
- evhp->base.pp_r.w = info.dst_config.pos.w;
- evhp->base.pp_r.h = info.dst_config.pos.h;
- }
-
- pp_buffer->content_r = evhp->base.pp_r;
-
- if (tdm_pp_attach(evhp->base.pp, input_buffer->tbm_surface, pp_buffer->tbm_surface))
- {
- VER("tdm_pp_attach() failed", evhp->base.ec);
- goto render_fail;
- }
-
- e_comp_wl_video_buffer_set_use(pp_buffer, EINA_TRUE);
-
- e_comp_wl_buffer_reference(&input_buffer->buffer_ref, comp_buffer);
-
- if (tdm_pp_commit(evhp->base.pp))
- {
- VER("tdm_pp_commit() failed", evhp->base.ec);
- e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
- goto render_fail;
- }
-
- evhp->base.old_geo = evhp->base.geo;
- evhp->base.old_comp_buffer = comp_buffer;
-
- goto done;
-
-render_fail:
- if (input_buffer)
- e_comp_wl_video_buffer_unref(input_buffer);
-
-done:
- if (!evhp->base.cb_registered)
- {
- evas_object_event_callback_add(evhp->base.ec->frame, EVAS_CALLBACK_RESIZE,
- _e_video_cb_evas_resize, evhp);
- evas_object_event_callback_add(evhp->base.ec->frame, EVAS_CALLBACK_MOVE,
- _e_video_cb_evas_move, evhp);
- evhp->base.cb_registered = EINA_TRUE;
- }
- DBG("======================================.");
-}
-
static Eina_Bool
_e_video_cb_ec_buffer_change(void *data, int type, void *event)
{
if (e_object_is_del(E_OBJECT(ec)))
return ECORE_CALLBACK_PASS_ON;
- _e_video_render(evhp, __FUNCTION__);
+ e_video_hwc_render((E_Video_Hwc *)evhp, __FUNCTION__);
return ECORE_CALLBACK_PASS_ON;
}
{
VIN("video need rendering..", evhp->base.ec);
e_comp_wl_viewport_apply(ec);
- _e_video_render(evhp, __FUNCTION__);
+ e_video_hwc_render((E_Video_Hwc *)evhp, __FUNCTION__);
}
return ECORE_CALLBACK_PASS_ON;
};
static void _e_video_destroy(E_Video_Hwc_Windows *evhw);
-static void _e_video_render(E_Video_Hwc_Windows *evhw, const char *func);
static Eina_Bool _e_video_frame_buffer_show(E_Video_Hwc_Windows *evhw, E_Comp_Wl_Video_Buf *vbuf);
static void _e_video_vblank_handler(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data);
static void
-_e_video_input_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
-{
- E_Video_Hwc_Windows *evhw = data;
- Eina_Bool need_hide = EINA_FALSE;
-
- DBG("Buffer(%p) to be free, refcnt(%d)", vbuf, vbuf->ref_cnt);
-
- evhw->base.input_buffer_list = eina_list_remove(evhw->base.input_buffer_list, vbuf);
-
- if (vbuf->comp_buffer)
- e_comp_wl_buffer_reference(&vbuf->buffer_ref, NULL);
-
- if (evhw->base.current_fb == vbuf)
- {
- VIN("current fb destroyed", evhw->base.ec);
- e_comp_wl_video_buffer_set_use(evhw->base.current_fb, EINA_FALSE);
- evhw->base.current_fb = NULL;
- need_hide = EINA_TRUE;
- }
-
- if (eina_list_data_find(evhw->base.committed_list, vbuf))
- {
- VIN("committed fb destroyed", evhw->base.ec);
- evhw->base.committed_list = eina_list_remove(evhw->base.committed_list, vbuf);
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
- need_hide = EINA_TRUE;
- }
-
- if (eina_list_data_find(evhw->base.waiting_list, vbuf))
- {
- VIN("waiting fb destroyed", evhw->base.ec);
- evhw->base.waiting_list = eina_list_remove(evhw->base.waiting_list, vbuf);
- }
-
- if (need_hide)
- _e_video_frame_buffer_show(evhw, NULL);
-}
-
-static E_Comp_Wl_Video_Buf *
-_e_video_input_buffer_get(E_Video_Hwc_Windows *evhw, E_Comp_Wl_Buffer *comp_buffer, Eina_Bool scanout)
-{
- E_Comp_Wl_Video_Buf *vbuf;
- Eina_Bool need_pp_scanout = EINA_FALSE;
-
- vbuf = e_video_hwc_vbuf_find_with_comp_buffer(evhw->base.input_buffer_list, comp_buffer);
- if (vbuf)
- {
- vbuf->content_r = evhw->base.geo.input_r;
- return vbuf;
- }
-
- vbuf = e_comp_wl_video_buffer_create_comp(comp_buffer);
- EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, NULL);
-
- if (evhw->base.pp_scanout)
- {
- Eina_Bool input_buffer_scanout = EINA_FALSE;
- input_buffer_scanout = e_video_hwc_video_buffer_scanout_check(vbuf);
- if (!input_buffer_scanout) need_pp_scanout = EINA_TRUE;
- }
-
- if (evhw->base.pp)
- {
- if ((evhw->base.pp_align != -1 && (vbuf->width_from_pitch % evhw->base.pp_align)) ||
- need_pp_scanout)
- {
- E_Comp_Wl_Video_Buf *temp;
-
- if (need_pp_scanout)
- temp = e_video_hwc_input_buffer_copy((E_Video_Hwc *)evhw, comp_buffer, vbuf, EINA_TRUE);
- else
- temp = e_video_hwc_input_buffer_copy((E_Video_Hwc *)evhw, comp_buffer, vbuf, scanout);
- if (!temp)
- {
- e_comp_wl_video_buffer_unref(vbuf);
- return NULL;
- }
- vbuf = temp;
- }
- }
-
- vbuf->content_r = evhw->base.geo.input_r;
-
- evhw->base.input_buffer_list = eina_list_append(evhw->base.input_buffer_list, vbuf);
- e_comp_wl_video_buffer_free_func_add(vbuf, _e_video_input_buffer_cb_free, evhw);
-
- DBG("Client(%s):PID(%d) RscID(%d), Buffer(%p) created, refcnt:%d"
- " scanout=%d", e_client_util_name_get(evhw->base.ec) ?: "No Name" ,
- evhw->base.ec->netwm.pid, wl_resource_get_id(evhw->base.ec->comp_data->surface), vbuf,
- vbuf->ref_cnt, scanout);
-
- return vbuf;
-}
-
-static void
_e_video_commit_handler(tdm_layer *layer, unsigned int sequence,
unsigned int tv_sec, unsigned int tv_usec,
void *user_data)
return EINA_TRUE;
}
+EINTERN Eina_Bool
+e_video_hwc_windows_frame_buffer_show(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf)
+{
+ E_Video_Hwc_Windows *evhw;
+
+ evhw = (E_Video_Hwc_Windows *)evh;
+ return _e_video_frame_buffer_show(evhw, vbuf);
+}
+
static void
_e_video_buffer_show(E_Video_Hwc_Windows *evhw, E_Comp_Wl_Video_Buf *vbuf, unsigned int transform)
{
_e_video_commit_buffer(evhw, vbuf);
}
-static void
-_e_video_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
-{
- E_Video_Hwc_Windows *evhw = data;
-
- if (e_video_hwc_geometry_map_apply(evhw->base.ec, &evhw->base.geo))
- _e_video_render(evhw, __FUNCTION__);
-}
-
-static void
-_e_video_cb_evas_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+EINTERN void
+e_video_hwc_windows_buffer_show(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf, unsigned int transform)
{
- E_Video_Hwc_Windows *evhw = data;
+ E_Video_Hwc_Windows *evhw;
- if (e_video_hwc_geometry_map_apply(evhw->base.ec, &evhw->base.geo))
- _e_video_render(evhw, __FUNCTION__);
+ evhw = (E_Video_Hwc_Windows *)evh;
+ _e_video_buffer_show(evhw, vbuf, transform);
}
static void
if (evhw->base.need_force_render)
{
VIN("video forcely rendering..", evhw->base.ec);
- _e_video_render(evhw, __FUNCTION__);
+ e_video_hwc_render((E_Video_Hwc *)evhw, __FUNCTION__);
}
/* if stand_alone is true, not show */
}
static void
-_e_video_hide(E_Video_Hwc_Windows *evhw)
-{
- E_Comp_Wl_Video_Buf *vbuf;
-
- if (evhw->base.current_fb || evhw->base.committed_list)
- _e_video_frame_buffer_show(evhw, NULL);
-
- if (evhw->base.current_fb)
- {
- e_comp_wl_video_buffer_set_use(evhw->base.current_fb, EINA_FALSE);
- evhw->base.current_fb = NULL;
- }
-
- if (evhw->base.old_comp_buffer)
- evhw->base.old_comp_buffer = NULL;
-
- EINA_LIST_FREE(evhw->base.committed_list, vbuf)
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-
- EINA_LIST_FREE(evhw->base.waiting_list, vbuf)
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
-}
-
-static void
_e_video_destroy(E_Video_Hwc_Windows *evhw)
{
- E_Comp_Wl_Video_Buf *vbuf;
- Eina_List *l = NULL, *ll = NULL;
-
if (!evhw)
return;
VIN("destroy", evhw->base.ec);
- if (evhw->base.cb_registered)
- {
- evas_object_event_callback_del_full(evhw->base.ec->frame, EVAS_CALLBACK_RESIZE,
- _e_video_cb_evas_resize, evhw);
- evas_object_event_callback_del_full(evhw->base.ec->frame, EVAS_CALLBACK_MOVE,
- _e_video_cb_evas_move, evhw);
- }
-
- _e_video_hide(evhw);
-
- /* others */
- EINA_LIST_FOREACH_SAFE(evhw->base.input_buffer_list, l, ll, vbuf)
- {
- e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
- e_comp_wl_video_buffer_unref(vbuf);
- }
-
- if (evhw->base.input_buffer_list)
- NEVER_GET_HERE();
-
- /* destroy converter second */
- if (evhw->base.pp)
- tdm_pp_destroy(evhw->base.pp);
-
e_hwc_window_free(evhw->hwc_window);
free(evhw);
#endif
}
-static Eina_Bool
-_e_video_check_if_pp_needed(E_Video_Hwc_Windows *evhw)
+EINTERN Eina_Bool
+e_video_hwc_windows_check_if_pp_needed(E_Video_Hwc *evh)
{
+ E_Video_Hwc_Windows *evhw;
int i, count = 0;
const tbm_format *formats;
Eina_Bool found = EINA_FALSE;
- E_Hwc *hwc = evhw->hwc;
+ E_Hwc *hwc;
+ evhw = (E_Video_Hwc_Windows *)evh;
+ hwc = evhw->hwc;
if (hwc->tdm_hwc_video_stream)
return EINA_FALSE;
return EINA_TRUE;
}
-static void
-_e_video_pp_cb_done(tdm_pp *pp, tbm_surface_h sb, tbm_surface_h db, void *user_data)
-{
- E_Video_Hwc_Windows *evhw = (E_Video_Hwc_Windows*)user_data;
- E_Comp_Wl_Video_Buf *input_buffer, *pp_buffer;
-
- input_buffer = e_video_hwc_vbuf_find(evhw->base.input_buffer_list, sb);
- if (input_buffer)
- e_comp_wl_video_buffer_unref(input_buffer);
-
- pp_buffer = e_video_hwc_vbuf_find(evhw->base.pp_buffer_list, db);
- if (pp_buffer)
- {
- e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
- if (!e_video_hwc_client_visible_get(evhw->base.ec)) return;
-
- _e_video_buffer_show(evhw, pp_buffer, 0);
- }
- else
- {
- VER("There is no pp_buffer", evhw->base.ec);
- // there is no way to set in_use flag.
- // This will cause issue when server get available pp_buffer.
- }
-}
-
-static void
-_e_video_render(E_Video_Hwc_Windows *evhw, const char *func)
-{
- E_Comp_Wl_Buffer *comp_buffer;
- E_Comp_Wl_Video_Buf *pp_buffer = NULL;
- E_Comp_Wl_Video_Buf *input_buffer = NULL;
- E_Client *topmost;
-
- EINA_SAFETY_ON_NULL_RETURN(evhw->base.ec);
-
- /* buffer can be NULL when camera/video's mode changed. Do nothing and
- * keep previous frame in this case.
- */
- if (!evhw->base.ec->pixmap)
- return;
-
- if (!e_video_hwc_client_visible_get(evhw->base.ec))
- {
- _e_video_hide(evhw);
- return;
- }
-
- comp_buffer = e_pixmap_resource_get(evhw->base.ec->pixmap);
- if (!comp_buffer) return;
-
- evhw->base.tbmfmt = e_video_hwc_comp_buffer_tbm_format_get(comp_buffer);
-
- /* not interested with other buffer type */
- if (!wayland_tbm_server_get_surface(NULL, comp_buffer->resource))
- return;
-
- topmost = e_comp_wl_topmost_parent_get(evhw->base.ec);
- EINA_SAFETY_ON_NULL_RETURN(topmost);
-
- if(e_comp_wl_viewport_is_changed(topmost))
- {
- VIN("need update viewport: apply topmost", evhw->base.ec);
- e_comp_wl_viewport_apply(topmost);
- }
-
- if (!e_video_hwc_geometry_get(evhw->base.ec, &evhw->base.geo))
- {
- if(!evhw->base.need_force_render && !e_video_hwc_client_parent_viewable_get(evhw->base.ec))
- {
- VIN("need force render", evhw->base.ec);
- evhw->base.need_force_render = EINA_TRUE;
- }
- return;
- }
-
- DBG("====================================== (%s)", func);
- VDB("old: "GEO_FMT" buf(%p)",
- evhw->base.ec, GEO_ARG(&evhw->base.old_geo), evhw->base.old_comp_buffer);
- VDB("new: "GEO_FMT" buf(%p) %c%c%c%c",
- evhw->base.ec, GEO_ARG(&evhw->base.geo), comp_buffer, FOURCC_STR(evhw->base.tbmfmt));
-
- if (!memcmp(&evhw->base.old_geo, &evhw->base.geo, sizeof evhw->base.geo) &&
- evhw->base.old_comp_buffer == comp_buffer)
- return;
-
- evhw->base.need_force_render = EINA_FALSE;
-
- e_video_hwc_input_buffer_valid((E_Video_Hwc *)evhw, comp_buffer);
-
- if (!_e_video_check_if_pp_needed(evhw))
- {
- /* 1. non converting case */
- input_buffer = _e_video_input_buffer_get(evhw, comp_buffer, EINA_TRUE);
- EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
-
- _e_video_buffer_show(evhw, input_buffer, evhw->base.geo.tdm.transform);
-
- evhw->base.old_geo = evhw->base.geo;
- evhw->base.old_comp_buffer = comp_buffer;
-
- goto done;
- }
-
- /* 2. converting case */
- if (!evhw->base.pp)
- {
- tdm_pp_capability pp_cap;
- tdm_error error = TDM_ERROR_NONE;
-
- evhw->base.pp = tdm_display_create_pp(e_comp->e_comp_screen->tdisplay, NULL);
- EINA_SAFETY_ON_NULL_GOTO(evhw->base.pp, render_fail);
-
- tdm_display_get_pp_available_size(e_comp->e_comp_screen->tdisplay, &evhw->base.pp_minw, &evhw->base.pp_minh,
- &evhw->base.pp_maxw, &evhw->base.pp_maxh, &evhw->base.pp_align);
-
- error = tdm_display_get_pp_capabilities(e_comp->e_comp_screen->tdisplay, &pp_cap);
- if (error == TDM_ERROR_NONE)
- {
- if (pp_cap & TDM_PP_CAPABILITY_SCANOUT)
- evhw->base.pp_scanout = EINA_TRUE;
- }
- }
-
- if ((evhw->base.pp_minw > 0 && (evhw->base.geo.input_r.w < evhw->base.pp_minw || evhw->base.geo.tdm.output_r.w < evhw->base.pp_minw)) ||
- (evhw->base.pp_minh > 0 && (evhw->base.geo.input_r.h < evhw->base.pp_minh || evhw->base.geo.tdm.output_r.h < evhw->base.pp_minh)) ||
- (evhw->base.pp_maxw > 0 && (evhw->base.geo.input_r.w > evhw->base.pp_maxw || evhw->base.geo.tdm.output_r.w > evhw->base.pp_maxw)) ||
- (evhw->base.pp_maxh > 0 && (evhw->base.geo.input_r.h > evhw->base.pp_maxh || evhw->base.geo.tdm.output_r.h > evhw->base.pp_maxh)))
- {
- INF("size(%dx%d, %dx%d) is out of PP range",
- evhw->base.geo.input_r.w, evhw->base.geo.input_r.h, evhw->base.geo.tdm.output_r.w, evhw->base.geo.tdm.output_r.h);
- goto done;
- }
-
- input_buffer = _e_video_input_buffer_get(evhw, comp_buffer, EINA_FALSE);
- EINA_SAFETY_ON_NULL_GOTO(input_buffer, render_fail);
-
- pp_buffer = e_video_hwc_pp_buffer_get((E_Video_Hwc *)evhw, evhw->base.geo.tdm.output_r.w, evhw->base.geo.tdm.output_r.h);
- EINA_SAFETY_ON_NULL_GOTO(pp_buffer, render_fail);
-
- if (memcmp(&evhw->base.old_geo, &evhw->base.geo, sizeof evhw->base.geo))
- {
- tdm_info_pp info;
-
- CLEAR(info);
- info.src_config.size.h = input_buffer->width_from_pitch;
- info.src_config.size.v = input_buffer->height_from_size;
- info.src_config.pos.x = evhw->base.geo.input_r.x;
- info.src_config.pos.y = evhw->base.geo.input_r.y;
- info.src_config.pos.w = evhw->base.geo.input_r.w;
- info.src_config.pos.h = evhw->base.geo.input_r.h;
- info.src_config.format = evhw->base.tbmfmt;
- info.dst_config.size.h = pp_buffer->width_from_pitch;
- info.dst_config.size.v = pp_buffer->height_from_size;
- info.dst_config.pos.w = evhw->base.geo.tdm.output_r.w;
- info.dst_config.pos.h = evhw->base.geo.tdm.output_r.h;
- info.dst_config.format = evhw->base.pp_tbmfmt;
- info.transform = evhw->base.geo.tdm.transform;
-
- if (tdm_pp_set_info(evhw->base.pp, &info))
- {
- VER("tdm_pp_set_info() failed", evhw->base.ec);
- goto render_fail;
- }
-
- if (tdm_pp_set_done_handler(evhw->base.pp, _e_video_pp_cb_done, evhw))
- {
- VER("tdm_pp_set_done_handler() failed", evhw->base.ec);
- goto render_fail;
- }
-
- CLEAR(evhw->base.pp_r);
- evhw->base.pp_r.w = info.dst_config.pos.w;
- evhw->base.pp_r.h = info.dst_config.pos.h;
- }
-
- pp_buffer->content_r = evhw->base.pp_r;
-
- if (tdm_pp_attach(evhw->base.pp, input_buffer->tbm_surface, pp_buffer->tbm_surface))
- {
- VER("tdm_pp_attach() failed", evhw->base.ec);
- goto render_fail;
- }
-
- e_comp_wl_video_buffer_set_use(pp_buffer, EINA_TRUE);
-
- e_comp_wl_buffer_reference(&input_buffer->buffer_ref, comp_buffer);
-
- if (tdm_pp_commit(evhw->base.pp))
- {
- VER("tdm_pp_commit() failed", evhw->base.ec);
- e_comp_wl_video_buffer_set_use(pp_buffer, EINA_FALSE);
- goto render_fail;
- }
-
- evhw->base.old_geo = evhw->base.geo;
- evhw->base.old_comp_buffer = comp_buffer;
-
- goto done;
-
-render_fail:
- if (input_buffer)
- e_comp_wl_video_buffer_unref(input_buffer);
-
-done:
- if (!evhw->base.cb_registered)
- {
- evas_object_event_callback_add(evhw->base.ec->frame, EVAS_CALLBACK_RESIZE,
- _e_video_cb_evas_resize, evhw);
- evas_object_event_callback_add(evhw->base.ec->frame, EVAS_CALLBACK_MOVE,
- _e_video_cb_evas_move, evhw);
- evhw->base.cb_registered = EINA_TRUE;
- }
- DBG("======================================.");
-}
-
static Eina_Bool
_e_video_cb_ec_buffer_change(void *data, int type, void *event)
{
if (!evhw->base.ec->comp_data->video_client)
return ECORE_CALLBACK_PASS_ON;
- _e_video_render(evhw, __FUNCTION__);
+ e_video_hwc_render((E_Video_Hwc *)evhw, __FUNCTION__);
return ECORE_CALLBACK_PASS_ON;
}
{
VIN("video need rendering..", evhw->base.ec);
e_comp_wl_viewport_apply(ec);
- _e_video_render(evhw, __FUNCTION__);
+ e_video_hwc_render((E_Video_Hwc *)evhw, __FUNCTION__);
}
return ECORE_CALLBACK_PASS_ON;