static void _e_video_hwc_buffer_show(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf, unsigned int transform);
static void _e_video_hwc_buffer_commit(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf);
+static void
+_coord_move_to_axis(int x_axis, int y_axis, int *ox, int *oy)
+{
+ *ox = *ox - x_axis;
+ *oy = *oy - y_axis;
+}
+
+static void
+_rectangle_to_coord(Eina_Rectangle *rect, Evas_Point p[2])
+{
+ p[0].x = rect->x;
+ p[0].y = rect->y;
+ p[1].x = rect->x + rect->w;
+ p[1].y = rect->y + rect->h;
+}
+
+static void
+_coord_to_rectangle(Evas_Point p[2], Eina_Rectangle *rect)
+{
+ rect->x = MIN(p[0].x, p[1].x);
+ rect->y = MIN(p[0].y, p[1].y);
+ rect->w = MAX(p[0].x, p[1].x) - rect->x;
+ rect->h = MAX(p[0].y, p[1].y) - rect->y;
+}
+
static E_Client *
_e_video_hwc_client_offscreen_parent_get(E_Client *ec)
{
e_comp_wl_video_buffer_set_use(vbuf, EINA_FALSE);
}
+/* Translate sx/sy position of src_rect-local coordinates to
+ * new position of dst_rect-local coordinates. */
+static void
+_e_video_hwc_coord_transform(Eina_Rectangle *src_rect, Eina_Rectangle *dst_rect, uint transform, int sx, int sy, int *dx, int *dy)
+{
+ float ratio_w, ratio_h;
+
+ switch (transform)
+ {
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ default:
+ *dx = sx, *dy = sy;
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ *dx = sx, *dy = src_rect->w - sx;
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ *dx = src_rect->w - sx, *dy = dst_rect->h - sy;
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ *dx = src_rect->y - sy, *dy = sx;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ *dx = src_rect->w - sx, *dy = sy;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ *dx = sy, *dy = sx;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ *dx = sx, *dy = src_rect->h - sy;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ *dx = src_rect->h - sy, *dy = src_rect->w - sx;
+ break;
+ }
+
+ if (transform & 0x1)
+ {
+ ratio_w = (float)dst_rect->w / src_rect->h;
+ ratio_h = (float)dst_rect->h / src_rect->w;
+ }
+ else
+ {
+ ratio_w = (float)dst_rect->w / src_rect->w;
+ ratio_h = (float)dst_rect->h / src_rect->h;
+ }
+
+ *dx = (*dx) * ratio_w + dst_rect->x;
+ *dy = (*dy) * ratio_h + dst_rect->y;
+}
+
+/* Clipping source/destination of viewport.
+ * @in zone A E_Zone instance to be used to get screen rectangle.
+ * @inout input_r A Source of viewport to be set to tdm_info.src_config
+ * tdm.output_r A Destination of viewport to be set to tdm_info.dst_pos
+ * tdm.output_r will be clipped by given region of zone, and then input_r will be
+ * clipped accordingly.
+ */
+static void
+_e_video_hwc_tdm_viewport_clip(E_Video_Hwc_Geometry *in_out, E_Zone *zone)
+{
+ Eina_Rectangle *dst_rect, *src_rect;
+ Eina_Rectangle new_dst_rect, clip_rect;
+ Evas_Point p[2];
+
+ EINA_RECTANGLE_SET(&clip_rect, zone->x, zone->y, zone->w, zone->h);
+ src_rect = &in_out->input_r;
+ dst_rect = &in_out->tdm.output_r;
+
+ /* No need to clip in case clip_rect contains dst_rect. */
+ if (E_CONTAINS(clip_rect.x, clip_rect.y, clip_rect.w, clip_rect.y,
+ dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->y))
+ return;
+
+ EINA_RECTANGLE_SET(&new_dst_rect,
+ dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
+ if (eina_rectangle_intersection(&new_dst_rect, &clip_rect) == EINA_FALSE)
+ {
+ VER("Warning! Video will not be displayed."
+ "No intersection between dst rect and clip rect.\n"
+ "dst(%d,%d %dx%d) clip(%d,%d %dx%d) => intersect(%d,%d %dx%d)",
+ NULL, EINA_RECTANGLE_ARGS(dst_rect),
+ EINA_RECTANGLE_ARGS(&clip_rect),
+ EINA_RECTANGLE_ARGS(&new_dst_rect));
+ EINA_RECTANGLE_SET(dst_rect, 0, 0, 0, 0);
+ /* NOTE: Does src_rect need to be handled as well? */
+ return;
+ }
+
+ VDB("Clipping viewport in order to set it to tdm", NULL);
+ VDB("Screen region %d,%d %dx%d", NULL, EINA_RECTANGLE_ARGS(&clip_rect));
+ VDB("Viewport src(%d,%d %dx%d) dst(%d,%d %dx%d)", NULL,
+ EINA_RECTANGLE_ARGS(src_rect), EINA_RECTANGLE_ARGS(dst_rect));
+
+ _rectangle_to_coord(&new_dst_rect, p);
+
+ /* Move coordinates of cropped rectangle into dst_rect-local coordinates. */
+ _coord_move_to_axis(dst_rect->x, dst_rect->y, &p[0].x, &p[0].y);
+ _coord_move_to_axis(dst_rect->x, dst_rect->y, &p[1].x, &p[1].y);
+
+ /* Calculate new coordinates of src according to cropping dst */
+ _e_video_hwc_coord_transform(dst_rect, src_rect, in_out->transform,
+ p[0].x, p[0].y, &p[0].x, &p[0].y);
+ _e_video_hwc_coord_transform(dst_rect, src_rect, in_out->transform,
+ p[1].x, p[1].y, &p[1].x, &p[1].y);
+
+ _coord_to_rectangle(p, src_rect);
+ EINA_RECTANGLE_SET(dst_rect,
+ new_dst_rect.x, new_dst_rect.y,
+ new_dst_rect.w, new_dst_rect.h);
+
+ VDB("Result source region %d,%d %dx%d", NULL, EINA_RECTANGLE_ARGS(src_rect));
+ VDB("Result output region %d,%d %dx%d", NULL, EINA_RECTANGLE_ARGS(dst_rect));
+}
+
static void
_e_video_hwc_geometry_tdm_config_update(E_Client *ec, E_Video_Hwc_Geometry *out)
{
ec, EINA_RECTANGLE_ARGS(&out->output_r), out->transform, transform,
EINA_RECTANGLE_ARGS(&out->tdm.output_r), out->tdm.transform);
+ _e_video_hwc_tdm_viewport_clip(out, zone);
+
return;
normal:
out->tdm.output_r = out->output_r;