Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci rework putchar():



details:   https://anonhg.NetBSD.org/src/rev/5e4d4bf8ce03
branches:  trunk
changeset: 772316:5e4d4bf8ce03
user:      macallan <macallan%NetBSD.org@localhost>
date:      Thu Dec 29 20:14:39 2011 +0000

description:
rework putchar():
- get rid of engine stalls when using the blitter to draw characters
- add a wrapper for non-accelerated putchar() so we only wait for the
  engine when we actually want to scribble into video memory
- rework accelerated putchar(), should work on R3xx now but needs testing

diffstat:

 sys/dev/pci/radeonfb.c |  234 ++++++++++++++++++++++--------------------------
 1 files changed, 109 insertions(+), 125 deletions(-)

diffs (truncated from 352 to 300 lines):

diff -r 2f95a232bd41 -r 5e4d4bf8ce03 sys/dev/pci/radeonfb.c
--- a/sys/dev/pci/radeonfb.c    Thu Dec 29 20:09:14 2011 +0000
+++ b/sys/dev/pci/radeonfb.c    Thu Dec 29 20:14:39 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: radeonfb.c,v 1.47 2011/12/29 20:09:14 macallan Exp $ */
+/*     $NetBSD: radeonfb.c,v 1.48 2011/12/29 20:14:39 macallan Exp $ */
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.47 2011/12/29 20:09:14 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: radeonfb.c,v 1.48 2011/12/29 20:14:39 macallan Exp $");
 
 #define RADEONFB_DEFAULT_DEPTH 8
 
@@ -99,6 +99,7 @@
 #include <dev/pci/radeonfbreg.h>
 #include <dev/pci/radeonfbvar.h>
 #include "opt_radeonfb.h"
+#include "opt_vcons.h"
 
 static int radeonfb_match(device_t, cfdata_t, void *);
 static void radeonfb_attach(device_t, device_t, void *);
@@ -140,9 +141,6 @@
     int width, int height, uint32_t color);
 static void radeonfb_bitblt(struct radeonfb_display *, int srcx, int srcy,
     int dstx, int dsty, int width, int height, int rop, uint32_t mask);
-static void radeonfb_feed_bytes(struct radeonfb_display *, int, uint8_t *);
-static void radeonfb_setup_mono(struct radeonfb_display *, int, int, int,
-    int, uint32_t, uint32_t);
 
 /* hw cursor support */
 static void radeonfb_cursor_cmap(struct radeonfb_display *);
@@ -1080,6 +1078,11 @@
                return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc,
                    sc->sc_pt, d);
 
+       case WSDISPLAYIO_GET_EDID: {
+               struct wsdisplayio_edid_info *ei = d;
+               return wsdisplayio_get_edid(sc->sc_dev, ei);
+       }
+
        default:
                return EPASSTHROUGH;
        }
@@ -2161,6 +2164,10 @@
        ri->ri_flg = RI_CENTER;
        ri->ri_bits = (void *)dp->rd_fbptr;
 
+#ifdef VCONS_DRAW_INTR
+       scr->scr_flags |= VCONS_DONT_READ;
+#endif
+
        /* XXX: 32 bpp only */
        /* this is rgb in "big-endian order..." */
        ri->ri_rnum = 8;
@@ -2196,10 +2203,15 @@
        ri->ri_ops.eraserows = radeonfb_eraserows;
        ri->ri_ops.erasecols = radeonfb_erasecols;
        ri->ri_ops.allocattr = radeonfb_allocattr;
-       if (!IS_R300(dp->rd_softc)) {
+       if (IS_R300(dp->rd_softc)) {
+               /*
+                * radeonfb_putchar() doesn't work right on some R3xx
+                * so we use software drawing here, the wrapper just makes
+                * sure the engine is idle before scribbling into vram
+                */
+               ri->ri_ops.putchar = radeonfb_putchar_wrapper;
+       } else {
                ri->ri_ops.putchar = radeonfb_putchar;
-       } else {
-               ri->ri_ops.putchar = radeonfb_putchar_wrapper;
        }
        ri->ri_ops.cursor = radeonfb_cursor;
 }
@@ -2380,10 +2392,15 @@
        struct rasops_info      *ri = cookie;
        struct vcons_screen     *scr = ri->ri_hw;
        struct radeonfb_display *dp = scr->scr_cookie;
+       struct radeonfb_softc   *sc = dp->rd_softc;
        struct wsdisplay_font   *font = PICK_FONT(ri, c);
