w100にshadow fbをつけてみた

気がつけば丸々3ヶ月放置してた。ナツヤスミトハナンダッタノカ

どうも最近rasops(9)が最近のトレンドみたいだったので(違)便乗してみるテスト。つーかrasops(9)のmanにこんなんが定義されていたので、w100の画面スクロールがものくそ遅い問題が回避できないかと試してみた。

/*
 * If you want shadow framebuffer support, point ri_hwbits
 * to the real framebuffer, and ri_bits to the shadow framebuffer
 */
u_char  *ri_hwbits;

んでとりあえず/usr/share/misc/style (476 行)をcatした結果。

  • shadow framebuffer なし: 96秒
  • shadow framebuffer あり: 30秒

shadow framebufferありのほうがメモリのコピー回数が増えているにもかかわらず3倍速くなりおった。つーかどんだけ遅いんだよVRAM。

ただし、

  • shadow framebufferとして常にメモリを614,400byte(640x480x2)消費する
  • 恩恵を受けられるのはrasopsだけで、mlterm-fbとかX.orgの速度には寄与しない(つまりメモリの無駄遣い)
  • ri_hwbitsを使っているドライバがほとんどない
  • w100的にはbitbltとかできる子だった(はず)ので、もっと適切な方法がある

というわけで、「フツーmlterm-fbやX.org使うよね」ということを考えると精々起動がちょっと速くなる(ブートメッセージの画面スクロールの部分)程度であまりおいしくない。

ちなみにmlterm-fbでさっきと同じようにcatを走らせると。

  • mlterm-fb : 0.3秒

∴ もう全部mlterm-fbでいいんじゃないかな

Index: sys/arch/zaurus/conf/GENERIC
==================================================================
--- sys/arch/zaurus/conf/GENERIC
+++ sys/arch/zaurus/conf/GENERIC
@@ -223,10 +223,11 @@
 # LCD
 lcd0 at pxaip?				# PXA2x0 integrated LCD Controller
 options 	PXA2X0_LCD_WRITETHROUGH
 wsdisplay* at lcd? console ?
 w100lcd0 at pxaip?			# ATI Imageon100 LCDcontroller
+#options		W100_SHADOW
 wsdisplay* at w100lcd? console ?
 lcdctl0 at zssp0
 
 # WM8750 Audio
 zaudio0 at iic? addr 0x1b

Index: sys/arch/zaurus/conf/files.zaurus
==================================================================
--- sys/arch/zaurus/conf/files.zaurus
+++ sys/arch/zaurus/conf/files.zaurus
@@ -78,10 +78,11 @@
 # LCD frame buffer for SL-C7x0
 device w100lcd: wsemuldisplaydev, rasops16, rasops8, rasops4, rasops_rotation
 attach w100lcd at pxaip
 file arch/zaurus/dev/w100lcd.c		w100lcd needs-flag
 file arch/zaurus/dev/w100.c		w100lcd
+defflag opt_w100.h			W100_SHADOW
 
 # backlight, brightness Controller
 device lcdctl
 attach lcdctl at zssp
 file arch/zaurus/dev/lcdctl.c		lcdctl needs-flag

Index: sys/arch/zaurus/dev/w100.c
==================================================================
--- sys/arch/zaurus/dev/w100.c
+++ sys/arch/zaurus/dev/w100.c
@@ -33,10 +33,11 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
 #include <sys/uio.h>
 #include <sys/malloc.h>
+#include <sys/kmem.h>
 #include <sys/kernel.h>			/* for cold */
 
 #include <uvm/uvm_extern.h>
 
 #include <dev/cons.h>
@@ -52,10 +53,11 @@
 
 #include <zaurus/dev/w100reg.h>
 #include <zaurus/dev/w100var.h>
 
 #include "wsdisplay.h"
+#include "opt_w100.h"
 
 /* Console */
 struct {
 	int is_console;
 	struct w100_wsscreen_descr *descr;
@@ -196,11 +198,16 @@
 			return;
 		}
 
 		ri = &scr->rinfo;
 		ri->ri_hw = (void *)scr;
-		ri->ri_bits = scr->buf_va;
+		if (scr->shadow != NULL) {
+			ri->ri_hwbits = scr->buf_va;
+			ri->ri_bits = scr->shadow;
+		} else {
+			ri->ri_bits = scr->buf_va;
+		}
 		w100_setup_rasops(sc, ri, descr, geom);
 
 		/* assumes 16 bpp */
 		(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
 
@@ -232,19 +239,26 @@
 static int
 w100_new_screen(struct w100_softc *sc, int depth, struct w100_screen **scrpp)
 {
 	struct w100_screen *scr = NULL;
 	int error = 0;
+#ifdef W100_SHADOW
+	size_t fbsize;
+#endif
 
 	scr = malloc(sizeof(*scr), M_DEVBUF, M_NOWAIT);
 	if (scr == NULL)
 		return ENOMEM;
 
 	memset(scr, 0, sizeof(*scr));
 
 	scr->buf_va = (u_char *)bus_space_vaddr(sc->iot, sc->ioh_vram);
 	scr->depth = depth;
+#ifdef W100_SHADOW
+	fbsize = (sc->display_width * depth / 8) * sc->display_height;
+	scr->shadow = kmem_alloc(fbsize, KM_SLEEP);
+#endif
 
 	LIST_INSERT_HEAD(&sc->screens, scr, link);
 	sc->n_screens++;
 
 	*scrpp = scr;
@@ -410,11 +424,16 @@
 	/*
 	 * initialize raster operation for this screen.
 	 */
 	scr->rinfo.ri_flg = 0;
 	scr->rinfo.ri_depth = type->depth;
-	scr->rinfo.ri_bits = scr->buf_va;
+	if (scr->shadow != NULL) {
+		scr->rinfo.ri_hwbits = scr->buf_va;
+		scr->rinfo.ri_bits = scr->shadow;
+	} else {
+		scr->rinfo.ri_bits = scr->buf_va;
+	}
 	scr->rinfo.ri_width = sc->display_width;
 	scr->rinfo.ri_height = sc->display_height;
 	scr->rinfo.ri_stride = scr->rinfo.ri_width * scr->rinfo.ri_depth / 8;
 	scr->rinfo.ri_wsfcookie = -1;	/* XXX */
 

Index: sys/arch/zaurus/dev/w100lcd.c
==================================================================
--- sys/arch/zaurus/dev/w100lcd.c
+++ sys/arch/zaurus/dev/w100lcd.c
@@ -69,11 +69,11 @@
 		.fontwidth = 8,
 		.fontheight = 16,
 		.capabilities = WSSCREEN_WSCOLORS,
 	},
 	.depth = 16,			/* bits per pixel */
-	.flags = 0,
+	.flags = RI_CLEAR,
 };
 
 static const struct wsscreen_descr *w100lcd_scr_descr[] = {
 	&w100lcd_std_screen.c
 };

Index: sys/arch/zaurus/dev/w100var.h
==================================================================
--- sys/arch/zaurus/dev/w100var.h
+++ sys/arch/zaurus/dev/w100var.h
@@ -10,10 +10,13 @@
 	LIST_ENTRY(w100_screen) link;
 
 	/* Frame buffer */
 	void 	*buf_va;
 	int     depth;
+
+	/* shadow framebuffer */
+	void	*shadow;
 
 	/* rasterop */
 	struct rasops_info rinfo;
 };