[psplash][RFC PATCH 05/14] Extract plot pixel from psplash-fb


Vasyl Vavrychuk
 

psplash_fb_plot_pixel is in fact framebuffer independent.

Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@...>
---
Makefile.am | 3 +-
psplash-draw.c | 120 +++++++++++++++++++++++++++++++
psplash-draw.h | 51 +++++++++++++
psplash-fb.c | 191 +++++++++++--------------------------------------
psplash-fb.h | 25 ++-----
psplash.c | 20 +++---
6 files changed, 229 insertions(+), 181 deletions(-)
create mode 100644 psplash-draw.c
create mode 100644 psplash-draw.h

diff --git a/Makefile.am b/Makefile.am
index 310e126..375b926 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,8 @@ AM_CFLAGS = $(GCC_FLAGS) $(EXTRA_GCC_FLAGS) -D_GNU_SOURCE -DFONT_HEADER=\"$(FONT
psplash_SOURCES = psplash.c psplash.h psplash-fb.c psplash-fb.h \
psplash-console.c psplash-console.h \
psplash-colors.h psplash-config.h \
- psplash-poky-img.h psplash-bar-img.h $(FONT_NAME)-font.h
+ psplash-poky-img.h psplash-bar-img.h $(FONT_NAME)-font.h \
+ psplash-draw.c psplash-draw.h
BUILT_SOURCES = psplash-poky-img.h psplash-bar-img.h

