Module Name:    src
Committed By:   nat
Date:           Mon Oct 17 20:04:48 UTC 2016

Modified Files:
        src/sys/dev/usb: udl.c udl.h

Log Message:
Add a kthread to update display with framebuffer contents.

X11 will now work with wsfb(4).

OK christos@


To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/sys/dev/usb/udl.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/usb/udl.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/udl.c
diff -u src/sys/dev/usb/udl.c:1.15 src/sys/dev/usb/udl.c:1.16
--- src/sys/dev/usb/udl.c:1.15	Mon Oct 17 19:58:42 2016
+++ src/sys/dev/usb/udl.c	Mon Oct 17 20:04:48 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: udl.c,v 1.15 2016/10/17 19:58:42 nat Exp $	*/
+/*	$NetBSD: udl.c,v 1.16 2016/10/17 20:04:48 nat Exp $	*/
 
 /*-
  * Copyright (c) 2009 FUKAUMI Naoki.
@@ -53,7 +53,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.15 2016/10/17 19:58:42 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.16 2016/10/17 20:04:48 nat Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -61,6 +61,8 @@ __KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.15
 #include <sys/proc.h>
 #include <sys/systm.h>
 #include <sys/kmem.h>
+#include <sys/kthread.h>
+#include <sys/condvar.h>
 #include <uvm/uvm.h>
 
 #include <sys/bus.h>
@@ -172,6 +174,7 @@ static uint16_t		udl_lfsr(uint16_t);
 static int		udl_set_resolution(struct udl_softc *,
 			    const struct videomode *);
 static const struct videomode *udl_videomode_lookup(const char *);
+static void		udl_update_thread(void *);
 
 static inline void
 udl_cmd_add_1(struct udl_softc *sc, uint8_t val)
@@ -468,6 +471,12 @@ udl_attach(device_t parent, device_t sel
 	    config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
 
 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
+
+	mutex_init(&sc->sc_thread_mtx, MUTEX_DEFAULT, IPL_NONE);
+	cv_init(&sc->sc_thread_cv, "udlcv");
+	sc->sc_dying = false;
+	kthread_create(PRI_BIO, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL,
+	    udl_update_thread, sc, &sc->sc_thread, "udlupd");
 }
 
 static int
@@ -492,9 +501,6 @@ udl_detach(device_t self, int flags)
 		usbd_close_pipe(sc->sc_tx_pipeh);
 	}
 
-	cv_destroy(&sc->sc_cv);
-	mutex_destroy(&sc->sc_mtx);
-
 	/*
 	 * Free Huffman table.
 	 */
@@ -504,6 +510,15 @@ udl_detach(device_t self, int flags)
 	 * Free framebuffer memory.
 	 */
 	udl_fbmem_free(sc);
