Skip to content

Commit b208152

Browse files
committed
drm/i915: Add plane alpha blending support, v2.
Add plane alpha blending support with the different blend modes. This has been tested on a icl to show the correct results, on earlier platforms small rounding errors cause issues. But this already happens case with fully transparant or fully opaque RGB8888 fb's. The recommended HW workaround is to disable alpha blending when the plane alpha is 0 (transparant, hide plane) or 0xff (opaque, disable blending). This is easy to implement on any platform, so just do that. The tests for userspace are also available, and pass on gen11. Changes since v1: - Change mistaken < 0xff0 to 0xff00. - Only set PLANE_KEYMSK_ALPHA_ENABLE when plane alpha < 0xff00, ignore blend mode. - Rework disabling FBC when per pixel alpha is used. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> [mlankhorst: Change MISSING_CASE default to explicit alpha disable (mattrope)] Link: https://patchwork.freedesktop.org/patch/msgid/20180815103405.22679-1-maarten.lankhorst@linux.intel.com Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
1 parent 7569bf9 commit b208152

File tree

5 files changed

+69
-18
lines changed

5 files changed

+69
-18
lines changed

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,8 @@ struct intel_fbc {
548548
int adjusted_y;
549549

550550
int y;
551+
552+
uint16_t pixel_blend_mode;
551553
} plane;
552554

