psplash: Fix so the code honours whatever bit order the display reports with fast...
authorRichard Purdie <richard.purdie@linuxfoundation.org>
Thu, 28 May 2009 22:13:33 +0000 (22:13 +0000)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Thu, 28 May 2009 22:13:33 +0000 (22:13 +0000)
ChangeLog
psplash-fb.c
psplash-fb.h
psplash.h

index 29539c0..8cf2156 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2009-05-28  Richard Purdie <rpurdie@linux.intel.com>
+
+       * psplash-fb.c:
+       * psplash-fb.h:
+       * psplash.h:
+       Fix so the code honours whatever bit order the display reports with 
+       fast paths for the most common cases.
+
 2009-05-19  Richard Purdie <rpurdie@linux.intel.com>
 
        * psplash-fb.c:
index 6fdba6a..71740cd 100644 (file)
@@ -142,6 +142,12 @@ psplash_fb_new (int angle)
         goto fail;
     }
 
+  if (ioctl (fb->fd, FBIOGET_VSCREENINFO, &fb_var) == -1)
+    {
+      perror ("Error getting variable framebuffer info (2)");
+      goto fail;
+    }
+
   /* NB: It looks like the fbdev concept of fixed vs variable screen info is
    * broken. The line_length is part of the fixed info but it can be changed
    * if you set a new pixel format. */
@@ -158,6 +164,33 @@ psplash_fb_new (int angle)
   fb->type   = fb_fix.type;
   fb->visual = fb_fix.visual;
 
+  fb->red_offset = fb_var.red.offset;
+  fb->red_length = fb_var.red.length;
+  fb->green_offset = fb_var.green.offset;
+  fb->green_length = fb_var.green.length;
+  fb->blue_offset = fb_var.blue.offset;
+  fb->blue_length = fb_var.blue.length;
+
+  if (fb->red_offset == 11 && fb->red_length == 5 &&
+      fb->green_offset == 5 && fb->green_length == 6 &&
+      fb->blue_offset == 0 && fb->blue_length == 5) {
+         fb->rgbmode = RGB565;
+  } else if (fb->red_offset == 0 && fb->red_length == 5 &&
+      fb->green_offset == 5 && fb->green_length == 6 &&
+      fb->blue_offset == 11 && fb->blue_length == 5) {
+         fb->rgbmode = BGR565;
+  } else if (fb->red_offset == 16 && fb->red_length == 8 &&
+      fb->green_offset == 8 && fb->green_length == 8 &&
+      fb->blue_offset == 0 && fb->blue_length == 8) {
+         fb->rgbmode = RGB888;
+  } else if (fb->red_offset == 0 && fb->red_length == 8 &&
+      fb->green_offset == 8 && fb->green_length == 8 &&
+      fb->blue_offset == 8 && fb->blue_length == 8) {
+         fb->rgbmode = BGR888;
+  } else {
+         fb->rgbmode = GENERIC;
+  }
+
   DBG("width: %i, height: %i, bpp: %i, stride: %i",
       fb->width, fb->height, fb->bpp, fb->stride);
 
@@ -257,24 +290,60 @@ psplash_fb_plot_pixel (PSplashFB    *fb,
       break;
     }
 