-       uint32_t                x, y, w, h;
-       uint32_t                bg, fg, flg;
-       uint8_t                 *data;
+       uint32_t                w, h;
+       int                     xd, yd, offset, i;
+       uint32_t                bg, fg, gmc;
+       uint32_t                reg;
+       uint8_t                 *data8;
+       uint16_t                *data16;
+       void                    *data;
 
        if (dp->rd_wsmode != WSDISPLAYIO_MODE_EMUL)
                return;
@@ -2394,26 +2411,67 @@
        w = font->fontwidth;
        h = font->fontheight;
 
-       flg = attr & 0xff;
-       if (flg & WSATTR_REVERSE) {
-               fg = ri->ri_devcmap[(attr >> 16) & 0xf];
-               bg = ri->ri_devcmap[(attr >> 24) & 0xf];
-       } else {
-               bg = ri->ri_devcmap[(attr >> 16) & 0xf];
-               fg = ri->ri_devcmap[(attr >> 24) & 0xf];
-       }
-
-       x = ri->ri_xorigin + col * w;
-       y = ri->ri_yorigin + row * h;
+       bg = ri->ri_devcmap[(attr >> 16) & 0xf];
+       fg = ri->ri_devcmap[(attr >> 24) & 0xf];
+
+       xd = ri->ri_xorigin + col * w;
+       yd = ri->ri_yorigin + row * h;
 
        if (c == 0x20) {
-               radeonfb_rectfill(dp, x, y, w, h, bg);
-       } else {
-               data = (uint8_t *)font->data +
-                   (c - font->firstchar) * ri->ri_fontscale;
-
-               radeonfb_setup_mono(dp, x, y, w, h, fg, bg);
-               radeonfb_feed_bytes(dp, ri->ri_fontscale, data);
+               radeonfb_rectfill(dp, xd, yd, w, h, bg);
+               return;
+       }
+       data = (uint8_t *)font->data + (c - font->firstchar) * ri->ri_fontscale;
+
+       gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT;
+
+       radeonfb_wait_fifo(sc, 9);
+       
+       PUT32(sc, RADEON_DP_GUI_MASTER_CNTL,
+           RADEON_GMC_BRUSH_NONE |
+           RADEON_GMC_SRC_DATATYPE_MONO_FG_BG |
+           RADEON_GMC_DST_CLIPPING |
+           RADEON_ROP3_S |
+           RADEON_DP_SRC_SOURCE_HOST_DATA |
+           RADEON_GMC_CLR_CMP_CNTL_DIS |
+           RADEON_GMC_WR_MSK_DIS |
+           gmc);
+
+       PUT32(sc, RADEON_SC_LEFT, xd);
+       PUT32(sc, RADEON_SC_RIGHT, xd + w);
+       PUT32(sc, RADEON_DP_SRC_FRGD_CLR, fg);
+       PUT32(sc, RADEON_DP_SRC_BKGD_CLR, bg);
+       PUT32(sc, RADEON_DP_CNTL,
+           RADEON_DST_X_LEFT_TO_RIGHT |
+           RADEON_DST_Y_TOP_TO_BOTTOM);
+
+       PUT32(sc, RADEON_SRC_X_Y, 0);
+       offset = 32 - (font->stride << 3);
+       PUT32(sc, RADEON_DST_X_Y, ((xd - offset) << 16) | yd);
+       PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (32 << 16) | h);
+
+       radeonfb_wait_fifo(sc, h);
+       switch (font->stride) {
+               case 1: {
+                       data8 = data;
+                       for (i = 0; i < h; i++) {
+                               reg = *data8;
+                               bus_space_write_stream_4(sc->sc_regt,
+                                   sc->sc_regh, RADEON_HOST_DATA0, reg);
+                               data8++;
+                       }
+                       break;
+               }
+               case 2: {
+                       data16 = data;
+                       for (i = 0; i < h; i++) {
+                               reg = *data16;
+                               bus_space_write_stream_4(sc->sc_regt,
+                                   sc->sc_regh, RADEON_HOST_DATA0, reg);
+                               data16++;
+                       }
+                       break;
+               }
        }
 }
 
@@ -2562,72 +2620,6 @@
 /*
  * Underlying acceleration support.
  */