psplash_write_SOURCES = psplash-write.c psplash.h
diff --git a/psplash-draw.c b/psplash-draw.c
new file mode 100644
index 0000000..570cfce
--- /dev/null
+++ b/psplash-draw.c
@@ -0,0 +1,120 @@
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
+ *
+ * Copyright (c) 2006 Matthew Allum <mallum@...>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#include "psplash-draw.h"
+
+#define OFFSET(canvas, x, y) (((y) * (canvas)->stride) + ((x) * ((canvas)->bpp >> 3)))
+
+/* TODO: change to 'static inline' as psplash_fb_plot_pixel was before */
+void
+psplash_plot_pixel(PSplashCanvas *canvas,
+ int x,
+ int y,
+ uint8 red,
+ uint8 green,
+ uint8 blue)
+{
+ /* Always write to back data (data) which points to the right data with or
+ * without double buffering support */
+ int off;
+
+ if (x < 0 || x > canvas->width-1 || y < 0 || y > canvas->height-1)
+ return;
+
+ switch (canvas->angle)
+ {
+ case 270:
+ off = OFFSET (canvas, canvas->height - y - 1, x);
+ break;
+ case 180:
+ off = OFFSET (canvas, canvas->width - x - 1, canvas->height - y - 1);
+ break;
+ case 90:
+ off = OFFSET (canvas, y, canvas->width - x - 1);
+ break;
+ case 0:
+ default:
+ off = OFFSET (canvas, x, y);
+ break;
+ }
+
+ if (canvas->rgbmode == RGB565 || canvas->rgbmode == RGB888) {
+ switch (canvas->bpp)
+ {
+ case 24:
+#if __BYTE_ORDER == __BIG_ENDIAN
+ *(canvas->data + off + 0) = red;
+ *(canvas->data + off + 1) = green;
+ *(canvas->data + off + 2) = blue;
+#else
+ *(canvas->data + off + 0) = blue;
+ *(canvas->data + off + 1) = green;
+ *(canvas->data + off + 2) = red;
+#endif
+ break;
+ case 32:
+ *(volatile uint32_t *) (canvas->data + off)
+ = (red << 16) | (green << 8) | (blue);
+ break;
+
+ case 16:
+ *(volatile uint16_t *) (canvas->data + off)
+ = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
+ break;
+ default:
+ /* depth not supported yet */
+ break;
+ }
+ } else if (canvas->rgbmode == BGR565 || canvas->rgbmode == BGR888) {
+ switch (canvas->bpp)
+ {
+ case 24:
+#if __BYTE_ORDER == __BIG_ENDIAN
+ *(canvas->data + off + 0) = blue;
+ *(canvas->data + off + 1) = green;
+ *(canvas->data + off + 2) = red;
+#else
+ *(canvas->data + off + 0) = red;
+ *(canvas->data + off + 1) = green;
+ *(canvas->data + off + 2) = blue;
+#endif
+ break;
+ case 32:
+ *(volatile uint32_t *) (canvas->data + off)
+ = (blue << 16) | (green << 8) | (red);
+ break;
+ case 16:
+ *(volatile uint16_t *) (canvas->data + off)
+ = ((blue >> 3) << 11) | ((green >> 2) << 5) | (red >> 3);
+ break;
+ default:
+ /* depth not supported yet */
+ break;
+ }
+ } else {
+ switch (canvas->bpp)
+ {
+ case 32:
+ *(volatile uint32_t *) (canvas->data + off)
+ = ((red >> (8 - canvas->red_length)) << canvas->red_offset)
+ | ((green >> (8 - canvas->green_length)) << canvas->green_offset)
+ | ((blue >> (8 - canvas->blue_length)) << canvas->blue_offset);
+ break;
+ case 16:
+ *(volatile uint16_t *) (canvas->data + off)
+ = ((red >> (8 - canvas->red_length)) << canvas->red_offset)
+ | ((green >> (8 - canvas->green_length)) << canvas->green_offset)
+ | ((blue >> (8 - canvas->blue_length)) << canvas->blue_offset);
+ break;
+ default:
+ /* depth not supported yet */
+ break;
+ }
+ }
+}
diff --git a/psplash-draw.h b/psplash-draw.h
new file mode 100644
index 0000000..ab2d4d2
--- /dev/null
+++ b/psplash-draw.h
@@ -0,0 +1,51 @@
+/*
+ * pslash - a lightweight framebuffer splashscreen for embedded devices.
+ *
+ * Copyright (c) 2006 Matthew Allum <mallum@...>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ */
+
+#ifndef _HAVE_PSPLASH_CANVAS_H
+#define _HAVE_PSPLASH_CANVAS_H
+
+#include "psplash.h"
+
+enum RGBMode {
+ RGB565,
+ BGR565,
+ RGB888,
+ BGR888,
+ GENERIC,
+};
+
+typedef struct PSplashCanvas
+{
+ int width, height;
+ int bpp;
+ int stride;
+ char *data;
+
+ int angle;
+
+ enum RGBMode rgbmode;
+ int red_offset;
+ int red_length;
+ int green_offset;
+ int green_length;
+ int blue_offset;
+ int blue_length;
+}
+PSplashCanvas;
+
+/* TODO: Remove after rest of drawing functions migrated to psplash-draw.c */
+void
+psplash_plot_pixel(PSplashCanvas *canvas,
+ int x,
+ int y,
+ uint8 red,
+ uint8 green,
+ uint8 blue);
+
+#endif
diff --git a/psplash-fb.c b/psplash-fb.c
index 5dea82a..a7029c5 100644
--- a/psplash-fb.c
+++ b/psplash-fb.c
@@ -42,10 +42,11 @@ psplash_fb_flip(PSplashFB *fb, int sync)
tmp = fb->fdata;
fb->fdata = fb->bdata;
fb->bdata = tmp;
+ fb->canvas.data = fb->bdata;

/* Sync new front to new back when requested */
if (sync) {
- memcpy(fb->bdata, fb->fdata, fb->stride * fb->real_height);
+ memcpy(fb->bdata, fb->fdata, fb->canvas.stride * fb->real_height);
}
}
}
@@ -220,42 +221,42 @@ psplash_fb_new (int angle, int fbdev_id)
}
}

