video: Clipping viewport of out of screen to be set as tdm info. 07/216907/3
authorSeunghun Lee <shiin.lee@samsung.com>
Wed, 23 Oct 2019 05:36:25 +0000 (14:36 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Tue, 5 Nov 2019 02:22:50 +0000 (02:22 +0000)
A backend of TDM does not guarantee that it will translate coordinates
of out of screen region.
This patch is to translate coordinates of viewport for this reason.

Change-Id: I3b18b9fbc71b41815e7243fea17239d0dd3c296c

src/bin/video/iface/e_video_hwc.c

index 6ec86d9b2f5850805e91cbd2f76aeb86f237ab1a..0d3a011c55c8c3ac98dd0bdbd951a23b01eb514c 100644 (file)
@@ -18,6 +18,31 @@ static void _e_video_hwc_render(E_Video_Hwc *evh, const char *func);
 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)
 {
@@ -730,6 +755,121 @@ _e_video_hwc_hide(E_Video_Hwc *evh)
       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)
 {
@@ -805,6 +945,8 @@ _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;