From 3237ae4a4ff9296a377ff9194a11038da161208f Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Wed, 7 Oct 2020 02:01:35 -0400 Subject: LCD core move buf ptr and address look up function viewport struct I'm currently running up against the limitations of the lcd_draw functions I want these functions to be able to be used on any size buffer not just buffers with a stride matching the underlying device [DONE] allow the framebuffer to be decoupled from the device framebuffer [DONE need examples] allow for some simple blit like transformations [DONE] remove the device framebuffer from the plugin api [DONE}ditto remote framebuffer [DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr while remote lcds may compile (and work in the sim) its not been tested on targets [FIXED] backdrops need work to be screen agnostic [FIXED] screen statusbar is not being combined into the main viewport correctly yet [FIXED] screen elements are displayed incorrectly after switch to void* [FIXED] core didn't restore proper viewport on splash etc. [NEEDS TESTING] remote lcd garbled data [FIXED] osd lib garbled screen on bmp_part [FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport [FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer [FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw) [UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear scrolling viewports no longer trigger wps refresh also fixed a bug where guisyncyesno was displaying and then disappearing [ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes (LCD_ and LCD_REMOTE_) LCD_STRIDE(w, h) same as STRIDE_MAIN LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH) test_viewports.c has an example of usage [FIXED!!] 2bit targets don't respect non-native strides [FIXED] Few define snags Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af --- firmware/export/lcd.h | 271 +++++++++++++++++++++++++++++++------------------- 1 file changed, 170 insertions(+), 101 deletions(-) (limited to 'firmware/export/lcd.h') diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index ae06307dca..af734da913 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -23,30 +23,11 @@ #define __LCD_H__ #include +#include #include "cpu.h" #include "config.h" #include "events.h" -#define VP_FLAG_ALIGN_RIGHT 0x01 -#define VP_FLAG_ALIGN_CENTER 0x02 - -#define VP_FLAG_ALIGNMENT_MASK \ - (VP_FLAG_ALIGN_RIGHT|VP_FLAG_ALIGN_CENTER) - -#define VP_IS_RTL(vp) (((vp)->flags & VP_FLAG_ALIGNMENT_MASK) == VP_FLAG_ALIGN_RIGHT) - -struct viewport { - int x; - int y; - int width; - int height; - int flags; - int font; - int drawmode; - /* needed for even for mono displays to support greylib */ - unsigned fg_pattern; - unsigned bg_pattern; -}; /* Frame buffer stride * @@ -101,7 +82,7 @@ enum screen_type { struct scrollinfo; -#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE #define STRIDE_MAIN(w, h) (h) #else #define STRIDE_MAIN(w, h) (w) @@ -115,46 +96,105 @@ struct scrollinfo; #if LCD_DEPTH <=8 #if (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) \ || (LCD_PIXELFORMAT == HORIZONTAL_INTERLEAVED) -typedef unsigned short fb_data; + typedef unsigned short fb_data; #define FB_DATA_SZ 2 #else -typedef unsigned char fb_data; + typedef unsigned char fb_data; #define FB_DATA_SZ 1 #endif #elif LCD_DEPTH <= 16 -typedef unsigned short fb_data; + typedef unsigned short fb_data; #define FB_DATA_SZ 2 #elif LCD_DEPTH <= 24 -struct _fb_pixel { - unsigned char b, g, r; -}; -typedef struct _fb_pixel fb_data; + struct _fb_pixel { + unsigned char b, g, r; + }; + typedef struct _fb_pixel fb_data; #define FB_DATA_SZ 3 #else /* LCD_DEPTH > 24 */ #if (LCD_PIXELFORMAT == XRGB8888) -struct _fb_pixel { - unsigned char b, g, r, x; -}; -typedef struct _fb_pixel fb_data; + struct _fb_pixel { + unsigned char b, g, r, x; + }; + typedef struct _fb_pixel fb_data; #else -typedef unsigned long fb_data; + typedef unsigned long fb_data; #endif #define FB_DATA_SZ 4 #endif /* LCD_DEPTH */ +#ifdef HAVE_REMOTE_LCD +#if LCD_REMOTE_DEPTH <= 8 +#if (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) \ + || (LCD_REMOTE_PIXELFORMAT == HORIZONTAL_INTERLEAVED) + typedef unsigned short fb_remote_data; +#define FB_RDATA_SZ 2 +#else + typedef unsigned char fb_remote_data; +#define FB_RDATA_SZ 1 +#endif +#elif LCD_DEPTH <= 16 + typedef unsigned short fb_remote_data; +#define FB_RDATA_SZ 2 +#else + typedef unsigned long fb_remote_data; +#define FB_RDATA_SZ 4 +#endif +#endif + #if defined(HAVE_LCD_MODES) -void lcd_set_mode(int mode); + void lcd_set_mode(int mode); #define LCD_MODE_RGB565 0x00000001 #define LCD_MODE_YUV 0x00000002 #define LCD_MODE_PAL256 0x00000004 #if HAVE_LCD_MODES & LCD_MODE_PAL256 - void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, + void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, int width, int height); - void lcd_pal256_update_pal(fb_data *palette); + void lcd_pal256_update_pal(fb_data *palette); #endif #endif +struct frame_buffer_t { + union + { + void *data; + char *ch_ptr; + fb_data *fb_ptr; +#ifdef HAVE_REMOTE_LCD + fb_remote_data *fb_remote_ptr; +#endif + }; + void *(*get_address_fn)(int x, int y); + ptrdiff_t stride; + size_t elems; +}; + +#define VP_FLAG_ALIGN_RIGHT 0x01 +#define VP_FLAG_ALIGN_CENTER 0x02 + +#define VP_FLAG_ALIGNMENT_MASK \ + (VP_FLAG_ALIGN_RIGHT|VP_FLAG_ALIGN_CENTER) + +#define VP_IS_RTL(vp) (((vp)->flags & VP_FLAG_ALIGNMENT_MASK) == VP_FLAG_ALIGN_RIGHT) + +#define VP_FLAG_VP_DIRTY 0x4000 +#define VP_FLAG_CLEAR_FLAG 0x8000 +#define VP_FLAG_VP_SET_CLEAN (VP_FLAG_CLEAR_FLAG | VP_FLAG_VP_DIRTY) + +struct viewport { + int x; + int y; + int width; + int height; + int flags; + int font; + int drawmode; + struct frame_buffer_t *buffer; + /* needed for even for mono displays to support greylib */ + unsigned fg_pattern; + unsigned bg_pattern; +}; /* common functions */ extern void lcd_write_command(int byte); @@ -171,7 +211,10 @@ extern int lcd_getwidth(void); extern int lcd_getheight(void); extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); -extern void lcd_set_viewport(struct viewport* vp); +extern struct viewport* lcd_init_viewport(struct viewport* vp); +extern struct viewport* lcd_set_viewport(struct viewport* vp); +extern struct viewport* lcd_set_viewport_ex(struct viewport* vp, int flags); + extern void lcd_update(void); extern void lcd_update_viewport(void); extern void lcd_update_viewport_rect(int x, int y, int width, int height); @@ -193,15 +236,15 @@ extern bool lcd_putsxy_scroll_func(int x, int y, const unsigned char *string, #if defined(HAVE_LCD_COLOR) #if MEMORYSIZE > 2 #define LCD_YUV_DITHER 0x1 -extern void lcd_yuv_set_options(unsigned options); -extern void lcd_blit_yuv(unsigned char * const src[3], + extern void lcd_yuv_set_options(unsigned options); + extern void lcd_blit_yuv(unsigned char * const src[3], int src_x, int src_y, int stride, int x, int y, int width, int height); #endif /* MEMORYSIZE > 2 */ #else -extern void lcd_blit_mono(const unsigned char *data, int x, int by, int width, + extern void lcd_blit_mono(const unsigned char *data, int x, int by, int width, int bheight, int stride); -extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, + extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, int bx, int by, int bwidth, int bheight, int stride); #endif @@ -211,9 +254,9 @@ extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, extern void lcd_update_rect(int x, int y, int width, int height); #ifdef HAVE_REMOTE_LCD -extern void lcd_remote_update(void); -/* update a fraction of the screen */ -extern void lcd_remote_update_rect(int x, int y, int width, int height); + extern void lcd_remote_update(void); + /* update a fraction of the screen */ + extern void lcd_remote_update_rect(int x, int y, int width, int height); #endif /* HAVE_REMOTE_LCD */ /* Bitmap formats */ @@ -239,13 +282,13 @@ enum typedef void lcd_pixelfunc_type(int x, int y); typedef void lcd_blockfunc_type(fb_data *address, unsigned mask, unsigned bits); #if LCD_DEPTH >= 8 -typedef void lcd_fastpixelfunc_type(fb_data *address); + typedef void lcd_fastpixelfunc_type(fb_data *address); #endif #if defined(HAVE_LCD_COLOR) && defined(LCD_REMOTE_DEPTH) && \ LCD_REMOTE_DEPTH > 1 /* Just return color for screens use */ -static inline unsigned lcd_color_to_native(unsigned color) + static inline unsigned lcd_color_to_native(unsigned color) { return color; } #define SCREEN_COLOR_TO_NATIVE(screen, color) (screen)->color_to_native(color) #else @@ -286,7 +329,7 @@ static inline unsigned lcd_color_to_native(unsigned color) (((b) >> 3) << 8) ) /* swap color once - not currenly used in static inits */ #define _SWAPUNPACK(x, _unp_) \ - ({ typeof (x) _x_ = swap16(x); _unp_(_x_); }) + ({ typeof (x) _x_ = swap16(x); _unp_(_x_); }) #define RGB_UNPACK_RED(x) _SWAPUNPACK((x), _RGB_UNPACK_RED) #define RGB_UNPACK_GREEN(x) _SWAPUNPACK((x), _RGB_UNPACK_GREEN) #define RGB_UNPACK_BLUE(x) _SWAPUNPACK((x), _RGB_UNPACK_BLUE) @@ -374,16 +417,16 @@ static inline unsigned lcd_color_to_native(unsigned color) * format, so it's the reverse of FB_SCALARPACK_LCD */ #if LCD_DEPTH >= 24 -static inline fb_data scalar_to_fb(unsigned p) -{ - union { fb_data st; unsigned sc; } convert; - convert.sc = p; return convert.st; -} -static inline unsigned fb_to_scalar(fb_data p) -{ - union { fb_data st; unsigned sc; } convert; - convert.st = p; return convert.sc; -} + static inline fb_data scalar_to_fb(unsigned p) + { + union { fb_data st; unsigned sc; } convert; + convert.sc = p; return convert.st; + } + static inline unsigned fb_to_scalar(fb_data p) + { + union { fb_data st; unsigned sc; } convert; + convert.st = p; return convert.sc; + } #define FB_RGBPACK(r_, g_, b_) ((fb_data){.r = r_, .g = g_, .b = b_}) #define FB_RGBPACK_LCD(r_, g_, b_) FB_RGBPACK(r_, g_, b_) #define FB_UNPACK_RED(fb) ((fb).r) @@ -411,17 +454,28 @@ static inline unsigned fb_to_scalar(fb_data p) /* Frame buffer dimensions */ #if LCD_DEPTH == 1 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING -#define LCD_FBWIDTH ((LCD_WIDTH+7)/8) +#define LCD_FBSTRIDE(w, h) ((w+7)/8) +#define LCD_FBWIDTH LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((h*LCD_FBSTRIDE(w, h)) + w) / sizeof(fb_data)) #else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ -#define LCD_FBHEIGHT ((LCD_HEIGHT+7)/8) +#define LCD_FBSTRIDE(w, h) ((h+7)/8) +#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data)) #endif /* LCD_PIXELFORMAT */ #elif LCD_DEPTH == 2 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING -#define LCD_FBWIDTH ((LCD_WIDTH+3)/4) +#define LCD_FBSTRIDE(w, h) ((w+3)>>2) +#define LCD_NATIVE_STRIDE(s) LCD_FBSTRIDE(s, s) +#define LCD_FBWIDTH LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((h*LCD_FBSTRIDE(w, h)) + w) / sizeof(fb_data)) #elif LCD_PIXELFORMAT == VERTICAL_PACKING -#define LCD_FBHEIGHT ((LCD_HEIGHT+3)/4) +#define LCD_FBSTRIDE(w, h) ((h+3)/4) +#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data)) #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED -#define LCD_FBHEIGHT ((LCD_HEIGHT+7)/8) +#define LCD_FBSTRIDE(w, h) ((h+7)/8) +#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data)) #endif /* LCD_PIXELFORMAT */ #endif /* LCD_DEPTH */ /* Set defaults if not defined different yet. The defaults apply to both @@ -432,13 +486,29 @@ static inline unsigned fb_to_scalar(fb_data p) #ifndef LCD_FBHEIGHT #define LCD_FBHEIGHT LCD_HEIGHT #endif -/* The actual framebuffer */ -extern fb_data *lcd_framebuffer; + +#ifndef LCD_NATIVE_STRIDE +/* 2-bit Horz is the only display that actually defines this */ +#define LCD_NATIVE_STRIDE(s) (s) +#endif + +#ifndef LCD_NBELEMS #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE -#define FBADDR(x, y) (lcd_framebuffer + ((x) * LCD_FBHEIGHT) + (y)) +#define LCD_NBELEMS(w, h) ((w*STRIDE_MAIN(w, h)) + h) #else -#define FBADDR(x, y) (lcd_framebuffer + ((y) * LCD_FBWIDTH) + (x)) +#define LCD_NBELEMS(w, h) ((h*STRIDE_MAIN(w, h)) + w) #endif +#define LCD_FBSTRIDE(w, h) STRIDE_MAIN(w, h) +#endif + +#ifndef LCD_STRIDE + #define LCD_STRIDE(w, h) STRIDE_MAIN(w, h) +#endif + +extern struct viewport* lcd_current_viewport; + +#define FBADDR(x,y) ((fb_data*) lcd_current_viewport->buffer->get_address_fn(x, y)) + #define FRAMEBUFFER_SIZE (sizeof(fb_data)*LCD_FBWIDTH*LCD_FBHEIGHT) /** Port-specific functions. Enable in port config file. **/ @@ -499,7 +569,7 @@ struct bitmap { extern void lcd_set_invert_display(bool yesno); #ifdef HAVE_BACKLIGHT_INVERSION -extern void lcd_set_backlight_inversion(bool yesno); + extern void lcd_set_backlight_inversion(bool yesno); #endif /* HAVE_BACKLIGHT_INVERSION */ extern void lcd_set_flip(bool yesno); @@ -510,13 +580,13 @@ extern int lcd_getfont(void); /* low level drawing function pointer arrays */ #if LCD_DEPTH >= 8 -extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; + extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; #elif LCD_DEPTH > 1 -extern lcd_pixelfunc_type* const *lcd_pixelfuncs; -extern lcd_blockfunc_type* const *lcd_blockfuncs; + extern lcd_pixelfunc_type* const *lcd_pixelfuncs; + extern lcd_blockfunc_type* const *lcd_blockfuncs; #else /* LCD_DEPTH == 1*/ -extern lcd_pixelfunc_type* const lcd_pixelfuncs[8]; -extern lcd_blockfunc_type* const lcd_blockfuncs[8]; + extern lcd_pixelfunc_type* const lcd_pixelfuncs[8]; + extern lcd_blockfunc_type* const lcd_blockfuncs[8]; #endif /* LCD_DEPTH */ extern void lcd_drawpixel(int x, int y); @@ -526,45 +596,44 @@ extern void lcd_vline(int x, int y1, int y2); extern void lcd_drawrect(int x, int y, int width, int height); extern void lcd_fillrect(int x, int y, int width, int height); extern void lcd_gradient_fillrect(int x, int y, int width, int height, - unsigned start_rgb, unsigned end_rgb); + unsigned start_rgb, unsigned end_rgb); extern void lcd_gradient_fillrect_part(int x, int y, int width, int height, - unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip); + unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip); extern void lcd_draw_border_viewport(void); extern void lcd_fill_viewport(void); extern void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, int stride, int x, int y, int width, int height); extern void lcd_bitmap(const fb_data *src, int x, int y, int width, int height); -extern void lcd_set_framebuffer(fb_data *fb); extern void lcd_scroll_step(int pixels); #if LCD_DEPTH > 1 -extern void lcd_set_foreground(unsigned foreground); -extern unsigned lcd_get_foreground(void); -extern void lcd_set_background(unsigned background); -extern unsigned lcd_get_background(void); + extern void lcd_set_foreground(unsigned foreground); + extern unsigned lcd_get_foreground(void); + extern void lcd_set_background(unsigned background); + extern unsigned lcd_get_background(void); #ifdef HAVE_LCD_COLOR -extern void lcd_set_selector_start(unsigned selector); -extern void lcd_set_selector_end(unsigned selector); -extern void lcd_set_selector_text(unsigned selector_text); + extern void lcd_set_selector_start(unsigned selector); + extern void lcd_set_selector_end(unsigned selector); + extern void lcd_set_selector_text(unsigned selector_text); #endif -extern void lcd_set_drawinfo(int mode, unsigned foreground, - unsigned background); -void lcd_set_backdrop(fb_data* backdrop); - -fb_data* lcd_get_backdrop(void); - -extern void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height); -extern void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, - int height); -extern void lcd_bitmap_transparent_part(const fb_data *src, - int src_x, int src_y, - int stride, int x, int y, int width, - int height); -extern void lcd_bitmap_transparent(const fb_data *src, int x, int y, - int width, int height); + extern void lcd_set_drawinfo(int mode, unsigned foreground, + unsigned background); + void lcd_set_backdrop(fb_data* backdrop); + + fb_data* lcd_get_backdrop(void); + + extern void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height); + extern void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, + int height); + extern void lcd_bitmap_transparent_part(const fb_data *src, + int src_x, int src_y, + int stride, int x, int y, int width, + int height); + extern void lcd_bitmap_transparent(const fb_data *src, int x, int y, + int width, int height); #else /* LCD_DEPTH == 1 */ #define lcd_mono_bitmap lcd_bitmap #define lcd_mono_bitmap_part lcd_bitmap_part @@ -577,10 +646,10 @@ extern void lcd_nine_segment_bmp(const struct bitmap* bm, int x, int y, /* TODO: Impement this for remote displays if ever needed */ #if defined(LCD_DPI) && (LCD_DPI > 0) -/* returns the pixel density of the display */ -static inline int lcd_get_dpi(void) { return LCD_DPI; } + /* returns the pixel density of the display */ + static inline int lcd_get_dpi(void) { return LCD_DPI; } #else -extern int lcd_get_dpi(void); + extern int lcd_get_dpi(void); #endif /* LCD_DPI */ #endif /* __LCD_H__ */ -- cgit v1.2.3