[media] vivid-tpg: split off the pattern drawing code
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 9 Mar 2015 14:52:43 +0000 (11:52 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Thu, 2 Apr 2015 23:49:36 +0000 (20:49 -0300)
The last part of the vivid-tpg refactoring: split off the pattern
drawing code into a function of its own. This greatly improves the
readability and maintainability of this code.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/platform/vivid/vivid-tpg.c

index 21c2f4b3242e79b56939def6564a5722c316875f..3f0ec9ab70305d156ec23114f7b41dc100b8a705 100644 (file)
@@ -1693,19 +1693,153 @@ static void tpg_fill_plane_extras(const struct tpg_data *tpg,
        }
 }
 
-void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
+static void tpg_fill_plane_pattern(const struct tpg_data *tpg,
+                                  const struct tpg_draw_params *params,
+                                  unsigned p, unsigned h, u8 *vbuf)
+{
+       unsigned twopixsize = params->twopixsize;
+       unsigned img_width = params->img_width;
+       unsigned mv_hor_old = params->mv_hor_old;
+       unsigned mv_hor_new = params->mv_hor_new;
+       unsigned mv_vert_old = params->mv_vert_old;
+       unsigned mv_vert_new = params->mv_vert_new;
+       unsigned frame_line = params->frame_line;
+       unsigned frame_line_next = params->frame_line_next;
+       unsigned line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
+       bool even;
+       bool fill_blank = false;
+       unsigned pat_line_old;
+       unsigned pat_line_new;
+       u8 *linestart_older;
+       u8 *linestart_newer;
+       u8 *linestart_top;
+       u8 *linestart_bottom;
+
+       even = !(frame_line & 1);
+
+       if (h >= params->hmax) {
+               if (params->hmax == tpg->compose.height)
+                       return;
+               if (!tpg->perc_fill_blank)
+                       return;
+               fill_blank = true;
+       }
+
+       if (tpg->vflip) {
+               frame_line = tpg->src_height - frame_line - 1;
+               frame_line_next = tpg->src_height - frame_line_next - 1;
+       }
+
+       if (fill_blank) {
+               linestart_older = tpg->contrast_line[p];
+               linestart_newer = tpg->contrast_line[p];
+       } else if (tpg->qual != TPG_QUAL_NOISE &&
+                  (frame_line < tpg->border.top ||
+                   frame_line >= tpg->border.top + tpg->border.height)) {
+               linestart_older = tpg->black_line[p];
+               linestart_newer = tpg->black_line[p];
+       } else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) {
+               linestart_older = tpg->random_line[p] +
+                                 twopixsize * prandom_u32_max(tpg->src_width / 2);
+               linestart_newer = tpg->random_line[p] +
+                                 twopixsize * prandom_u32_max(tpg->src_width / 2);
+       } else {
+               unsigned frame_line_old =
+                       (frame_line + mv_vert_old) % tpg->src_height;
+               unsigned frame_line_new =
+                       (frame_line + mv_vert_new) % tpg->src_height;
+               unsigned pat_line_next_old;
+               unsigned pat_line_next_new;
+
+               pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
+               pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
+               linestart_older = tpg->lines[pat_line_old][p] + mv_hor_old;
+               linestart_newer = tpg->lines[pat_line_new][p] + mv_hor_new;
+
+               if (tpg->vdownsampling[p] > 1 && frame_line != frame_line_next) {
+                       int avg_pat;
+
+                       /*
+                        * Now decide whether we need to use downsampled_lines[].
+                        * That's necessary if the two lines use different patterns.
+                        */
+                       pat_line_next_old = tpg_get_pat_line(tpg,
+                                       (frame_line_next + mv_vert_old) % tpg->src_height);
+                       pat_line_next_new = tpg_get_pat_line(tpg,
+                                       (frame_line_next + mv_vert_new) % tpg->src_height);
+
+                       switch (tpg->field) {
+                       case V4L2_FIELD_INTERLACED:
+                       case V4L2_FIELD_INTERLACED_BT:
+                       case V4L2_FIELD_INTERLACED_TB:
+                               avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
+                               if (avg_pat < 0)
+                                       break;
+                               linestart_older = tpg->downsampled_lines[avg_pat][p] + mv_hor_old;
+                               linestart_newer = linestart_older;
+                               break;
+                       case V4L2_FIELD_NONE:
+                       case V4L2_FIELD_TOP:
+                       case V4L2_FIELD_BOTTOM:
+                       case V4L2_FIELD_SEQ_BT:
+                       case V4L2_FIELD_SEQ_TB:
+                               avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
+                               if (avg_pat >= 0)
+                                       linestart_older = tpg->downsampled_lines[avg_pat][p] +
+                                               mv_hor_old;
+                               avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
+                               if (avg_pat >= 0)
+                                       linestart_newer = tpg->downsampled_lines[avg_pat][p] +
+                                               mv_hor_new;
+                               break;
+                       }
+               }
+               linestart_older += line_offset;
+               linestart_newer += line_offset;
+       }
+       if (tpg->field_alternate) {
+               linestart_top = linestart_bottom = linestart_older;
+       } else if (params->is_60hz) {
+               linestart_top = linestart_newer;
+               linestart_bottom = linestart_older;
+       } else {
+               linestart_top = linestart_older;
+               linestart_bottom = linestart_newer;
+       }
+
+       switch (tpg->field) {
+       case V4L2_FIELD_INTERLACED:
+       case V4L2_FIELD_INTERLACED_TB:
+       case V4L2_FIELD_SEQ_TB:
+       case V4L2_FIELD_SEQ_BT:
+               if (even)
+                       memcpy(vbuf, linestart_top, img_width);
+               else
+                       memcpy(vbuf, linestart_bottom, img_width);
+               break;
+       case V4L2_FIELD_INTERLACED_BT:
+               if (even)
+                       memcpy(vbuf, linestart_bottom, img_width);
+               else
+                       memcpy(vbuf, linestart_top, img_width);
+               break;
+       case V4L2_FIELD_TOP:
+               memcpy(vbuf, linestart_top, img_width);
+               break;
+       case V4L2_FIELD_BOTTOM:
+               memcpy(vbuf, linestart_bottom, img_width);
+               break;
+       case V4L2_FIELD_NONE:
+       default:
+               memcpy(vbuf, linestart_older, img_width);
+               break;
+       }
+}
+
+void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
+                          unsigned p, u8 *vbuf)
 {
        struct tpg_draw_params params;
-       unsigned mv_hor_old;
-       unsigned mv_hor_new;
-       unsigned mv_vert_old;
-       unsigned mv_vert_new;
-       int h;
-       unsigned twopixsize;
-       unsigned vdiv = tpg->vdownsampling[p];
-       unsigned img_width;
-       unsigned line_offset;
-       unsigned stride;
        unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
 
        /* Coarse scaling with Bresenham */
@@ -1713,6 +1847,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
        unsigned fract_part = (tpg->crop.height / factor) % tpg->compose.height;
        unsigned src_y = 0;
        unsigned error = 0;
+       unsigned h;
 
        tpg_recalc(tpg);
 
@@ -1724,37 +1859,15 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
        params.hmax = (tpg->compose.height * tpg->perc_fill) / 100;
 
        tpg_fill_params_pattern(tpg, p, &params);
-
-       mv_hor_old = params.mv_hor_old;
-       mv_hor_new = params.mv_hor_new;
-       mv_vert_old = params.mv_vert_old;
-       mv_vert_new = params.mv_vert_new;
-
        tpg_fill_params_extras(tpg, p, &params);
 
-       twopixsize = params.twopixsize;
-       img_width = params.img_width;
-       stride = params.stride;
-
        vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
-       line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
 
        for (h = 0; h < tpg->compose.height; h++) {
-               bool even;
-               bool fill_blank = false;
-               unsigned frame_line;
                unsigned buf_line;
-               unsigned pat_line_old;
-               unsigned pat_line_new;
-               u8 *linestart_older;
-               u8 *linestart_newer;
-               u8 *linestart_top;
-               u8 *linestart_bottom;
 
                params.frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
                params.frame_line_next = params.frame_line;
-               frame_line = params.frame_line;
-               even = !(frame_line & 1);
                buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
                src_y += int_part;
                error += fract_part;
@@ -1763,7 +1876,7 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
                        src_y++;
                }
 
-               if (vdiv > 1) {
+               if (tpg->vdownsampling[p] > 1) {
                        /*
                         * When doing vertical downsampling the field setting
                         * matters: for SEQ_BT/TB we downsample each field
@@ -1774,135 +1887,26 @@ void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8
                         */
                        if (tpg->field == V4L2_FIELD_SEQ_BT ||
                            tpg->field == V4L2_FIELD_SEQ_TB) {
+                               unsigned next_src_y = src_y;
+
                                if ((h & 3) >= 2)
                                        continue;
-                       } else if (h & 1) {
-                               continue;
-                       }
-
-                       buf_line /= vdiv;
-               }
-
-               if (h >= params.hmax) {
-                       if (params.hmax == tpg->compose.height)
-                               continue;
-                       if (!tpg->perc_fill_blank)
-                               continue;
-                       fill_blank = true;
-               }
-
-               if (tpg->vflip)
-                       frame_line = tpg->src_height - frame_line - 1;
-
-               if (fill_blank) {
-                       linestart_older = tpg->contrast_line[p];
-                       linestart_newer = tpg->contrast_line[p];
-               } else if (tpg->qual != TPG_QUAL_NOISE &&
-                          (frame_line < tpg->border.top ||
-                           frame_line >= tpg->border.top + tpg->border.height)) {
-                       linestart_older = tpg->black_line[p];
-                       linestart_newer = tpg->black_line[p];
-               } else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) {
-                       linestart_older = tpg->random_line[p] +
-                                         twopixsize * prandom_u32_max(tpg->src_width / 2);
-                       linestart_newer = tpg->random_line[p] +
-                                         twopixsize * prandom_u32_max(tpg->src_width / 2);
-               } else {
-                       unsigned frame_line_old =
-                               (frame_line + mv_vert_old) % tpg->src_height;
-                       unsigned frame_line_new =
-                               (frame_line + mv_vert_new) % tpg->src_height;
-                       unsigned pat_line_next_old;
-                       unsigned pat_line_next_new;
-
-                       pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
-                       pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
-                       linestart_older = tpg->lines[pat_line_old][p] + mv_hor_old;
-                       linestart_newer = tpg->lines[pat_line_new][p] + mv_hor_new;
-
-                       if (vdiv > 1) {
-                               unsigned frame_line_next;
-                               int avg_pat;
-
-                               /*
-                                * Now decide whether we need to use downsampled_lines[].
-                                * That's necessary if the two lines use different patterns.
-                                */
-                               frame_line_next = tpg_calc_frameline(tpg, src_y, tpg->field);
-                               if (tpg->vflip)
-                                       frame_line_next = tpg->src_height - frame_line_next - 1;
-                               pat_line_next_old = tpg_get_pat_line(tpg,
-                                               (frame_line_next + mv_vert_old) % tpg->src_height);
-                               pat_line_next_new = tpg_get_pat_line(tpg,
-                                               (frame_line_next + mv_vert_new) % tpg->src_height);
-
-                               switch (tpg->field) {
-                               case V4L2_FIELD_INTERLACED:
-                               case V4L2_FIELD_INTERLACED_BT:
-                               case V4L2_FIELD_INTERLACED_TB:
-                                       avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
-                                       if (avg_pat < 0)
-                                               break;
-                                       linestart_older = tpg->downsampled_lines[avg_pat][p] + mv_hor_old;
-                                       linestart_newer = linestart_older;
-                                       break;
-                               case V4L2_FIELD_NONE:
-                               case V4L2_FIELD_TOP:
-                               case V4L2_FIELD_BOTTOM:
-                               case V4L2_FIELD_SEQ_BT:
-                               case V4L2_FIELD_SEQ_TB:
-                                       avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
-                                       if (avg_pat >= 0)
-                                               linestart_older = tpg->downsampled_lines[avg_pat][p] +
-                                                       mv_hor_old;
-                                       avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
-                                       if (avg_pat >= 0)
-                                               linestart_newer = tpg->downsampled_lines[avg_pat][p] +
-                                                       mv_hor_new;
-                                       break;
-                               }
+                               next_src_y += int_part;
+                               if (error + fract_part >= tpg->compose.height)
+                                       next_src_y++;
+                               params.frame_line_next =
+                                       tpg_calc_frameline(tpg, next_src_y, tpg->field);
+                       } else {
+                               if (h & 1)
+                                       continue;
+                               params.frame_line_next =
+                                       tpg_calc_frameline(tpg, src_y, tpg->field);
                        }
-                       linestart_older += line_offset;
-                       linestart_newer += line_offset;
-               }
-               if (tpg->field_alternate) {
-                       linestart_top = linestart_bottom = linestart_older;
-               } else if (params.is_60hz) {
-                       linestart_top = linestart_newer;
-                       linestart_bottom = linestart_older;
-               } else {
-                       linestart_top = linestart_older;
-                       linestart_bottom = linestart_newer;
-               }
 
-               switch (tpg->field) {
-               case V4L2_FIELD_INTERLACED:
-               case V4L2_FIELD_INTERLACED_TB:
-               case V4L2_FIELD_SEQ_TB:
-               case V4L2_FIELD_SEQ_BT:
-                       if (even)
-                               memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-                       else
-                               memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-                       break;
-               case V4L2_FIELD_INTERLACED_BT:
-                       if (even)
-                               memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-                       else
-                               memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-                       break;
-               case V4L2_FIELD_TOP:
-                       memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-                       break;
-               case V4L2_FIELD_BOTTOM:
-                       memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-                       break;
-               case V4L2_FIELD_NONE:
-               default:
-                       memcpy(vbuf + buf_line * stride, linestart_older, img_width);
-                       break;
+                       buf_line /= tpg->vdownsampling[p];
                }
-
+               tpg_fill_plane_pattern(tpg, &params, p, h,
+                               vbuf + buf_line * params.stride);
                tpg_fill_plane_extras(tpg, &params, p, h,
                                vbuf + buf_line * params.stride);
        }