Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/wscons add a cache so when we update the screen we o...



details:   https://anonhg.NetBSD.org/src/rev/3ee202c2e2ef
branches:  trunk
changeset: 765397:3ee202c2e2ef
user:      macallan <macallan%NetBSD.org@localhost>
date:      Wed May 25 06:01:38 2011 +0000

description:
add a cache so when we update the screen we only redraw the character cells
that actually changed since last time. This gives a noticeable speedup on
slower hardware with dumb framebuffers.
For now this works with VCONS_DRAW_INTR and VCONS_DONT_READ only.

diffstat:

 sys/dev/wscons/wsdisplay_vcons.c      |  224 ++++++++++++++++++++++++++++++---
 sys/dev/wscons/wsdisplay_vcons_util.c |    6 +-
 sys/dev/wscons/wsdisplay_vconsvar.h   |   15 ++-
 3 files changed, 221 insertions(+), 24 deletions(-)

diffs (truncated from 466 to 300 lines):

diff -r 5d563af1a46e -r 3ee202c2e2ef sys/dev/wscons/wsdisplay_vcons.c
--- a/sys/dev/wscons/wsdisplay_vcons.c  Wed May 25 05:42:37 2011 +0000
+++ b/sys/dev/wscons/wsdisplay_vcons.c  Wed May 25 06:01:38 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wsdisplay_vcons.c,v 1.24 2011/02/18 13:56:11 jmcneill Exp $ */
+/*     $NetBSD: wsdisplay_vcons.c,v 1.25 2011/05/25 06:01:38 macallan Exp $ */
 
 /*-
  * Copyright (c) 2005, 2006 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.24 2011/02/18 13:56:11 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.25 2011/05/25 06:01:38 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -102,6 +102,9 @@
 static void vcons_copyrows(void *, int, int, int);
 static void vcons_eraserows(void *, int, int, long);
 static void vcons_putchar(void *, int, int, u_int, long);
+#ifdef VCONS_DRAW_INTR
+static void vcons_putchar_cached(void *, int, int, u_int, long);
+#endif
 static void vcons_cursor(void *, int, int, int);
 
 /*
@@ -159,6 +162,12 @@
        vd->currenttype = def;
        callout_init(&vd->switch_callout, 0);
        callout_setfunc(&vd->switch_callout, vcons_do_switch, vd);
+#ifdef VCONS_DRAW_INTR
+       vd->cells = 0;
+       vd->attrs = NULL;
+       vd->chars = NULL;
+       vd->cursor_offset = -1;
+#endif
 
        /*
         * a lock to serialize access to the framebuffer.
@@ -234,6 +243,9 @@
 {
        struct rasops_info *ri = &scr->scr_ri;
        int cnt, i;
+#ifdef VCONS_DRAW_INTR
+       int size;
+#endif
 
        scr->scr_cookie = vd->cookie;
        scr->scr_vd = scr->scr_origvd = vd;
@@ -313,6 +325,18 @@
                scr->scr_chars[i] = 0x20;
        }
 
+#ifdef VCONS_DRAW_INTR
+       size = ri->ri_cols * ri->ri_rows;
+       if (size > vd->cells) {
+               if (vd->chars != NULL) free(vd->chars, M_DEVBUF);
+               if (vd->attrs != NULL) free(vd->attrs, M_DEVBUF);
+               vd->cells = size;
+               vd->chars = malloc(size * sizeof(uint16_t), M_DEVBUF, M_WAITOK);
+               vd->attrs = malloc(size * sizeof(long), M_DEVBUF, M_WAITOK);
+               vcons_invalidate_cache(vd);
+       }
+#endif
+
        if(vd->active == NULL) {
                vd->active = scr;
                SCREEN_VISIBLE(scr);
@@ -402,7 +426,8 @@
        uint16_t *charptr = scr->scr_chars;
        long *attrptr = scr->scr_attrs;
        struct rasops_info *ri = &scr->scr_ri;
-       int i, j, offset;
+       struct vcons_data *vd = scr->scr_vd;
+       int i, j, offset, boffset = 0;
 
        vcons_lock(scr);
        if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
@@ -412,7 +437,7 @@
                 * going to overwrite every single character cell anyway
                 */
                if (ri->ri_flg & RI_FULLCLEAR) {
-                       scr->scr_vd->eraserows(ri, 0, ri->ri_rows,
+                       vd->eraserows(ri, 0, ri->ri_rows,
                            scr->scr_defattr);
                }
 
@@ -430,17 +455,80 @@
                                 * and we already made sure the screen we're
                                 * working on is visible
                                 */
-                               scr->scr_vd->putchar(ri, i, j, 
+                               vd->putchar(ri, i, j, 
                                    charptr[offset], attrptr[offset]);
+#ifdef VCONS_DRAW_INTR
+                               vd->chars[boffset] = charptr[offset];
+                               vd->attrs[boffset] = attrptr[offset];
+#endif
                                offset++;
+                               boffset++;
                        }
                }
                ri->ri_flg &= ~RI_CURSOR;
                scr->scr_vd->cursor(ri, 1, ri->ri_crow, ri->ri_ccol);
