Re: [PATCH v2] drm/tegra: dc: Implement legacy blending
On 21.12.2017 17:03, Thierry Reding wrote: > From: Thierry Reding> > This implements alpha blending on legacy display controllers (Tegra20, > Tegra30 and Tegra114). While it's theoretically possible to support the > zpos property to enable userspace to specify the Z-order of each plane > individually, this is not currently supported and the same fixed Z- > order as previously defined is used. > > Reverts commit 71835caa00e8 ("drm/tegra: fb: Force alpha formats") since > the opaque formats are now supported. > > Reported-by: Dmitry Osipenko > Fixes: 7772fdaef939 ("drm/tegra: Support ARGB and ABGR formats") > Signed-off-by: Thierry Reding > --- > Changes in v2: > - properly implement blending if windows have different pixel formats > > drivers/gpu/drm/tegra/dc.c| 81 + > drivers/gpu/drm/tegra/dc.h| 12 > drivers/gpu/drm/tegra/fb.c| 12 > drivers/gpu/drm/tegra/plane.c | 138 > ++ > drivers/gpu/drm/tegra/plane.h | 8 +++ > 5 files changed, 226 insertions(+), 25 deletions(-) > > diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c > index 2a0c1e93f82e..4507063029e0 100644 > --- a/drivers/gpu/drm/tegra/dc.c > +++ b/drivers/gpu/drm/tegra/dc.c > @@ -154,30 +154,53 @@ static inline u32 compute_initial_dda(unsigned int in) > > static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane) > { > + u32 background[3] = { > + BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE, > + BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE, > + BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE, > + }; > + u32 foreground = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255) | > + BLEND_COLOR_KEY_NONE; > + u32 blendnokey = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255); > + struct tegra_plane_state *state; > + unsigned int i; > + > + state = to_tegra_plane_state(plane->base.state); > + > + /* alpha contribution is 1 minus sum of overlapping windows */ > + for (i = 0; i < 3; i++) { > + if (state->dependent[i]) > + background[i] |= BLEND_CONTROL_DEPENDENT; > + } > + > + /* enable alpha blending if pixel format has an alpha component */ > + if (!state->opaque) > + foreground |= BLEND_CONTROL_ALPHA; > + > /* >* Disable blending and assume Window A is the bottom-most window, >* Window C is the top-most window and Window B is in the middle. >*/ > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_NOKEY); > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_1WIN); > + tegra_plane_writel(plane, blendnokey, DC_WIN_BLEND_NOKEY); > + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_1WIN); > > switch (plane->index) { > case 0: > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_X); > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_Y); > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_3WIN_XY); > + tegra_plane_writel(plane, background[0], DC_WIN_BLEND_2WIN_X); > + tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y); > + tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY); > break; > > case 1: > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_X); > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_Y); > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_3WIN_XY); > + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X); > + tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y); > + tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY); > break; > > case 2: > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_X); > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_Y); > - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_3WIN_XY); > + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X); > + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_Y); > + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_3WIN_XY); > break; > } > } > @@ -353,6 +376,11 @@ static const u32 tegra20_primary_formats[] = { > DRM_FORMAT_RGBA5551, > DRM_FORMAT_ABGR, > DRM_FORMAT_ARGB, > + /* non-native formats */ > + DRM_FORMAT_XRGB1555, > + DRM_FORMAT_RGBX5551, > + DRM_FORMAT_XBGR, > + DRM_FORMAT_XRGB, > }; > > static const u32 tegra114_primary_formats[] = { > @@ -409,18 +437,40 @@ static int tegra_plane_atomic_check(struct drm_plane > *plane, > struct tegra_bo_tiling *tiling = _state->tiling; > struct tegra_plane *tegra =
Re: [PATCH v2] drm/tegra: dc: Implement legacy blending
On 21.12.2017 21:46, Dmitry Osipenko wrote: > On 21.12.2017 17:03, Thierry Reding wrote: >> From: Thierry Reding>> >> This implements alpha blending on legacy display controllers (Tegra20, >> Tegra30 and Tegra114). While it's theoretically possible to support the >> zpos property to enable userspace to specify the Z-order of each plane >> individually, this is not currently supported and the same fixed Z- >> order as previously defined is used. >> >> Reverts commit 71835caa00e8 ("drm/tegra: fb: Force alpha formats") since >> the opaque formats are now supported. >> >> Reported-by: Dmitry Osipenko >> Fixes: 7772fdaef939 ("drm/tegra: Support ARGB and ABGR formats") >> Signed-off-by: Thierry Reding >> --- [snip] >> + >> +void tegra_plane_check_dependent(struct tegra_plane *tegra, >> + struct tegra_plane_state *state) >> +{ >> +struct drm_plane_state *old, *new; >> +struct drm_plane *plane; >> +unsigned int zpos[2]; >> +unsigned int i; >> + >> +for (i = 0; i < 3; i++) >> +state->dependent[i] = false; >> + >> +for (i = 0; i < 2; i++) >> +zpos[i] = 0; >> + >> +for_each_oldnew_plane_in_state(state->base.state, plane, old, new, i) { > > Somehow this works when 2 windows are blended (primary plane + cursor). But > unfortunately this doesn't work at all in a case when 3 windows blended > (primary > + video overlay + cursor), for some reason there is only one plane in the > state > here, so blending dependency tracking doesn't work at all. I'll continue to > look > into it, but for now I don't know why it doesn't work as expected. If you have > any idea, please tell. Actually, I think this code only works when all planes are updated in a single commit. We need to handle cases when only some of the active planes are adjusting the state. [snip] ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm/tegra: dc: Implement legacy blending
From: Thierry RedingThis implements alpha blending on legacy display controllers (Tegra20, Tegra30 and Tegra114). While it's theoretically possible to support the zpos property to enable userspace to specify the Z-order of each plane individually, this is not currently supported and the same fixed Z- order as previously defined is used. Reverts commit 71835caa00e8 ("drm/tegra: fb: Force alpha formats") since the opaque formats are now supported. Reported-by: Dmitry Osipenko Fixes: 7772fdaef939 ("drm/tegra: Support ARGB and ABGR formats") Signed-off-by: Thierry Reding --- Changes in v2: - properly implement blending if windows have different pixel formats drivers/gpu/drm/tegra/dc.c| 81 + drivers/gpu/drm/tegra/dc.h| 12 drivers/gpu/drm/tegra/fb.c| 12 drivers/gpu/drm/tegra/plane.c | 138 ++ drivers/gpu/drm/tegra/plane.h | 8 +++ 5 files changed, 226 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 2a0c1e93f82e..4507063029e0 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -154,30 +154,53 @@ static inline u32 compute_initial_dda(unsigned int in) static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane) { + u32 background[3] = { + BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE, + BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE, + BLEND_WEIGHT1(0) | BLEND_WEIGHT0(0) | BLEND_COLOR_KEY_NONE, + }; + u32 foreground = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255) | +BLEND_COLOR_KEY_NONE; + u32 blendnokey = BLEND_WEIGHT1(255) | BLEND_WEIGHT0(255); + struct tegra_plane_state *state; + unsigned int i; + + state = to_tegra_plane_state(plane->base.state); + + /* alpha contribution is 1 minus sum of overlapping windows */ + for (i = 0; i < 3; i++) { + if (state->dependent[i]) + background[i] |= BLEND_CONTROL_DEPENDENT; + } + + /* enable alpha blending if pixel format has an alpha component */ + if (!state->opaque) + foreground |= BLEND_CONTROL_ALPHA; + /* * Disable blending and assume Window A is the bottom-most window, * Window C is the top-most window and Window B is in the middle. */ - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_NOKEY); - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_1WIN); + tegra_plane_writel(plane, blendnokey, DC_WIN_BLEND_NOKEY); + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_1WIN); switch (plane->index) { case 0: - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_X); - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_Y); - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_3WIN_XY); + tegra_plane_writel(plane, background[0], DC_WIN_BLEND_2WIN_X); + tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y); + tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY); break; case 1: - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_X); - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_Y); - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_3WIN_XY); + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X); + tegra_plane_writel(plane, background[1], DC_WIN_BLEND_2WIN_Y); + tegra_plane_writel(plane, background[2], DC_WIN_BLEND_3WIN_XY); break; case 2: - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_X); - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_2WIN_Y); - tegra_plane_writel(plane, 0x00, DC_WIN_BLEND_3WIN_XY); + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_X); + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_2WIN_Y); + tegra_plane_writel(plane, foreground, DC_WIN_BLEND_3WIN_XY); break; } } @@ -353,6 +376,11 @@ static const u32 tegra20_primary_formats[] = { DRM_FORMAT_RGBA5551, DRM_FORMAT_ABGR, DRM_FORMAT_ARGB, + /* non-native formats */ + DRM_FORMAT_XRGB1555, + DRM_FORMAT_RGBX5551, + DRM_FORMAT_XBGR, + DRM_FORMAT_XRGB, }; static const u32 tegra114_primary_formats[] = { @@ -409,18 +437,40 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, struct tegra_bo_tiling *tiling = _state->tiling; struct tegra_plane *tegra = to_tegra_plane(plane); struct tegra_dc *dc = to_tegra_dc(state->crtc); + unsigned int format; int err; /* no need for