+	
+	sc->sc_dying = true;
+	cv_broadcast(&sc->sc_thread_cv);
+	kthread_join(sc->sc_thread);
+
+	cv_destroy(&sc->sc_cv);
+	mutex_destroy(&sc->sc_mtx);
+	cv_destroy(&sc->sc_thread_cv);
+	mutex_destroy(&sc->sc_thread_mtx);
 
 	/*
 	 * Detach wsdisplay.
@@ -637,6 +652,7 @@ udl_mmap(void *v, void *vs, off_t off, i
 	if (udl_fbmem_alloc(sc) != 0)
 		return -1;
 
+	cv_broadcast(&sc->sc_thread_cv);
 	vaddr = (vaddr_t)sc->sc_fbmem + off;
 	rv = pmap_extract(pmap_kernel(), vaddr, &paddr);
 	KASSERT(rv);
@@ -810,11 +826,24 @@ static int
 udl_fbmem_alloc(struct udl_softc *sc)
 {
 
+	mutex_enter(&sc->sc_thread_mtx);
 	if (sc->sc_fbmem == NULL) {
-		sc->sc_fbmem = kmem_alloc(UDL_FBMEM_SIZE(sc), KM_SLEEP);
-		if (sc->sc_fbmem == NULL)
+		sc->sc_fbmem = kmem_zalloc(UDL_FBMEM_SIZE(sc), KM_SLEEP);
+		if (sc->sc_fbmem == NULL) {
+			mutex_exit(&sc->sc_thread_mtx);
+			return -1;
+		}
+	}
+	if (sc->sc_fbmem_prev == NULL) {
+		sc->sc_fbmem_prev = kmem_zalloc(UDL_FBMEM_SIZE(sc), KM_SLEEP);
+		if (sc->sc_fbmem_prev == NULL) {
+			kmem_free(sc->sc_fbmem, UDL_FBMEM_SIZE(sc));
+			sc->sc_fbmem = NULL;
+			mutex_exit(&sc->sc_thread_mtx);
 			return -1;
+		}
 	}
+	mutex_exit(&sc->sc_thread_mtx);
 
 	return 0;
 }
@@ -823,10 +852,16 @@ static void
 udl_fbmem_free(struct udl_softc *sc)
 {
 
+	mutex_enter(&sc->sc_thread_mtx);
 	if (sc->sc_fbmem != NULL) {
 		kmem_free(sc->sc_fbmem, UDL_FBMEM_SIZE(sc));
 		sc->sc_fbmem = NULL;
 	}
+	if (sc->sc_fbmem_prev != NULL) {
+		kmem_free(sc->sc_fbmem_prev, UDL_FBMEM_SIZE(sc));
+		sc->sc_fbmem_prev = NULL;
+	}
+	mutex_exit(&sc->sc_thread_mtx);
 }
 
 static int
@@ -1763,3 +1798,82 @@ udl_videomode_lookup(const char *name)
 
 	return NULL;
 }
+
+static void
+udl_update_thread(void *v)
+{
+	struct udl_softc *sc = v;
+	int stride;
+#ifdef notyet
+	bool update = false;
+	int linecount, x, y;
+	uint16_t *fb, *fbcopy;
+	uint8_t *curfb;
+#else
+	uint16_t *fb;
+	int offs;
+#endif
+
+	mutex_enter(&sc->sc_thread_mtx);
+
+	for (;;) {
+		stride = min(sc->sc_width, UDL_CMD_WIDTH_MAX - 8);
+		if (sc->sc_dying == true) {
+			mutex_exit(&sc->sc_thread_mtx);
+			kthread_exit(0);
+		}
+
+		if (sc->sc_fbmem == NULL)
+			goto thread_wait;
+
+#ifdef notyet
+		curfb = kmem_zalloc(UDL_FBMEM_SIZE(sc), KM_SLEEP);
+		memcpy(curfb, sc->sc_fbmem, sc->sc_height * sc->sc_width * 2);
+		fb = (uint16_t *)curfb;
+		fbcopy = (uint16_t *)sc->sc_fbmem_prev;
+		for (y = 0; y < sc->sc_height; y++) {
+			linecount = 0;
+			update = false;
+			for (x = 0; x < sc->sc_width; x++) {
+				if (linecount >= stride) {
+					udl_draw_line(sc, &fb[y * sc->sc_width
+					    + x - linecount], y * sc->sc_width
+					    + x - linecount, linecount);
+					linecount = 0;
+					update = false;
+				}
+				if (fb[y * sc->sc_width + x] ^ fbcopy[y *
+				    sc->sc_width + x]) {
+					update = true;
+					linecount ++;
+				} else if (update == true) {
+					udl_draw_line(sc, &fb[y * sc->sc_width
+					    + x - linecount], y * sc->sc_width
+					    + x - linecount, linecount);
+					linecount = 0;
+					update = false;
+				}
+			}
+			if (linecount) {
+				udl_draw_line(sc, &fb[y * sc->sc_width + x -
+				    linecount], y * sc->sc_width  + x -
+				    linecount, linecount);
+			}
+		}
+		memcpy(sc->sc_fbmem_prev, curfb, sc->sc_height * sc->sc_width
+		    * 2);
+		kmem_free(curfb, UDL_FBMEM_SIZE(sc));
+#else
+		fb = (uint16_t *)sc->sc_fbmem;
+		for (offs = 0; offs < sc->sc_height * sc->sc_width; offs += stride)
+			udl_draw_line(sc, &fb[offs], offs, stride);
+			
+#endif
+
+		kpause("udlslp", false, (40 * hz)/1000 + 1, &sc->sc_thread_mtx);
+		continue;
+
+thread_wait:
+		cv_wait(&sc->sc_thread_cv, &sc->sc_thread_mtx);
+	}
+}

Index: src/sys/dev/usb/udl.h
diff -u src/sys/dev/usb/udl.h:1.2 src/sys/dev/usb/udl.h:1.3
--- src/sys/dev/usb/udl.h:1.2	Sat Apr 23 10:15:32 2016
+++ src/sys/dev/usb/udl.h	Mon Oct 17 20:04:48 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: udl.h,v 1.2 2016/04/23 10:15:32 skrll Exp $	*/
+/*	$NetBSD: udl.h,v 1.3 2016/10/17 20:04:48 nat Exp $	*/
 
 /*-
  * Copyright (c) 2009 FUKAUMI Naoki.
@@ -108,6 +108,7 @@ struct udl_softc {
 	uint8_t			 sc_nscreens;
 
 	uint8_t			*sc_fbmem;	/* framebuffer for X11 */
+	uint8_t			*sc_fbmem_prev;	/* prev. framebuffer */
 #define UDL_FBMEM_SIZE(sc) \
     ((sc)->sc_width * (sc)->sc_height * ((sc)->sc_depth / 8))
 
@@ -115,6 +116,11 @@ struct udl_softc {
 	uint8_t			*sc_huffman_base;
 	size_t			 sc_huffman_size;
 
+	kcondvar_t		 sc_thread_cv;
+	kmutex_t		 sc_thread_mtx;
+	bool			 sc_dying;
+	lwp_t			*sc_thread;
+
 	kcondvar_t		 sc_cv;
 	kmutex_t		 sc_mtx;
 

Reply via email to