capture: support multi layer oneshot capture 69/203269/1
authorJunkyeong Kim <jk0430.kim@samsung.com>
Thu, 11 Apr 2019 07:41:03 +0000 (16:41 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Thu, 11 Apr 2019 07:41:10 +0000 (16:41 +0900)
if src buffer is smaller than current mode, calculate correct crop position.

Change-Id: I15210218ca7663fe59df7cd138a93ba7b391d12d
Signed-off-by: Junkyeong Kim <jk0430.kim@samsung.com>
src/tdm_exynos_capture.c

index a6ca9d9bfa035e56fadf8acb20a7d76de4f9558c..b5a8fe435d28badf3ad8e2acb21a1ec5618c6cb2 100644 (file)
@@ -394,6 +394,122 @@ _tdm_exynos_capture_oneshot_rect_scale(int src_w, int src_h, int dst_w, int dst_
        scale->h = scale->h * ratio;
 }
 
+static void
+_tdm_exynos_capture_oneshot_get_showing_rect(tdm_pos *out_rect, tdm_pos *dst_rect, tdm_pos *showing_rect)
+{
+       showing_rect->x = dst_rect->x;
+       showing_rect->y = dst_rect->y;
+
+       if (dst_rect->x >= out_rect->w)
+               showing_rect->w = 0;
+       else if (dst_rect->x + dst_rect->w > out_rect->w)
+               showing_rect->w = out_rect->w - dst_rect->x;
+       else
+               showing_rect->w = dst_rect->w;
+
+       if (dst_rect->y >= out_rect->h)
+               showing_rect->h = 0;
+       else if (dst_rect->y + dst_rect->h > out_rect->h)
+               showing_rect->h = out_rect->h - dst_rect->y;
+       else
+               showing_rect->h = dst_rect->h;
+}
+
+static void
+_tdm_exynos_capture_oneshot_get_src_crop_info(tdm_exynos_capture_data *capture_data,
+                                                                                         tdm_exynos_layer_data *layer_data, tdm_pos *src_crop, tdm_pos *showing_rect)
+{
+       tdm_exynos_output_data *output_data = capture_data->output_data;
+       float ratio_x, ratio_y;
+       tdm_pos out_rect;
+       tdm_pos dst_rect;
+
+       out_rect.x = 0;
+       out_rect.y = 0;
+       out_rect.w = output_data->current_mode->hdisplay;
+       out_rect.h = output_data->current_mode->vdisplay;
+
+       dst_rect.x = layer_data->info.dst_pos.x;
+       dst_rect.y = layer_data->info.dst_pos.y;
+       dst_rect.w = layer_data->info.dst_pos.w;
+       dst_rect.h = layer_data->info.dst_pos.h;
+
+       _tdm_exynos_capture_oneshot_get_showing_rect(&out_rect, &dst_rect, showing_rect);
+
+       src_crop->x = layer_data->info.src_config.pos.x;
+       src_crop->y = layer_data->info.src_config.pos.y;
+
+       if (layer_data->info.transform % 2 == 0) {
+               ratio_x = (float)layer_data->info.src_config.pos.w / dst_rect.w;
+               ratio_y = (float)layer_data->info.src_config.pos.h / dst_rect.h;
+
+               src_crop->w = showing_rect->w * ratio_x;
+               src_crop->h = showing_rect->h * ratio_y;
+       } else {
+               ratio_x = (float)layer_data->info.src_config.pos.w / dst_rect.h;
+               ratio_y = (float)layer_data->info.src_config.pos.h / dst_rect.w;
+
+               src_crop->w = showing_rect->h * ratio_x;
+               src_crop->h = showing_rect->w * ratio_y;
+       }
+}
+
+static void
+_tdm_exynos_capture_oneshot_get_dst_crop_info(tdm_exynos_capture_data *capture_data, tdm_exynos_layer_data *layer_data,
+                                                                                         tdm_pos *dst_pos, tdm_pos *showing_pos, tdm_pos *dst_crop,
+                                                                                         tdm_transform transform)
+{
+       tdm_exynos_output_data *output_data = capture_data->output_data;
+
+       if (layer_data->info.src_config.pos.w == output_data->current_mode->hdisplay &&
+               layer_data->info.src_config.pos.h == output_data->current_mode->vdisplay &&
+               dst_pos->x == 0 && dst_pos->y == 0 &&
+               dst_pos->w == capture_data->info.dst_config.size.h &&
+               dst_pos->h == capture_data->info.dst_config.size.v) {
+               dst_crop->x = dst_pos->x;
+               dst_crop->y = dst_pos->y;
+               dst_crop->w = dst_pos->w;
+               dst_crop->h = dst_pos->h;
+       } else if ((output_data->current_mode->hdisplay == dst_pos->w) &&
+                          (output_data->current_mode->vdisplay == dst_pos->h) &&
+                          (showing_pos->w == dst_pos->w) && (showing_pos->h == dst_pos->h)) {
+               dst_crop->x = layer_data->info.dst_pos.x + dst_pos->x;
+               dst_crop->y = layer_data->info.dst_pos.y + dst_pos->y;
+               dst_crop->w = layer_data->info.dst_pos.w;
+               dst_crop->h = layer_data->info.dst_pos.h;
+       } else if (transform == TDM_TRANSFORM_NORMAL || transform == TDM_TRANSFORM_FLIPPED) {
+               dst_crop->x = showing_pos->x * dst_pos->w / output_data->current_mode->hdisplay + dst_pos->x;
+               dst_crop->y = showing_pos->y * dst_pos->h / output_data->current_mode->vdisplay + dst_pos->y;
+               dst_crop->w = showing_pos->w * dst_pos->w / output_data->current_mode->hdisplay;
+               dst_crop->h = showing_pos->h * dst_pos->h / output_data->current_mode->vdisplay;
+       } else if (transform == TDM_TRANSFORM_90 || transform == TDM_TRANSFORM_FLIPPED_90) {
+               dst_crop->x = (output_data->current_mode->vdisplay - showing_pos->y - showing_pos->h) *
+                                         dst_pos->w / output_data->current_mode->vdisplay + dst_pos->x;
+               dst_crop->y = showing_pos->x * dst_pos->h / output_data->current_mode->hdisplay + dst_pos->y;
+               dst_crop->w = showing_pos->h * dst_pos->w / output_data->current_mode->vdisplay;
+               dst_crop->h = showing_pos->w * dst_pos->h / output_data->current_mode->hdisplay;
+       } else if (transform == TDM_TRANSFORM_180 || transform == TDM_TRANSFORM_FLIPPED_180) {
+               dst_crop->x = (output_data->current_mode->hdisplay - showing_pos->x - showing_pos->w) *
+                                         dst_pos->w / output_data->current_mode->hdisplay + dst_pos->x;
+               dst_crop->y = (output_data->current_mode->vdisplay - showing_pos->y - showing_pos->h) *
+                                         dst_pos->h / output_data->current_mode->vdisplay + dst_pos->y;
+               dst_crop->w = showing_pos->w * dst_pos->w / output_data->current_mode->hdisplay;
+               dst_crop->h = showing_pos->h * dst_pos->h / output_data->current_mode->vdisplay;
+       } else if (transform == TDM_TRANSFORM_270 || transform == TDM_TRANSFORM_FLIPPED_270) {
+               dst_crop->x = showing_pos->y * dst_pos->w / output_data->current_mode->vdisplay + dst_pos->x;
+               dst_crop->y = (output_data->current_mode->hdisplay - showing_pos->x - showing_pos->w) *
+                                         dst_pos->h / output_data->current_mode->hdisplay + dst_pos->y;
+               dst_crop->w = showing_pos->h * dst_pos->w / output_data->current_mode->vdisplay;
+               dst_crop->h = showing_pos->w * dst_pos->h / output_data->current_mode->hdisplay;
+       } else {
+               dst_crop->x = dst_pos->x;
+               dst_crop->y = dst_pos->y;
+               dst_crop->w = dst_pos->w;
+               dst_crop->h = dst_pos->h;
+               TDM_ERR("oneshot: get_crop unknown case error");
+       }
+}
+
 static void
 _tdm_exynos_capture_oneshot_composite_layers_sw(tdm_exynos_capture_data *capture_data, tbm_surface_h buffer)
 {
@@ -408,6 +524,9 @@ _tdm_exynos_capture_oneshot_composite_layers_sw(tdm_exynos_capture_data *capture
        LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
                tbm_surface_h buf;
                tdm_pos dst_pos;
+               tdm_pos showing_pos;
+               tdm_pos src_crop;
+               tdm_pos dst_crop;
                tdm_transform transform = TDM_TRANSFORM_NORMAL;
 
                if (!layer_data->display_buffer)
@@ -421,13 +540,20 @@ _tdm_exynos_capture_oneshot_composite_layers_sw(tdm_exynos_capture_data *capture
                        _tdm_exynos_capture_oneshot_rect_scale(output_data->current_mode->hdisplay,
                                                                                                   output_data->current_mode->vdisplay,
                                                                                                   buf_info.width, buf_info.height, &dst_pos);
-
                } else {
                        dst_pos = capture_data->info.dst_config.pos;
                        transform = capture_data->info.transform;
                }
+
+               _tdm_exynos_capture_oneshot_get_src_crop_info(capture_data, layer_data, &src_crop, &showing_pos);
+               _tdm_exynos_capture_oneshot_get_dst_crop_info(capture_data, layer_data, &dst_pos, &showing_pos, &dst_crop, transform);
+
+               TDM_DBG("oneshot convert buff: src_crop(%dx%d, %dx%d), dst_crop(%dx%d, %dx%d)\n",
+                               src_crop.x, src_crop.y, src_crop.w, src_crop.h,
+                               dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h);
+
                tdm_helper_convert_buffer(buf, buffer,
-                                                                 &layer_data->info.src_config.pos, &dst_pos, transform, 1);
+                                                                 &src_crop, &dst_crop, transform, 1);
        }
 }