From f0504ac0abd16b5e98456fb3ea2777e6b64418ec Mon Sep 17 00:00:00 2001 From: Vasyl Vavrychuk Date: Mon, 25 Apr 2022 10:59:45 +0300 Subject: [PATCH 06/17] Extract plot pixel from psplash-fb psplash_fb_plot_pixel is in fact framebuffer independent. drm-backend backport from: https://patchwork.yoctoproject.org/project/yocto/cover/20220425075954.10427-1-vasyl.vavrychuk@opensynergy.com/ Signed-off-by: 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 + * + * 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 + * + * 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 -#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.25.1