VESA: move pixel formatting into __vesacon_copy_to_screen() syslinux-3.62-pre5
authorH. Peter Anvin <hpa@zytor.com>
Thu, 14 Feb 2008 03:00:12 +0000 (19:00 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 14 Feb 2008 03:00:12 +0000 (19:00 -0800)
Make pixel formatting an integral part of __vesacon_copy_to_screen().
In order to cut down on the dispatch overhead, make the formatting
functions contain the pixel loop, so we only do indirect dispatch
twice per pixel row - once for the formatting and once for copying to
the screen.

com32/lib/Makefile
com32/lib/sys/vesa/background.c
com32/lib/sys/vesa/drawtxt.c
com32/lib/sys/vesa/fmtpixel.c [moved from com32/lib/sys/vesa/fmtpixel.h with 51% similarity]
com32/lib/sys/vesa/initvesa.c
com32/lib/sys/vesa/screencpy.c
com32/lib/sys/vesa/video.h

index cd0cebd..cb33024 100644 (file)
@@ -43,7 +43,7 @@ LIBOBJS = \
        \
        sys/vesacon_write.o sys/vesaserial_write.o                      \
        sys/vesa/initvesa.o sys/vesa/drawtxt.o  sys/vesa/background.o   \
-       sys/vesa/alphatbl.o sys/vesa/screencpy.o                        \
+       sys/vesa/alphatbl.o sys/vesa/screencpy.o sys/vesa/fmtpixel.o    \
        \
        pci/cfgtype.o pci/scan.o                                        \
        pci/readb.o pci/readw.o pci/readl.o pci/readbios.o              \
index d7a0d01..5794db2 100644 (file)
@@ -35,7 +35,6 @@
 #include <minmax.h>
 #include "vesa.h"
 #include "video.h"
-#include "fmtpixel.h"
 
 static size_t filesize(FILE *fp)
 {
@@ -52,18 +51,12 @@ static size_t filesize(FILE *fp)
    aligned dwords. */
 static void draw_background_line(int line, int start, int npixels)
 {
-  uint8_t line_buf[VIDEO_X_SIZE*4], *lbp;
   uint32_t *bgptr = &__vesacon_background[line][start];
   unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel;
-  enum vesa_pixel_format pixel_format = __vesacon_pixel_format;
   uint8_t *fbptr = (uint8_t *)__vesa_info.mi.lfb_ptr +
     line*__vesa_info.mi.logical_scan + start*bytes_per_pixel;
   
-  lbp = line_buf;
-  while (npixels--)
-    lbp = format_pixel(lbp, *bgptr++, pixel_format);
-
-  __vesacon_copy_to_screen(fbptr, line_buf, lbp-line_buf);
+  __vesacon_copy_to_screen(fbptr, bgptr, npixels);
 }
 
 /* This draws the border, then redraws the text area */
index 9e222ec..023c364 100644 (file)
@@ -29,7 +29,6 @@
 #include <colortbl.h>
 #include "vesa.h"
 #include "video.h"
-#include "fmtpixel.h"
 #include "fill.h"
 
 /*
@@ -84,7 +83,7 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols)
   struct vesa_char *rowptr, *rowsptr, *cptr, *csptr;
   unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel;
   unsigned long pixel_offset;
-  uint8_t row_buffer[VIDEO_X_SIZE*4], *rowbufptr;
+  uint32_t row_buffer[VIDEO_X_SIZE], *rowbufptr;
   uint8_t *fbrowptr;
   uint8_t sha;
 
@@ -174,14 +173,11 @@ static void vesacon_update_characters(int row, int col, int nrows, int ncols)
        color &= 0x3f3f3f;
       }
 
-      rowbufptr = format_pixel(rowbufptr, color, __vesacon_pixel_format);
+      *rowbufptr++ = color;
     }
 
     /* Copy to frame buffer */
-    /* Note that the dword_count is rounded down, not up.  That's because
-       the row_buffer includes a spillover pixel. */
-    __vesacon_copy_to_screen(fbrowptr, row_buffer,
-                            (rowbufptr-row_buffer) & ~3);
+    __vesacon_copy_to_screen(fbrowptr, row_buffer, rowbufptr-row_buffer);
 
     bgrowptr += VIDEO_X_SIZE;
     fbrowptr += __vesa_info.mi.logical_scan;
similarity index 51%
rename from com32/lib/sys/vesa/fmtpixel.h
rename to com32/lib/sys/vesa/fmtpixel.c
index dcde010..74c79ef 100644 (file)
  * ----------------------------------------------------------------------- */
 
 /*
- * fmtpixel.h
+ * fmtpixel.c
  *
- * Inline function to format a single pixel
+ * Functions to format a single pixel
  */
 
-#ifndef LIB_SYS_VESA_FMTPIXEL_H
-#define LIB_SYS_VESA_FMTPIXEL_H
-
 #include <inttypes.h>
 #include "video.h"
 
 /* Format a pixel and return the advanced pointer.
    THIS FUNCTION IS ALLOWED TO WRITE BEYOND THE END OF THE PIXEL. */
 
-static inline __attribute__((always_inline))
-  void *format_pixel(void *ptr, uint32_t bgra, enum vesa_pixel_format fmt)
+static inline uint32_t *copy_dword(uint32_t *dst, const uint32_t *src,
+                                  size_t dword_count)
 {
-  switch (fmt) {
-  case PXF_BGRA32:
-    *(uint32_t *)ptr = bgra;
-    ptr = (uint32_t *)ptr + 1;
-    break;
-
-  case PXF_BGR24:
-    *(uint32_t *)ptr = bgra;
-    ptr = (uint8_t *)ptr + 3;
-    break;
+  asm volatile("cld; rep; movsl"
+              : "+D" (dst), "+S" (src), "+c" (dword_count));
+  return dst;                  /* Updated destination pointer */
+}
 
-  case PXF_LE_RGB16_565:
-    {
-      uint16_t pxv =
-       ((bgra >> 3) & 0x1f) +
-       ((bgra >> (2+8-5)) & (0x3f << 5)) +
-       ((bgra >> (3+16-11)) & (0x1f << 11));
+static void *format_pxf_bgra32(void *ptr, const uint32_t *p, size_t n)
+{
+  return copy_dword(ptr, p, n);
+}
 
-      *(uint16_t *)ptr = pxv;
-      ptr = (uint16_t *)ptr + 1;
-    }
-    break;
+static void *format_pxf_bgr24(void *ptr, const uint32_t *p, size_t n)
+{
+  char *q = ptr;
 
-  case PXF_LE_RGB15_555:
-    {
-      uint16_t pxv =
-       ((bgra >> 3) & 0x1f) +
-       ((bgra >> (2+8-5)) & (0x1f << 5)) +
-       ((bgra >> (3+16-10)) & (0x1f << 10));
+  while (n--) {
+    *(uint32_t *)q = *p++;
+    q += 3;
+  }
+  return q;
+}
 
-      *(uint16_t *)ptr = pxv;
-      ptr = (uint16_t *)ptr + 1;
-    }
-    break;
+static void *format_pxf_le_rgb16_565(void *ptr, const uint32_t *p, size_t n)
+{
+  uint32_t bgra;
+  uint16_t *q = ptr;
 
-  case PXF_NONE:               /* Shuts up gcc */
-    break;
+  while (n--) {
+    bgra = *p++;
+    *q++ =
+      ((bgra >> 3) & 0x1f) +
+      ((bgra >> (2+8-5)) & (0x3f << 5)) +
+      ((bgra >> (3+16-11)) & (0x1f << 11));
   }
+  return q;
+}
 
-  return ptr;
+static void *format_pxf_le_rgb15_555(void *ptr, const uint32_t *p, size_t n)
+{
+  uint32_t bgra;
+  uint16_t *q = ptr;
+
+  while (n--) {
+    bgra = *p++;
+    *q++ =
+      ((bgra >> 3) & 0x1f) +
+      ((bgra >> (2+8-5)) & (0x1f << 5)) +
+      ((bgra >> (3+16-10)) & (0x1f << 10));
+  }
+  return q;
 }
 
-#endif /* LIB_SYS_VESA_FMTPIXEL_H */
+__vesacon_format_pixels_t __vesacon_format_pixels;
+
+const __vesacon_format_pixels_t __vesacon_format_pixels_list[PXF_NONE] = {
+  [PXF_BGRA32]       = format_pxf_bgra32,
+  [PXF_BGR24]        = format_pxf_bgr24,
+  [PXF_LE_RGB16_565] = format_pxf_le_rgb16_565,
+  [PXF_LE_RGB15_555] = format_pxf_le_rgb15_555,
+};
index d5aa9ba..b5aba98 100644 (file)
@@ -236,6 +236,7 @@ static int vesacon_set_mode(void)
   mi = &__vesa_info.mi;
   mode = bestmode;
   __vesacon_bytes_per_pixel = (mi->bpp+7) >> 3;
+  __vesacon_format_pixels = __vesacon_format_pixels_list[bestpxf];
 
   /* Download the SYSLINUX- or BIOS-provided font */
   rm.eax.w[0] = 0x0018;                /* Query custom font */
index a8be430..f526de5 100644 (file)
@@ -42,7 +42,7 @@ static struct win_info {
 } wi;
 
 static void *
-vesacon_copy_to_paged_screen(void *dst, const void *src, size_t len);
+memcpy_to_paged_screen(void *dst, const void *src, size_t len);
 
 static inline int __constfunc ilog2(unsigned int x)
 {
@@ -50,15 +50,17 @@ static inline int __constfunc ilog2(unsigned int x)
   return x;
 }
 
+static void * (*memcpy_to_screen)(void *, const void *, size_t);
+
 void __vesacon_init_copy_to_screen(void)
 {
   struct vesa_mode_info * const mi = &__vesa_info.mi;
   int winn;
 
   if (mi->mode_attr & 0x0080) {
-    __vesacon_copy_to_screen = memcpy; /* Really easy... */
+    memcpy_to_screen = memcpy;
   } else {
-    __vesacon_copy_to_screen = vesacon_copy_to_paged_screen;
+    memcpy_to_screen = memcpy_to_paged_screen;
 
     mi->lfb_ptr = 0;           /* Zero-base this */
     wi.win_pos = -1;           /* Undefined position */
@@ -76,8 +78,17 @@ void __vesacon_init_copy_to_screen(void)
   }
 }
 
+void __vesacon_copy_to_screen(void *dst, const uint32_t *src, size_t npixels)
+{
+  size_t bytes = npixels * __vesacon_bytes_per_pixel;
+  char rowbuf[bytes+4];
+
+  __vesacon_format_pixels(rowbuf, src, npixels);
+  memcpy_to_screen(dst, rowbuf, bytes);
+}
+
 static void *
-vesacon_copy_to_paged_screen(void *dst, const void *src, size_t len)
+memcpy_to_paged_screen(void *dst, const void *src, size_t len)
 {
   size_t win_pos, win_off;
   size_t win_size = wi.win_size;
@@ -86,18 +97,16 @@ vesacon_copy_to_paged_screen(void *dst, const void *src, size_t len)
   size_t l;
   size_t d = (size_t)dst;
   const char *s = src;
-  com32sys_t ireg;
-
-  memset(&ireg, 0, sizeof ireg);
-  ireg.eax.w[0] = 0x4F05;      /* VBE Window Control */
-  /* BH = 0 -> Set memory window */
-  ireg.ebx.b[0] = wi.win_num;
 
   while (len) {
     win_off = d & omask;
     win_pos = d & ~omask;
 
     if (win_pos != wi.win_pos) {
+      com32sys_t ireg;
+      memset(&ireg, 0, sizeof ireg);
+      ireg.eax.w[0] = 0x4F05;
+      ireg.ebx.b[0] = wi.win_num;
       ireg.edx.w[0] = win_pos >> wi.win_gshift;
       __intcall(0x10, &ireg, NULL);
       wi.win_pos = win_pos;
index 699d4e9..3905208 100644 (file)
@@ -58,12 +58,15 @@ enum vesa_pixel_format {
   PXF_LE_RGB15_555,            /* 15-bit littleendian 5:5:5 RGB */
   PXF_NONE
 };
+extern enum vesa_pixel_format __vesacon_pixel_format;
+extern unsigned int __vesacon_bytes_per_pixel;
+typedef void * (*__vesacon_format_pixels_t)(void *, const uint32_t *, size_t);
+extern __vesacon_format_pixels_t __vesacon_format_pixels;
+extern const __vesacon_format_pixels_t __vesacon_format_pixels_list[PXF_NONE];
 
 extern struct vesa_char *__vesacon_text_display;
 
 extern int __vesacon_font_height, __vesacon_text_rows;
-extern enum vesa_pixel_format __vesacon_pixel_format;
-extern unsigned int __vesacon_bytes_per_pixel;
 extern uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
 extern uint32_t __vesacon_background[VIDEO_Y_SIZE][VIDEO_X_SIZE];
 extern uint32_t __vesacon_shadowfb[VIDEO_Y_SIZE][VIDEO_X_SIZE];
@@ -81,7 +84,7 @@ void __vesacon_write_char(int, int, uint8_t, attr_t);
 void __vesacon_redraw_text(void);
 void __vesacon_doit(void);
 void __vesacon_set_cursor(int, int, int);
-void * (*__vesacon_copy_to_screen)(void *, const void *, size_t);
+void __vesacon_copy_to_screen(void *, const uint32_t *, size_t);
 void __vesacon_init_copy_to_screen(void);
 
 #endif /* LIB_SYS_VESA_VIDEO_H */