summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2013-04-14 19:04:37 +0000
committerkettenis <kettenis@openbsd.org>2013-04-14 19:04:37 +0000
commit12e1fe1166061bf8678840ec0862fa2b2ebd2330 (patch)
tree3b716b12d26c2c504d91eeea27c113760e8905bc
parentBe sure to turn hsync/vsync back on at crt enable (v2) (diff)
downloadwireguard-openbsd-12e1fe1166061bf8678840ec0862fa2b2ebd2330.tar.xz
wireguard-openbsd-12e1fe1166061bf8678840ec0862fa2b2ebd2330.zip
Take a different approach towards framebuffer accelartion. Instead of using
the blitter, scroll by double-mapping the framebuffer and reprogramming the registers that determine the first visible pixel, much in the same way as the vga text console uses the 6845. This makes scrolling very fast, and since we no longer need to issue commands to any of the rings, we can enable this when X is running and safely scroll when printing panic messages or if we've entered ddb. Testes by many.
-rw-r--r--sys/dev/pci/agpvar.h3
-rw-r--r--sys/dev/pci/drm/drm_drv.c18
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c231
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.h9
-rw-r--r--sys/dev/pci/drm/i915/intel_fb.c5
5 files changed, 62 insertions, 204 deletions
diff --git a/sys/dev/pci/agpvar.h b/sys/dev/pci/agpvar.h
index 556d019d250..8e1eda3a271 100644
--- a/sys/dev/pci/agpvar.h
+++ b/sys/dev/pci/agpvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: agpvar.h,v 1.26 2013/03/18 12:02:56 jsg Exp $ */
+/* $OpenBSD: agpvar.h,v 1.27 2013/04/14 19:04:37 kettenis Exp $ */
/* $NetBSD: agpvar.h,v 1.4 2001/10/01 21:54:48 fvdl Exp $ */
/*-
@@ -47,6 +47,7 @@
#define BUS_DMA_GTT_NOCACHE (1 << 30)
#define BUS_DMA_GTT_CACHE_LLC (1 << 29)
#define BUS_DMA_GTT_CACHE_LLC_MLC (1 << 28)
+#define BUS_DMA_GTT_WRAPAROUND (1 << 27)
struct agp_attach_args {
char *aa_busname;
diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c
index 45dd52488e4..7b5d7cf97c9 100644
--- a/sys/dev/pci/drm/drm_drv.c
+++ b/sys/dev/pci/drm/drm_drv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: drm_drv.c,v 1.103 2013/04/10 01:35:55 guenther Exp $ */
+/* $OpenBSD: drm_drv.c,v 1.104 2013/04/14 19:04:37 kettenis Exp $ */
/*-
* Copyright 2007-2009 Owain G. Ainsworth <oga@openbsd.org>
* Copyright © 2008 Intel Corporation
@@ -1707,6 +1707,22 @@ drm_gem_load_uao(bus_dma_tag_t dmat, bus_dmamap_t map, struct uvm_object *uao,
if ((ret = bus_dmamap_load_raw(dmat, map, segs, i, size, flags)) != 0)
goto unwire;
+ /*
+ * Create a mapping that wraps around once; the second half
+ * maps to the same set of physical pages as the first half.
+ * Used to implement fast vertical scrolling in inteldrm(4).
+ *
+ * XXX This is an ugly hack that wastes pages and abuses the
+ * internals of the scatter gather DMA code.
+ */
+ if (flags & BUS_DMA_GTT_WRAPAROUND) {
+ struct sg_page_map *spm = map->_dm_cookie;
+
+ for (i = spm->spm_pagecnt / 2; i < spm->spm_pagecnt; i++)
+ spm->spm_map[i].spe_pa = spm->spm_map[i - spm->spm_pagecnt / 2].spe_pa;
+ agp_bus_dma_rebind(dmat, map, flags);
+ }
+
*segp = segs;
return (0);
diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c
index 839f06c1f92..6683df9ea51 100644
--- a/sys/dev/pci/drm/i915/i915_drv.c
+++ b/sys/dev/pci/drm/i915/i915_drv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.c,v 1.17 2013/04/05 02:54:51 jsg Exp $ */
+/* $OpenBSD: i915_drv.c,v 1.18 2013/04/14 19:04:37 kettenis Exp $ */
/*
* Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
*
@@ -751,204 +751,53 @@ inteldrm_doswitch(void *v, void *cookie)
* Accelerated routines.
*/
-int inteldrm_copycols(void *, int, int, int, int);
-int inteldrm_erasecols(void *, int, int, int, long);
int inteldrm_copyrows(void *, int, int, int);
-int inteldrm_eraserows(void *cookie, int, int, long);
-void inteldrm_copyrect(struct inteldrm_softc *, int, int, int, int, int, int);
-void inteldrm_fillrect(struct inteldrm_softc *, int, int, int, int, int);
-
-int
-inteldrm_copycols(void *cookie, int row, int src, int dst, int num)
-{
- struct rasops_info *ri = cookie;
- struct inteldrm_softc *sc = ri->ri_hw;
- struct drm_device *dev = (struct drm_device *)sc->drmdev;
-
- if (dev->open_count > 0 || sc->noaccel)
- return sc->noaccel_copycols(cookie, row, src, dst, num);
-
- num *= ri->ri_font->fontwidth;
- src *= ri->ri_font->fontwidth;
- dst *= ri->ri_font->fontwidth;
- row *= ri->ri_font->fontheight;
-
- inteldrm_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
- ri->ri_xorigin + dst, ri->ri_yorigin + row,
- num, ri->ri_font->fontheight);
-
- return 0;
-}
-
-int
-inteldrm_erasecols(void *cookie, int row, int col, int num, long attr)
-{
- struct rasops_info *ri = cookie;
- struct inteldrm_softc *sc = ri->ri_hw;
- struct drm_device *dev = (struct drm_device *)sc->drmdev;
- int bg, fg;
-
- if (dev->open_count > 0 || sc->noaccel)
- return sc->noaccel_erasecols(cookie, row, col, num, attr);
-
- ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
-
- row *= ri->ri_font->fontheight;
- col *= ri->ri_font->fontwidth;
- num *= ri->ri_font->fontwidth;
-
- inteldrm_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
- num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
-
- return 0;
-}
int
inteldrm_copyrows(void *cookie, int src, int dst, int num)
{
struct rasops_info *ri = cookie;
struct inteldrm_softc *sc = ri->ri_hw;
- struct drm_device *dev = (struct drm_device *)sc->drmdev;
-
- if (dev->open_count > 0 || sc->noaccel)
- return sc->noaccel_copyrows(cookie, src, dst, num);
-
- num *= ri->ri_font->fontheight;
- src *= ri->ri_font->fontheight;
- dst *= ri->ri_font->fontheight;
-
- inteldrm_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
- ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
-
- return 0;
-}
-
-int
-inteldrm_eraserows(void *cookie, int row, int num, long attr)
-{
- struct rasops_info *ri = cookie;
- struct inteldrm_softc *sc = ri->ri_hw;
- struct drm_device *dev = (struct drm_device *)sc->drmdev;
- int bg, fg;
- int x, y, w;
-
- if (dev->open_count > 0 || sc->noaccel)
- return sc->noaccel_eraserows(cookie, row, num, attr);
-
- ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
- if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
- num = ri->ri_height;
- x = y = 0;
- w = ri->ri_width;
- } else {
- num *= ri->ri_font->fontheight;
- x = ri->ri_xorigin;
- y = ri->ri_yorigin + row * ri->ri_font->fontheight;
- w = ri->ri_emuwidth;
- }
- inteldrm_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
-
- return 0;
-}
-
-void
-inteldrm_copyrect(struct inteldrm_softc *dev_priv, int sx, int sy,
- int dx, int dy, int w, int h)
-{
- struct drm_device *dev = (struct drm_device *)dev_priv->drmdev;
- bus_addr_t base = dev_priv->fbdev->ifb.obj->gtt_offset;
- uint32_t pitch = dev_priv->fbdev->ifb.base.pitches[0];
- struct intel_ring_buffer *ring;
- uint32_t seqno;
- int ret, i;
-
- if (HAS_BLT(dev))
- ring = &dev_priv->rings[BCS];
- else
- ring = &dev_priv->rings[RCS];
-
- ret = intel_ring_begin(ring, 8);
- if (ret)
- return;
-
- intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD |
- XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB);
- intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | pitch);
- intel_ring_emit(ring, (dx << 0) | (dy << 16));
- intel_ring_emit(ring, ((dx + w) << 0) | ((dy + h) << 16));
- intel_ring_emit(ring, base);
- intel_ring_emit(ring, (sx << 0) | (sy << 16));
- intel_ring_emit(ring, pitch);
- intel_ring_emit(ring, base);
- intel_ring_advance(ring);
-
- ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS);
- if (ret)
- return;
-
- ret = i915_add_request(ring, NULL, &seqno);
- if (ret)
- return;
-
- for (i = 1000000; i != 0; i--) {
- if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
- break;
- DELAY(1);
- }
-
- i915_gem_retire_requests_ring(ring);
-}
-
-void
-inteldrm_fillrect(struct inteldrm_softc *dev_priv, int x, int y,
- int w, int h, int color)
-{
- struct drm_device *dev = (struct drm_device *)dev_priv->drmdev;
- bus_addr_t base = dev_priv->fbdev->ifb.obj->gtt_offset;
- uint32_t pitch = dev_priv->fbdev->ifb.base.pitches[0];
- struct intel_ring_buffer *ring;
- uint32_t seqno;
- int ret, i;
-
- if (HAS_BLT(dev))
- ring = &dev_priv->rings[BCS];
- else
- ring = &dev_priv->rings[RCS];
+ if (dst == 0 && (src + num) == ri->ri_rows) {
+ struct inteldrm_softc *dev_priv = sc;
+ struct drm_fb_helper *helper = &dev_priv->fbdev->helper;
+ size_t size = dev_priv->fbdev->ifb.obj->base.size / 2;
+ int delta = src * ri->ri_font->fontheight * ri->ri_stride;
+ int i;
- ret = intel_ring_begin(ring, 6);
- if (ret)
- return;
+ bzero(ri->ri_bits, delta);
-#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|4)
-#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
-#define XY_COLOR_BLT_WRITE_RGB (1<<20)
-#define BLT_ROP_PATCOPY (0xf0<<16)
-
- intel_ring_emit(ring, XY_COLOR_BLT_CMD |
- XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
- intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_PATCOPY | pitch);
- intel_ring_emit(ring, (x << 0) | (y << 16));
- intel_ring_emit(ring, ((x + w) << 0) | ((y + h) << 16));
- intel_ring_emit(ring, base);
- intel_ring_emit(ring, color);
- intel_ring_advance(ring);
-
- ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS);
- if (ret)
- return;
+ sc->sc_offset += delta;
+ ri->ri_bits += delta;
+ ri->ri_origbits += delta;
+ if (sc->sc_offset > size) {
+ sc->sc_offset -= size;
+ ri->ri_bits -= size;
+ ri->ri_origbits -= size;
+ }
- ret = i915_add_request(ring, NULL, &seqno);
- if (ret)
- return;
+ for (i = 0; i < helper->crtc_count; i++) {
+ struct drm_mode_set *mode_set =
+ &helper->crtc_info[i].mode_set;
+ struct drm_crtc *crtc = mode_set->crtc;
+ struct drm_framebuffer *fb = helper->fb;
+
+ if (!crtc->enabled)
+ continue;
+
+ mode_set->x = (sc->sc_offset % ri->ri_stride) /
+ (ri->ri_depth / 8);
+ mode_set->y = sc->sc_offset / ri->ri_stride;
+ if (fb == crtc->fb)
+ dev_priv->display.update_plane(crtc, fb,
+ mode_set->x, mode_set->y);
+ }
- for (i = 1000000; i != 0; i--) {
- if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
- break;
- DELAY(1);
+ return 0;
}
- i915_gem_retire_requests_ring(ring);
+ return sc->sc_copyrows(cookie, src, dst, num);
}
void
@@ -1171,14 +1020,8 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
rasops_init(ri, 96, 132);
ri->ri_hw = dev_priv;
- dev_priv->noaccel_copyrows = ri->ri_copyrows;
- dev_priv->noaccel_copycols = ri->ri_copycols;
- dev_priv->noaccel_eraserows = ri->ri_eraserows;
- dev_priv->noaccel_erasecols = ri->ri_erasecols;
+ dev_priv->sc_copyrows = ri->ri_copyrows;
ri->ri_copyrows = inteldrm_copyrows;
- ri->ri_copycols = inteldrm_copycols;
- ri->ri_eraserows = inteldrm_eraserows;
- ri->ri_erasecols = inteldrm_erasecols;
inteldrm_stdscreen.capabilities = ri->ri_caps;
inteldrm_stdscreen.nrows = ri->ri_rows;
@@ -1202,6 +1045,8 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
aa.console = 1;
}
+ printf("%s: %dx%d\n", dev_priv->dev.dv_xname, ri->ri_width, ri->ri_height);
+
vga_sc->sc_type = -1;
config_found(parent, &aa, wsemuldisplaydevprint);
}
@@ -1257,7 +1102,6 @@ inteldrm_activate(struct device *arg, int act)
switch (act) {
case DVACT_QUIESCE:
// inteldrm_quiesce(dev_priv);
- dev_priv->noaccel = 1;
i915_drm_freeze(dev);
break;
case DVACT_SUSPEND:
@@ -1270,7 +1114,6 @@ inteldrm_activate(struct device *arg, int act)
// wakeup(&dev_priv->flags);
i915_drm_thaw(dev);
intel_fb_restore_mode(dev);
- dev_priv->noaccel = 0;
break;
}
diff --git a/sys/dev/pci/drm/i915/i915_drv.h b/sys/dev/pci/drm/i915/i915_drv.h
index c3a6f99ffa6..bf35b7d46a7 100644
--- a/sys/dev/pci/drm/i915/i915_drv.h
+++ b/sys/dev/pci/drm/i915/i915_drv.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i915_drv.h,v 1.12 2013/04/03 07:36:57 jsg Exp $ */
+/* $OpenBSD: i915_drv.h,v 1.13 2013/04/14 19:04:37 kettenis Exp $ */
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
/*
@@ -512,11 +512,8 @@ struct inteldrm_softc {
struct workq_task switchwqt;
struct rasops_info ro;
- int noaccel;
- int (*noaccel_copycols)(void *, int, int, int, int);
- int (*noaccel_erasecols)(void *, int, int, int, long);
- int (*noaccel_copyrows)(void *, int, int, int);
- int (*noaccel_eraserows)(void *, int, int, long);
+ int sc_offset;
+ int (*sc_copyrows)(void *, int, int, int);
uint32_t gpio_mmio_base;
diff --git a/sys/dev/pci/drm/i915/intel_fb.c b/sys/dev/pci/drm/i915/intel_fb.c
index d415bb82509..dc0f448deba 100644
--- a/sys/dev/pci/drm/i915/intel_fb.c
+++ b/sys/dev/pci/drm/i915/intel_fb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intel_fb.c,v 1.2 2013/03/19 03:58:10 jsg Exp $ */
+/* $OpenBSD: intel_fb.c,v 1.3 2013/04/14 19:04:37 kettenis Exp $ */
/*
* Copyright © 2007 David Airlie
*
@@ -66,13 +66,14 @@ intelfb_create(struct intel_fbdev *ifbdev,
sizes->surface_depth);
size = mode_cmd.pitches[0] * mode_cmd.height;
- size = roundup2(size, PAGE_SIZE);
+ size = roundup2(size, PAGE_SIZE) * 2;
obj = i915_gem_alloc_object(dev, size);
if (!obj) {
DRM_ERROR("failed to allocate framebuffer\n");
ret = -ENOMEM;
goto out;
}
+ obj->dma_flags |= BUS_DMA_GTT_WRAPAROUND;
DRM_LOCK();