Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Add a kthread to update display with framebuffer...



details:   https://anonhg.NetBSD.org/src/rev/a08427144e2c
branches:  trunk
changeset: 818546:a08427144e2c
user:      nat <nat%NetBSD.org@localhost>
date:      Mon Oct 17 20:04:48 2016 +0000

description:
Add a kthread to update display with framebuffer contents.

X11 will now work with wsfb(4).

OK christos@

diffstat:

 sys/dev/usb/udl.c |  128 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 sys/dev/usb/udl.h |    8 ++-
 2 files changed, 128 insertions(+), 8 deletions(-)

diffs (238 lines):

diff -r 76a3d884f001 -r a08427144e2c sys/dev/usb/udl.c
--- a/sys/dev/usb/udl.c Mon Oct 17 20:00:25 2016 +0000
+++ b/sys/dev/usb/udl.c Mon Oct 17 20:04:48 2016 +0000
@@ -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 @@
 #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 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 @@
            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 @@
                usbd_close_pipe(sc->sc_tx_pipeh);
        }
 
-       cv_destroy(&sc->sc_cv);
-       mutex_destroy(&sc->sc_mtx);
-
        /*
         * Free Huffman table.
         */
@@ -504,6 +510,15 @@
         * 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 @@
        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 @@
 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 @@
 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 @@
 
        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);
+       }
+}
diff -r 76a3d884f001 -r a08427144e2c sys/dev/usb/udl.h
--- a/sys/dev/usb/udl.h Mon Oct 17 20:00:25 2016 +0000
+++ b/sys/dev/usb/udl.h Mon Oct 17 20:04:48 2016 +0000
@@ -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 @@
        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 @@
        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;
 



Home | Main Index | Thread Index | Old Index