+#ifdef VCONS_DRAW_INTR
+               vd->cursor_offset = ri->ri_crow * ri->ri_cols + ri->ri_ccol;
+#endif
        }
        vcons_unlock(scr);
 }
 
+#ifdef VCONS_DRAW_INTR
+void
+vcons_update_screen(struct vcons_screen *scr)
+{
+       uint16_t *charptr = scr->scr_chars;
+       long *attrptr = scr->scr_attrs;
+       struct rasops_info *ri = &scr->scr_ri;
+       struct vcons_data *vd = scr->scr_vd;
+       int i, j, offset, boffset = 0;
+
+       vcons_lock(scr);
+       if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
+
+               /* redraw the screen */
+#ifdef WSDISPLAY_SCROLLSUPPORT
+               offset = scr->scr_current_offset;
+#else
+               offset = 0;
+#endif
+               /*
+                * we mark the character cell occupied by the cursor as dirty
+                * so we don't have to deal with it
+                * notice that this isn't necessarily the position where rasops
+                * thinks it is, just where we drew it the last time
+                */
+               if (vd->cursor_offset >= 0)
+                       vd->attrs[vd->cursor_offset] = 0xffffffff;
+
+               for (i = 0; i < ri->ri_rows; i++) {
+                       for (j = 0; j < ri->ri_cols; j++) {
+                               /*
+                                * no need to use the wrapper function - we 
+                                * don't change any characters or attributes
+                                * and we already made sure the screen we're
+                                * working on is visible
+                                */
+                               if ((vd->chars[boffset] != charptr[offset]) ||
+                                   (vd->attrs[boffset] != attrptr[offset])) {
+                                       vd->putchar(ri, i, j, 
+                                          charptr[offset], attrptr[offset]);
+                                       vd->chars[boffset] = charptr[offset];
+                                       vd->attrs[boffset] = attrptr[offset];
+                               }
+                               offset++;
+                               boffset++;
+                       }
+               }
+               ri->ri_flg &= ~RI_CURSOR;
+               scr->scr_vd->cursor(ri, 1, ri->ri_crow, ri->ri_ccol);
+               vd->cursor_offset = ri->ri_crow * ri->ri_cols + ri->ri_ccol;
+       }
+       vcons_unlock(scr);
+}
+#endif
+
 static int
 vcons_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
        struct lwp *l)
@@ -618,20 +706,33 @@
 {
        struct rasops_info *ri = cookie;
        struct vcons_screen *scr = ri->ri_hw;
+       struct vcons_data *vd = scr->scr_vd;
 
        if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
-               int pos, c, offset;
+               int pos, c, offset, ppos;
 
 #ifdef WSDISPLAY_SCROLLSUPPORT
                offset = scr->scr_current_offset;
 #else
                offset = 0;
 #endif
-               pos = ri->ri_cols * row + dstcol + offset;
+               ppos = ri->ri_cols * row + dstcol;
+               pos = ppos + offset;
                for (c = dstcol; c < (dstcol + ncols); c++) {
-                       scr->scr_vd->putchar(cookie, row, c, 
-                          scr->scr_chars[pos], scr->scr_attrs[pos]);
+#ifdef VCONS_DRAW_INTR
+                       if ((scr->scr_chars[pos] != vd->chars[ppos]) ||
+                           (scr->scr_attrs[pos] != vd->attrs[ppos])) {
+                               vd->putchar(cookie, row, c, 
+                                  scr->scr_chars[pos], scr->scr_attrs[pos]);
+                               vd->chars[ppos] = scr->scr_chars[pos];
+                               vd->attrs[ppos] = scr->scr_attrs[pos];
+                       }
+#else
+                       vd->putchar(cookie, row, c, scr->scr_chars[pos],
+                           scr->scr_attrs[pos]);
+#endif
                        pos++;
+                       ppos++;
                }
        }
 }