- fb->real_width = fb->width = fb_var.xres;
- fb->real_height = fb->height = fb_var.yres;
- fb->bpp = fb_var.bits_per_pixel;
- fb->stride = fb_fix.line_length;
+ fb->real_width = fb->canvas.width = fb_var.xres;
+ fb->real_height = fb->canvas.height = fb_var.yres;
+ fb->canvas.bpp = fb_var.bits_per_pixel;
+ fb->canvas.stride = fb_fix.line_length;
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 == 16 && fb->blue_length == 8) {
- fb->rgbmode = BGR888;
+ fb->canvas.red_offset = fb_var.red.offset;
+ fb->canvas.red_length = fb_var.red.length;
+ fb->canvas.green_offset = fb_var.green.offset;
+ fb->canvas.green_length = fb_var.green.length;
+ fb->canvas.blue_offset = fb_var.blue.offset;
+ fb->canvas.blue_length = fb_var.blue.length;
+
+ if (fb->canvas.red_offset == 11 && fb->canvas.red_length == 5 &&
+ fb->canvas.green_offset == 5 && fb->canvas.green_length == 6 &&
+ fb->canvas.blue_offset == 0 && fb->canvas.blue_length == 5) {
+ fb->canvas.rgbmode = RGB565;
+ } else if (fb->canvas.red_offset == 0 && fb->canvas.red_length == 5 &&
+ fb->canvas.green_offset == 5 && fb->canvas.green_length == 6 &&
+ fb->canvas.blue_offset == 11 && fb->canvas.blue_length == 5) {
+ fb->canvas.rgbmode = BGR565;
+ } else if (fb->canvas.red_offset == 16 && fb->canvas.red_length == 8 &&
+ fb->canvas.green_offset == 8 && fb->canvas.green_length == 8 &&
+ fb->canvas.blue_offset == 0 && fb->canvas.blue_length == 8) {
+ fb->canvas.rgbmode = RGB888;
+ } else if (fb->canvas.red_offset == 0 && fb->canvas.red_length == 8 &&
+ fb->canvas.green_offset == 8 && fb->canvas.green_length == 8 &&
+ fb->canvas.blue_offset == 16 && fb->canvas.blue_length == 8) {
+ fb->canvas.rgbmode = BGR888;
} else {
- fb->rgbmode = GENERIC;
+ fb->canvas.rgbmode = GENERIC;
}

DBG("width: %i, height: %i, bpp: %i, stride: %i",
- fb->width, fb->height, fb->bpp, fb->stride);
+ fb->canvas.width, fb->canvas.height, fb->canvas.bpp, fb->canvas.stride);

fb->base = (char *) mmap ((caddr_t) NULL,
fb_fix.smem_len,
@@ -279,16 +280,17 @@ psplash_fb_new (int angle, int fbdev_id)
if (fb->fb_var.yoffset == 0) {
printf("to back\n");
fb->fdata = fb->data;
- fb->bdata = fb->data + fb->stride * fb->height;
+ fb->bdata = fb->data + fb->canvas.stride * fb->canvas.height;
} else {
printf("to front\n");
- fb->fdata = fb->data + fb->stride * fb->height;
+ fb->fdata = fb->data + fb->canvas.stride * fb->canvas.height;
fb->bdata = fb->data;
}
} else {
fb->fdata = fb->data;
fb->bdata = fb->data;
}
+ fb->canvas.data = fb->bdata;

#if 0
/* FIXME: No support for 8pp as yet */
@@ -312,14 +314,14 @@ psplash_fb_new (int angle, int fbdev_id)
status = 2;
#endif

- fb->angle = angle;
+ fb->canvas.angle = angle;

- switch (fb->angle)
+ switch (angle)
{
case 270:
case 90:
- fb->width = fb->real_height;
- fb->height = fb->real_width;
+ fb->canvas.width = fb->real_height;
+ fb->canvas.height = fb->real_width;
break;
case 180:
case 0:
@@ -337,115 +339,6 @@ psplash_fb_new (int angle, int fbdev_id)
return NULL;
}