553555
struct {

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6554,8 +6554,10 @@ enum {
65546554
#define _PLANE_KEYVAL_2_A 0x70294
65556555
#define _PLANE_KEYMSK_1_A 0x70198
65566556
#define _PLANE_KEYMSK_2_A 0x70298
6557+
#define PLANE_KEYMSK_ALPHA_ENABLE (1 << 31)
65576558
#define _PLANE_KEYMAX_1_A 0x701a0
65586559
#define _PLANE_KEYMAX_2_A 0x702a0
6560+
#define PLANE_KEYMAX_ALPHA_SHIFT 24
65596561
#define _PLANE_AUX_DIST_1_A 0x701c0
65606562
#define _PLANE_AUX_DIST_2_A 0x702c0
65616563
#define _PLANE_AUX_OFFSET_1_A 0x701c4

drivers/gpu/drm/i915/intel_display.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3155,6 +3155,10 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
31553155
if (ret)
31563156
return ret;
31573157

3158+
/* HW only has 8 bits pixel precision, disable plane if invisible */
3159+
if (!(plane_state->base.alpha >> 8))
3160+
plane_state->base.visible = false;
3161+
31583162
if (!plane_state->base.visible)
31593163
return 0;
31603164

@@ -3568,29 +3572,38 @@ static u32 skl_plane_ctl_format(uint32_t pixel_format)
35683572
return 0;
35693573
}
35703574

3571-
/*
3572-
* XXX: For ARBG/ABGR formats we default to expecting scanout buffers
3573-
* to be already pre-multiplied. We need to add a knob (or a different
3574-
* DRM_FORMAT) for user-space to configure that.
3575-
*/
3576-
static u32 skl_plane_ctl_alpha(uint32_t pixel_format)
3575+
static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
35773576
{
3578-
switch (pixel_format) {
3579-
case DRM_FORMAT_ABGR8888:
3580-
case DRM_FORMAT_ARGB8888:
3577+
if (!plane_state->base.fb->format->has_alpha)
3578+
return PLANE_CTL_ALPHA_DISABLE;
3579+
3580+
switch (plane_state->base.pixel_blend_mode) {
3581+
case DRM_MODE_BLEND_PIXEL_NONE:
3582+
return PLANE_CTL_ALPHA_DISABLE;
3583+
case DRM_MODE_BLEND_PREMULTI:
35813584
return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
3585+
case DRM_MODE_BLEND_COVERAGE:
3586+
return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
35823587
default:
3588+
MISSING_CASE(plane_state->base.pixel_blend_mode);
35833589
return PLANE_CTL_ALPHA_DISABLE;
35843590
}
35853591
}
35863592

3587-
static u32 glk_plane_color_ctl_alpha(uint32_t pixel_format)
3593+
static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
35883594
{
3589-
switch (pixel_format) {
3590-
case DRM_FORMAT_ABGR8888:
3591-
case DRM_FORMAT_ARGB8888:
3595+
if (!plane_state->base.fb->format->has_alpha)
3596+
return PLANE_COLOR_ALPHA_DISABLE;
3597+
3598+
switch (plane_state->base.pixel_blend_mode) {
3599+
case DRM_MODE_BLEND_PIXEL_NONE:
3600+
return PLANE_COLOR_ALPHA_DISABLE;
3601+
case DRM_MODE_BLEND_PREMULTI:
35923602
return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
3603+
case DRM_MODE_BLEND_COVERAGE:
3604+
return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
35933605
default:
3606+
MISSING_CASE(plane_state->base.pixel_blend_mode);
35943607
return PLANE_COLOR_ALPHA_DISABLE;
35953608
}
35963609
}
@@ -3667,7 +3680,7 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
36673680
plane_ctl = PLANE_CTL_ENABLE;
36683681

36693682
if (INTEL_GEN(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) {
3670-
plane_ctl |= skl_plane_ctl_alpha(fb->format->format);
3683+
plane_ctl |= skl_plane_ctl_alpha(plane_state);
36713684
plane_ctl |=
36723685
PLANE_CTL_PIPE_GAMMA_ENABLE |
36733686
PLANE_CTL_PIPE_CSC_ENABLE |
@@ -3709,7 +3722,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
37093722
plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
37103723
}
37113724
plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
3712-
plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format);
3725+
plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
37133726

37143727
if (fb->format->is_yuv) {
37153728
if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
@@ -13863,7 +13876,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
1386313876
DRM_MODE_ROTATE_0,
1386413877
supported_rotations);
1386513878

13866-
if (INTEL_GEN(dev_priv) >= 9)
13879+
if (INTEL_GEN(dev_priv) >= 9) {
1386713880
drm_plane_create_color_properties(&primary->base,
1386813881
BIT(DRM_COLOR_YCBCR_BT601) |
1386913882
BIT(DRM_COLOR_YCBCR_BT709),
@@ -13872,6 +13885,13 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
1387213885
DRM_COLOR_YCBCR_BT709,
1387313886
DRM_COLOR_YCBCR_LIMITED_RANGE);
1387413887

13888+
drm_plane_create_alpha_property(&primary->base);
13889+
drm_plane_create_blend_mode_property(&primary->base,
13890+
BIT(DRM_MODE_BLEND_PIXEL_NONE) |
13891+
BIT(DRM_MODE_BLEND_PREMULTI) |
13892+
BIT(DRM_MODE_BLEND_COVERAGE));
13893+
}
13894+
1387513895
drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
1387613896

1387713897
return primary;

drivers/gpu/drm/i915/intel_fbc.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
674674
cache->plane.adjusted_y = plane_state->color_plane[0].y;
675675
cache->plane.y = plane_state->base.src.y1 >> 16;
676676

677+
cache->plane.pixel_blend_mode = plane_state->base.pixel_blend_mode;
678+
677679
if (!cache->plane.visible)
678680
return;
679681

@@ -748,6 +750,12 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
748750
return false;
749751
}
750752

753+
if (cache->plane.pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE &&
754+
cache->fb.format->has_alpha) {
755+
fbc->no_fbc_reason = "per-pixel alpha blending is incompatible with FBC";
756+
return false;
757+
}
758+
751759
/* WaFbcExceedCdClockThreshold:hsw,bdw */
752760
if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) &&
753761
cache->crtc.hsw_bdw_pixel_rate >= dev_priv->cdclk.hw.cdclk * 95 / 100) {

drivers/gpu/drm/i915/intel_sprite.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ skl_update_plane(struct intel_plane *plane,
380380
uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
381381
uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
382382
unsigned long irqflags;
383+
u32 keymsk = 0, keymax = 0;
383384

384385
/* Sizes are 0 based */
385386
src_w--;
@@ -393,10 +394,19 @@ skl_update_plane(struct intel_plane *plane,
393394

394395
if (key->flags) {
395396
I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
396-
I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value);
397-
I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
397+
398+
keymax |= key->max_value & 0xffffff;
399+
keymsk |= key->channel_mask & 0x3ffffff;
398400
}
399401

402+
keymax |= (plane_state->base.alpha >> 8) << PLANE_KEYMAX_ALPHA_SHIFT;
403+
404+
if (plane_state->base.alpha < 0xff00)
405+
keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
406+
407+
I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
408+
I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
409+
400410
I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
401411
I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
402412
I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
@@ -1916,6 +1926,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
19161926
DRM_COLOR_YCBCR_BT709,
19171927
DRM_COLOR_YCBCR_LIMITED_RANGE);
19181928

1929+
if (INTEL_GEN(dev_priv) >= 9) {
1930+
drm_plane_create_alpha_property(&intel_plane->base);
1931+
1932+
drm_plane_create_blend_mode_property(&intel_plane->base,
1933+
BIT(DRM_MODE_BLEND_PIXEL_NONE) |
1934+
BIT(DRM_MODE_BLEND_PREMULTI) |
1935+
BIT(DRM_MODE_BLEND_COVERAGE));
1936+
}
1937+
19191938
drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
19201939

19211940
return intel_plane;

0 commit comments

Comments
 (0)