-static void
-radeonfb_setup_mono(struct radeonfb_display *dp, int xd, int yd, int width,
-    int height, uint32_t fg, uint32_t bg)
-{
-       struct radeonfb_softc   *sc = dp->rd_softc;
-       uint32_t                gmc;
-       uint32_t                padded_width = (width+7) & 0xfff8;
-       uint32_t                topleft, bottomright;
-       
-       gmc = dp->rd_format << RADEON_GMC_DST_DATATYPE_SHIFT;
-
-       if (width != padded_width) {
-
-               radeonfb_wait_fifo(sc, 2);
-               topleft = ((yd << 16) & 0x1fff0000) | (xd & 0x1fff);
-               bottomright = (((yd + height) << 16) & 0x1fff0000) | 
-                   ((xd + width) & 0x1fff);
-               PUT32(sc, RADEON_SC_TOP_LEFT, topleft);
-               PUT32(sc, RADEON_SC_BOTTOM_RIGHT, bottomright);
-       }
-
-       radeonfb_wait_fifo(sc, 5);
-       
-       PUT32(sc, RADEON_DP_GUI_MASTER_CNTL,
-           RADEON_GMC_BRUSH_NONE |
-           RADEON_GMC_SRC_DATATYPE_MONO_FG_BG |
-           //RADEON_GMC_BYTE_LSB_TO_MSB |
-           RADEON_GMC_DST_CLIPPING |
-           RADEON_ROP3_S |
-           RADEON_DP_SRC_SOURCE_HOST_DATA |
-           RADEON_GMC_CLR_CMP_CNTL_DIS |
-           RADEON_GMC_WR_MSK_DIS |
-           gmc);
-
-       PUT32(sc, RADEON_DP_SRC_FRGD_CLR, fg);
-       PUT32(sc, RADEON_DP_SRC_BKGD_CLR, bg);
-
-       PUT32(sc, RADEON_DST_X_Y, (xd << 16) | yd);
-       PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (padded_width << 16) | height);
-       
-}
-
-static void
-radeonfb_feed_bytes(struct radeonfb_display *dp, int count, uint8_t *data)
-{
-       struct radeonfb_softc   *sc = dp->rd_softc;
-       int i;
-       uint32_t latch = 0;
-       int shift = 0;
-       
-       for (i = 0; i < count; i++) {
-               latch |= (data[i] << shift);
-               if (shift == 24) {
-                       radeonfb_wait_fifo(sc, 1);
-                       PUT32(sc, RADEON_HOST_DATA0, latch);
-                       latch = 0;
-                       shift = 0;
-               } else
-                       shift += 8;
-       }
-       if (shift != 0) {
-               radeonfb_wait_fifo(sc, 1);
-               PUT32(sc, RADEON_HOST_DATA0, latch);
-       }
-       radeonfb_unclip(sc);
-}
 
 static void
 radeonfb_rectfill(struct radeonfb_display *dp, int dstx, int dsty,
@@ -2654,12 +2646,6 @@
        PUT32(sc, RADEON_DST_Y_X, (dsty << 16) | dstx);
        PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (width << 16) | (height));
 
-       /*
-        * XXX: we don't wait for the fifo to empty -- that would slow
-        * things down!  The linux radeonfb driver waits, but xfree doesn't
-        */
-       /* XXX: for now we do, to make it safe for direct drawing */
-       radeonfb_engine_idle(sc);
 }
 
 static void
@@ -2701,28 +2687,16 @@
        PUT32(sc, RADEON_SRC_Y_X, (srcy << 16) | srcx);
        PUT32(sc, RADEON_DST_Y_X, (dsty << 16) | dstx);
        PUT32(sc, RADEON_DST_WIDTH_HEIGHT, (width << 16) | (height));
-
-       /*
-        * XXX: we don't wait for the fifo to empty -- that would slow
-        * things down!  The linux radeonfb driver waits, but xfree doesn't
-        */
-       /* XXX: for now we do, to make it safe for direct drawing */
-       radeonfb_engine_idle(sc);
 }
 
 static void
 radeonfb_engine_idle(struct radeonfb_softc *sc)
 {
-       int     i;
 
        radeonfb_wait_fifo(sc, 64);
-       for (i = RADEON_TIMEOUT; i; i--) {
-               if ((GET32(sc, RADEON_RBBM_STATUS) &
-                       RADEON_RBBM_ACTIVE) == 0) {
-                       radeonfb_engine_flush(sc);
-                       break;
-               }
-       }
+       while ((GET32(sc, RADEON_RBBM_STATUS) &
+                       RADEON_RBBM_ACTIVE) != 0);
+       radeonfb_engine_flush(sc);
 }
 



Home | Main Index | Thread Index | Old Index