-#define OFFSET(fb,x,y) (((y) * (fb)->stride) + ((x) * ((fb)->bpp >> 3)))
-
-static inline void
-psplash_fb_plot_pixel (PSplashFB *fb,
- int x,
- int y,
- uint8 red,
- uint8 green,
- uint8 blue)
-{
- /* Always write to back data (bdata) which points to the right data with or
- * without double buffering support */
- int off;
-
- if (x < 0 || x > fb->width-1 || y < 0 || y > fb->height-1)
- return;
-
- switch (fb->angle)
- {
- case 270:
- off = OFFSET (fb, fb->height - y - 1, x);
- break;
- case 180:
- off = OFFSET (fb, fb->width - x - 1, fb->height - y - 1);
- break;
- case 90:
- off = OFFSET (fb, y, fb->width - x - 1);
- break;
- case 0:
- default:
- off = OFFSET (fb, x, y);
- break;
- }
-
- if (fb->rgbmode == RGB565 || fb->rgbmode == RGB888) {
- switch (fb->bpp)
- {
- case 24:
-#if __BYTE_ORDER == __BIG_ENDIAN
- *(fb->bdata + off + 0) = red;
- *(fb->bdata + off + 1) = green;
- *(fb->bdata + off + 2) = blue;
-#else
- *(fb->bdata + off + 0) = blue;
- *(fb->bdata + off + 1) = green;
- *(fb->bdata + off + 2) = red;
-#endif
- break;
- case 32:
- *(volatile uint32_t *) (fb->bdata + off)
- = (red << 16) | (green << 8) | (blue);
- break;
-
- case 16:
- *(volatile uint16_t *) (fb->bdata + 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:
-#if __BYTE_ORDER == __BIG_ENDIAN
- *(fb->bdata + off + 0) = blue;
- *(fb->bdata + off + 1) = green;
- *(fb->bdata + off + 2) = red;
-#else
- *(fb->bdata + off + 0) = red;
- *(fb->bdata + off + 1) = green;
- *(fb->bdata + off + 2) = blue;
-#endif
- break;
- case 32:
- *(volatile uint32_t *) (fb->bdata + off)
- = (blue << 16) | (green << 8) | (red);
- break;
- case 16:
- *(volatile uint16_t *) (fb->bdata + 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->bdata + 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->bdata + 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
psplash_fb_draw_rect (PSplashFB *fb,
int x,
@@ -460,7 +353,7 @@ psplash_fb_draw_rect (PSplashFB *fb,

for (dy=0; dy < height; dy++)
for (dx=0; dx < width; dx++)
- psplash_fb_plot_pixel (fb, x+dx, y+dy, red, green, blue);
+ psplash_plot_pixel(&fb->canvas, x+dx, y+dy, red, green, blue);
}

void
@@ -493,7 +386,7 @@ psplash_fb_draw_image (PSplashFB *fb,
do
{
if ((img_bytes_per_pixel < 4 || *(p+3)) && dx < img_width)
- psplash_fb_plot_pixel (fb, x+dx, y+dy, *(p), *(p+1), *(p+2));
+ psplash_plot_pixel(&fb->canvas, x+dx, y+dy, *(p), *(p+1), *(p+2));
if (++dx * img_bytes_per_pixel >= img_rowstride) { dx=0; dy++; }
}
while (--len);
@@ -507,7 +400,7 @@ psplash_fb_draw_image (PSplashFB *fb,
do
{
if ((img_bytes_per_pixel < 4 || *(p+3)) && dx < img_width)
- psplash_fb_plot_pixel (fb, x+dx, y+dy, *(p), *(p+1), *(p+2));
+ psplash_plot_pixel(&fb->canvas, x+dx, y+dy, *(p), *(p+1), *(p+2));
if (++dx * img_bytes_per_pixel >= img_rowstride) { dx=0; dy++; }
p += img_bytes_per_pixel;
}
@@ -613,7 +506,7 @@ psplash_fb_draw_text (PSplashFB *fb,
for (cx = 0; cx < w; cx++)
{
if (g & 0x80000000)
- psplash_fb_plot_pixel (fb, x+dx+cx, y+dy+cy,
+ psplash_plot_pixel(&fb->canvas, x+dx+cx, y+dy+cy,
red, green, blue);
g <<= 1;
}
diff --git a/psplash-fb.h b/psplash-fb.h
index 4d5c460..eb02c62 100644
--- a/psplash-fb.h
+++ b/psplash-fb.h
@@ -11,25 +11,16 @@
#define _HAVE_PSPLASH_FB_H

#include <linux/fb.h>
-#include "psplash.h"
-
-enum RGBMode {
- RGB565,
- BGR565,
- RGB888,
- BGR888,
- GENERIC,
-};
+#include "psplash-draw.h"

typedef struct PSplashFB
{
+ PSplashCanvas canvas;
+
int fd;
struct fb_var_screeninfo fb_var;
int type;
int visual;
- int width, height;
- int bpp;
- int stride;
char *data;
char *base;

@@ -38,16 +29,8 @@ typedef struct PSplashFB
char *bdata;
char *fdata;

- int angle, fbdev_id;
+ int fbdev_id;
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;

diff --git a/psplash.c b/psplash.c
index 18c012b..f23f03d 100644
--- a/psplash.c
+++ b/psplash.c
@@ -22,10 +22,10 @@
#include FONT_HEADER

#define SPLIT_LINE_POS(fb) \
- ( (fb)->height \
+ ( (fb)->canvas.height \
- (( PSPLASH_IMG_SPLIT_DENOMINATOR \
- PSPLASH_IMG_SPLIT_NUMERATOR) \
- * (fb)->height / PSPLASH_IMG_SPLIT_DENOMINATOR) \
+ * (fb)->canvas.height / PSPLASH_IMG_SPLIT_DENOMINATOR) \
)

void
@@ -50,12 +50,12 @@ psplash_draw_msg (PSplashFB *fb, const char *msg)
psplash_fb_draw_rect (fb,
0,
SPLIT_LINE_POS(fb) - h,
- fb->width,
+ fb->canvas.width,
h,
PSPLASH_BACKGROUND_COLOR);

psplash_fb_draw_text (fb,
- (fb->width-w)/2,
+ (fb->canvas.width-w)/2,
SPLIT_LINE_POS(fb) - h,
PSPLASH_TEXT_COLOR,
&FONT_DEF,
@@ -69,7 +69,7 @@ psplash_draw_progress (PSplashFB *fb, int value)
int x, y, width, height, barwidth;

/* 4 pix border */
- x = ((fb->width - BAR_IMG_WIDTH)/2) + 4 ;
+ x = ((fb->canvas.width - BAR_IMG_WIDTH)/2) + 4 ;
y = SPLIT_LINE_POS(fb) + 4;
width = BAR_IMG_WIDTH - 8;
height = BAR_IMG_HEIGHT - 8;
@@ -301,16 +301,16 @@ main (int argc, char** argv)
#endif

/* Clear the background with #ecece1 */
- psplash_fb_draw_rect (fb, 0, 0, fb->width, fb->height,
+ psplash_fb_draw_rect (fb, 0, 0, fb->canvas.width, fb->canvas.height,
PSPLASH_BACKGROUND_COLOR);

/* Draw the Poky logo */
psplash_fb_draw_image (fb,
- (fb->width - POKY_IMG_WIDTH)/2,
+ (fb->canvas.width - POKY_IMG_WIDTH)/2,
#if PSPLASH_IMG_FULLSCREEN
- (fb->height - POKY_IMG_HEIGHT)/2,
+ (fb->canvas.height - POKY_IMG_HEIGHT)/2,
#else
- (fb->height * PSPLASH_IMG_SPLIT_NUMERATOR
+ (fb->canvas.height * PSPLASH_IMG_SPLIT_NUMERATOR
/ PSPLASH_IMG_SPLIT_DENOMINATOR - POKY_IMG_HEIGHT)/2,
#endif
POKY_IMG_WIDTH,
@@ -322,7 +322,7 @@ main (int argc, char** argv)
#ifdef PSPLASH_SHOW_PROGRESS_BAR
/* Draw progress bar border */
psplash_fb_draw_image (fb,
- (fb->width - BAR_IMG_WIDTH)/2,
+ (fb->canvas.width - BAR_IMG_WIDTH)/2,
SPLIT_LINE_POS(fb),
BAR_IMG_WIDTH,
BAR_IMG_HEIGHT,
--
2.30.2