kernel/syscons: Add simple font scaling when using KMS drivers.
authorSascha Wildner <saw@online.de>
Wed, 10 Jun 2015 21:04:40 +0000 (23:04 +0200)
committerSascha Wildner <saw@online.de>
Wed, 10 Jun 2015 21:04:40 +0000 (23:04 +0200)
This commit lets the user choose the number of columns for KMS syscons
with a new tunable, kern.kms_columns. If it is not set, the default is
to scale as close as possible to 80x25 using natural numbers as scaling
factors (e.g., on 1680x1050 the default would be a 105x32 char console
using a 16x32 font).

The commit also separates (scaled) character drawing into a new
function, blit_blk(), and does some cleanups.

Submitted-by: dillon
share/man/man4/i915kms.4
share/man/man4/radeonkms.4
share/man/man4/syscons.4
sys/dev/misc/syscons/sckmsrndr.c
sys/dev/misc/syscons/scmouse.c
sys/dev/misc/syscons/scterm-sc.c
sys/dev/misc/syscons/scvgarndr.c
sys/dev/misc/syscons/scvidctl.c
sys/dev/misc/syscons/syscons.c
sys/dev/misc/syscons/syscons.h

index 58a691c..157a61d 100644 (file)
@@ -28,7 +28,7 @@
 .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 9, 2015
+.Dd June 10, 2015
 .Dt I915KMS 4
 .Os
 .Sh NAME
 The
 .Nm
 driver provides support for integrated graphics chips by Intel.
+Please refer the
+.Sx Loader Tunables
+section in
+.Xr syscons 4
+for more information about how to make the console work with
+.Nm .
 .Sh SYSCTL VARIABLES
 If display backlight level can be controlled by the GPU (which is often
 the case in notebooks), the sysctl
index 481d4ac..64a39ef 100644 (file)
@@ -28,7 +28,7 @@
 .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 9, 2015
+.Dd June 10, 2015
 .Dt RADEONKMS 4
 .Os
 .Sh NAME
 The
 .Nm
 driver provides support for the AMD Radeon graphics chips.
+Please refer the
+.Sx Loader Tunables
+section in
+.Xr syscons 4
+for more information about how to make the console work with
+.Nm .
 .Sh LOADER TUNABLES
 Tunables can be set at the
 .Xr loader 8
index 55143cf..0259829 100644 (file)
@@ -26,7 +26,7 @@
 .\"
 .\" $FreeBSD: src/share/man/man4/syscons.4,v 1.10.2.14 2003/04/25 21:21:36 brueffer Exp $
 .\"
-.Dd August 19, 2007
+.Dd June 10, 2015
 .Dt SYSCONS 4
 .Os
 .Sh NAME
@@ -64,9 +64,17 @@ The
 .Nm
 driver is implemented on top of the keyboard driver
 .Pq Xr atkbd 4
-and the video card driver
-.Pq Xr vga 4
-and so requires both of them to be configured in the system.
+and the video card drivers
+.Xr ( i915kms 4 ,
+.Xr radeonkms 4 ,
+or
+.Xr vga 4 ) .
+Please see
+.Sx Loader Tunables
+below on how to make the console work with
+.Xr i915kms 4
+or
+.Xr radeonkms 4 .
 .Pp
 There can be only one
 .Nm
@@ -241,6 +249,31 @@ and
 .Xr vidcontrol 1
 for more details.
 .Sh DRIVER CONFIGURATION
+.Ss Loader Tunables
+The following tunable is available and can be set in
+.Xr loader.conf 5 .
+.Bl -tag -width ".Va kern.kms_console"
+.It Va kern.kms_console
+Setting this tunable to 1 enables experimental framebuffer support
+in conjunction with the
+.Xr i915kms 4
+or
+.Xr radeonkms 4
+drivers.
+It is 0 by default.
+.It Va kern.kms_columns
+The number of columns to use in conjunction with the
+.Xr i915kms 4
+and
+.Xr radeonkms 4
+drivers.
+This requires
+.Va kern.kms_console
+to be set to 1.
+By default,
+.Nm
+tries to find a more or less pleasant looking default.
+.El
 .Ss Kernel Configuration Options
 The following kernel configuration options control the
 .Nm
@@ -360,19 +393,6 @@ This option implies the
 .Dv SC_NO_CUTPASTE
 option too.
 .El
-.Ss Loader Tunables
-The following tunable is available and can be set in
-.Xr loader.conf 5 .
-.Bl -tag -width ".Va kern.kms_console"
-.It Va kern.kms_console
-Setting this tunable to 1 enables experimental framebuffer support
-in conjunction with the
-.Nm i915kms
-or
-.Nm radeonkms
-drivers.
-It is 0 by default.
-.El
 .Ss Driver Flags
 The following driver flags can be used to control the
 .Nm
index 0091cef..dfd60b9 100644 (file)
@@ -2,6 +2,11 @@
  * Copyright (c) 2014 Imre Vadász <imre@vdsz.com>
  * All rights reserved.
  *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Sascha Wildner <saw@online.de>.
+ *
+ * Simple font scaling code by Sascha Wildner and Matthew Dillon
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -110,6 +115,93 @@ kms_nop(scr_stat *scp, ...)
 {
 }
 