@@ -664,6 +765,23 @@
 #endif
 }
 
+#ifdef VCONS_DRAW_INTR
+static void
+vcons_erasecols_cached(void *cookie, int row, int startcol, int ncols, long fillattr)
+{
+       struct rasops_info *ri = cookie;
+       struct vcons_screen *scr = ri->ri_hw;
+       struct vcons_data *vd = scr->scr_vd;
+       int i, pos = row * ri->ri_cols + startcol;
+
+       for (i = pos; i < ncols; i++) {
+               vd->chars[i] = 0x20;
+               vd->attrs[i] = fillattr;
+       }
+       vd->erasecols(cookie, row, startcol, ncols, fillattr);
+}
+#endif
+
 static void
 vcons_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
 {
@@ -686,8 +804,12 @@
                            fillattr);
                } else
 #endif
-                       scr->scr_vd->erasecols(cookie, row, startcol, ncols, 
+#ifdef VCONS_DRAW_INTR
+                       vcons_erasecols_cached(cookie, row, startcol, ncols, 
                            fillattr);
+#else
+               scr->scr_vd->erasecols(cookie, row, startcol, ncols, fillattr);
+#endif 
        }
        vcons_unlock(scr);
 }
@@ -763,21 +885,36 @@
 {
        struct rasops_info *ri = cookie;
        struct vcons_screen *scr = ri->ri_hw;
+       struct vcons_data *vd = scr->scr_vd;
+       int dist;
 
        if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
-               int pos, l, c, offset;
+               int pos, l, c, offset, ppos;
 
 #ifdef WSDISPLAY_SCROLLSUPPORT
                offset = scr->scr_current_offset;
 #else
                offset = 0;
 #endif
-               pos = ri->ri_cols * dstrow + offset;
+               dist = (dstrow - srcrow) * ri->ri_cols;
+               ppos = ri->ri_cols * dstrow;
+               pos = ppos + offset;
                for (l = dstrow; l < (dstrow + nrows); l++) {
                        for (c = 0; c < ri->ri_cols; c++) {
-                               scr->scr_vd->putchar(cookie, l, c, 
-                                  scr->scr_chars[pos], scr->scr_attrs[pos]);
+#ifdef VCONS_DRAW_INTR
+                               if ((scr->scr_chars[pos] != vd->chars[ppos]) ||
+                                   (scr->scr_attrs[pos] != vd->attrs[ppos])) {
+                                       vd->putchar(cookie, l, c, 
+                                          scr->scr_chars[pos], scr->scr_attrs[pos]);
+                                       vd->chars[ppos] = scr->scr_chars[pos];
+                                       vd->attrs[ppos] = scr->scr_attrs[pos];
+                               }
+#else
+                               vd->putchar(cookie, l, c, scr->scr_chars[pos],
+                                   scr->scr_attrs[pos]);
+#endif
                                pos++;
+                               ppos++;
                        }
                }
        }
@@ -832,7 +969,7 @@
                        vcons_eraserows_async(cookie, row, nrows, fillattr);
                } else
 #endif
-                       scr->scr_vd->eraserows(cookie, row, nrows, fillattr);
+               scr->scr_vd->eraserows(cookie, row, nrows, fillattr);
        }
        vcons_unlock(scr);
 }
@@ -868,6 +1005,27 @@
 #endif
 }



Home | Main Index | Thread Index | Old Index