Skip to content

Commit 76818cd

Browse files
amd-sungkimalexdeucher
authored andcommitted
drm/amd/display: add Coverage blend mode for overlay plane
According to the KMS man page, there is a "Coverage" alpha blend mode that assumes the pixel color values have NOT been pre-multiplied and will be done when the actual blending to the background color values happens. Previously, this mode hasn't been enabled in our driver and it was assumed that all normal overlay planes are pre-multiplied by default. When a 3rd party app is used to input a image in a specific format, e.g. PNG, as a source of a overlay plane to blend with the background primary plane, the pixel color values are not pre-multiplied. So by adding "Coverage" blend mode, our driver will support those cases. Issue fixed: Overlay plane alpha channel blending is incorrect Issue tracker: https://gitlab.freedesktop.org/drm/amd/-/issues/1769 Reference: https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#plane-composition-properties Adding Coverage support also enables IGT kms_plane_alpha_blend Coverage subtests: 1. coverage-7efc 2. coverage-vs-premult-vs-constant Changes 1. Add DRM_MODE_BLEND_COVERAGE blend mode capability 2. Add "pre_multiplied_alpha" flag for Coverage case 3. Read the correct flag and set the DCN MPCC pre_multiplied register bit (only on overlay plane) Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1769 Signed-off-by: Sung Joon Kim <[email protected]> Reviewed-by: Melissa Wen <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent a35faec commit 76818cd

File tree

5 files changed

+40
-24
lines changed

5 files changed

+40
-24
lines changed

drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5381,17 +5381,19 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
53815381

53825382
static void
53835383
fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
5384-
bool *per_pixel_alpha, bool *global_alpha,
5385-
int *global_alpha_value)
5384+
bool *per_pixel_alpha, bool *pre_multiplied_alpha,
5385+
bool *global_alpha, int *global_alpha_value)
53865386
{
53875387
*per_pixel_alpha = false;
5388+
*pre_multiplied_alpha = true;
53885389
*global_alpha = false;
53895390
*global_alpha_value = 0xff;
53905391

53915392
if (plane_state->plane->type != DRM_PLANE_TYPE_OVERLAY)
53925393
return;
53935394

5394-
if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) {
5395+
if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
5396+
plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
53955397
static const uint32_t alpha_formats[] = {
53965398
DRM_FORMAT_ARGB8888,
53975399
DRM_FORMAT_RGBA8888,
@@ -5406,6 +5408,9 @@ fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
54065408
break;
54075409
}
54085410
}
5411+
5412+
if (per_pixel_alpha && plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE)
5413+
*pre_multiplied_alpha = false;
54095414
}
54105415

54115416
if (plane_state->alpha < 0xffff) {
@@ -5568,7 +5573,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
55685573
return ret;
55695574

55705575
fill_blending_from_plane_state(
5571-
plane_state, &plane_info->per_pixel_alpha,
5576+
plane_state, &plane_info->per_pixel_alpha, &plane_info->pre_multiplied_alpha,
55725577
&plane_info->global_alpha, &plane_info->global_alpha_value);
55735578

55745579
return 0;
@@ -5615,6 +5620,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
56155620
dc_plane_state->tiling_info = plane_info.tiling_info;
56165621
dc_plane_state->visible = plane_info.visible;
56175622
dc_plane_state->per_pixel_alpha = plane_info.per_pixel_alpha;
5623+
dc_plane_state->pre_multiplied_alpha = plane_info.pre_multiplied_alpha;
56185624
dc_plane_state->global_alpha = plane_info.global_alpha;
56195625
dc_plane_state->global_alpha_value = plane_info.global_alpha_value;
56205626
dc_plane_state->dcc = plane_info.dcc;
@@ -7911,7 +7917,8 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
79117917
if (plane->type == DRM_PLANE_TYPE_OVERLAY &&
79127918
plane_cap && plane_cap->per_pixel_alpha) {
79137919
unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
7914-
BIT(DRM_MODE_BLEND_PREMULTI);
7920+
BIT(DRM_MODE_BLEND_PREMULTI) |
7921+
BIT(DRM_MODE_BLEND_COVERAGE);
79157922

79167923
drm_plane_create_alpha_property(plane);
79177924
drm_plane_create_blend_mode_property(plane, blend_caps);

drivers/gpu/drm/amd/display/dc/core/dc_surface.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *pl
6161
plane_state->blend_tf->type = TF_TYPE_BYPASS;
6262
}
6363

64+
plane_state->pre_multiplied_alpha = true;
65+
6466
}
6567

