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

Message ID 20220425075954.10427-6-vasyl.vavrychuk@opensynergy.com
State New
Headers show
Series Implement DRM backend | expand

Commit Message

Vasyl Vavrychuk April 25, 2022, 7:59 a.m. UTC
psplash_fb_plot_pixel is in fact framebuffer independent.

Signed-off-by: Vasyl Vavrychuk <vasyl.vavrychuk@opensynergy.com>
---
 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

Patch

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@o-hand.com>
+ *
+ *  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@o-hand.com>
+ *
+ *  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,