+/*
+ * Scaled font rendering.  Simple blit blitter copy operation with bitmap
+ * scaling.  Scales the bitmap char_data(sw x sh) to the output bitmap
+ * draw_pos(dw x dh).
+ *
+ * This function does not do fractional scaling.
+ *
+ * SET - Sets both the fg and bg pen
+ *
+ * MASK        - Sets only the fg pen based on the source mask and leaves
+ *       the background untouched.
+ */
+#define BLIT_SET       0
+#define BLIT_MASK      1
+
+static void
+blit_blk(scr_stat *scp, u_char *char_data, int sw, int sh,
+        vm_offset_t draw_pos, int pixel_size, int dw, int dh,
+        int line_width, uint32_t fg, uint32_t bg, int how)
+{
+       vm_offset_t p;
+       int pos;
+       int x;          /* destination iterator (whole pixels) */
+       int y;
+       int sx, sx_inc; /* source iterator (fractional) */
+       int sy, sy_inc;
+       uint8_t c;
+
+       /*
+        * Calculate fractional iterator for source
+        */
+       if (dw)
+               sx_inc = (sw << 16) / dw;
+       else
+               sx_inc = 0;
+
+       if (dh)
+               sy_inc = (sh << 16) / dh;
+       else
+               sy_inc = 0;
+
+       sy = 0;
+       c = 0;
+
+       /*
+        * For each pixel row in the target
+        */
+       for (y = 0; y < dh; ++y) {
+               sx = 0;
+               p = draw_pos;
+
+               /*
+                * Render all pixel columns in the target by calculating
+                * which bit in the source is applicable.
+                */
+               switch(how) {
+               case BLIT_SET:
+                       for (x = 0; x < dw; ++x) {
+                               if ((sx & 0x00070000) == 0)
+                                       c = char_data[sx >> 19];
+                               pos = ~(sx >> 16) & 7;
+                               writel(p, (c & (1 << pos) ? fg : bg));
+                               p += pixel_size;
+                               sx += sx_inc;
+                       }
+                       break;
+               case BLIT_MASK:
+                       for (x = 0; x < dw; ++x) {
+                               if ((sx & 0x00070000) == 0)
+                                       c = char_data[sx >> 19];
+                               pos = ~(sx >> 16) & 7;
+                               if (c & (1 << pos))
+                                       writel(p, fg);
+                               p += pixel_size;
+                               sx += sx_inc;
+                       }
+                       break;
+               }
+               draw_pos += line_width;
+               sy += sy_inc;
+               if (sy >= 0x10000) {
+                       char_data += (sy >> 16) * (sw >> 3);
+                       sy &= 0x0FFFF;
+               }
+       }
+}
+
 /* KMS renderer */
 
 static void
@@ -117,17 +209,17 @@ kms_draw(scr_stat *scp, int from, int count, int flip)
 {
        sc_softc_t *sc = scp->sc;
        u_char *char_data;
-       int a, i, j;
+       int a, i;
        uint32_t fg, bg;
        vm_offset_t draw_pos, p;
-       int pos, line_width, pixel_size;
+       int line_width, pixel_size;
 
        line_width = sc->fbi->stride;
        pixel_size = 4;
 
        draw_pos = sc->fbi->vaddr +
-           8 * pixel_size * (from % scp->xsize) +
-           scp->font_size * line_width * (from / scp->xsize);
+           scp->blk_width * pixel_size * (from % scp->xsize) +
+           scp->blk_height * line_width * (from / scp->xsize);
 
        if (from + count > scp->xsize * scp->ysize)
                count = scp->xsize * scp->ysize - from;
@@ -135,7 +227,7 @@ kms_draw(scr_stat *scp, int from, int count, int flip)
        for (i = from; count-- > 0; i++) {
                p = draw_pos;
                char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
-                   scp->font_size]);
+                                       scp->font_height]);
 
                a = sc_vtb_geta(&scp->vtb, i);
                if (flip) {
@@ -145,15 +237,13 @@ kms_draw(scr_stat *scp, int from, int count, int flip)
                        fg = colormap[(a & 0x0f00) >> 8];
                        bg = colormap[((a & 0xf000) >> 4) >> 8];
                }
-
-               for (j = 0; j < scp->font_size; j++, char_data++) {
-                       for (pos = 7; pos >= 0; pos--, p += pixel_size)
-                               writel(p, *char_data & (1 << pos) ? fg : bg);
-                       p += line_width - 8 * pixel_size;
-               }
-               draw_pos += 8 * pixel_size;
+               blit_blk(scp, char_data, scp->font_width, scp->font_height,
+                        p, pixel_size, scp->blk_width, scp->blk_height,
+                        line_width, fg, bg, BLIT_SET);
+               draw_pos += scp->blk_width * pixel_size;
                if ((i % scp->xsize) == scp->xsize - 1) {
-                       draw_pos += (scp->font_size - 1) * line_width +
+                       draw_pos +=
+                           (scp->blk_height - 1) * line_width +
                            scp->xpad * pixel_size;
                }
        }
@@ -163,19 +253,23 @@ static void
 draw_kmscursor(scr_stat *scp, int at, int on, int flip)
 {
        sc_softc_t *sc = scp->sc;
-       int line_width, pixel_size, height;
-       int a, i, pos;
+       int line_width, pixel_size;
+       int cursor_base;
+       int blk_base;
+       int a;
        uint32_t fg, bg;
        unsigned char *char_data;
        vm_offset_t draw_pos;
 
        line_width = sc->fbi->stride;
        pixel_size = 4;
+       cursor_base = /* scp->font_height - */ scp->cursor_base;
+       blk_base = scp->blk_height * cursor_base / scp->font_height;
 
        draw_pos = sc->fbi->vaddr +
-           8 * pixel_size * (at % scp->xsize) +
-           scp->font_size * line_width * (at / scp->xsize) +
-           (scp->font_size - scp->cursor_base - 1) * line_width;
+           scp->blk_width * pixel_size * (at % scp->xsize) +
+           scp->blk_height * line_width * (at / scp->xsize) +
+           blk_base * line_width;
 
        a = sc_vtb_geta(&scp->vtb, at);
        if (flip) {
@@ -190,15 +284,14 @@ draw_kmscursor(scr_stat *scp, int at, int on, int flip)
                    ((a & 0xf000) >> 4)) >> 8];
        }
 
-       char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
-           scp->font_size - scp->cursor_base - 1]);
-       height = imin(scp->cursor_height, scp->font_size);
+       char_data = &scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height];
+       char_data += cursor_base;
 
-       for (i = 0; i < height; i++, char_data--) {
-               for (pos = 7; pos >= 0; pos--, draw_pos += pixel_size)
-                       writel(draw_pos, *char_data & (1 << pos) ? fg : bg);
-               draw_pos -= line_width + 8 * pixel_size;
-       }
+       blit_blk(scp, char_data,
+                scp->font_width, scp->font_height - cursor_base,
+                draw_pos, pixel_size,
+                scp->blk_width, scp->blk_height - blk_base,
+                line_width, fg, bg, BLIT_SET);
 }
 
 static int pxlblinkrate = 0;
@@ -249,28 +342,31 @@ draw_kmsmouse(scr_stat *scp, int x, int y)
 {
        sc_softc_t *sc = scp->sc;
        int line_width, pixel_size;
-       int xend, yend;
-       int i, j;
+       int blk_width, blk_height;
        vm_offset_t draw_pos;
 
        line_width = sc->fbi->stride;
        pixel_size = 4;
 
-       xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
-       yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
-
-       draw_pos = sc->fbi->vaddr + y * line_width + x * pixel_size;
-
-       for (i = 0; i < (yend - y); i++) {
-               for (j = (xend - x - 1); j >= 0; j--) {
-                       if (mouse_or_mask[i] & 1 << (15 - j))
-                               writel(draw_pos + pixel_size * j, colormap[15]);
-                       else if (mouse_and_mask[i] & 1 << (15 - j))
-                               writel(draw_pos + pixel_size * j, colormap[0]);
-               }
+       if (x + scp->font_width < scp->font_width * scp->xsize)
+               blk_width = scp->blk_width;
+       else
+               blk_width = scp->font_width * scp->xsize - x;
 
-               draw_pos += line_width;
-       }
+       if (y + scp->font_height < scp->font_height * scp->ysize)
+               blk_height = scp->blk_height;
+       else
+               blk_height = scp->font_height * scp->ysize - y;
+
+       draw_pos = sc->fbi->vaddr + y * scp->blk_height / scp->font_height *
+                  line_width +
+                  x * scp->blk_width / scp->font_width * pixel_size;
+       blit_blk(scp, (unsigned char *)mouse_and_mask, 16, 16,
+                draw_pos, pixel_size, blk_width, blk_height,
+                line_width, colormap[0], 0, BLIT_MASK);
+       blit_blk(scp, (unsigned char *)mouse_or_mask, 16, 16,
+                draw_pos, pixel_size, blk_width, blk_height,
+                line_width, colormap[15], 0, BLIT_MASK);
 }
 
 static void
@@ -281,9 +377,9 @@ remove_kmsmouse(scr_stat *scp, int x, int y)
        int i;
 
        /* erase the mouse cursor image */
-       col = x/8 - scp->xoff;
-       row = y/scp->font_size - scp->yoff;
-       pos = row*scp->xsize + col;
+       col = x / scp->font_width - scp->xoff;
+       row = y / scp->font_height - scp->yoff;
+       pos = row * scp->xsize + col;
        i = (col < scp->xsize - 1) ? 2 : 1;
        (*scp->rndr->draw)(scp, pos, i, FALSE);
        if (row < scp->ysize - 1)
index 0cb4dc8..13fb2dc 100644 (file)
@@ -104,11 +104,12 @@ sc_mouse_move(scr_stat *scp, int x, int y)
     crit_enter();
     scp->mouse_xpos = scp->mouse_oldxpos = x;
     scp->mouse_ypos = scp->mouse_oldypos = y;
-    if (scp->font_size <= 0)
+    if (scp->font_height <= 0)
        scp->mouse_pos = scp->mouse_oldpos = 0;
     else
        scp->mouse_pos = scp->mouse_oldpos = 
-           (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
+           (y / scp->font_height - scp->yoff) * scp->xsize +
+           x / scp->font_width - scp->xoff;
     scp->status |= MOUSE_MOVED;
     crit_exit();
 }
@@ -117,28 +118,29 @@ sc_mouse_move(scr_stat *scp, int x, int y)
 static void
 set_mouse_pos(scr_stat *scp)
 {
-    if (scp->mouse_xpos < scp->xoff*8)
-       scp->mouse_xpos = scp->xoff*8;
-    if (scp->mouse_ypos < scp->yoff*scp->font_size)
-       scp->mouse_ypos = scp->yoff*scp->font_size;
+    if (scp->mouse_xpos < scp->xoff * scp->font_width)
+       scp->mouse_xpos = scp->xoff * scp->font_width;
+    if (scp->mouse_ypos < scp->yoff * scp->font_height)
+       scp->mouse_ypos = scp->yoff * scp->font_height;
     if (ISGRAPHSC(scp)) {
-        if (scp->mouse_xpos > scp->xpixel-1)
-           scp->mouse_xpos = scp->xpixel-1;
-        if (scp->mouse_ypos > scp->ypixel-1)
-           scp->mouse_ypos = scp->ypixel-1;
+        if (scp->mouse_xpos > scp->xpixel - 1)
+           scp->mouse_xpos = scp->xpixel - 1;
+        if (scp->mouse_ypos > scp->ypixel - 1)
+           scp->mouse_ypos = scp->ypixel - 1;
        return;
     } else {
-       if (scp->mouse_xpos > (scp->xsize + scp->xoff)*8 - 1)
-           scp->mouse_xpos = (scp->xsize + scp->xoff)*8 - 1;
-       if (scp->mouse_ypos > (scp->ysize + scp->yoff)*scp->font_size - 1)
-           scp->mouse_ypos = (scp->ysize + scp->yoff)*scp->font_size - 1;
+       if (scp->mouse_xpos > (scp->xsize + scp->xoff) * scp->font_width - 1)
+           scp->mouse_xpos = (scp->xsize + scp->xoff) * scp->font_width - 1;
+       if (scp->mouse_ypos > (scp->ysize + scp->yoff) * scp->font_height - 1)
+           scp->mouse_ypos = (scp->ysize + scp->yoff) * scp->font_height - 1;
     }
 
-    if (scp->mouse_xpos != scp->mouse_oldxpos || scp->mouse_ypos != scp->mouse_oldypos) {
+    if (scp->mouse_xpos != scp->mouse_oldxpos ||
+       scp->mouse_ypos != scp->mouse_oldypos) {
        scp->status |= MOUSE_MOVED;
        scp->mouse_pos =
-           (scp->mouse_ypos/scp->font_size - scp->yoff)*scp->xsize 
-               + scp->mouse_xpos/8 - scp->xoff;
+           (scp->mouse_ypos / scp->font_height - scp->yoff) * scp->xsize +
+           scp->mouse_xpos / scp->font_width - scp->xoff;
 #ifndef SC_NO_CUTPASTE
        if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING))
            mouse_cut(scp);
@@ -174,11 +176,12 @@ sc_remove_mouse_image(scr_stat *scp)
 
     ++scp->sc->videoio_in_progress;
     (*scp->rndr->draw_mouse)(scp,
-                            (scp->mouse_oldpos%scp->xsize + scp->xoff)*8,
-                            (scp->mouse_oldpos/scp->xsize + scp->yoff)
-                                * scp->font_size,
+                            (scp->mouse_oldpos%scp->xsize + scp->xoff) *
+                             scp->font_width,
+                            (scp->mouse_oldpos/scp->xsize + scp->yoff) *
+                             scp->font_height,
                             FALSE);
-    size = scp->xsize*scp->ysize;
+    size = scp->xsize * scp->ysize;
     i = scp->mouse_oldpos;
     mark_for_update(scp, i);
     mark_for_update(scp, i);
@@ -883,7 +886,8 @@ sc_mouse_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
                sc_remove_all_mouse(scp->sc);
 #ifndef SC_NO_FONT_LOADING
                if (ISTEXTSC(cur_scp) && (cur_scp->font != NULL))
-                   sc_load_font(cur_scp, 0, cur_scp->font_size, cur_scp->font,
+                   sc_load_font(cur_scp, 0, cur_scp->font_height,
+                                cur_scp->font,
                                 cur_scp->sc->mouse_char, 4);
 #endif
                scp->sc->mouse_char = mouse->u.mouse_char;
index 47d5fee..8737970 100644 (file)
@@ -564,10 +564,21 @@ scterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c)
                                else
                                        sc->flags &= ~SC_CHAR_CURSOR;
                        } else if (tcp->num_param == 2) {
-                               sc->cursor_base = scp->font_size 
+                               sc->cursor_base = scp->font_height 
                                                - (tcp->param[1] & 0x1F) - 1;
                                sc->cursor_height = (tcp->param[1] & 0x1F) 
                                                - (tcp->param[0] & 0x1F) + 1;
+                               if (sc->cursor_base < 0)
+                                       sc->cursor_base = 0;
+
+                               if (sc->cursor_height < 1) {
+                                       sc->cursor_height = 1;
+                               } else if (sc->cursor_height >
+                                          scp->font_height -
+                                          scp->cursor_base) {
+                                       sc->cursor_height = scp->font_height -
+                                                           scp->cursor_base;
+                               }
                        }
                        /* 
                         * The cursor shape is global property; 
index 9e079c4..8e98e34 100644 (file)
@@ -196,7 +196,7 @@ vga_txtdraw(scr_stat *scp, int from, int count, int flip)
 static void 
 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
 {
-       if (base < 0 || base >= scp->font_size)
+       if (base < 0 || base >= scp->font_height)
                return;
 
        /* the caller may set height <= 0 in order to disable the cursor */
@@ -206,7 +206,8 @@ vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
 #endif
        (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
                                                        base, height,
-                                                       scp->font_size, blink);
+                                                       scp->font_height,
+                                                       blink);
 
 }
 
@@ -225,10 +226,10 @@ draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
                int h;
                int i;
 
-               if (scp->font_size < 14) {
+               if (scp->font_height < 14) {
                        font = sc->font_8;
                        h = 8;
-               } else if (scp->font_size >= 16) {
+               } else if (scp->font_height >= 16) {
                        font = sc->font_16;
                        h = 16;
                } else {
@@ -339,35 +340,37 @@ draw_txtmouse(scr_stat *scp, int x, int y)
        int i;
 
        /* prepare mousepointer char's bitmaps */
-       pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
-       bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size,
-             &font_buf[0], scp->font_size);
-       bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size,
-             &font_buf[32], scp->font_size);
+       pos = (y / scp->font_height - scp->yoff) * scp->xsize +
+             x / scp->font_width - scp->xoff;
+       bcopy(scp->font + sc_vtb_getc(&scp->scr, pos) * scp->font_height,
+             &font_buf[0], scp->font_height);
+       bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1) * scp->font_height,
+             &font_buf[32], scp->font_height);
        bcopy(scp->font 
-                + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size,
-             &font_buf[64], scp->font_size);
-       bcopy(scp->font
-                + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size,
-             &font_buf[96], scp->font_size);
-       for (i = 0; i < scp->font_size; ++i) {
-               cursor[i] = font_buf[i]<<8 | font_buf[i+32];
-               cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
+                + sc_vtb_getc(&scp->scr, pos + scp->xsize) * scp->font_height,
+             &font_buf[64], scp->font_height);
+       bcopy(scp->font +
+             sc_vtb_getc(&scp->scr, pos + scp->xsize + 1) * scp->font_height,
+             &font_buf[96], scp->font_height);
+       for (i = 0; i < scp->font_height; ++i) {
+               cursor[i] = (font_buf[i]<<8) | font_buf[i+32];
+               cursor[i + scp->font_height] = (font_buf[i+64]<<8) |
+                                              font_buf[i+96];
        }
 
        /* now and-or in the mousepointer image */
-       xoffset = x%8;
-       yoffset = y%scp->font_size;
+       xoffset = x % scp->font_width;
+       yoffset = y % scp->font_height;
        for (i = 0; i < 16; ++i) {
                cursor[i + yoffset] =
                        (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
                        | (mouse_or_mask[i] >> xoffset);
        }
-       for (i = 0; i < scp->font_size; ++i) {
+       for (i = 0; i < scp->font_height; ++i) {
                font_buf[i] = (cursor[i] & 0xff00) >> 8;
                font_buf[i + 32] = cursor[i] & 0xff;
-               font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
-               font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
+               font_buf[i + 64] = (cursor[i + scp->font_height] & 0xff00) >> 8;
+               font_buf[i + 96] = cursor[i + scp->font_height] & 0xff;
        }
 
 #if 1
@@ -401,7 +404,8 @@ draw_txtmouse(scr_stat *scp, int x, int y)
        int color;
        int a;
 
-       pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
+       pos = (y / scp->font_height - scp->yoff)*
+             scp->xsize + x / scp->font_width - scp->xoff;
        a = sc_vtb_geta(&scp->scr, pos);
        if (scp->sc->adp->va_flags & V_ADP_COLOR)
                color = (col_conv[(a & 0xf000) >> 12] << 12)
@@ -449,13 +453,13 @@ vga_pxlborder_direct(scr_stat *scp, int color)
 
        if (scp->yoff > 0) {
                draw_pos = scp->sc->adp->va_window;
-               draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
+               draw_end = draw_pos + line_width * scp->yoff * scp->font_height;
 
                for (p = draw_pos; p < draw_end; p += 4)
                        writel(p, u32);
        }
 
-       y = (scp->yoff + scp->ysize) * scp->font_size;
+       y = (scp->yoff + scp->ysize) * scp->font_height;
 
        if (scp->ypixel > y) {
                draw_pos = scp->sc->adp->va_window + line_width * y;
@@ -465,14 +469,15 @@ vga_pxlborder_direct(scr_stat *scp, int color)
                        writel(p, u32); 
        }
 
-       y = scp->yoff * scp->font_size;
-       x = scp->xpixel / 8 - scp->xoff - scp->xsize;
+       y = scp->yoff * scp->font_height;
+       x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize;
 
-       for (i = 0; i < scp->ysize * scp->font_size; ++i) {
+       for (i = 0; i < scp->ysize * scp->font_height; ++i) {
                if (scp->xoff > 0) {
                        draw_pos = scp->sc->adp->va_window +
                            line_width * (y + i);
-                       draw_end = draw_pos + scp->xoff * 8 * pixel_size;
+                       draw_end = draw_pos +
+                                  scp->xoff * scp->font_width * pixel_size;
 
                        for (p = draw_pos; p < draw_end; p += 4)
                                writel(p, u32);
@@ -504,13 +509,13 @@ vga_pxlborder_packed(scr_stat *scp, int color)
 
        if (scp->yoff > 0) {
                draw_pos = scp->sc->adp->va_window;
-               draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
+               draw_end = draw_pos + line_width * scp->yoff * scp->font_height;
 
                for (p = draw_pos; p < draw_end; p += 4)
                        writel(p, u32);
        }
 
-       y = (scp->yoff + scp->ysize) * scp->font_size;
+       y = (scp->yoff + scp->ysize) * scp->font_height;
 
        if (scp->ypixel > y) {
                draw_pos = scp->sc->adp->va_window + line_width * y;
@@ -520,14 +525,14 @@ vga_pxlborder_packed(scr_stat *scp, int color)
                        writel(p, u32);
        }
 
-       y = scp->yoff * scp->font_size;
-       x = scp->xpixel / 8 - scp->xoff - scp->xsize;
+       y = scp->yoff * scp->font_height;
+       x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize;
 
-       for (i = 0; i < scp->ysize * scp->font_size; ++i) {
+       for (i = 0; i < scp->ysize * scp->font_height; ++i) {
                if (scp->xoff > 0) {
                        draw_pos = scp->sc->adp->va_window +
                            line_width * (y + i);
-                       draw_end = draw_pos + scp->xoff * 8;
+                       draw_end = draw_pos + scp->xoff * scp->font_width;
 
                        for (p = draw_pos; p < draw_end; p += 4)
                                writel(p, u32);
@@ -566,13 +571,14 @@ vga_pxlborder_planar(scr_stat *scp, int color)
        line_width = scp->sc->adp->va_line_width;
        p = scp->sc->adp->va_window;
        if (scp->yoff > 0)
-               bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
-       y = (scp->yoff + scp->ysize)*scp->font_size;
+               bzero_io((void *)p, line_width*scp->yoff*scp->font_height);
+       y = (scp->yoff + scp->ysize)*scp->font_height;
        if (scp->ypixel > y)
-               bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y));
-       y = scp->yoff*scp->font_size;
-       x = scp->xpixel/8 - scp->xoff - scp->xsize;
-       for (i = 0; i < scp->ysize*scp->font_size; ++i) {
+               bzero_io((void *)(p + line_width*y),
+                        line_width*(scp->ypixel - y));
+       y = scp->yoff*scp->font_height;
+       x = scp->xpixel/scp->font_width - scp->xoff - scp->xsize;
+       for (i = 0; i < scp->ysize*scp->font_height; ++i) {
                if (scp->xoff > 0)
                        bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
                if (x > 0)
@@ -616,9 +622,9 @@ vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
 
                p = draw_pos;
                char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
-                   scp->font_size]);
+                   scp->font_height]);
 
-               for (j = 0; j < scp->font_size; ++j, ++char_data) {
+               for (j = 0; j < scp->font_height; ++j, ++char_data) {
                        pos = 7;
 
                        for (k = 0; k < 2 * pixel_size; ++k) {
@@ -640,7 +646,7 @@ vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
 
                if ((i % scp->xsize) == scp->xsize - 1)
                        draw_pos += scp->xoff * 16 * pixel_size +
-                            (scp->font_size - 1) * line_width;
+                            (scp->font_height - 1) * line_width;
        }
 }
 
@@ -673,9 +679,9 @@ vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
 
                p = draw_pos;
                char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
-                   scp->font_size]);
+                   scp->font_height]);
 
-               for (j = 0; j < scp->font_size; ++j, ++char_data) {
+               for (j = 0; j < scp->font_height; ++j, ++char_data) {
                        u32 = ((*char_data & 1 ? fg : bg) << 24) +
                              ((*char_data & 2 ? fg : bg) << 16) +
                              ((*char_data & 4 ? fg : bg) << 8) +
@@ -691,11 +697,11 @@ vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
                        p += line_width;
                }
 
-               draw_pos += 8;
+               draw_pos += scp->font_width;
 
                if ((i % scp->xsize) == scp->xsize - 1)
                        draw_pos += scp->xoff * 16 +
-                            (scp->font_size - 1) * line_width;
+                            (scp->font_height - 1) * line_width;
        }
 }
 
@@ -744,15 +750,15 @@ vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
                /* foreground color */
                outw(GDCIDX, col1 | 0x00);      /* set/reset */
                e = d;
-               f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
-               for (j = 0; j < scp->font_size; ++j, ++f) {
+               f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_height]);
+               for (j = 0; j < scp->font_height; ++j, ++f) {
                        writeb(e, *f);
                        e += line_width;
                }
                ++d;
                if ((i % scp->xsize) == scp->xsize - 1)
                        d += scp->xoff*2 
-                                + (scp->font_size - 1)*line_width;
+                                + (scp->font_height - 1)*line_width;
        }
        outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
        outw(GDCIDX, 0x0000);           /* set/reset */
@@ -762,7 +768,7 @@ vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
 static void 
 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
 {
-       if (base < 0 || base >= scp->font_size)
+       if (base < 0 || base >= scp->font_height)
                return;
        /* the caller may set height <= 0 in order to disable the cursor */
 #if 0
@@ -783,8 +789,8 @@ draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
        line_width = scp->sc->adp->va_line_width;
        pixel_size = scp->sc->adp->va_info.vi_pixel_size;
 
-       draw_pos = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) +
-           (scp->font_size - scp->cursor_base - 1) * line_width;
+       draw_pos = VIDEO_MEMORY_POS(scp, at, scp->font_width * pixel_size) +
+           (scp->font_height - scp->cursor_base - 1) * line_width;
 
        a = sc_vtb_geta(&scp->vtb, at);
 
@@ -800,10 +806,10 @@ draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
                    ((a & 0xf000) >> 4)) >> 8];
        }
 
-       char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
-           scp->font_size - scp->cursor_base - 1]);
+       char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height +
+           scp->font_height - scp->cursor_base - 1]);
 
-       height = imin(scp->cursor_height, scp->font_size);
+       height = imin(scp->cursor_height, scp->font_height);
 
        for (i = 0; i < height; ++i, --char_data) {
                pos = 7;
@@ -836,7 +842,7 @@ draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
        line_width = scp->sc->adp->va_line_width;
 
        draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
-           (scp->font_size - scp->cursor_base - 1) * line_width;
+           (scp->font_height - scp->cursor_base - 1) * line_width;
 
        a = sc_vtb_geta(&scp->vtb, at);
 
@@ -848,10 +854,10 @@ draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
                bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
        }
 
-       char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
-           scp->font_size - scp->cursor_base - 1]);
+       char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height +
+           scp->font_height - scp->cursor_base - 1]);
 
-       height = imin(scp->cursor_height, scp->font_size);
+       height = imin(scp->cursor_height, scp->font_height);
 
        for (i = 0; i < height; ++i, --char_data) {
                u32 = ((*char_data & 1 ? fg : bg) << 24) +
@@ -885,7 +891,7 @@ draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
        line_width = scp->sc->adp->va_line_width;
 
        d = VIDEO_MEMORY_POS(scp, at, 1) +
-           (scp->font_size - scp->cursor_base - 1) * line_width;
+           (scp->font_height - scp->cursor_base - 1) * line_width;
 
        outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
        outw(GDCIDX, 0x0003);           /* data rotate/function select */
@@ -906,9 +912,9 @@ draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
        else
                col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
        outw(GDCIDX, col | 0x00);       /* set/reset */
-       f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
-               + scp->font_size - scp->cursor_base - 1]);
-       height = imin(scp->cursor_height, scp->font_size);
+       f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_height
+               + scp->font_height - scp->cursor_base - 1]);
+       height = imin(scp->cursor_height, scp->font_height);
        for (i = 0; i < height; ++i, --f) {
                outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
                writeb(d, 0);
@@ -1055,7 +1061,7 @@ draw_pxlmouse_direct(scr_stat *scp, int x, int y)
        pixel_size = scp->sc->adp->va_info.vi_pixel_size;
 
        xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
-       yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
+       yend = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize));
 
        draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
 
@@ -1097,9 +1103,10 @@ draw_pxlmouse_packed(scr_stat *scp, int x, int y)
 
        line_width = scp->sc->adp->va_line_width;
 
-       xend = imin(8 * (scp->xoff + scp->xsize), imin(x + 16, scp->xpixel));
-       yend = imin(scp->font_size * (scp->yoff + scp->ysize),
-           imin(y + 16, scp->ypixel));
+       xend = imin(scp->font_width * (scp->xoff + scp->xsize),
+                   imin(x + 16, scp->xpixel));
+       yend = imin(scp->font_height * (scp->yoff + scp->ysize),
+                   imin(y + 16, scp->ypixel));
 
        draw_pos = scp->sc->adp->va_window + y * line_width + x;
 
@@ -1127,7 +1134,7 @@ draw_pxlmouse_planar(scr_stat *scp, int x, int y)
 
        line_width = scp->sc->adp->va_line_width;
        xoff = (x - scp->xoff*8)%8;
-       ymax = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
+       ymax = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize));
 
        outw(GDCIDX, 0x0805);           /* read mode 1, write mode 0 */
        outw(GDCIDX, 0x0001);           /* set/reset enable */
@@ -1179,9 +1186,9 @@ remove_pxlmouse(scr_stat *scp, int x, int y)
        int i;
 
        /* erase the mouse cursor image */
-       col = x/8 - scp->xoff;
-       row = y/scp->font_size - scp->yoff;
-       pos = row*scp->xsize + col;
+       col = x / scp->font_width - scp->xoff;
+       row = y / scp->font_height - scp->yoff;
+       pos = row * scp->xsize + col;
        i = (col < scp->xsize - 1) ? 2 : 1;
        (*scp->rndr->draw)(scp, pos, i, FALSE);
        if (row < scp->ysize - 1)
index 9a997bd..3ee3714 100644 (file)
@@ -5,7 +5,9 @@
  * All rights reserved.
  *
  * This code is derived from software contributed to The DragonFly Project
- * by Sascha Wildner <saw@online.de>
+ * by Sascha Wildner <saw@online.de>.
+ *
+ * Simple font scaling code by Sascha Wildner and Matthew Dillon
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -49,6 +51,9 @@
 
 SET_DECLARE(scrndr_set, const sc_renderer_t);
 
+static int desired_cols = 0;
+TUNABLE_INT("kern.kms_columns", &desired_cols);
+
 int
 sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
                 int fontsize)
@@ -144,7 +149,8 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
     scp->xpixel = scp->xsize*8;
     scp->ypixel = scp->ysize*fontsize;
     scp->font = font;
-    scp->font_size = fontsize;
+    scp->font_height = fontsize;
+    scp->font_width = 8;
 
     /* allocate buffers */
     sc_alloc_scr_buffer(scp, TRUE, TRUE);
@@ -223,7 +229,8 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
     scp->xpixel = info.vi_width;
     scp->ypixel = info.vi_height;
     scp->font = NULL;
-    scp->font_size = 0;
+    scp->font_height = 0;
+    scp->font_width = 0;
 #ifndef SC_NO_SYSMOUSE
     /* move the mouse cursor at the center of the screen */
     sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
@@ -375,7 +382,8 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
     scp->xoff = (scp->xpixel/8 - xsize)/2;
     scp->yoff = (scp->ypixel/fontsize - ysize)/2;
     scp->font = font;
-    scp->font_size = fontsize;
+    scp->font_height = fontsize;
+    scp->font_width = 8;
 
     /* allocate buffers */
     sc_alloc_scr_buffer(scp, TRUE, TRUE);
@@ -623,7 +631,7 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
            if (scp->status & GRAPHICS_MODE) {
                lwkt_reltoken(&tty_token);
                return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 
-                                        scp->font_size);
+                                        scp->font_height);
            }
            crit_enter();
            if ((error = sc_clean_up(scp))) {
@@ -796,9 +804,40 @@ sc_update_render(scr_stat *scp)
                scp->model = V_INFO_MM_TEXT;
                scp->xpixel = scp->fbi->width;
                scp->ypixel = scp->fbi->height;
-               scp->xsize = scp->xpixel / 8;
-               scp->ysize = scp->ypixel / scp->font_size;
-               scp->xpad = scp->fbi->stride / 4 - scp->xsize * 8;
+
+               /*
+                * Assume square pixels for now
+                */
+               kprintf("kms console: xpixels %d ypixels %d\n",
+                       scp->xpixel, scp->ypixel);
+
+               /*
+                * If columns not specified in /boot/loader.conf then
+                * calculate a non-fractional scaling that yields a
+                * reasonable number of rows and columns.
+                */
+               if (desired_cols == 0) {
+                       int nomag = 1;
+                       while (scp->xpixel / (scp->font_width * nomag) >= 80 &&
+                              scp->ypixel / (scp->font_height * nomag) >= 25) {
+                               ++nomag;
+                       }
+                       if (nomag > 1)
+                               --nomag;
+                       desired_cols = scp->xpixel / (scp->font_width * nomag);
+               }
+               scp->blk_width = scp->xpixel / desired_cols;
+               scp->blk_height = scp->blk_width * scp->font_height /
+                                 scp->font_width;
+
+               /* scp->xsize = scp->xpixel / scp->blk_width; total possible */
+               scp->xsize = desired_cols;
+               scp->ysize = scp->ypixel / scp->blk_height;
+               scp->xpad = scp->fbi->stride / 4 - scp->xsize * scp->blk_width;
+
+               kprintf("kms console: scale-to %dx%d cols=%d rows=%d\n",
+                       scp->blk_width, scp->blk_height,
+                       scp->xsize, scp->ysize);
 
                /* allocate buffers */
                sc_alloc_scr_buffer(scp, TRUE, TRUE);
index 2c0d400..12341ef 100644 (file)
@@ -5,6 +5,8 @@
  * This code is derived from software contributed to The DragonFly Project
  * by Sascha Wildner <saw@online.de>
  *
+ * Simple font scaling code by Sascha Wildner and Matthew Dillon
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -881,7 +883,7 @@ scioctl(struct dev_ioctl_args *ap)
        vid_info_t *ptr = (vid_info_t*)data;
        if (ptr->size == sizeof(struct vid_info)) {
            ptr->m_num = sc->cur_scp->index;
-           ptr->font_size = scp->font_size;
+           ptr->font_size = scp->font_height;
            ptr->mv_col = scp->xpos;
            ptr->mv_row = scp->ypos;
            ptr->mv_csz = scp->xsize;
@@ -1441,7 +1443,7 @@ scioctl(struct dev_ioctl_args *ap)
         * Always use the font page #0. XXX
         * Don't load if the current font size is not 8x8.
         */
-       if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size < 14))
+       if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_height < 14))
            sc_load_font(sc->cur_scp, 0, 8, sc->font_8, 0, 256);
        syscons_unlock();
        lwkt_reltoken(&tty_token);
@@ -1476,8 +1478,8 @@ scioctl(struct dev_ioctl_args *ap)
         * Don't load if the current font size is not 8x14.
         */
        if (ISTEXTSC(sc->cur_scp)
-           && (sc->cur_scp->font_size >= 14)
-           && (sc->cur_scp->font_size < 16)) {
+           && (sc->cur_scp->font_height >= 14)
+           && (sc->cur_scp->font_height < 16)) {
            sc_load_font(sc->cur_scp, 0, 14, sc->font_14, 0, 256);
        }
        syscons_unlock();
@@ -1512,7 +1514,7 @@ scioctl(struct dev_ioctl_args *ap)
         * Always use the font page #0. XXX
         * Don't load if the current font size is not 8x16.
         */
-       if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_size >= 16))
+       if (ISTEXTSC(sc->cur_scp) && (sc->cur_scp->font_height >= 16))
            sc_load_font(sc->cur_scp, 0, 16, sc->font_16, 0, 256);
        syscons_unlock();
        lwkt_reltoken(&tty_token);
@@ -2741,10 +2743,10 @@ update_cursor_image(scr_stat *scp)
 
     if (scp->sc->flags & SC_CHAR_CURSOR) {
        scp->cursor_base = imax(0, scp->sc->cursor_base);
-       scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
+       scp->cursor_height = imin(scp->sc->cursor_height, scp->font_height);
     } else {
        scp->cursor_base = 0;
-       scp->cursor_height = scp->font_size;
+       scp->cursor_height = scp->font_height;
     }
     blink = scp->sc->flags & SC_BLINK_CURSOR;
 
@@ -2763,10 +2765,10 @@ sc_set_cursor_image(scr_stat *scp)
 {
     if (scp->sc->flags & SC_CHAR_CURSOR) {
        scp->cursor_base = imax(0, scp->sc->cursor_base);
-       scp->cursor_height = imin(scp->sc->cursor_height, scp->font_size);
+       scp->cursor_height = imin(scp->sc->cursor_height, scp->font_height);
     } else {
        scp->cursor_base = 0;
-       scp->cursor_height = scp->font_size;
+       scp->cursor_height = scp->font_height;
     }
 
     /* assert(scp == scp->sc->cur_scp); */
@@ -2903,12 +2905,12 @@ scinit(int unit, int flags)
        scp->xpos = col;
        scp->ypos = row;
        scp->cursor_pos = scp->cursor_oldpos = row*scp->xsize + col;
-       if (bios_value.cursor_end < scp->font_size)
-           sc->cursor_base = scp->font_size - bios_value.cursor_end - 1;
+       if (bios_value.cursor_end < scp->font_height)
+           sc->cursor_base = scp->font_height - bios_value.cursor_end - 1;
        else
            sc->cursor_base = 0;
        i = bios_value.cursor_end - bios_value.cursor_start + 1;
-       sc->cursor_height = imin(i, scp->font_size);
+       sc->cursor_height = imin(i, scp->font_height);
 #ifndef SC_NO_SYSMOUSE
        sc_mouse_move(scp, scp->xpixel/2, scp->ypixel/2);
 #endif
@@ -2926,18 +2928,18 @@ scinit(int unit, int flags)
            bcopy(dflt_font_14, sc->font_14, sizeof(dflt_font_14));
            bcopy(dflt_font_16, sc->font_16, sizeof(dflt_font_16));
            sc->fonts_loaded = FONT_16 | FONT_14 | FONT_8;
-           if (scp->font_size < 14) {
+           if (scp->font_height < 14) {
                sc_load_font(scp, 0, 8, sc->font_8, 0, 256);
-           } else if (scp->font_size >= 16) {
+           } else if (scp->font_height >= 16) {
                sc_load_font(scp, 0, 16, sc->font_16, 0, 256);
            } else {
                sc_load_font(scp, 0, 14, sc->font_14, 0, 256);
            }
 #else /* !SC_DFLT_FONT */
-           if (scp->font_size < 14) {
+           if (scp->font_height < 14) {
                sc_save_font(scp, 0, 8, sc->font_8, 0, 256);
                sc->fonts_loaded = FONT_8;
-           } else if (scp->font_size >= 16) {
+           } else if (scp->font_height >= 16) {
                sc_save_font(scp, 0, 16, sc->font_16, 0, 256);
                sc->fonts_loaded = FONT_16;
            } else {
@@ -3142,6 +3144,7 @@ static void
 init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
 {
     video_info_t info;
+    int scaled_font_height;
 
     bzero(scp, sizeof(*scp));
 
@@ -3159,29 +3162,31 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
        scp->ypixel = info.vi_height;
        scp->xsize = info.vi_width/8;
        scp->ysize = info.vi_height/info.vi_cheight;
-       scp->font_size = 0;
+       scp->font_height = 0;
+       scp->font_width = 0;
        scp->font = NULL;
     } else {
        scp->xsize = info.vi_width;
        scp->ysize = info.vi_height;
        scp->xpixel = scp->xsize*8;
        scp->ypixel = scp->ysize*info.vi_cheight;
+       scp->font_width = 8;
        if (info.vi_cheight < 14) {
-           scp->font_size = 8;
+           scp->font_height = 8;
 #ifndef SC_NO_FONT_LOADING
            scp->font = sc->font_8;
 #else
            scp->font = NULL;
 #endif
        } else if (info.vi_cheight >= 16) {
-           scp->font_size = 16;
+           scp->font_height = 16;
 #ifndef SC_NO_FONT_LOADING
            scp->font = sc->font_16;
 #else
            scp->font = NULL;
 #endif
        } else {
-           scp->font_size = 14;
+           scp->font_height = 14;
 #ifndef SC_NO_FONT_LOADING
            scp->font = sc->font_14;
 #else
@@ -3195,8 +3200,14 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
     if (scp->fbi != NULL) {
        scp->xpixel = scp->fbi->width;
        scp->ypixel = scp->fbi->height;
-       scp->xsize = scp->xpixel / 8;
-       scp->ysize = scp->ypixel / scp->font_size;
+
+       scp->blk_width = scp->xpixel / 80;
+       scaled_font_height = scp->blk_width * 100 / scp->font_width;
+       scp->blk_height = scp->ypixel * 100 / scaled_font_height;
+
+       scp->xsize = scp->xpixel / scp->blk_width;
+       scp->ysize = scp->ypixel / scp->blk_height;
+       scp->xpad = scp->fbi->stride / 4 - scp->xsize * scp->blk_width;
     }
     sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);
@@ -3207,8 +3218,8 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
     scp->rndr = NULL;
     scp->border = BG_BLACK;
     scp->cursor_base = sc->cursor_base;
-    scp->cursor_height = imin(sc->cursor_height, scp->font_size);
-    scp->mouse_cut_start = scp->xsize*scp->ysize;
+    scp->cursor_height = imin(sc->cursor_height, scp->font_height);
+    scp->mouse_cut_start = scp->xsize * scp->ysize;
     scp->mouse_cut_end = -1;
     scp->mouse_signal = 0;
     scp->mouse_pid = 0;
@@ -3701,10 +3712,10 @@ set_mode(scr_stat *scp)
     /* load appropriate font */
     if (!(scp->status & GRAPHICS_MODE)) {
        if (!(scp->status & PIXEL_MODE) && ISFONTAVAIL(scp->sc->adp->va_flags)) {
-           if (scp->font_size < 14) {
+           if (scp->font_height < 14) {
                if (scp->sc->fonts_loaded & FONT_8)
                    sc_load_font(scp, 0, 8, scp->sc->font_8, 0, 256);
-           } else if (scp->font_size >= 16) {
+           } else if (scp->font_height >= 16) {
                if (scp->sc->fonts_loaded & FONT_16)
                    sc_load_font(scp, 0, 16, scp->sc->font_16, 0, 256);
            } else {
index d9bf126..7d7a15e 100644 (file)
@@ -112,9 +112,10 @@ MALLOC_DECLARE(M_SYSCONS);
 #define        VIDEO_MEMORY_POS(scp, pos, x)                                   \
        ((scp)->sc->adp->va_window +                                    \
         (x) * (scp)->xoff +                                            \
-        (scp)->yoff * (scp)->font_size * (scp)->sc->adp->va_line_width +\
+        (scp)->yoff * (scp)->font_height * (scp)->sc->adp->va_line_width +\
         (x) * ((pos) % (scp)->xsize) +                                 \
-        (scp)->font_size * (scp)->sc->adp->va_line_width * (pos / (scp)->xsize))
+        (scp)->font_height * (scp)->sc->adp->va_line_width *           \
+        (pos / (scp)->xsize))
 #endif
 
 /* vty status flags (scp->status) */
@@ -262,12 +263,15 @@ typedef struct scr_stat {
        int             ysize;                  /* Y text size */
        int             xpixel;                 /* X graphics size */
        int             ypixel;                 /* Y graphics size */
-       int             xpad;                   /* for fbi->stride % 8 != 0 */
+       int             xpad;           /* for fbi->stride % font_width != 0 */
        int             xoff;                   /* X offset in pixel mode */
        int             yoff;                   /* Y offset in pixel mode */
 
        u_char          *font;                  /* current font */
-       int             font_size;              /* fontsize in Y direction */
+       int             font_height;            /* font source Y pixels */
+       int             font_width;             /* font source X pixels */
+       int             blk_height;             /* fbtarget Y pixels */
+       int             blk_width;              /* fbtarget X pixels */
 
        int             start;                  /* modified area start */
        int             end;                    /* modified area end */