6668
static void dc_plane_destruct(struct dc_plane_state *plane_state)

drivers/gpu/drm/amd/display/dc/dc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,7 @@ struct dc_plane_state {
10111011

10121012
bool is_tiling_rotated;
10131013
bool per_pixel_alpha;
1014+
bool pre_multiplied_alpha;
10141015
bool global_alpha;
10151016
int global_alpha_value;
10161017
bool visible;
@@ -1045,6 +1046,7 @@ struct dc_plane_info {
10451046
bool horizontal_mirror;
10461047
bool visible;
10471048
bool per_pixel_alpha;
1049+
bool pre_multiplied_alpha;
10481050
bool global_alpha;
10491051
int global_alpha_value;
10501052
bool input_csc_enabled;

drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,12 +2550,21 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
25502550
blnd_cfg.overlap_only = false;
25512551
blnd_cfg.global_gain = 0xff;
25522552

2553-
if (per_pixel_alpha && pipe_ctx->plane_state->global_alpha) {
2554-
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
2555-
blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
2556-
} else if (per_pixel_alpha) {
2557-
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2553+
if (per_pixel_alpha) {
2554+
/* DCN1.0 has output CM before MPC which seems to screw with
2555+
* pre-multiplied alpha.
2556+
*/
2557+
blnd_cfg.pre_multiplied_alpha = (is_rgb_cspace(
2558+
pipe_ctx->stream->output_color_space)
2559+
&& pipe_ctx->plane_state->pre_multiplied_alpha);
2560+
if (pipe_ctx->plane_state->global_alpha) {
2561+
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
2562+
blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
2563+
} else {
2564+
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2565+
}
25582566
} else {
2567+
blnd_cfg.pre_multiplied_alpha = false;
25592568
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
25602569
}
25612570

@@ -2564,14 +2573,6 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
25642573
else
25652574
blnd_cfg.global_alpha = 0xff;
25662575

2567-
/* DCN1.0 has output CM before MPC which seems to screw with
2568-
* pre-multiplied alpha.
2569-
*/
2570-
blnd_cfg.pre_multiplied_alpha = is_rgb_cspace(
2571-
pipe_ctx->stream->output_color_space)
2572-
&& per_pixel_alpha;
2573-
2574-
25752576
/*
25762577
* TODO: remove hack
25772578
* Note: currently there is a bug in init_hw such that

drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2345,12 +2345,16 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
23452345
blnd_cfg.overlap_only = false;
23462346
blnd_cfg.global_gain = 0xff;
23472347

2348-
if (per_pixel_alpha && pipe_ctx->plane_state->global_alpha) {
2349-
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
2350-
blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
2351-
} else if (per_pixel_alpha) {
2352-
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2348+
if (per_pixel_alpha) {
2349+
blnd_cfg.pre_multiplied_alpha = pipe_ctx->plane_state->pre_multiplied_alpha;
2350+
if (pipe_ctx->plane_state->global_alpha) {
2351+
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
2352+
blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
2353+
} else {
2354+
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2355+
}
23532356
} else {
2357+
blnd_cfg.pre_multiplied_alpha = false;
23542358
blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
23552359
}
23562360

@@ -2364,7 +2368,7 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
23642368
blnd_cfg.top_gain = 0x1f000;
23652369
blnd_cfg.bottom_inside_gain = 0x1f000;
23662370
blnd_cfg.bottom_outside_gain = 0x1f000;
2367-
blnd_cfg.pre_multiplied_alpha = per_pixel_alpha;
2371+
23682372
if (pipe_ctx->plane_state->format
23692373
== SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA)
23702374
blnd_cfg.pre_multiplied_alpha = false;

0 commit comments

Comments
 (0)