xref: /aosp_15_r20/external/mesa3d/src/amd/vpelib/src/core/background.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* Copyright 2022 Advanced Micro Devices, Inc.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a
4  * copy of this software and associated documentation files (the "Software"),
5  * to deal in the Software without restriction, including without limitation
6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7  * and/or sell copies of the Software, and to permit persons to whom the
8  * Software is furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
16  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
17  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19  * OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * Authors: AMD
22  *
23  */
24 
25 #include "background.h"
26 #include "common.h"
27 #include "vpe_priv.h"
28 #include "color_bg.h"
29 
vpe_create_bg_segments(struct vpe_priv * vpe_priv,struct vpe_rect * gaps,uint16_t gaps_cnt,enum vpe_cmd_ops ops)30 void vpe_create_bg_segments(
31     struct vpe_priv *vpe_priv, struct vpe_rect *gaps, uint16_t gaps_cnt, enum vpe_cmd_ops ops)
32 {
33     uint16_t            gap_index;
34     struct scaler_data *scaler_data;
35     struct stream_ctx  *stream_ctx = &(vpe_priv->stream_ctx[0]);
36     int32_t             vp_x       = stream_ctx->stream.scaling_info.src_rect.x;
37     int32_t             vp_y       = stream_ctx->stream.scaling_info.src_rect.y;
38     uint16_t            src_h_div  = vpe_is_yuv420(stream_ctx->stream.surface_info.format) ? 2 : 1;
39     uint16_t            src_v_div  = vpe_is_yuv420(stream_ctx->stream.surface_info.format) ? 2 : 1;
40     uint16_t            dst_h_div  = vpe_is_yuv420(vpe_priv->output_ctx.surface.format) ? 2 : 1;
41     uint16_t            dst_v_div  = vpe_is_yuv420(vpe_priv->output_ctx.surface.format) ? 2 : 1;
42 
43     for (gap_index = 0; gap_index < gaps_cnt; gap_index++) {
44 
45         scaler_data = &(vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].inputs[0].scaler_data);
46 
47         /* format */
48         scaler_data->format             = stream_ctx->stream.surface_info.format;
49         scaler_data->lb_params.alpha_en = stream_ctx->per_pixel_alpha;
50 
51         /* recout */
52 
53         scaler_data->recout.x      = 0;
54         scaler_data->recout.y      = 0;
55         scaler_data->recout.height = VPE_MIN_VIEWPORT_SIZE;
56         scaler_data->recout.width  = VPE_MIN_VIEWPORT_SIZE;
57 
58         /* ratios */
59         scaler_data->ratios.horz = vpe_fixpt_one;
60         scaler_data->ratios.vert = vpe_fixpt_one;
61 
62         if (vpe_is_yuv420(scaler_data->format)) {
63             scaler_data->ratios.horz_c = vpe_fixpt_from_fraction(1, 2);
64             scaler_data->ratios.vert_c = vpe_fixpt_from_fraction(1, 2);
65         }
66         else {
67             scaler_data->ratios.horz_c = vpe_fixpt_one;
68             scaler_data->ratios.vert_c = vpe_fixpt_one;
69         }
70 
71         /* Active region */
72         scaler_data->h_active = gaps[gap_index].width;
73         scaler_data->v_active = gaps[gap_index].height;
74 
75         /* viewport */
76 
77         scaler_data->viewport.x      = vp_x;
78         scaler_data->viewport.y      = vp_y;
79         scaler_data->viewport.width  = VPE_MIN_VIEWPORT_SIZE;
80         scaler_data->viewport.height = VPE_MIN_VIEWPORT_SIZE;
81 
82         scaler_data->viewport_c.x      = scaler_data->viewport.x / src_h_div;
83         scaler_data->viewport_c.y      = scaler_data->viewport.y / src_v_div;
84         scaler_data->viewport_c.width  = scaler_data->viewport.width / src_h_div;
85         scaler_data->viewport_c.height = scaler_data->viewport.height / src_v_div;
86 
87         /* destination viewport */
88         scaler_data->dst_viewport = gaps[gap_index];
89 
90         scaler_data->dst_viewport_c.x      = scaler_data->dst_viewport.x / dst_h_div;
91         scaler_data->dst_viewport_c.y      = scaler_data->dst_viewport.y / dst_v_div;
92         scaler_data->dst_viewport_c.width  = scaler_data->dst_viewport.width / dst_h_div;
93         scaler_data->dst_viewport_c.height = scaler_data->dst_viewport.height / dst_v_div;
94 
95         /* taps and inits */
96         scaler_data->taps.h_taps = scaler_data->taps.v_taps = 4;
97         scaler_data->taps.h_taps_c = scaler_data->taps.v_taps_c = 2;
98 
99         scaler_data->inits.h = vpe_fixpt_div_int(
100             vpe_fixpt_add_int(scaler_data->ratios.horz, (int)(scaler_data->taps.h_taps + 1)), 2);
101         scaler_data->inits.v = vpe_fixpt_div_int(
102             vpe_fixpt_add_int(scaler_data->ratios.vert, (int)(scaler_data->taps.v_taps + 1)), 2);
103         scaler_data->inits.h_c = vpe_fixpt_div_int(
104             vpe_fixpt_add_int(scaler_data->ratios.horz_c, (int)(scaler_data->taps.h_taps_c + 1)),
105             2);
106         scaler_data->inits.v_c = vpe_fixpt_div_int(
107             vpe_fixpt_add_int(scaler_data->ratios.vert_c, (int)(scaler_data->taps.v_taps_c + 1)),
108             2);
109 
110         VPE_ASSERT(gaps_cnt - gap_index - 1 <= (uint16_t)0xF);
111 
112         // background takes stream_idx 0 as its input
113         vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].inputs[0].stream_idx      = 0;
114         vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].num_outputs               = 1;
115         vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].outputs[0].dst_viewport   = scaler_data->dst_viewport;
116         vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].outputs[0].dst_viewport_c = scaler_data->dst_viewport_c;
117         vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].num_inputs                = 1;
118         vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].ops                       = ops;
119         vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].cd                        = (uint8_t)(gaps_cnt - gap_index - 1);
120         vpe_priv->vpe_cmd_info[vpe_priv->num_vpe_cmds].tm_enabled                = false; // currently only support frontend tm
121 
122         vpe_priv->num_vpe_cmds++;
123     }
124 }
125 
vpe_full_bg_gaps(struct vpe_rect * gaps,const struct vpe_rect * target_rect,uint16_t max_gaps)126 void vpe_full_bg_gaps(struct vpe_rect *gaps, const struct vpe_rect *target_rect, uint16_t max_gaps)
127 {
128     uint16_t gap_index;
129     int32_t  last_covered;
130     uint32_t gap_width, gap_remainder;
131 
132     last_covered  = target_rect->x;
133     gap_width     = target_rect->width / max_gaps;
134     gap_remainder = target_rect->width % max_gaps;
135 
136     for (gap_index = 0; gap_index < max_gaps; gap_index++) {
137         gaps[gap_index].x     = last_covered;
138         gaps[gap_index].y     = target_rect->y;
139         gaps[gap_index].width = gap_width;
140         if (gap_index >= max_gaps - gap_remainder) {
141             gaps[gap_index].width += 1;
142         }
143         gaps[gap_index].height = target_rect->height;
144         last_covered           = last_covered + (int32_t)gaps[gap_index].width;
145     }
146 }
147 
148 /* calculates the gaps in target_rect which are not covered by the first stream
149    and returns the number of gaps */
vpe_find_bg_gaps(struct vpe_priv * vpe_priv,const struct vpe_rect * target_rect,struct vpe_rect * gaps,uint16_t max_gaps)150 uint16_t vpe_find_bg_gaps(struct vpe_priv *vpe_priv, const struct vpe_rect *target_rect,
151     struct vpe_rect *gaps, uint16_t max_gaps)
152 {
153     uint16_t         num_gaps = 0;
154     uint16_t         num_segs;
155     struct vpe_rect *dst_viewport_rect;
156     bool             full_bg       = false;
157     const uint32_t   max_seg_width = vpe_priv->pub.caps->plane_caps.max_viewport_width;
158 #ifdef VPE_BUILD_1_1
159     const uint16_t num_multiple = vpe_priv->vpe_num_instance ? vpe_priv->vpe_num_instance : 1;
160 #else
161     const uint16_t num_multiple = 1;
162 #endif
163 
164     num_segs          = vpe_priv->stream_ctx[0].num_segments;
165     dst_viewport_rect = &(vpe_priv->stream_ctx[0].segment_ctx[0].scaler_data.dst_viewport);
166 
167     if (target_rect->x < dst_viewport_rect->x) {
168 
169         if (target_rect->width <= max_seg_width) {
170             goto full_bg;
171         }
172         gaps[0].x      = target_rect->x;
173         gaps[0].y      = target_rect->y;
174         gaps[0].width  = (uint32_t)(dst_viewport_rect->x - target_rect->x);
175         gaps[0].height = target_rect->height;
176         num_gaps++;
177         if (gaps[0].width > max_seg_width) {
178             if (!vpe_priv->resource.split_bg_gap(
179                     gaps, target_rect, max_seg_width, max_gaps, &num_gaps, num_multiple)) {
180                 goto full_bg;
181             }
182         }
183     }
184     dst_viewport_rect =
185         &(vpe_priv->stream_ctx[0].segment_ctx[num_segs - 1].scaler_data.dst_viewport);
186 
187     if (target_rect->x + (int32_t)target_rect->width >
188         dst_viewport_rect->x + (int32_t)dst_viewport_rect->width) {
189 
190         if (num_gaps == max_gaps) {
191             goto full_bg;
192         }
193 
194         gaps[num_gaps].x = dst_viewport_rect->x + (int32_t)dst_viewport_rect->width;
195         gaps[num_gaps].y = target_rect->y;
196         gaps[num_gaps].width =
197             (uint32_t)(target_rect->x + (int32_t)target_rect->width -
198                        (dst_viewport_rect->x + (int32_t)dst_viewport_rect->width));
199         gaps[num_gaps].height = target_rect->height;
200         num_gaps++;
201         if (gaps[num_gaps - 1].width > max_seg_width) {
202             if (!vpe_priv->resource.split_bg_gap(
203                     gaps, target_rect, max_seg_width, max_gaps, &num_gaps, num_multiple)) {
204                 goto full_bg;
205             }
206         }
207     }
208     return num_gaps;
209 
210 full_bg:
211     vpe_full_bg_gaps(gaps, target_rect, max_gaps);
212     return max_gaps;
213 }
214