Skip to content
This repository has been archived by the owner on Oct 11, 2019. It is now read-only.

Commit

Permalink
psplash: Fix so the code honours whatever bit order the display repor…
Browse files Browse the repository at this point in the history
…ts with fast paths for the most common cases.

git-svn-id: http://svn.o-hand.com/repos/misc/trunk/psplash@422 f5eea0f0-44ea-0310-b729-df5b855dafe5
  • Loading branch information
richard committed May 28, 2009
1 parent bb80e9e commit 0575ab6
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 22 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
2009-05-28 Richard Purdie <[email protected]>

* 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 <[email protected]>

* psplash-fb.c:
Expand Down
109 changes: 89 additions & 20 deletions psplash-fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down
16 changes: 16 additions & 0 deletions psplash-fb.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
#ifndef _HAVE_PSPLASH_FB_H
#define _HAVE_PSPLASH_FB_H

enum RGBMode {
RGB565,
BGR565,
RGB888,
BGR888,
GENERIC,
};

typedef struct PSplashFB
{
int fd;
Expand All @@ -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;

Expand Down
5 changes: 3 additions & 2 deletions psplash.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand All @@ -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
Expand Down

0 comments on commit 0575ab6

Please sign in to comment.