mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 11:48:06 +02:00
amd/vpelib: Visual Confirm Fix
[WHY] VPE Visual confirm hanging with color format output due to misalignment. VPE Visual confirm hanging with performance mode. [HOW] Adjust bg segment generation Adjust per op programming and reset second pipe mux. Signed-off-by: Roy Chan <roy.chan@amd.com> Acked-by: Chuanyu Tseng <Chuanyu.Tseng@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40210>
This commit is contained in:
parent
4f93449774
commit
852b85ed48
10 changed files with 76 additions and 47 deletions
|
|
@ -667,6 +667,7 @@ enum vpe_status vpe10_calculate_segments(
|
|||
const uint32_t max_downscale_factor = vpe_priv->pub.caps->plane_caps.max_downscale_factor;
|
||||
struct dpp *dpp = vpe_priv->resource.dpp[0];
|
||||
const uint32_t max_lb_size = dpp->funcs->get_line_buffer_size();
|
||||
uint16_t alignment = 1;
|
||||
|
||||
for (stream_idx = 0; stream_idx < vpe_priv->num_streams; stream_idx++) {
|
||||
stream_ctx = &vpe_priv->stream_ctx[stream_idx];
|
||||
|
|
@ -747,7 +748,8 @@ enum vpe_status vpe10_calculate_segments(
|
|||
if (!gaps)
|
||||
return VPE_STATUS_NO_MEMORY;
|
||||
|
||||
gaps_cnt = vpe_priv->resource.find_bg_gaps(vpe_priv, &(params->target_rect), gaps, max_gaps);
|
||||
gaps_cnt = vpe_priv->resource.find_bg_gaps(
|
||||
vpe_priv, &(params->target_rect), gaps, alignment, max_gaps);
|
||||
|
||||
if (gaps_cnt > 0)
|
||||
vpe_priv->resource.create_bg_segments(vpe_priv, gaps, gaps_cnt, VPE_CMD_OPS_BG);
|
||||
|
|
|
|||
|
|
@ -122,36 +122,35 @@ void vpe_create_bg_segments(
|
|||
}
|
||||
}
|
||||
|
||||
void vpe_full_bg_gaps(struct vpe_rect *gaps, const struct vpe_rect *target_rect, uint16_t max_gaps)
|
||||
void vpe_full_bg_gaps(struct vpe_rect *gaps, const struct vpe_rect *target_rect, uint32_t alignment,
|
||||
uint16_t max_gaps)
|
||||
{
|
||||
uint16_t gap_index;
|
||||
int32_t last_covered;
|
||||
uint32_t gap_width, gap_remainder;
|
||||
|
||||
if (max_gaps == 0) {
|
||||
VPE_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
last_covered = target_rect->x;
|
||||
gap_width = target_rect->width / max_gaps;
|
||||
gap_remainder = target_rect->width % max_gaps;
|
||||
|
||||
for (gap_index = 0; gap_index < max_gaps; gap_index++) {
|
||||
gaps[gap_index].x = last_covered;
|
||||
gaps[gap_index].y = target_rect->y;
|
||||
gaps[gap_index].width = gap_width;
|
||||
if (gap_index >= max_gaps - gap_remainder) {
|
||||
gaps[gap_index].width += 1;
|
||||
}
|
||||
gaps[gap_index].height = target_rect->height;
|
||||
last_covered = last_covered + (int32_t)gaps[gap_index].width;
|
||||
uint32_t gap_width_unaligned = (target_rect->width / max_gaps);
|
||||
uint32_t gap_width_aligned = vpe_align_seg(gap_width_unaligned, alignment);
|
||||
uint32_t start_x = target_rect->x;
|
||||
|
||||
for (int i = 0; i < max_gaps - 1; i++) {
|
||||
gaps[i].x = i * gap_width_aligned + start_x;
|
||||
gaps[i].width = gap_width_aligned;
|
||||
gaps[i].y = target_rect->y;
|
||||
gaps[i].height = target_rect->height;
|
||||
}
|
||||
|
||||
gaps[max_gaps - 1].x = (max_gaps - 1) * gap_width_aligned + start_x;
|
||||
gaps[max_gaps - 1].width = (start_x + target_rect->width) - gaps[max_gaps - 1].x;
|
||||
gaps[max_gaps - 1].y = target_rect->y;
|
||||
gaps[max_gaps - 1].height = target_rect->height;
|
||||
}
|
||||
|
||||
/* calculates the gaps in target_rect which are not covered by the first stream
|
||||
and returns the number of gaps */
|
||||
uint16_t vpe_find_bg_gaps(struct vpe_priv *vpe_priv, const struct vpe_rect *target_rect,
|
||||
struct vpe_rect *gaps, uint16_t max_gaps)
|
||||
struct vpe_rect *gaps, uint32_t alignment, uint16_t max_gaps)
|
||||
{
|
||||
uint16_t num_gaps = 0;
|
||||
uint16_t bg_index = vpe_priv->resource.get_bg_stream_idx(vpe_priv);
|
||||
|
|
@ -219,6 +218,6 @@ uint16_t vpe_find_bg_gaps(struct vpe_priv *vpe_priv, const struct vpe_rect *targ
|
|||
return num_gaps;
|
||||
|
||||
full_bg:
|
||||
vpe_full_bg_gaps(gaps, target_rect, max_gaps);
|
||||
vpe_full_bg_gaps(gaps, target_rect, alignment, max_gaps);
|
||||
return max_gaps;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -650,3 +650,18 @@ enum vpe_status vpe_check_blending_support(
|
|||
return result;
|
||||
}
|
||||
|
||||
// Returns the smallest number greater than (or equal to) seg_size divisible by alignment
|
||||
uint32_t vpe_align_seg(uint32_t seg_size, uint32_t alignment)
|
||||
{
|
||||
VPE_ASSERT(alignment != 0);
|
||||
|
||||
uint32_t aligned_size = seg_size;
|
||||
if (alignment != 0) {
|
||||
uint32_t rem = seg_size % alignment;
|
||||
if (rem != 0) {
|
||||
aligned_size = seg_size + alignment - rem;
|
||||
}
|
||||
}
|
||||
return aligned_size;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,10 @@ void vpe_create_bg_segments(
|
|||
struct vpe_priv *vpe_priv, struct vpe_rect *gaps, uint16_t gaps_cnt, enum vpe_cmd_ops ops);
|
||||
|
||||
uint16_t vpe_find_bg_gaps(struct vpe_priv *vpe_priv, const struct vpe_rect *target_rect,
|
||||
struct vpe_rect *gaps, uint16_t max_gaps);
|
||||
struct vpe_rect *gaps, uint32_t alignment, uint16_t max_gaps);
|
||||
|
||||
void vpe_full_bg_gaps(struct vpe_rect *gaps, const struct vpe_rect *target_rect, uint16_t max_gaps);
|
||||
void vpe_full_bg_gaps(struct vpe_rect *gaps, const struct vpe_rect *target_rect, uint32_t alignment,
|
||||
uint16_t max_gaps);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ enum vpe_status vpe_check_blending_support(
|
|||
|
||||
uint8_t vpe_get_element_size_in_bytes(enum vpe_surface_pixel_format format, int plane_idx);
|
||||
|
||||
uint32_t vpe_align_seg(uint32_t seg_size, uint32_t alignment);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ struct resource {
|
|||
uint16_t (*get_bg_stream_idx)(struct vpe_priv *vpe_priv);
|
||||
|
||||
uint16_t (*find_bg_gaps)(struct vpe_priv *vpe_priv, const struct vpe_rect *target_rect,
|
||||
struct vpe_rect *gaps, uint16_t max_gaps);
|
||||
struct vpe_rect *gaps, uint32_t alignment, uint16_t max_gaps);
|
||||
|
||||
void (*create_bg_segments)(
|
||||
struct vpe_priv *vpe_priv, struct vpe_rect *gaps, uint16_t gaps_cnt, enum vpe_cmd_ops ops);
|
||||
|
|
@ -190,6 +190,8 @@ const struct vpe_caps *vpe_get_capability(enum vpe_ip_level ip_level);
|
|||
|
||||
void vpe_setup_check_funcs(struct vpe_check_support_funcs *funcs, enum vpe_ip_level ip_level);
|
||||
|
||||
uint32_t vpe_get_recout_width_alignment(const struct vpe_build_param *params);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ extern "C" {
|
|||
#define MAX_LINE_SIZE 1024 // without 16 pixels for the seams
|
||||
#define MAX_LINE_CNT 4
|
||||
|
||||
#define VPE_NO_ALIGNMENT 1
|
||||
enum vpe_cmd_ops {
|
||||
VPE_CMD_OPS_BLENDING,
|
||||
VPE_CMD_OPS_BG,
|
||||
|
|
|
|||
|
|
@ -833,6 +833,14 @@ void vpe_backend_config_callback(
|
|||
&vpe_priv->vpe_desc_writer, cfg_base_gpu, false, (uint8_t)vpe_priv->config_writer.buf->tmz);
|
||||
}
|
||||
|
||||
uint32_t vpe_get_recout_width_alignment(const struct vpe_build_param *params)
|
||||
{
|
||||
uint16_t recout_alignment;
|
||||
recout_alignment = VPE_NO_ALIGNMENT;
|
||||
|
||||
return recout_alignment;
|
||||
}
|
||||
|
||||
bool vpe_rec_is_equal(struct vpe_rect rec1, struct vpe_rect rec2)
|
||||
{
|
||||
return (rec1.x == rec2.x && rec1.y == rec2.y && rec1.width == rec2.width &&
|
||||
|
|
|
|||
|
|
@ -41,12 +41,19 @@ static bool should_generate_visual_confirm(enum vpe_stream_type stream_type)
|
|||
}
|
||||
}
|
||||
|
||||
static uint16_t get_visual_confirm_segs_count(uint32_t max_seg_width, uint32_t target_rect_width)
|
||||
static uint16_t get_visual_confirm_segs_count(
|
||||
uint32_t max_seg_width, uint32_t target_rect_width, uint32_t target_width_alignment)
|
||||
{
|
||||
// Unlike max_gaps logic in vpe10_calculate_segments, we are pure BG seg, no need to worry
|
||||
// stream splitted among one of the segment. so no need to "+1", just round up the calculated
|
||||
// number of segments.
|
||||
uint16_t seg_cnt = (uint16_t)(max((target_rect_width + max_seg_width - 1) / max_seg_width, 1));
|
||||
|
||||
uint16_t seg_cnt = (uint16_t)(max(int_divide_with_ceil(target_rect_width, max_seg_width), 1));
|
||||
uint16_t segment_width = (uint16_t)int_divide_with_ceil(target_rect_width, seg_cnt);
|
||||
uint32_t aligned_segment_width = vpe_align_seg(segment_width, target_width_alignment);
|
||||
if (aligned_segment_width > max_seg_width) {
|
||||
seg_cnt++;
|
||||
}
|
||||
|
||||
return seg_cnt;
|
||||
}
|
||||
|
|
@ -58,19 +65,20 @@ static uint16_t vpe_get_visual_confirm_total_seg_count(
|
|||
uint16_t total_visual_confirm_segs = 0;
|
||||
uint16_t stream_idx;
|
||||
struct stream_ctx *stream_ctx;
|
||||
uint32_t alignment = vpe_get_recout_width_alignment(params);
|
||||
|
||||
if (vpe_priv->init.debug.visual_confirm_params.input_format) {
|
||||
for (stream_idx = 0; stream_idx < vpe_priv->num_streams; stream_idx++) {
|
||||
stream_ctx = &vpe_priv->stream_ctx[stream_idx];
|
||||
if (should_generate_visual_confirm(stream_ctx->stream_type))
|
||||
total_visual_confirm_segs += get_visual_confirm_segs_count(
|
||||
max_seg_width, stream_ctx->stream.scaling_info.dst_rect.width);
|
||||
max_seg_width, stream_ctx->stream.scaling_info.dst_rect.width, alignment);
|
||||
}
|
||||
}
|
||||
|
||||
if (vpe_priv->init.debug.visual_confirm_params.output_format) {
|
||||
total_visual_confirm_segs +=
|
||||
get_visual_confirm_segs_count(max_seg_width, params->target_rect.width);
|
||||
get_visual_confirm_segs_count(max_seg_width, params->target_rect.width, alignment);
|
||||
}
|
||||
|
||||
return total_visual_confirm_segs;
|
||||
|
|
@ -187,6 +195,7 @@ enum vpe_status vpe_create_visual_confirm_segs(
|
|||
uint16_t total_seg_cnt =
|
||||
vpe_get_visual_confirm_total_seg_count(vpe_priv, max_seg_width, params);
|
||||
uint16_t seg_cnt = 0;
|
||||
uint32_t recout_alignment = vpe_get_recout_width_alignment(params);
|
||||
|
||||
if (!total_seg_cnt)
|
||||
return VPE_STATUS_OK;
|
||||
|
|
@ -197,7 +206,7 @@ enum vpe_status vpe_create_visual_confirm_segs(
|
|||
|
||||
current_gap = visual_confirm_gaps;
|
||||
|
||||
// Do visual confirm bg generation for intput format
|
||||
// Do visual confirm bg generation for input format
|
||||
if (vpe_priv->init.debug.visual_confirm_params.input_format &&
|
||||
params->target_rect.height > 2 * VISUAL_CONFIRM_HEIGHT) {
|
||||
for (stream_idx = 0; stream_idx < params->num_streams; stream_idx++) {
|
||||
|
|
@ -206,8 +215,8 @@ enum vpe_status vpe_create_visual_confirm_segs(
|
|||
visual_confirm_rect.y += 0;
|
||||
visual_confirm_rect.height = VISUAL_CONFIRM_HEIGHT;
|
||||
seg_cnt = get_visual_confirm_segs_count(
|
||||
max_seg_width, stream_ctx->stream.scaling_info.dst_rect.width);
|
||||
vpe_full_bg_gaps(current_gap, &visual_confirm_rect, seg_cnt);
|
||||
max_seg_width, stream_ctx->stream.scaling_info.dst_rect.width, recout_alignment);
|
||||
vpe_full_bg_gaps(current_gap, &visual_confirm_rect, recout_alignment, seg_cnt);
|
||||
vpe_priv->resource.create_bg_segments(
|
||||
vpe_priv, current_gap, seg_cnt, VPE_CMD_OPS_BG_VSCF_INPUT);
|
||||
current_gap += seg_cnt;
|
||||
|
|
@ -219,8 +228,9 @@ enum vpe_status vpe_create_visual_confirm_segs(
|
|||
visual_confirm_rect = params->target_rect;
|
||||
visual_confirm_rect.y += VISUAL_CONFIRM_HEIGHT;
|
||||
visual_confirm_rect.height = VISUAL_CONFIRM_HEIGHT;
|
||||
seg_cnt = get_visual_confirm_segs_count(max_seg_width, params->target_rect.width);
|
||||
vpe_full_bg_gaps(current_gap, &visual_confirm_rect, seg_cnt);
|
||||
seg_cnt = get_visual_confirm_segs_count(
|
||||
max_seg_width, params->target_rect.width, recout_alignment);
|
||||
vpe_full_bg_gaps(current_gap, &visual_confirm_rect, recout_alignment, seg_cnt);
|
||||
vpe_priv->resource.create_bg_segments(
|
||||
vpe_priv, current_gap, seg_cnt, VPE_CMD_OPS_BG_VSCF_OUTPUT);
|
||||
current_gap += seg_cnt;
|
||||
|
|
|
|||
|
|
@ -360,7 +360,6 @@ static enum vpe_status populate_bg_stream(struct vpe_priv *vpe_priv, const struc
|
|||
|
||||
if (param->dst_surface.plane_size.surface_size.width < VPE_MIN_VIEWPORT_SIZE ||
|
||||
param->dst_surface.plane_size.surface_size.height < VPE_MIN_VIEWPORT_SIZE ||
|
||||
param->dst_surface.plane_size.surface_pitch < 256 / 4 || // 256bytes, 4bpp
|
||||
param->target_rect.width < VPE_MIN_VIEWPORT_SIZE ||
|
||||
param->target_rect.height < VPE_MIN_VIEWPORT_SIZE) {
|
||||
return VPE_STATUS_ERROR;
|
||||
|
|
@ -370,26 +369,16 @@ static enum vpe_status populate_bg_stream(struct vpe_priv *vpe_priv, const struc
|
|||
surface_info = &stream->surface_info;
|
||||
scaling_info = &stream->scaling_info;
|
||||
polyphaseCoeffs = &stream->polyphase_scaling_coeffs;
|
||||
surface_info->address.type = param->dst_surface.address.type;
|
||||
surface_info->address.tmz_surface = param->dst_surface.address.tmz_surface;
|
||||
surface_info->address.grph.addr.quad_part =
|
||||
param->dst_surface.address.grph.addr.quad_part;
|
||||
|
||||
surface_info->swizzle = param->dst_surface.swizzle; // treat it as linear for simple
|
||||
memcpy(surface_info, ¶m->dst_surface, sizeof(struct vpe_surface_info));
|
||||
|
||||
surface_info->plane_size.surface_size.x = 0;
|
||||
surface_info->plane_size.surface_size.y = 0;
|
||||
// min width & height in pixels
|
||||
surface_info->plane_size.surface_size.width = VPE_MIN_VIEWPORT_SIZE;
|
||||
surface_info->plane_size.surface_size.height = VPE_MIN_VIEWPORT_SIZE;
|
||||
surface_info->plane_size.surface_pitch = param->dst_surface.plane_size.surface_pitch;
|
||||
surface_info->plane_size.surface_aligned_height = param->dst_surface.plane_size.surface_aligned_height;
|
||||
surface_info->dcc.enable = false;
|
||||
surface_info->format = param->dst_surface.format;
|
||||
surface_info->cs.encoding = param->dst_surface.cs.encoding;
|
||||
surface_info->cs.range = param->dst_surface.cs.range;
|
||||
surface_info->cs.tf = param->dst_surface.cs.tf;
|
||||
surface_info->cs.cositing = param->dst_surface.cs.cositing;
|
||||
surface_info->cs.primaries = param->dst_surface.cs.primaries;
|
||||
|
||||
// min width & height in pixels
|
||||
scaling_info->src_rect.x = 0;
|
||||
scaling_info->src_rect.y = 0;
|
||||
scaling_info->src_rect.width = VPE_MIN_VIEWPORT_SIZE;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue