Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic Use hardware sprite for the text mode cursor.



details:   https://anonhg.NetBSD.org/src/rev/26f1105cb3cc
branches:  trunk
changeset: 547005:26f1105cb3cc
user:      uwe <uwe%NetBSD.org@localhost>
date:      Sun May 11 03:20:09 2003 +0000

description:
Use hardware sprite for the text mode cursor.
Fail cursor related ioctls with EBUSY while in text mode.

Don't do uvm_useracc checks before copyout, instead check copyout()
return value directly.

Minor cleanups.

diffstat:

 sys/dev/ic/igsfb.c    |  184 +++++++++++++++++++++++++++++++++++++++++++++----
 sys/dev/ic/igsfbvar.h |   14 ++-
 2 files changed, 176 insertions(+), 22 deletions(-)

diffs (truncated from 350 to 300 lines):

diff -r c499dac3b64d -r 26f1105cb3cc sys/dev/ic/igsfb.c
--- a/sys/dev/ic/igsfb.c        Sun May 11 01:55:18 2003 +0000
+++ b/sys/dev/ic/igsfb.c        Sun May 11 03:20:09 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: igsfb.c,v 1.10 2003/05/10 16:20:23 uwe Exp $ */
+/*     $NetBSD: igsfb.c,v 1.11 2003/05/11 03:20:09 uwe Exp $ */
 
 /*
  * Copyright (c) 2002, 2003 Valeriy E. Ushakov
@@ -31,7 +31,7 @@
  * Integraphics Systems IGA 168x and CyberPro series.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: igsfb.c,v 1.10 2003/05/10 16:20:23 uwe Exp $");
+__KERNEL_RCSID(0, "$NetBSD: igsfb.c,v 1.11 2003/05/11 03:20:09 uwe Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -97,11 +97,21 @@
        igsfb_alloc_screen,
        igsfb_free_screen,
        igsfb_show_screen,
-       NULL /* load_font */
+       NULL,                   /* load_font */
+       NULL,                   /* pollc */
+       NULL,                   /* getwschar */
+       NULL                    /* putwschar */
 };
 
 
 /*
+ * acceleration
+ */
+static int     igsfb_make_text_cursor(struct igsfb_devconfig *);
+static void    igsfb_accel_cursor(void *, int, int, int);
+
+
+/*
  * internal functions
  */
 static int     igsfb_init_video(struct igsfb_devconfig *);
@@ -140,6 +150,8 @@
        igsfb_init_video(dc);
        igsfb_init_wsdisplay(dc);
 
+       dc->dc_nscreens = 1;
+
        ri = &dc->dc_ri;
        (*ri->ri_ops.allocattr)(ri,
                                WSCOL_BLACK, /* fg */
@@ -346,7 +358,7 @@
        /* propagate to the device */
        igsfb_update_cmap(dc, 0, IGS_CMAP_SIZE);
 
-       /* set overscan color (XXX: use defattr's background) */
+       /* set overscan color (XXX: use defattr's background?) */
        igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_RED,   0);
        igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_GREEN, 0);
        igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_BLUE,  0);
@@ -404,9 +416,21 @@
        ri->ri_wsfcookie = wsfcookie;
 
 
-       /* XXX: TODO: compute term size based on font dimensions. */
+       /* XXX: TODO: compute term size based on font dimensions? */
        rasops_init(ri, 34, 80);
 
+       /* use the sprite for the text mode cursor */
+       igsfb_make_text_cursor(dc);
+
+       /* the cursor is "busy" while we are in the text mode */
+       dc->dc_hwflags |= IGSFB_HW_TEXT_CURSOR;
+
+       /* propagate sprite data to the device */
+       igsfb_update_cursor(dc, WSDISPLAY_CURSOR_DOSHAPE);
+
+       /* override rasops default method */
+       ri->ri_ops.cursor = igsfb_accel_cursor;
+
        igsfb_stdscreen.nrows = ri->ri_rows;
        igsfb_stdscreen.ncols = ri->ri_cols;
        igsfb_stdscreen.textops = &ri->ri_ops;
@@ -415,6 +439,53 @@
 
 
 /*
+ * Init cursor data in dc_cursor for the accelerated text cursor.
+ */
+static int
+igsfb_make_text_cursor(dc)
+       struct igsfb_devconfig *dc;
+{
+       struct wsdisplay_font *f = dc->dc_ri.ri_font;
+       u_int16_t cc_scan[8];   /* one sprite scanline */
+       u_int16_t s;
+       int w, i;
+
+       KASSERT(f->fontwidth <= IGS_CURSOR_MAX_SIZE);
+       KASSERT(f->fontheight <= IGS_CURSOR_MAX_SIZE);
+
+       w = f->fontwidth;
+       for (i = 0; i < f->stride; ++i) {
+               if (w >= 8) {
+                       s = 0xffff; /* all inverted */
+                       w -= 8;
+               } else {
+                       /* first w pixels inverted, the rest is transparent */
+                       s = ~(0x5555 << (w * 2));
+                       if (IGSFB_HW_SOFT_BSWAP(dc))
+                               s = bswap16(s);
+                       w = 0;
+               }
+               cc_scan[i] = s;
+       }
+
+       dc->dc_cursor.cc_size.x = f->fontwidth;
+       dc->dc_cursor.cc_size.y = f->fontheight;
+
+       dc->dc_cursor.cc_hot.x = 0;
+       dc->dc_cursor.cc_hot.y = 0;
+
+       /* init sprite array to be all transparent */
+       memset(dc->dc_cursor.cc_sprite, 0xaa, IGS_CURSOR_DATA_SIZE);
+
+       for (i = 0; i < f->fontheight; ++i)
+               memcpy(&dc->dc_cursor.cc_sprite[i * 8],
+                      cc_scan, f->stride * sizeof(u_int16_t));
+
+       return (0);
+}
+
+
+/*
  * Spread a byte (abcd.efgh) into two (0a0b.0c0d 0e0f.0g0h).
  * Helper function for igsfb_init_bit_table().
  */
@@ -484,8 +555,13 @@
 {
        struct igsfb_devconfig *dc = v;
        struct rasops_info *ri;
+       int cursor_busy;
        int turnoff;
 
+       /* don't permit cursor ioctls if we use sprite for text cursor */
+       cursor_busy = !dc->dc_mapped
+               && (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR);
+
        switch (cmd) {
 
        case WSDISPLAYIO_GTYPE:
@@ -502,6 +578,23 @@
 #undef wsd_fbip
                return (0);
 
+       case WSDISPLAYIO_SMODE:
+#define d (*(int *)data)
+               if (d == WSDISPLAYIO_MODE_MAPPED)
+                       dc->dc_mapped = 1;
+               else {
+                       dc->dc_mapped = 0;
+                       /* reinit sprite for text cursor */
+                       if (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR) {
+                               igsfb_make_text_cursor(dc);
+                               dc->dc_curenb = 0;
+                               igsfb_update_cursor(dc,
+                                         WSDISPLAY_CURSOR_DOSHAPE
+                                       | WSDISPLAY_CURSOR_DOCUR);
+                       }
+               }
+               return (0);
+
        case WSDISPLAYIO_GVIDEO:
                *(u_int *)data = dc->dc_blanked ?
                    WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
@@ -527,17 +620,25 @@
                return (0);
 
        case WSDISPLAYIO_GCURPOS:
+               if (cursor_busy)
+                       return (EBUSY);
                *(struct wsdisplay_curpos *)data = dc->dc_cursor.cc_pos;
                return (0);
 
        case WSDISPLAYIO_SCURPOS:
+               if (cursor_busy)
+                       return (EBUSY);
                igsfb_set_curpos(dc, (struct wsdisplay_curpos *)data);
                return (0);
 
        case WSDISPLAYIO_GCURSOR:
+               if (cursor_busy)
+                       return (EBUSY);
                return (igsfb_get_cursor(dc, (struct wsdisplay_cursor *)data));
 
        case WSDISPLAYIO_SCURSOR:
+               if (cursor_busy)
+                       return (EBUSY);
                return (igsfb_set_cursor(dc, (struct wsdisplay_cursor *)data));
        }
 
@@ -570,19 +671,24 @@
        struct igsfb_devconfig *dc;
        struct wsdisplay_cmap *p;
 {
-       u_int index = p->index, count = p->count;
+       u_int index, count;
+       int err;
+
+       index = p->index;
+       count = p->count;
 
        if (index >= IGS_CMAP_SIZE || count > IGS_CMAP_SIZE - index)
                return (EINVAL);
 
-       if (!uvm_useracc(p->red, count, B_WRITE) ||
-           !uvm_useracc(p->green, count, B_WRITE) ||
-           !uvm_useracc(p->blue, count, B_WRITE))
-               return (EFAULT);
-
-       copyout(&dc->dc_cmap.r[index], p->red, count);
-       copyout(&dc->dc_cmap.g[index], p->green, count);
-       copyout(&dc->dc_cmap.b[index], p->blue, count);
+       err = copyout(&dc->dc_cmap.r[index], p->red, count);
+       if (err)
+               return (err);
+       err = copyout(&dc->dc_cmap.g[index], p->green, count);
+       if (err)
+               return (err);
+       err = copyout(&dc->dc_cmap.b[index], p->blue, count);
+       if (err)
+               return (err);
 
        return (0);
 }
@@ -597,7 +703,10 @@
        struct igsfb_devconfig *dc;
        const struct wsdisplay_cmap *p;
 {
-       u_int index = p->index, count = p->count;
+       u_int index, count;
+
+       index = p->index;
+       count = p->count;
 
        if (index >= IGS_CMAP_SIZE || count > IGS_CMAP_SIZE - index)
                return (EINVAL);
@@ -611,7 +720,8 @@
        copyin(p->green, &dc->dc_cmap.g[index], count);
        copyin(p->blue, &dc->dc_cmap.b[index], count);
 
-       igsfb_update_cmap(dc, p->index, p->count);
+       /* propagate changes to the device */
+       igsfb_update_cmap(dc, index, count);
 
        return (0);
 }
@@ -669,6 +779,7 @@
        dc->dc_cursor.cc_pos.x = x;
        dc->dc_cursor.cc_pos.y = y;
 
+       /* propagate changes to the device */
        igsfb_update_curpos(dc);
 }
 
@@ -1019,3 +1130,44 @@
        /* XXX */
        return (0);
 }
+
+
+
+/*
+ * Accelerated text mode cursor that uses hardware sprite.
+ */
+static void
+igsfb_accel_cursor(cookie, on, row, col)
+       void *cookie;
+       int on, row, col;
+{
+       struct rasops_info *ri = (struct rasops_info *)cookie;
+       struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw;
+       struct igs_hwcursor *cc = &dc->dc_cursor;
+       u_int which;
+
+       ri->ri_crow = row;
+       ri->ri_ccol = col;
+
+       which = 0;
+       if (on) {
+               ri->ri_flg |= RI_CURSOR;
+
+               /* only bother to move the cursor if it's visibile */
+               cc->cc_pos.x = ri->ri_xorigin
+                       + ri->ri_ccol * ri->ri_font->fontwidth;
+               cc->cc_pos.y = ri->ri_yorigin
+                       + ri->ri_crow * ri->ri_font->fontheight;
+               which |= WSDISPLAY_CURSOR_DOPOS;
+
+       } else
+               ri->ri_flg &= ~RI_CURSOR;



Home | Main Index | Thread Index | Old Index