grub-devel
[Top][All Lists]
Advanced

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

[PATCH] Optimise scrolling by avoiding function calls and aligned memory


From: Vladimir 'φ-coder/phcoder' Serbinenko
Subject: [PATCH] Optimise scrolling by avoiding function calls and aligned memory copy
Date: Mon, 30 Nov 2009 11:10:10 +0100
User-agent: Mozilla-Thunderbird 2.0.0.22 (X11/20091109)

Available in experimental. In QEMU benchmark scrolling 1000 lines
decreased from 72s to 32s.

-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko

=== added file 'ChangeLog.scrollopt'
--- ChangeLog.scrollopt 1970-01-01 00:00:00 +0000
+++ ChangeLog.scrollopt 2009-11-30 09:26:26 +0000
@@ -0,0 +1,4 @@
+2009-11-30  Vladimir Serbinenko  <address@hidden>
+
+       * video/fb/video_fb.c (grub_video_fb_scroll): Optimise by avoiding
+       unnecessary calls.

=== modified file 'video/fb/video_fb.c'
--- video/fb/video_fb.c 2009-08-28 13:54:20 +0000
+++ video/fb/video_fb.c 2009-11-30 09:52:10 +0000
@@ -974,32 +974,83 @@
     {
       /* 3. Move data in render target.  */
       struct grub_video_fbblit_info target;
-      grub_uint8_t *src;
-      grub_uint8_t *dst;
-      int j;
+      int i, j;
+      int linedelta, linelen;
 
       target.mode_info = &render_target->mode_info;
       target.data = render_target->data;
 
-      /* Check vertical direction of the move.  */
-      if (dy <= 0)
-       /* 3a. Move data upwards.  */
-       for (j = 0; j < height; j++)
-         {
-           dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j);
-           src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j);
-           grub_memmove (dst, src,
-                         width * target.mode_info->bytes_per_pixel);
-         }
+      linedelta = target.mode_info->pitch
+       - width * target.mode_info->bytes_per_pixel;
+      linelen = width * target.mode_info->bytes_per_pixel;
+#define DO_SCROLL                                                    \
+      /* Check vertical direction of the move.  */                   \
+      if (dy < 0 || (dy == 0 && dx < 0))                             \
+       {                                                            \
+         dst = (void *) grub_video_fb_get_video_ptr (&target,       \
+                                                     dst_x, dst_y); \
+         src = (void *) grub_video_fb_get_video_ptr (&target,       \
+                                                     src_x, src_y); \
+         /* 3a. Move data upwards.  */                              \
+         for (j = 0; j < height; j++)                               \
+           {                                                        \
+             for (i = 0; i < linelen; i++)                          \
+               *(dst++) = *(src++);                                 \
+             dst += linedelta;                                      \
+             src += linedelta;                                      \
+           }                                                        \
+       }                                                            \
+      else                                                           \
+       {                                                            \
+         /* 3b. Move data downwards.  */                            \
+         dst = (void *) grub_video_fb_get_video_ptr (&target,       \
+                                            dst_x + width - 1,      \
+                                            dst_y + height - 1);    \
+         src = (void *) grub_video_fb_get_video_ptr (&target,       \
+                                            src_x + width - 1,      \
+                                            src_y + height - 1);    \
+         for (j = 0; j < height; j++)                               \
+           {                                                        \
+             for (i = 0; i < linelen; i++)                          \
+               *(dst--) = *(src--);                                 \
+             dst -= linedelta;                                      \
+             src -= linedelta;                                      \
+           }                                                        \
+       }
+
+      /* If everything is aligned on 32-bit use 32-bit copy.  */
+      if ((grub_addr_t) grub_video_fb_get_video_ptr (&target, src_x, src_y)
+         % sizeof (grub_uint32_t) == 0
+         && (grub_addr_t) grub_video_fb_get_video_ptr (&target, dst_x, dst_y) 
+         % sizeof (grub_uint32_t) == 0
+         && linelen % sizeof (grub_uint32_t) == 0
+         && linedelta % sizeof (grub_uint32_t) == 0)
+       {
+         grub_uint32_t *src, *dst;
+         linelen /= sizeof (grub_uint32_t);
+         linedelta /= sizeof (grub_uint32_t);
+         DO_SCROLL
+       }
+      /* If everything is aligned on 16-bit use 16-bit copy.  */
+      else if ((grub_addr_t) grub_video_fb_get_video_ptr (&target, src_x, 
src_y)
+              % sizeof (grub_uint16_t) == 0
+              && (grub_addr_t) grub_video_fb_get_video_ptr (&target,
+                                                            dst_x, dst_y) 
+              % sizeof (grub_uint16_t) == 0
+              && linelen % sizeof (grub_uint16_t) == 0
+              && linedelta % sizeof (grub_uint16_t) == 0)
+       {
+         grub_uint16_t *src, *dst;
+         linelen /= sizeof (grub_uint16_t);
+         linedelta /= sizeof (grub_uint16_t);
+         DO_SCROLL
+       }
+      /* If not aligned at all use 8-bit copy.  */
       else
-       /* 3b. Move data downwards.  */
-       for (j = (height - 1); j >= 0; j--)
-         {
-           dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j);
-           src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j);
-           grub_memmove (dst, src,
-                         width * target.mode_info->bytes_per_pixel);
-         }
+       {
+         grub_uint8_t *src, *dst;
+         DO_SCROLL
+       }       
     }
 
   /* 4. Fill empty space with specified color.  In this implementation

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]