For some reason the drawing engine occasionally scribbles past the right

boundary when filling rectangles, especially annoying when we draw whitespaces
As a workaround we draw all rectangles less than 50 pixels wide by drawing
a 50 pixel rectangle into off-screen memory to the right of the visible fb and
then copy the portion we want. Keeps track of the colour and size of the
off-screen rectangle so we can avoid redrawing it whenever possible.
This commit is contained in:
macallan 2024-03-28 12:50:31 +00:00
parent f8aba72830
commit 5a795c59e3
1 changed files with 36 additions and 13 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: gftfb.c,v 1.11 2024/03/27 09:08:38 macallan Exp $ */
/* $NetBSD: gftfb.c,v 1.12 2024/03/28 12:50:31 macallan Exp $ */
/* $OpenBSD: sti_pci.c,v 1.7 2009/02/06 22:51:04 miod Exp $ */
@ -88,6 +88,7 @@ struct gftfb_softc {
#define HW_FB 0
#define HW_FILL 1
#define HW_BLIT 2
uint32_t sc_rect_colour, sc_rect_height;
/* cursor stuff */
int sc_cursor_x, sc_cursor_y;
int sc_hot_x, sc_hot_y, sc_enabled;
@ -250,7 +251,9 @@ gftfb_attach(device_t parent, device_t self, void *aux)
sc->sc_width = sc->sc_scr.scr_cfg.scr_width;
sc->sc_height = sc->sc_scr.scr_cfg.scr_height;
sc->sc_rect_colour = 0xf0000000;
sc->sc_rect_height = 0;
aprint_normal_dev(sc->sc_dev, "%s at %dx%d\n", sc->sc_scr.name,
sc->sc_width, sc->sc_height);
gftfb_setup(sc);
@ -687,6 +690,9 @@ gftfb_setup(struct gftfb_softc *sc)
sc->sc_enabled = 0;
sc->sc_video_on = 1;
sc->sc_rect_colour = 0xf0000000;
sc->sc_rect_height = 0;
/* set Bt458 read mask register to all planes */
gftfb_wait(sc);
ngle_bt458_write(memt, memh, 0x08, 0x04);
@ -1051,7 +1057,7 @@ gftfb_wait_fifo(struct gftfb_softc *sc, uint32_t slots)
}
static void
gftfb_rectfill(struct gftfb_softc *sc, int x, int y, int wi, int he,
gftfb_real_rectfill(struct gftfb_softc *sc, int x, int y, int wi, int he,
uint32_t bg)
{
struct sti_rom *rom = sc->sc_base.sc_rom;
@ -1081,6 +1087,30 @@ gftfb_rectfill(struct gftfb_softc *sc, int x, int y, int wi, int he,
}
static void
gftfb_rectfill(struct gftfb_softc *sc, int x, int y, int wi, int he,
uint32_t bg)
{
/*
* For some reason my 4MB VisEG always draws rectangles at least 32
* pixels wide - no idea why, the bitblt command doesn't have this
* problem.
* So, as a workaround, we draw a 50xFontHeight rectangle to the right
* of the visible fb, keep track of the colour so we don't need to
* redraw every time, and bitblt the portion we need
*/
if (wi < 50) {
if ((bg != sc->sc_rect_colour) ||
(he > sc->sc_rect_height)) {
gftfb_real_rectfill(sc, sc->sc_width + 10, 0, 50,
he, bg);
sc->sc_rect_colour = bg;
sc->sc_rect_height = he;
}
gftfb_bitblt(sc, sc->sc_width + 10, 0, x, y, wi, he, RopSrc);
} else
gftfb_real_rectfill(sc, x, y, wi, he, bg);
}
static void
gftfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi,
@ -1161,9 +1191,8 @@ gftfb_putchar(void *cookie, int row, int col, u_int c, long attr)
struct vcons_screen *scr = ri->ri_hw;
struct gftfb_softc *sc = scr->scr_cookie;
int x, y, wi, he, rv = GC_NOPE;
#if 0
uint32_t bg;
#endif
if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
return;
@ -1179,20 +1208,14 @@ gftfb_putchar(void *cookie, int row, int col, u_int c, long attr)
x = ri->ri_xorigin + col * wi;
y = ri->ri_yorigin + row * he;
#if 0
bg = ri->ri_devcmap[(attr >> 16) & 0xf];
/* XXX
* rectfill currently draws rectangles less than 32 pixels wide as
* 32 pixels wide, no idea why. So until I figure that one out we
* draw blanks by software
* bitblt doesn't seem to have this problem
*/
if (c == 0x20) {
gftfb_rectfill(sc, x, y, wi, he, bg);
return;
}
#endif
rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
if (rv == GC_OK)
return;