linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Antonino A. Daplas" <adaplas@gmail.com>
To: linux-fbdev-devel@lists.sourceforge.net
Subject: Re: [PATCH] smart blitter usage for scrolling
Date: Wed, 09 May 2007 22:19:18 +0800	[thread overview]
Message-ID: <1178720358.4861.27.camel@daplas> (raw)
In-Reply-To: <464172cc491d5@wp.pl>

On Wed, 2007-05-09 at 09:05 +0200, Krzysztof Helt wrote:
> 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.

This sounds quite logical to me.  However, I would rather that you
create a new scrolling mode (ie SCROLL_MOVE_REDRAW and
SCROLL_WRAP_REDRAW). Then create a new FBINFO_HWACCEL flag that will
enable SCROLL_PAN/WRAP_MOVE_REDRAW and perhaps another one that will
enable MERGE_BLIT.

To illustrate, see further comments below.


> 
> 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

You can remove those #ifdef's (they're ugly anyway if used within a
function).

So something like:

if (info->flags & FBINFO_HWACCEL_MERGEBLIT)
	was_blit = 1;
> +					x += s - start;
> +					start = s;
> +				}
> +			}
> +			if (c == scr_readw(d)) {
> +				if (s > start) {
> +#ifdef MERGE_BLITS
> +					if (!was_blit) {
> +#endif

and,

if (info->flags & FBINFO_HWACCEL_MERGEBLIT || !was_blit) 

or something to that effect.


> +						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

Again, you can remove the #ifdef and just do:
	
		case SCROLL_MOVE_REDRAW:	
> +			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

Same here.

> +			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:

And all those selection magic  you can do in update_scrollmode().

Hopefully, you get what I'm trying to illustrate. Choose the most
effective method you want (not necessarily my example), but let's
eliminate the ugly #ifdefs and make this a new scrolling mode selectable
by the driver by setting certain bits in info->flags. 

Tony


-------------------------------------------------------------------------
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/

  reply	other threads:[~2007-05-09 14:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-09  7:05 [PATCH] smart blitter usage for scrolling Krzysztof Helt
2007-05-09 14:19 ` Antonino A. Daplas [this message]
2007-05-10  5:40   ` Krzysztof Helt
2007-05-10  5:49     ` Antonino A. Daplas
2007-05-10  5:56       ` Antonino A. Daplas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1178720358.4861.27.camel@daplas \
    --to=adaplas@gmail.com \
    --cc=linux-fbdev-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).