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 support for asynchronous drawing in vcons.
details: https://anonhg.NetBSD.org/src/rev/23c5912c006c
branches: trunk
changeset: 761373:23c5912c006c
user: macallan <macallan%NetBSD.org@localhost>
date: Tue Jan 25 20:28:21 2011 +0000
description:
Add support for asynchronous drawing in vcons.
This is not finished but good enough for others to play with, enable with
options VCONS_DRAW_ASYNC
With this all drawing operations will be posted to a ring buffer instead
of being run directly, and run by a kernel thread. This avoids having to wait
for drawing operations to finish with the kernel lock held ( to a degree at
least ) and scrolling a (slow) framebuffer console should not disrupt other
operations anymore.
Problems:
- we need to switch back to synchronous operations when panicing or entering
ddb, also re-enable async drawing when leaving ddb
- there are still occasional glitches
tested on an SS20 with cg14 and cg6 for dumb and accelerated cases
diffstat:
sys/dev/wscons/files.wscons | 4 +-
sys/dev/wscons/wsdisplay_vcons.c | 471 ++++++++++++++++++++++++++++++-----
sys/dev/wscons/wsdisplay_vconsvar.h | 42 ++-
3 files changed, 435 insertions(+), 82 deletions(-)
diffs (truncated from 713 to 300 lines):
diff -r d2d94546dfca -r 23c5912c006c sys/dev/wscons/files.wscons
--- a/sys/dev/wscons/files.wscons Tue Jan 25 19:13:44 2011 +0000
+++ b/sys/dev/wscons/files.wscons Tue Jan 25 20:28:21 2011 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.wscons,v 1.41 2009/08/20 02:01:08 macallan Exp $
+# $NetBSD: files.wscons,v 1.42 2011/01/25 20:28:21 macallan Exp $
#
# "Workstation Console" glue; attaches frame buffer to emulator & keyboard,
@@ -75,4 +75,4 @@
# generic virtual console support on bitmapped framebuffers
file dev/wscons/wsdisplay_vcons.c vcons
file dev/wscons/wsdisplay_vcons_util.c vcons
-defflag opt_vcons.h VCONS_SWITCH_ASYNC
+defflag opt_vcons.h VCONS_DRAW_ASYNC VCONS_ASYNC_DEBUG
diff -r d2d94546dfca -r 23c5912c006c sys/dev/wscons/wsdisplay_vcons.c
--- a/sys/dev/wscons/wsdisplay_vcons.c Tue Jan 25 19:13:44 2011 +0000
+++ b/sys/dev/wscons/wsdisplay_vcons.c Tue Jan 25 20:28:21 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wsdisplay_vcons.c,v 1.18 2010/09/21 03:33:14 macallan Exp $ */
+/* $NetBSD: wsdisplay_vcons.c,v 1.19 2011/01/25 20:28:21 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.18 2010/09/21 03:33:14 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.19 2011/01/25 20:28:21 macallan Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -42,6 +42,7 @@
#include <sys/proc.h>
#include <sys/kthread.h>
#include <sys/tprintf.h>
+#include <sys/atomic.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wscons/wsconsio.h>
@@ -78,6 +79,16 @@
static void vcons_eraserows_buffer(void *, int, int, long);
static void vcons_putchar_buffer(void *, int, int, u_int, long);
+#ifdef VCONS_DRAW_ASYNC
+/* methods that work asynchronously */
+static void vcons_copycols_async(void *, int, int, int, int);
+static void vcons_erasecols_async(void *, int, int, int, long);
+static void vcons_copyrows_async(void *, int, int, int);
+static void vcons_eraserows_async(void *, int, int, long);
+static void vcons_putchar_async(void *, int, int, u_int, long);
+static void vcons_cursor_async(void *, int, int, int);
+#endif
+
/*
* actual wrapper methods which call both the _buffer ones above and the
* driver supplied ones to do the drawing
@@ -103,7 +114,7 @@
static void vcons_lock(struct vcons_screen *);
static void vcons_unlock(struct vcons_screen *);
-#ifdef VCONS_SWITCH_ASYNC
+#ifdef VCONS_DRAW_ASYNC
static void vcons_kthread(void *);
#endif
@@ -148,9 +159,9 @@
#ifdef DIAGNOSTIC
vd->switch_poll_count = 0;
#endif
-#ifdef VCONS_SWITCH_ASYNC
+#ifdef VCONS_DRAW_ASYNC
kthread_create(PRI_NONE, 0, NULL, vcons_kthread, vd,
- &vd->redraw_thread, "vcons_draw");
+ &vd->drawing_thread, "vcons_draw");
#endif
return 0;
}
@@ -181,9 +192,6 @@
#ifdef VCONS_PARANOIA
splx(s);
#endif
-#ifdef VCONS_SWITCH_ASYNC
- wakeup(&scr->scr_vd->done_drawing);
-#endif
}
static void
@@ -223,28 +231,29 @@
* our wrappers
*/
vd->eraserows = ri->ri_ops.eraserows;
- vd->copyrows = ri->ri_ops.copyrows;
vd->erasecols = ri->ri_ops.erasecols;
- vd->copycols = ri->ri_ops.copycols;
vd->putchar = ri->ri_ops.putchar;
vd->cursor = ri->ri_ops.cursor;
+ if (scr->scr_flags & VCONS_NO_COPYCOLS) {
+ vd->copycols = vcons_copycols_noread;
+ } else {
+ vd->copycols = ri->ri_ops.copycols;
+ }
+
+ if (scr->scr_flags & VCONS_NO_COPYROWS) {
+ vd->copyrows = vcons_copyrows_noread;
+ } else {
+ vd->copyrows = ri->ri_ops.copyrows;
+ }
+
ri->ri_ops.eraserows = vcons_eraserows;
ri->ri_ops.erasecols = vcons_erasecols;
ri->ri_ops.putchar = vcons_putchar;
ri->ri_ops.cursor = vcons_cursor;
+ ri->ri_ops.copycols = vcons_copycols;
+ ri->ri_ops.copyrows = vcons_copyrows;
- if (scr->scr_flags & VCONS_NO_COPYCOLS) {
- ri->ri_ops.copycols = vcons_copycols_noread;
- } else {
- ri->ri_ops.copycols = vcons_copycols;
- }
-
- if (scr->scr_flags & VCONS_NO_COPYROWS) {
- ri->ri_ops.copyrows = vcons_copyrows_noread;
- } else {
- ri->ri_ops.copyrows = vcons_copyrows;
- }
ri->ri_hw = scr;
@@ -520,10 +529,6 @@
vd->wanted = scr;
vd->switch_cb = cb;
vd->switch_cb_arg = cb_arg;
-#ifdef VCONS_SWITCH_ASYNC
- wakeup(&vd->start_drawing);
- return EAGAIN;
-#else
if (cb) {
callout_schedule(&vd->switch_callout, 0);
return EAGAIN;
@@ -531,7 +536,6 @@
vcons_do_switch(vd);
return 0;
-#endif
}
/* wrappers for rasops_info methods */
@@ -570,7 +574,13 @@
vcons_lock(scr);
if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
- scr->scr_vd->copycols(cookie, row, srccol, dstcol, ncols);
+#ifdef VCONS_DRAW_ASYNC
+ struct vcons_data *vd = scr->scr_vd;
+ if (vd->use_async) {
+ vcons_copycols_async(cookie, row, srccol, dstcol, ncols);
+ } else
+#endif
+ scr->scr_vd->copycols(cookie, row, srccol, dstcol, ncols);
}
vcons_unlock(scr);
}
@@ -581,9 +591,6 @@
struct rasops_info *ri = cookie;
struct vcons_screen *scr = ri->ri_hw;
- vcons_copycols_buffer(cookie, row, srccol, dstcol, ncols);
-
- vcons_lock(scr);
if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
int pos, c, offset;
@@ -599,7 +606,6 @@
pos++;
}
}
- vcons_unlock(scr);
}
static void
@@ -636,8 +642,15 @@
vcons_lock(scr);
if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
- scr->scr_vd->erasecols(cookie, row, startcol, ncols,
- fillattr);
+#ifdef VCONS_DRAW_ASYNC
+ struct vcons_data *vd = scr->scr_vd;
+ if (vd->use_async) {
+ vcons_erasecols_async(cookie, row, startcol, ncols,
+ fillattr);
+ } else
+#endif
+ scr->scr_vd->erasecols(cookie, row, startcol, ncols,
+ fillattr);
}
vcons_unlock(scr);
}
@@ -688,7 +701,13 @@
vcons_lock(scr);
if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
- scr->scr_vd->copyrows(cookie, srcrow, dstrow, nrows);
+#ifdef VCONS_DRAW_ASYNC
+ struct vcons_data *vd = scr->scr_vd;
+ if (vd->use_async) {
+ vcons_copyrows_async(cookie, srcrow, dstrow, nrows);
+ } else
+#endif
+ scr->scr_vd->copyrows(cookie, srcrow, dstrow, nrows);
}
vcons_unlock(scr);
}
@@ -699,9 +718,6 @@
struct rasops_info *ri = cookie;
struct vcons_screen *scr = ri->ri_hw;
- vcons_copyrows_buffer(cookie, srcrow, dstrow, nrows);
-
- vcons_lock(scr);
if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
int pos, l, c, offset;
@@ -719,7 +735,6 @@
}
}
}
- vcons_unlock(scr);
}
static void
@@ -756,7 +771,13 @@
vcons_lock(scr);
if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
- scr->scr_vd->eraserows(cookie, row, nrows, fillattr);
+#ifdef VCONS_DRAW_ASYNC
+ struct vcons_data *vd = scr->scr_vd;
+ if (vd->use_async) {
+ vcons_eraserows_async(cookie, row, nrows, fillattr);
+ } else
+#endif
+ scr->scr_vd->eraserows(cookie, row, nrows, fillattr);
}
vcons_unlock(scr);
}
@@ -798,7 +819,13 @@
vcons_lock(scr);
if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
- scr->scr_vd->putchar(cookie, row, col, c, attr);
+#ifdef VCONS_DRAW_ASYNC
+ struct vcons_data *vd = scr->scr_vd;
+ if (vd->use_async) {
+ vcons_putchar_async(cookie, row, col, c, attr);
+ } else
+#endif
+ scr->scr_vd->putchar(cookie, row, col, c, attr);
}
vcons_unlock(scr);
}
@@ -811,7 +838,13 @@
vcons_lock(scr);
if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
- scr->scr_vd->cursor(cookie, on, row, col);
+#ifdef VCONS_DRAW_ASYNC
+ struct vcons_data *vd = scr->scr_vd;
+ if (vd->use_async) {
+ vcons_cursor_async(cookie, on, row, col);
+ } else
+#endif
+ scr->scr_vd->cursor(cookie, on, row, col);
} else {
scr->scr_ri.ri_crow = row;
scr->scr_ri.ri_ccol = col;
@@ -967,46 +1000,334 @@
/* async drawing using a kernel thread */
-#ifdef VCONS_SWITCH_ASYNC
+#ifdef VCONS_DRAW_ASYNC
+
+static inline uint32_t
+vcons_words_in_buffer(struct vcons_data *vd)
+{
+ int len = vd->rb_write - vd->rb_read;
+
+ if (len < 0) len += VCONS_RING_BUFFER_LENGTH;
+ if (len < 0) vd->use_async = 0;
+ if (len >= VCONS_RING_BUFFER_LENGTH) vd->use_async = 0;
+ return (uint32_t)len;
+}
+
+static inline int
+vcons_wait_buffer(struct vcons_data *vd, uint32_t words)
Home |
Main Index |
Thread Index |
Old Index