linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] smart blitter usage for scrolling
@ 2007-05-09  7:05 Krzysztof Helt
  2007-05-09 14:19 ` Antonino A. Daplas
  0 siblings, 1 reply; 5+ messages in thread
From: Krzysztof Helt @ 2007-05-09  7:05 UTC (permalink / raw)
  To: linux-fbdev-devel

[-- Attachment #1: Type: text/plain, Size: 7048 bytes --]

From: Krzysztof Helt <krzysztof.h1@wp.pl>

This patch adds option to uses blitter only to move characters
which have to be moved instead of current brute force approach
(move whole screen).

Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>

---

This patch uses the same logic as the fbcon_redraw() but uses
bmove() instead of putcs(). On my system (dual P3 866MHz and
Permedia 2 with 83MHz clock) this gives the SCROLL_MOVE up to 5%
slower than non accelerated SCROLL_REDRAW. Previously, the
SCROLL_MOVE was few times (up to 10) slower. I tested it with
"time dmesg" at 1024x768 and 1600x1200 resolutions.

I think that this new approach can completely replace the brute
force SCROLL_MOVE method used currently. It should help all
drivers which uses SCROLL_MOVE method (probably not many), reduce
difference between SCROLL_REDRAW and SCROLL_MOVE and do nothing
to drivers useng SCROLL_REDRAW method.

There is additional possibility to improve performance by
enabling MERGE_BLIT definition. In this case, the first matching
character to scroll (in source and destination location) is
ignored. This produces about half of blits requests (in my test
case - around 100 instead of around 200) but blits are larger
(each one is one character larger). This may help on cards where
the blitter is fast but slow to start (any known card?). If it is
not a case it can be dropped completely (to simplify the code).
In my case it has not produced any speed improvement (and even
slower scrolling by 1-2%).

This patch is indented for your review and tests on different
hardware. I will also test it on hardware I have (I can borrow
slower machine and I have few other GFX cards to tests).

Kind regards,
Krzysztof

diff -urp linux-2.6.21/drivers/video/Kconfig
linux-2.6.21.mod/drivers/video/Kconfig
--- linux-2.6.21/drivers/video/Kconfig	2007-05-08
23:38:34.055228990 +0200
+++ linux-2.6.21.mod/drivers/video/Kconfig	2007-05-09
00:13:34.910949935 +0200
@@ -139,6 +139,23 @@ config FB_TILEBLITTING
 	 This is particularly important to one driver, matroxfb.  If
 	 unsure, say N.
 
+config FB_SMALL_BLITS
+       bool "Enable Enhanced Blitting Support (EXPERIMENTAL)"
+       depends on FB && EXPERIMENTAL
+       default n
+       ---help---
+         This enables smart usage of blitter to sroll screen. A
standard
+	 way is to use blitter to move almost whole screen. The enhanced
+	 blitting moves only characters which have to be moved. The same
+	 logic is used for redrawing characters during scroll if the
+	 blitting is not used to scroll.
+	 It may or may not speed up scrolling of your framebuffer. It
+	 depends on relative speed of your CPU and GPU. If you have
+	 fast CPU and slow GPU this option may slow down scrolling.
+	 If the opposite is true this may speed up scrolling for you.
+
+	 If unsure, say N.
+
 comment "Frame buffer hardware drivers"
 	depends on FB
 
diff -urp linux-2.6.21/drivers/video/console/fbcon.c
linux-2.6.21.mod/drivers/video/console/fbcon.c
--- linux-2.6.21/drivers/video/console/fbcon.c	2007-04-26
05:08:32.000000000 +0200
+++ linux-2.6.21.mod/drivers/video/console/fbcon.c	2007-05-09
00:15:37.501935997 +0200
@@ -1663,6 +1663,81 @@ static void fbcon_redraw_move(struct vc_
 	}
 }
 
+static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info
*info,
+			struct display *p, int line, int count, int ycount)
+{
+	int offset = ycount * vc->vc_cols;
+	unsigned short *d = (unsigned short *)
+	    (vc->vc_origin + vc->vc_size_row * line);
+	unsigned short *s = d + offset;
+	struct fbcon_ops *ops = info->fbcon_par;
+
+	while (count--) {
+		unsigned short *start = s;
+		unsigned short *le = advance_row(s, 1);
+		unsigned short c;
+		int x = 0;
+		unsigned short attr = 1;
+#ifdef MERGE_BLITS
+		int was_blit = 1;
+#endif
+
+		do {
+			c = scr_readw(s);
+			if (attr != (c & 0xff00)) {
+				attr = c & 0xff00;
+				if (s > start) {
+					ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start);
+#ifdef MERGE_BLITS
+					was_blit = 1;
+#endif
+					x += s - start;
+					start = s;
+				}
+			}
+			if (c == scr_readw(d)) {
+				if (s > start) {
+#ifdef MERGE_BLITS
+					if (!was_blit) {
+#endif
+						ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start);
+						x += s - start + 1;
+						start = s + 1;
+#ifdef MERGE_BLITS
+					}
+					was_blit = !was_blit;
+#endif
+				} else {
+#ifdef MERGE_BLITS
+					if (was_blit) {
+#endif
+						x++;
+						start++;
+#ifdef MERGE_BLITS
+					}
+#endif
+				}
+			}
+			scr_writew(c, d);
+			console_conditional_schedule();
+			s++;
+			d++;
+		} while (s < le);
+		if (s > start) {
+			ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start);
+		}
+		console_conditional_schedule();
+		if (ycount > 0)
+			line++;
+		else {
+			line--;
+			/* NOTE: We subtract two lines from these pointers */
+			s -= vc->vc_size_row;
+			d -= vc->vc_size_row;
+		}
+	}
+}
+
 static void fbcon_redraw(struct vc_data *vc, struct display *p,
 			 int line, int count, int offset)
 {
@@ -1748,7 +1823,9 @@ static int fbcon_scroll(struct vc_data *
 {
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
+#ifndef CONFIG_FB_SMALL_BLITS
 	struct fbcon_ops *ops = info->fbcon_par;
+#endif
 	int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
 
 	if (fbcon_is_inactive(vc, info))
@@ -1772,10 +1849,22 @@ static int fbcon_scroll(struct vc_data *
 			goto redraw_up;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
+#ifndef CONFIG_FB_SMALL_BLITS
 			ops->bmove(vc, info, t + count, 0, t, 0,
 				    b - t - count, vc->vc_cols);
 			ops->clear(vc, info, b - count, 0, count,
 				  vc->vc_cols);
+#else
+			fbcon_redraw_blit(vc, info, p, t, b - t - count,
+				     count);
+			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+			scr_memsetw((unsigned short *) (vc->vc_origin +
+							vc->vc_size_row *
+							(b - count)),
+				    vc->vc_video_erase_char,
+				    vc->vc_size_row * count);
+			return 1;
+#endif
 			break;
 
 		case SCROLL_WRAP_MOVE:
@@ -1858,9 +1947,21 @@ static int fbcon_scroll(struct vc_data *
 			goto redraw_down;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
+#ifndef CONFIG_FB_SMALL_BLITS
 			ops->bmove(vc, info, t, 0, t + count, 0,
 				    b - t - count, vc->vc_cols);
 			ops->clear(vc, info, t, 0, count, vc->vc_cols);
+#else
+			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
+				     -count);
+			fbcon_clear(vc, t, 0, count, vc->vc_cols);
+			scr_memsetw((unsigned short *) (vc->vc_origin +
+							vc->vc_size_row *
+							t),
+				    vc->vc_video_erase_char,
+				    vc->vc_size_row * count);
+			return 1;
+#endif
 			break;
 
 		case SCROLL_WRAP_MOVE:





----------------------------------------------------
Sprawdź ile wart jest Twój samochód. 
Wycena aut jak na dłoni: http://klik.wp.pl/?adr=www.wycenyaut.wp.pl&sid=1132

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: video-small-blit.diff --]
[-- Type: text/x-patch; name="video-small-blit.diff", Size: 4944 bytes --]

diff -urp linux-2.6.21/drivers/video/Kconfig linux-2.6.21.mod/drivers/video/Kconfig
--- linux-2.6.21/drivers/video/Kconfig	2007-05-08 23:38:34.055228990 +0200
+++ linux-2.6.21.mod/drivers/video/Kconfig	2007-05-09 00:13:34.910949935 +0200
@@ -139,6 +139,23 @@ config FB_TILEBLITTING
 	 This is particularly important to one driver, matroxfb.  If
 	 unsure, say N.
 
+config FB_SMALL_BLITS
+       bool "Enable Enhanced Blitting Support (EXPERIMENTAL)"
+       depends on FB && EXPERIMENTAL
+       default n
+       ---help---
+         This enables smart usage of blitter to sroll screen. A standard
+	 way is to use blitter to move almost whole screen. The enhanced
+	 blitting moves only characters which have to be moved. The same
+	 logic is used for redrawing characters during scroll if the
+	 blitting is not used to scroll.
+	 It may or may not speed up scrolling of your framebuffer. It
+	 depends on relative speed of your CPU and GPU. If you have
+	 fast CPU and slow GPU this option may slow down scrolling.
+	 If the opposite is true this may speed up scrolling for you.
+
+	 If unsure, say N.
+
 comment "Frame buffer hardware drivers"
 	depends on FB
 
diff -urp linux-2.6.21/drivers/video/console/fbcon.c linux-2.6.21.mod/drivers/video/console/fbcon.c
--- linux-2.6.21/drivers/video/console/fbcon.c	2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21.mod/drivers/video/console/fbcon.c	2007-05-09 00:15:37.501935997 +0200
@@ -1663,6 +1663,81 @@ static void fbcon_redraw_move(struct vc_
 	}
 }
 
+static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
+			struct display *p, int line, int count, int ycount)
+{
+	int offset = ycount * vc->vc_cols;
+	unsigned short *d = (unsigned short *)
+	    (vc->vc_origin + vc->vc_size_row * line);
+	unsigned short *s = d + offset;
+	struct fbcon_ops *ops = info->fbcon_par;
+
+	while (count--) {
+		unsigned short *start = s;
+		unsigned short *le = advance_row(s, 1);
+		unsigned short c;
+		int x = 0;
+		unsigned short attr = 1;
+#ifdef MERGE_BLITS
+		int was_blit = 1;
+#endif
+
+		do {
+			c = scr_readw(s);
+			if (attr != (c & 0xff00)) {
+				attr = c & 0xff00;
+				if (s > start) {
+					ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start);
+#ifdef MERGE_BLITS
+					was_blit = 1;
+#endif
+					x += s - start;
+					start = s;
+				}
+			}
+			if (c == scr_readw(d)) {
+				if (s > start) {
+#ifdef MERGE_BLITS
+					if (!was_blit) {
+#endif
+						ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start);
+						x += s - start + 1;
+						start = s + 1;
+#ifdef MERGE_BLITS
+					}
+					was_blit = !was_blit;
+#endif
+				} else {
+#ifdef MERGE_BLITS
+					if (was_blit) {
+#endif
+						x++;
+						start++;
+#ifdef MERGE_BLITS
+					}
+#endif
+				}
+			}
+			scr_writew(c, d);
+			console_conditional_schedule();
+			s++;
+			d++;
+		} while (s < le);
+		if (s > start) {
+			ops->bmove(vc, info, line + ycount, x, line, x, 1, s-start);
+		}
+		console_conditional_schedule();
+		if (ycount > 0)
+			line++;
+		else {
+			line--;
+			/* NOTE: We subtract two lines from these pointers */
+			s -= vc->vc_size_row;
+			d -= vc->vc_size_row;
+		}
+	}
+}
+
 static void fbcon_redraw(struct vc_data *vc, struct display *p,
 			 int line, int count, int offset)
 {
@@ -1748,7 +1823,9 @@ static int fbcon_scroll(struct vc_data *
 {
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
+#ifndef CONFIG_FB_SMALL_BLITS
 	struct fbcon_ops *ops = info->fbcon_par;
+#endif
 	int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
 
 	if (fbcon_is_inactive(vc, info))
@@ -1772,10 +1849,22 @@ static int fbcon_scroll(struct vc_data *
 			goto redraw_up;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
+#ifndef CONFIG_FB_SMALL_BLITS
 			ops->bmove(vc, info, t + count, 0, t, 0,
 				    b - t - count, vc->vc_cols);
 			ops->clear(vc, info, b - count, 0, count,
 				  vc->vc_cols);
+#else
+			fbcon_redraw_blit(vc, info, p, t, b - t - count,
+				     count);
+			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
+			scr_memsetw((unsigned short *) (vc->vc_origin +
+							vc->vc_size_row *
+							(b - count)),
+				    vc->vc_video_erase_char,
+				    vc->vc_size_row * count);
+			return 1;
+#endif
 			break;
 
 		case SCROLL_WRAP_MOVE:
@@ -1858,9 +1947,21 @@ static int fbcon_scroll(struct vc_data *
 			goto redraw_down;
 		switch (p->scrollmode) {
 		case SCROLL_MOVE:
+#ifndef CONFIG_FB_SMALL_BLITS
 			ops->bmove(vc, info, t, 0, t + count, 0,
 				    b - t - count, vc->vc_cols);
 			ops->clear(vc, info, t, 0, count, vc->vc_cols);
+#else
+			fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
+				     -count);
+			fbcon_clear(vc, t, 0, count, vc->vc_cols);
+			scr_memsetw((unsigned short *) (vc->vc_origin +
+							vc->vc_size_row *
+							t),
+				    vc->vc_video_erase_char,
+				    vc->vc_size_row * count);
+			return 1;
+#endif
 			break;
 
 		case SCROLL_WRAP_MOVE:

[-- Attachment #3: Type: text/plain, Size: 286 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

[-- Attachment #4: Type: text/plain, Size: 182 bytes --]

_______________________________________________
Linux-fbdev-devel mailing list
Linux-fbdev-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-fbdev-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-05-10  5:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-09  7:05 [PATCH] smart blitter usage for scrolling Krzysztof Helt
2007-05-09 14:19 ` Antonino A. Daplas
2007-05-10  5:40   ` Krzysztof Helt
2007-05-10  5:49     ` Antonino A. Daplas
2007-05-10  5:56       ` Antonino A. Daplas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).