-  /* FIXME: handle no RGB orderings */
-  switch (fb->bpp)
-    {
-    case 24:
-    case 32:
-      *(fb->data + off)     = red;
-      *(fb->data + off + 1) = green;
-      *(fb->data + off + 2) = blue;
-      break;
-    case 16:
-      *(volatile uint16 *) (fb->data + off)
-       = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
-      break;
-    default:
-      /* depth not supported yet */
-      break;
-    }
-
+  if (fb->rgbmode == RGB565 || fb->rgbmode == RGB888) {
+    switch (fb->bpp)
+      {
+      case 24:
+      case 32:
+        *(fb->data + off)     = blue;
+        *(fb->data + off + 1) = green;
+        *(fb->data + off + 2) = red;
+        break;
+      case 16:
+        *(volatile uint16_t *) (fb->data + off)
+         = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
+        break;
+      default:
+        /* depth not supported yet */
+        break;
+      }
+  } else if (fb->rgbmode == BGR565 || fb->rgbmode == BGR888) {
+    switch (fb->bpp)
+      {
+      case 24:
+      case 32:
+        *(fb->data + off)     = red;
+        *(fb->data + off + 1) = green;
+        *(fb->data + off + 2) = blue;
+        break;
+      case 16:
+        *(volatile uint16_t *) (fb->data + off)
+         = ((blue >> 3) << 11) | ((green >> 2) << 5) | (red >> 3);
+        break;
+      default:
+        /* depth not supported yet */
+        break;
+      }
+  } else {
+    switch (fb->bpp)
+      {
+      case 32:
+        *(volatile uint32_t *) (fb->data + off)
+         = ((red >> (8 - fb->red_length)) << fb->red_offset) 
+             | ((green >> (8 - fb->green_length)) << fb->green_offset)
+             | ((blue >> (8 - fb->blue_length)) << fb->blue_offset);
+        break;
+      case 16:
+        *(volatile uint16_t *) (fb->data + off)
+         = ((red >> (8 - fb->red_length)) << fb->red_offset) 
+             | ((green >> (8 - fb->green_length)) << fb->green_offset)
+             | ((blue >> (8 - fb->blue_length)) << fb->blue_offset);
+        break;
+      default:
+        /* depth not supported yet */
+        break;
+      }
+  }
 }
 
 void
@@ -323,7 +392,7 @@ psplash_fb_draw_image (PSplashFB    *fb,
          do
            {
              if (img_bytes_per_pixel < 4 || *(p+3))
-               psplash_fb_plot_pixel (fb, x+dx, y+dy, *(p+2), *(p+1), *(p));
+               psplash_fb_plot_pixel (fb, x+dx, y+dy, *(p), *(p+1), *(p+2));
              if (++dx >= img_width) { dx=0; dy++; }
            }
          while (--len && (p - rle_data) < total_len);
@@ -337,7 +406,7 @@ psplash_fb_draw_image (PSplashFB    *fb,
          do
            {
              if (img_bytes_per_pixel < 4 || *(p+3))
-               psplash_fb_plot_pixel (fb, x+dx, y+dy, *(p+2), *(p+1), *(p));
+               psplash_fb_plot_pixel (fb, x+dx, y+dy, *(p), *(p+1), *(p+2));
              if (++dx >= img_width) { dx=0; dy++; }
              p += img_bytes_per_pixel;
            }
index 6c661f9..ef5b39e 100644 (file)
 #ifndef _HAVE_PSPLASH_FB_H
 #define _HAVE_PSPLASH_FB_H
 
+enum RGBMode {
+    RGB565,
+    BGR565,
+    RGB888,
+    BGR888,
+    GENERIC,
+};
+
 typedef struct PSplashFB
 {
   int            fd;                   
@@ -32,6 +40,14 @@ typedef struct PSplashFB
 
   int            angle;
   int            real_width, real_height;
+
+  enum RGBMode   rgbmode;
+  int            red_offset;
+  int            red_length;
+  int            green_offset;
+  int            green_length;
+  int            blue_offset;
+  int            blue_length;
 }
 PSplashFB;
 
index 36d63c5..22d73a3 100644 (file)
--- a/psplash.h
+++ b/psplash.h
@@ -29,6 +29,7 @@
 #include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #if defined(__i386__) || defined(__alpha__)
@@ -42,8 +43,8 @@
 #include <termios.h>
 #include <unistd.h>
 
-typedef unsigned char  uint8;
-typedef unsigned short uint16;
+typedef uint8_t  uint8;
+typedef uint16_t uint16;
 typedef int            bool;
 
 #ifndef FALSE