diff mbox series

fbdev: core: tileblit: Implement missing margin clearing for tileblit

Message ID c8cc27ea-05a8-14b7-0047-4f1fa6d73f93@singularcrew.hu
State New
Headers show
Series fbdev: core: tileblit: Implement missing margin clearing for tileblit | expand

Commit Message

Soci/Singular Feb. 1, 2025, 8:18 a.m. UTC
I was wondering why there's garbage at the bottom of the screen when
tile blitting is used with an odd mode like 1080, 600 or 200. Sure there's
only space for half a tile but the same area is clean when the buffer
is bitmap.

Then later I found that it's supposed to be cleaned but that's not
implemented. So I took what's in bitblit and adapted it for tileblit.

This implementation was tested for both the horizontal and vertical case,
and now does the same as what's done for bitmap buffers.

If anyone is interested to reproduce the problem then I could bet that'd
be on a S3 or Ark. Just set up a mode with an odd line count and make
sure that the virtual size covers the complete tile at the bottom. E.g.
for 600 lines that's 608 virtual lines for a 16 tall tile. Then the
bottom area should be cleaned.

For the right side it's more difficult as there the drivers won't let an
odd size happen, unless the code is modified. But once it reports back a
few pixel columns short then fbcon won't use the last column. With the
patch that column is now clean.

Btw. the virtual size should be rounded up by the driver for both axes
(not only the horizontal) so that it's dividable by the tile size.
That's a driver bug but correcting it is not in scope for this patch.

Implement missing margin clearing for tileblit

Signed-off-by: Zsolt Kajtar <soci@c64.rulez.org>
---
 drivers/video/fbdev/core/tileblit.c | 37 ++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

Comments

Helge Deller Feb. 3, 2025, 7:41 p.m. UTC | #1
On 2/1/25 09:18, Soci/Singular wrote:
> I was wondering why there's garbage at the bottom of the screen when
> tile blitting is used with an odd mode like 1080, 600 or 200. Sure there's
> only space for half a tile but the same area is clean when the buffer
> is bitmap.
>
> Then later I found that it's supposed to be cleaned but that's not
> implemented. So I took what's in bitblit and adapted it for tileblit.
>
> This implementation was tested for both the horizontal and vertical case,
> and now does the same as what's done for bitmap buffers.
>
> If anyone is interested to reproduce the problem then I could bet that'd
> be on a S3 or Ark. Just set up a mode with an odd line count and make
> sure that the virtual size covers the complete tile at the bottom. E.g.
> for 600 lines that's 608 virtual lines for a 16 tall tile. Then the
> bottom area should be cleaned.
>
> For the right side it's more difficult as there the drivers won't let an
> odd size happen, unless the code is modified. But once it reports back a
> few pixel columns short then fbcon won't use the last column. With the
> patch that column is now clean.
>
> Btw. the virtual size should be rounded up by the driver for both axes
> (not only the horizontal) so that it's dividable by the tile size.
> That's a driver bug but correcting it is not in scope for this patch.
>
> Implement missing margin clearing for tileblit
>
> Signed-off-by: Zsolt Kajtar <soci@c64.rulez.org>

applied to fbdev git tree.

Helge

> ---
>   drivers/video/fbdev/core/tileblit.c | 37 ++++++++++++++++++++++++++++-
>   1 file changed, 36 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c
> index eff7ec4da..98e528d38 100644
> --- a/drivers/video/fbdev/core/tileblit.c
> +++ b/drivers/video/fbdev/core/tileblit.c
> @@ -76,7 +76,42 @@ static void tile_putcs(struct vc_data *vc, struct fb_info *info,
>   static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
>   			       int color, int bottom_only)
>   {
> -	return;
> +	unsigned int cw = vc->vc_font.width;
> +	unsigned int ch = vc->vc_font.height;
> +	unsigned int rw = info->var.xres - (vc->vc_cols*cw);
> +	unsigned int bh = info->var.yres - (vc->vc_rows*ch);
> +	unsigned int rs = info->var.xres - rw;
> +	unsigned int bs = info->var.yres - bh;
> +	unsigned int vwt = info->var.xres_virtual / cw;
> +	unsigned int vht = info->var.yres_virtual / ch;
> +	struct fb_tilerect rect;
> +
> +	rect.index = vc->vc_video_erase_char &
> +		((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
> +	rect.fg = color;
> +	rect.bg = color;
> +
> +	if ((int) rw > 0 && !bottom_only) {
> +		rect.sx = (info->var.xoffset + rs + cw - 1) / cw;
> +		rect.sy = 0;
> +		rect.width = (rw + cw - 1) / cw;
> +		rect.height = vht;
> +		if (rect.width + rect.sx > vwt)
> +			rect.width = vwt - rect.sx;
> +		if (rect.sx < vwt)
> +			info->tileops->fb_tilefill(info, &rect);
> +	}
> +
> +	if ((int) bh > 0) {
> +		rect.sx = info->var.xoffset / cw;
> +		rect.sy = (info->var.yoffset + bs) / ch;
> +		rect.width = rs / cw;
> +		rect.height = (bh + ch - 1) / ch;
> +		if (rect.height + rect.sy > vht)
> +			rect.height = vht - rect.sy;
> +		if (rect.sy < vht)
> +			info->tileops->fb_tilefill(info, &rect);
> +	}
>   }
>
>   static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
diff mbox series

Patch

diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c
index eff7ec4da..98e528d38 100644
--- a/drivers/video/fbdev/core/tileblit.c
+++ b/drivers/video/fbdev/core/tileblit.c
@@ -76,7 +76,42 @@  static void tile_putcs(struct vc_data *vc, struct fb_info *info,
 static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
 			       int color, int bottom_only)
 {
-	return;
+	unsigned int cw = vc->vc_font.width;
+	unsigned int ch = vc->vc_font.height;
+	unsigned int rw = info->var.xres - (vc->vc_cols*cw);
+	unsigned int bh = info->var.yres - (vc->vc_rows*ch);
+	unsigned int rs = info->var.xres - rw;
+	unsigned int bs = info->var.yres - bh;
+	unsigned int vwt = info->var.xres_virtual / cw;
+	unsigned int vht = info->var.yres_virtual / ch;
+	struct fb_tilerect rect;
+
+	rect.index = vc->vc_video_erase_char &
+		((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
+	rect.fg = color;
+	rect.bg = color;
+
+	if ((int) rw > 0 && !bottom_only) {
+		rect.sx = (info->var.xoffset + rs + cw - 1) / cw;
+		rect.sy = 0;
+		rect.width = (rw + cw - 1) / cw;
+		rect.height = vht;
+		if (rect.width + rect.sx > vwt)
+			rect.width = vwt - rect.sx;
+		if (rect.sx < vwt)
+			info->tileops->fb_tilefill(info, &rect);
+	}
+
+	if ((int) bh > 0) {
+		rect.sx = info->var.xoffset / cw;
+		rect.sy = (info->var.yoffset + bs) / ch;
+		rect.width = rs / cw;
+		rect.height = (bh + ch - 1) / ch;
+		if (rect.height + rect.sy > vht)
+			rect.height = vht - rect.sy;
+		if (rect.sy < vht)
+			info->tileops->fb_tilefill(info, &rect);
+	}
 }
 
 static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable,