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/drivers/lcd-16bit-common.c | 112 +++++++++--------- firmware/drivers/lcd-16bit-vert.c | 98 ++++++++-------- firmware/drivers/lcd-16bit.c | 93 ++++++++------- firmware/drivers/lcd-1bit-vert.c | 176 +++++++++++++++++----------- firmware/drivers/lcd-24bit.c | 180 ++++++++++++++--------------- firmware/drivers/lcd-2bit-horz.c | 215 ++++++++++++++++++++--------------- firmware/drivers/lcd-2bit-vert.c | 210 +++++++++++++++++++--------------- firmware/drivers/lcd-2bit-vi.c | 202 +++++++++++++++++++------------- firmware/drivers/lcd-bitmap-common.c | 166 ++++++++++++++++++--------- firmware/drivers/lcd-color-common.c | 95 ++++++++++------ firmware/drivers/lcd-scroll.c | 8 +- 11 files changed, 906 insertions(+), 649 deletions(-) (limited to 'firmware/drivers') diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c index a7e80c7244..7c766dab8a 100644 --- a/firmware/drivers/lcd-16bit-common.c +++ b/firmware/drivers/lcd-16bit-common.c @@ -35,10 +35,10 @@ void lcd_clear_viewport(void) int x, y, width, height; int len, step; - x = current_vp->x; - y = current_vp->y; - width = current_vp->width; - height = current_vp->height; + x = lcd_current_viewport->x; + y = lcd_current_viewport->y; + width = lcd_current_viewport->width; + height = lcd_current_viewport->height; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -70,11 +70,11 @@ void lcd_clear_viewport(void) dst = FBADDR(x, y); dst_end = FBADDR(x + width - 1 , y + height - 1); - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { do { - memset16(dst, current_vp->fg_pattern, len); + memset16(dst, lcd_current_viewport->fg_pattern, len); dst += step; } while (dst <= dst_end); @@ -85,7 +85,7 @@ void lcd_clear_viewport(void) { do { - memset16(dst, current_vp->bg_pattern, len); + memset16(dst, lcd_current_viewport->bg_pattern, len); dst += step; } while (dst <= dst_end); @@ -102,22 +102,24 @@ void lcd_clear_viewport(void) } } - if (current_vp == &default_vp) + if (lcd_current_viewport == &default_vp) lcd_scroll_stop(); else - lcd_scroll_stop_viewport(current_vp); + lcd_scroll_stop_viewport(lcd_current_viewport); + + lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /*** low-level drawing functions ***/ static void ICODE_ATTR setpixel(fb_data *address) { - *address = current_vp->fg_pattern; + *address = lcd_current_viewport->fg_pattern; } static void ICODE_ATTR clearpixel(fb_data *address) { - *address = current_vp->bg_pattern; + *address = lcd_current_viewport->bg_pattern; } static void ICODE_ATTR clearimgpixel(fb_data *address) @@ -157,8 +159,8 @@ void lcd_fillrect(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -171,14 +173,14 @@ void lcd_fillrect(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -205,14 +207,14 @@ void lcd_fillrect(int x, int y, int width, int height) #endif /* drawmode and optimisation */ - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (lcd_current_viewport->drawmode & DRMODE_BG) { if (!lcd_backdrop) { fillopt = OPT_SET; - bits = current_vp->bg_pattern; + bits = lcd_current_viewport->bg_pattern; } else fillopt = OPT_COPY; @@ -220,13 +222,13 @@ void lcd_fillrect(int x, int y, int width, int height) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = OPT_SET; - bits = current_vp->fg_pattern; + bits = lcd_current_viewport->fg_pattern; } } - if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) + if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT) return; dst = FBADDR(x, y); @@ -284,13 +286,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, const unsigned char *src_end; fb_data *dst, *dst_col; unsigned dmask = 0x100; /* bit 8 == sentinel */ - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; int row; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -305,14 +307,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -404,7 +406,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_BG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; do { if (!(data & 0x01)) @@ -417,7 +419,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_FG: - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { if (data & 0x01) @@ -430,7 +432,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_SOLID|DRMODE_INT_BD: - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; bo = lcd_backdrop_offset; do { @@ -443,8 +445,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_SOLID: - fg = current_vp->fg_pattern; - bg = current_vp->bg_pattern; + fg = lcd_current_viewport->fg_pattern; + bg = lcd_current_viewport->bg_pattern; do { *dst = (data & 0x01) ? fg : bg; @@ -549,10 +551,10 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, { fb_data *dst, *dst_row; unsigned dmask = 0x00000000; - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; /* initialize blending */ BLEND_INIT; @@ -570,14 +572,14 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -668,7 +670,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, /* go through the rows and update each pixel */ do { - /* saving current_vp->fg/bg_pattern and lcd_backdrop_offset into these + /* saving lcd_current_viewport->fg/bg_pattern and lcd_backdrop_offset into these * temp vars just before the loop helps gcc to opimize the loop better * (testing showed ~15% speedup) */ unsigned fg, bg; @@ -727,7 +729,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_BG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; do { *dst = blend_two_colors(bg, *dst, data & ALPHA_COLOR_LOOKUP_SIZE ); @@ -747,7 +749,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_FG: - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { *dst = blend_two_colors(*dst, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); @@ -758,7 +760,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, break; case DRMODE_SOLID|DRMODE_INT_BD: bo = lcd_backdrop_offset; - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { fb_data *c = (fb_data *)((uintptr_t)dst + bo); @@ -769,7 +771,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_SOLID|DRMODE_INT_IMG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; img_offset = image - dst; do { @@ -792,8 +794,8 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_SOLID: - bg = current_vp->bg_pattern; - fg = current_vp->fg_pattern; + bg = lcd_current_viewport->bg_pattern; + fg = lcd_current_viewport->fg_pattern; do { *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); diff --git a/firmware/drivers/lcd-16bit-vert.c b/firmware/drivers/lcd-16bit-vert.c index ffe2b85b3c..b336e78c78 100644 --- a/firmware/drivers/lcd-16bit-vert.c +++ b/firmware/drivers/lcd-16bit-vert.c @@ -39,7 +39,7 @@ #include "scroll_engine.h" #define ROW_INC 1 -#define COL_INC LCD_HEIGHT +#define COL_INC lcd_current_viewport->buffer->stride extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[]; @@ -61,7 +61,9 @@ void lcd_hline(int x1, int x2, int y) { int x; fb_data *dst, *dst_end; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + int stride_dst; + + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; /* direction flip */ if (x2 < x1) @@ -73,20 +75,20 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || - (x1 >= current_vp->width) || + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || + (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* Adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -103,12 +105,13 @@ void lcd_hline(int x1, int x2, int y) #endif dst = FBADDR(x1 , y ); - dst_end = dst + (x2 - x1) * LCD_HEIGHT; + stride_dst = lcd_current_viewport->buffer->stride; + dst_end = dst + (x2 - x1) * stride_dst; do { pfunc(dst); - dst += LCD_HEIGHT; + dst += stride_dst; } while (dst <= dst_end); } @@ -131,20 +134,20 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || - (y1 >= current_vp->height) || + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || + (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - x += current_vp->x; - y1 += current_vp->y; - y2 += current_vp->y; + x += lcd_current_viewport->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -163,14 +166,14 @@ void lcd_vline(int x, int y1, int y2) height = y2 - y1 + 1; /* drawmode and optimisation */ - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (lcd_current_viewport->drawmode & DRMODE_BG) { if (!lcd_backdrop) { fillopt = OPT_SET; - bits = current_vp->bg_pattern; + bits = lcd_current_viewport->bg_pattern; } else fillopt = OPT_COPY; @@ -178,13 +181,13 @@ void lcd_vline(int x, int y1, int y2) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = OPT_SET; - bits = current_vp->fg_pattern; + bits = lcd_current_viewport->fg_pattern; } } - if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) + if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT) return; dst = FBADDR(x, y1); @@ -215,11 +218,11 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, int height) { fb_data *dst; - + int stride_dst; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -235,14 +238,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -272,13 +275,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, src += stride * src_x + src_y; /* move starting point */ dst = FBADDR(x, y); - fb_data *dst_end = dst + width * LCD_HEIGHT; + stride_dst = lcd_current_viewport->buffer->stride; + fb_data *dst_end = dst + width * stride_dst; do { memcpy(dst, src, height * sizeof(fb_data)); src += stride; - dst += LCD_HEIGHT; + dst += stride_dst; } while (dst < dst_end); } @@ -289,11 +293,12 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, int y, int width, int height) { fb_data *dst, *dst_end; + int stride_dst; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -309,14 +314,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -346,7 +351,8 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, src += stride * src_x + src_y; /* move starting point */ dst = FBADDR(x, y); - dst_end = dst + width * LCD_HEIGHT; + stride_dst = lcd_current_viewport->buffer->stride; + dst_end = dst + width * stride_dst; do { @@ -354,12 +360,12 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, for(i = 0;i < height;i++) { if (src[i] == REPLACEWITHFG_COLOR) - dst[i] = current_vp->fg_pattern; + dst[i] = lcd_current_viewport->fg_pattern; else if(src[i] != TRANSPARENT_COLOR) dst[i] = src[i]; } src += stride; - dst += LCD_HEIGHT; + dst += stride_dst; } while (dst < dst_end); } diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index b792be4e02..03c50f8ebf 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c @@ -38,7 +38,7 @@ #include "bidi.h" #include "scroll_engine.h" -#define ROW_INC LCD_WIDTH +#define ROW_INC lcd_current_viewport->buffer->stride #define COL_INC 1 extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; @@ -74,20 +74,20 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || - (x1 >= current_vp->width) || + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || + (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* Adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -106,14 +106,14 @@ void lcd_hline(int x1, int x2, int y) width = x2 - x1 + 1; /* drawmode and optimisation */ - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (lcd_current_viewport->drawmode & DRMODE_BG) { if (!lcd_backdrop) { fillopt = OPT_SET; - bits = current_vp->bg_pattern; + bits = lcd_current_viewport->bg_pattern; } else fillopt = OPT_COPY; @@ -121,13 +121,13 @@ void lcd_hline(int x1, int x2, int y) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = OPT_SET; - bits = current_vp->fg_pattern; + bits = lcd_current_viewport->fg_pattern; } } - if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) + if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT) return; dst = FBADDR(x1, y); @@ -157,7 +157,8 @@ void lcd_vline(int x, int y1, int y2) { int y; fb_data *dst, *dst_end; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + int stride_dst; + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; /* direction flip */ if (y2 < y1) @@ -169,20 +170,20 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || - (y1 >= current_vp->height) || + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || + (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - x += current_vp->x; - y1 += current_vp->y; - y2 += current_vp->y; + x += lcd_current_viewport->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -199,12 +200,13 @@ void lcd_vline(int x, int y1, int y2) #endif dst = FBADDR(x , y1); - dst_end = dst + (y2 - y1) * LCD_WIDTH; + stride_dst = lcd_current_viewport->buffer->stride; + dst_end = dst + (y2 - y1) * stride_dst; do { pfunc(dst); - dst += LCD_WIDTH; + dst += stride_dst; } while (dst <= dst_end); } @@ -215,11 +217,12 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, int height) { fb_data *dst; + int stride_dst; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -235,14 +238,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -272,12 +275,13 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, src += stride * src_y + src_x; /* move starting point */ dst = FBADDR(x, y); + stride_dst = lcd_current_viewport->buffer->stride; do { memcpy(dst, src, width * sizeof(fb_data)); src += stride; - dst += LCD_WIDTH; + dst += stride_dst; } while (--height > 0); } @@ -288,12 +292,13 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, int y, int width, int height) { fb_data *dst; - unsigned fg = current_vp->fg_pattern; + unsigned fg = lcd_current_viewport->fg_pattern; + int stride_dst = lcd_current_viewport->buffer->stride; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -309,14 +314,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -371,7 +376,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, [s]"+&r"(src), [d]"+&r"(dst) : [width]"r"(width), [sstp]"r"(stride - width), - [dstp]"r"(LCD_WIDTH - width), + [dstp]"r"(stride_dst - width), [transcolor]"r"(TRANSPARENT_COLOR), [fgcolor]"r"(REPLACEWITHFG_COLOR), [fgpat]"r"(fg) @@ -395,7 +400,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, } while (++dst_row < row_end); src += stride; - dst += LCD_WIDTH; + dst += stride_dst; } while (--height > 0); #endif diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c index 668c685187..57abdb91a6 100644 --- a/firmware/drivers/lcd-1bit-vert.c +++ b/firmware/drivers/lcd-1bit-vert.c @@ -44,9 +44,26 @@ #define MAIN_LCD #endif +#ifdef MAIN_LCD +#define THIS_STRIDE STRIDE_MAIN +#else +#define THIS_STRIDE STRIDE_REMOTE +#endif + +#define CURRENT_VP LCDFN(current_viewport) /*** globals ***/ -FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; -FBFN(data) *LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; +static FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; + +static void *LCDFN(frameaddress_default)(int x, int y); + +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t LCDFN(framebuffer_default) = +{ + .FBFN(ptr) = &LCDFN(static_framebuffer)[0][0], + .get_address_fn = &LCDFN(frameaddress_default), + .stride = THIS_STRIDE(LCDM(WIDTH), LCDM(HEIGHT)), + .elems = (LCDM(FBWIDTH)*LCDM(FBHEIGHT)), +}; static struct viewport default_vp = { @@ -56,55 +73,73 @@ static struct viewport default_vp = .height = LCDM(HEIGHT), .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, + .buffer = NULL, }; -static struct viewport* current_vp = &default_vp; +struct viewport* CURRENT_VP; + +static void *LCDFN(frameaddress_default)(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = CURRENT_VP->buffer; +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCDM(NATIVE_STRIDE)(fb->stride)) + y; +#else + size_t element = (y * LCDM(NATIVE_STRIDE)(fb->stride)) + x; +#endif + + return fb->FBFN(ptr) + element;/*(element % fb->elems);*/ +} /* LCD init */ void LCDFN(init)(void) { + + /* Initialize the viewport */ + LCDFN(set_viewport)(NULL); LCDFN(clear_display)(); LCDFN(init_device)(); #ifdef MAIN_LCD scroll_init(); #endif + } /*** parameter handling ***/ void LCDFN(set_drawmode)(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + CURRENT_VP->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int LCDFN(get_drawmode)(void) { - return current_vp->drawmode; + return CURRENT_VP->drawmode; } int LCDFN(getwidth)(void) { - return current_vp->width; + return CURRENT_VP->width; } int LCDFN(getheight)(void) { - return current_vp->height; + return CURRENT_VP->height; } void LCDFN(setfont)(int newfont) { - current_vp->font = newfont; + CURRENT_VP->font = newfont; } int LCDFN(getfont)(void) { - return current_vp->font; + return CURRENT_VP->font; } int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, CURRENT_VP->font); } /*** low-level drawing functions ***/ @@ -134,7 +169,7 @@ LCDFN(pixelfunc_type)* const LCDFN(pixelfuncs)[8] = { flippixel, nopixel, setpixel, setpixel, nopixel, clearpixel, nopixel, clearpixel }; - + static void ICODE_ATTR flipblock(FBFN(data) *address, unsigned mask, unsigned bits) { @@ -199,9 +234,9 @@ LCDFN(blockfunc_type)* const LCDFN(blockfuncs)[8] = { /* Clear the whole display */ void LCDFN(clear_display)(void) { - unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; + unsigned bits = (CURRENT_VP->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; - memset(LCDFN(framebuffer), bits, FBSIZE); + memset(LCDFB(0, 0), bits, FBSIZE); LCDFN(scroll_info).lines = 0; } @@ -210,37 +245,40 @@ void LCDFN(clear_viewport)(void) { int oldmode; - if (current_vp == &default_vp) + if (CURRENT_VP == &default_vp && + default_vp.buffer == &LCDFN(framebuffer_default)) { LCDFN(clear_display)(); } else { - oldmode = current_vp->drawmode; + oldmode = CURRENT_VP->drawmode; /* Invert the INVERSEVID bit and set basic mode to SOLID */ - current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) | + CURRENT_VP->drawmode = (~CURRENT_VP->drawmode & DRMODE_INVERSEVID) | DRMODE_SOLID; - LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); + LCDFN(fillrect)(0, 0, CURRENT_VP->width, CURRENT_VP->height); - current_vp->drawmode = oldmode; + CURRENT_VP->drawmode = oldmode; - LCDFN(scroll_stop_viewport)(current_vp); + LCDFN(scroll_stop_viewport)(CURRENT_VP); } + + CURRENT_VP->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /* Set a single pixel */ void LCDFN(drawpixel)(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)CURRENT_VP->width) + && ((unsigned)y < (unsigned)CURRENT_VP->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCDM(WIDTH)) && ((unsigned)y < (unsigned)LCDM(HEIGHT)) #endif ) - LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x + x, current_vp->y + y); + LCDFN(pixelfuncs)[CURRENT_VP->drawmode](CURRENT_VP->x + x, CURRENT_VP->y + y); } /* Draw a line */ @@ -252,7 +290,7 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[current_vp->drawmode]; + LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode]; deltax = abs(x2 - x1); if (deltax == 0) @@ -308,14 +346,14 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)CURRENT_VP->width) + && ((unsigned)y < (unsigned)CURRENT_VP->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCDM(WIDTH)) && ((unsigned)y < (unsigned)LCDM(HEIGHT)) #endif ) - pfunc(current_vp->x + x, current_vp->y + y); + pfunc(CURRENT_VP->x + x, CURRENT_VP->y + y); if (d < 0) { @@ -350,19 +388,19 @@ void LCDFN(hline)(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) + if (((unsigned)y >= (unsigned)CURRENT_VP->height) || (x1 >= CURRENT_VP->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= CURRENT_VP->width) + x2 = CURRENT_VP->width-1; /* adjust to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += CURRENT_VP->x; + x2 += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -380,7 +418,7 @@ void LCDFN(hline)(int x1, int x2, int y) width = x2 - x1 + 1; - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x1,y>>3); mask = BIT_N(y & 7); @@ -395,6 +433,7 @@ void LCDFN(vline)(int x, int y1, int y2) { int ny; FBFN(data) *dst; + int stride_dst; unsigned mask, mask_bottom; LCDFN(blockfunc_type) *bfunc; @@ -408,19 +447,19 @@ void LCDFN(vline)(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) + if (((unsigned)x >= (unsigned)CURRENT_VP->width) || (y1 >= CURRENT_VP->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= CURRENT_VP->height) + y2 = CURRENT_VP->height-1; /* adjust for viewport */ - y1 += current_vp->y; - y2 += current_vp->y; - x += current_vp->x; + y1 += CURRENT_VP->y; + y2 += CURRENT_VP->y; + x += CURRENT_VP->x; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -436,16 +475,17 @@ void LCDFN(vline)(int x, int y1, int y2) y2 = LCDM(HEIGHT)-1; #endif - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x,y1>>3); ny = y2 - (y1 & ~7); mask = 0xFFu << (y1 & 7); mask_bottom = 0xFFu >> (~ny & 7); + stride_dst = CURRENT_VP->buffer->stride; for (; ny >= 8; ny -= 8) { bfunc(dst, mask, 0xFFu); - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -472,6 +512,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height) { int ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; unsigned bits = 0; LCDFN(blockfunc_type) *bfunc; @@ -479,8 +520,8 @@ void LCDFN(fillrect)(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) + || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -493,14 +534,14 @@ void LCDFN(fillrect)(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -526,26 +567,27 @@ void LCDFN(fillrect)(int x, int y, int width, int height) height = LCDM(HEIGHT) - y; #endif - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (CURRENT_VP->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (CURRENT_VP->drawmode & DRMODE_BG) { fillopt = true; } } else { - if (current_vp->drawmode & DRMODE_FG) + if (CURRENT_VP->drawmode & DRMODE_FG) { fillopt = true; bits = 0xFFu; } } - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x,y>>3); ny = height - 1 + (y & 7); mask = 0xFFu << (y & 7); mask_bottom = 0xFFu >> (~ny & 7); + stride_dst = CURRENT_VP->buffer->stride; for (; ny >= 8; ny -= 8) { @@ -561,7 +603,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height) while (dst_row < dst_end); } - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -595,13 +637,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, { int shift, ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; LCDFN(blockfunc_type) *bfunc; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) + || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; /* clip image in viewport */ @@ -617,14 +660,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -656,16 +699,17 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, src_y &= 7; y -= src_y; dst = LCDFB(x,y>>3); + stride_dst = CURRENT_VP->buffer->stride; shift = y & 7; ny = height - 1 + shift + src_y; - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; mask = 0xFFu << (shift + src_y); mask_bottom = 0xFFu >> (~ny & 7); if (shift == 0) { - bool copyopt = (current_vp->drawmode == DRMODE_SOLID); + bool copyopt = (CURRENT_VP->drawmode == DRMODE_SOLID); for (; ny >= 8; ny -= 8) { @@ -683,7 +727,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, } src += stride; - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -721,7 +765,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, mask_col >>= 8; src_col += stride; - dst_col += LCDM(WIDTH); + dst_col += stride_dst; data >>= 8; } data |= *src_col << shift; diff --git a/firmware/drivers/lcd-24bit.c b/firmware/drivers/lcd-24bit.c index 8820e632d4..65fa01f37f 100644 --- a/firmware/drivers/lcd-24bit.c +++ b/firmware/drivers/lcd-24bit.c @@ -39,7 +39,7 @@ #include "bidi.h" #include "scroll_engine.h" -#define ROW_INC LCD_WIDTH +#define ROW_INC lcd_current_viewport->buffer->stride #define COL_INC 1 extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; @@ -62,10 +62,10 @@ void lcd_clear_viewport(void) int x, y, width, height; int len, step; - x = current_vp->x; - y = current_vp->y; - width = current_vp->width; - height = current_vp->height; + x = lcd_current_viewport->x; + y = lcd_current_viewport->y; + width = lcd_current_viewport->width; + height = lcd_current_viewport->height; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -97,9 +97,9 @@ void lcd_clear_viewport(void) dst = FBADDR(x, y); dst_end = FBADDR(x + width - 1 , y + height - 1); - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - fb_data px = FB_SCALARPACK(current_vp->fg_pattern); + fb_data px = FB_SCALARPACK(lcd_current_viewport->fg_pattern); do { fb_data *end = dst + len; @@ -114,7 +114,7 @@ void lcd_clear_viewport(void) { if (!lcd_backdrop) { - fb_data px = FB_SCALARPACK(current_vp->bg_pattern); + fb_data px = FB_SCALARPACK(lcd_current_viewport->bg_pattern); do { fb_data *end = dst + len; @@ -137,22 +137,24 @@ void lcd_clear_viewport(void) } } - if (current_vp == &default_vp) + if (lcd_current_viewport == &default_vp) lcd_scroll_stop(); else - lcd_scroll_stop_viewport(current_vp); + lcd_scroll_stop_viewport(lcd_current_viewport); + + lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /*** low-level drawing functions ***/ static void ICODE_ATTR setpixel(fb_data *address) { - *address = FB_SCALARPACK(current_vp->fg_pattern); + *address = FB_SCALARPACK(lcd_current_viewport->fg_pattern); } static void ICODE_ATTR clearpixel(fb_data *address) { - *address = FB_SCALARPACK(current_vp->bg_pattern); + *address = FB_SCALARPACK(lcd_current_viewport->bg_pattern); } static void ICODE_ATTR clearimgpixel(fb_data *address) @@ -194,8 +196,8 @@ void lcd_fillrect(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -208,14 +210,14 @@ void lcd_fillrect(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -242,14 +244,14 @@ void lcd_fillrect(int x, int y, int width, int height) #endif /* drawmode and optimisation */ - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (lcd_current_viewport->drawmode & DRMODE_BG) { if (!lcd_backdrop) { fillopt = OPT_SET; - bits = FB_SCALARPACK(current_vp->bg_pattern); + bits = FB_SCALARPACK(lcd_current_viewport->bg_pattern); } else fillopt = OPT_COPY; @@ -257,13 +259,13 @@ void lcd_fillrect(int x, int y, int width, int height) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = OPT_SET; - bits = FB_SCALARPACK(current_vp->fg_pattern); + bits = FB_SCALARPACK(lcd_current_viewport->fg_pattern); } } - if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) + if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT) return; dst = FBADDR(x, y); @@ -327,13 +329,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, const unsigned char *src_end; fb_data *dst, *dst_col; unsigned dmask = 0x100; /* bit 8 == sentinel */ - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; int row; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -348,14 +350,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -447,7 +449,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_BG: - bg = FB_SCALARPACK(current_vp->bg_pattern); + bg = FB_SCALARPACK(lcd_current_viewport->bg_pattern); do { if (!(data & 0x01)) @@ -460,7 +462,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_FG: - fg = FB_SCALARPACK(current_vp->fg_pattern); + fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern); do { if (data & 0x01) @@ -473,7 +475,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_SOLID|DRMODE_INT_BD: - fg = FB_SCALARPACK(current_vp->fg_pattern); + fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern); bo = lcd_backdrop_offset; do { @@ -486,8 +488,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_SOLID: - fg = FB_SCALARPACK(current_vp->fg_pattern); - bg = FB_SCALARPACK(current_vp->bg_pattern); + fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern); + bg = FB_SCALARPACK(lcd_current_viewport->bg_pattern); do { *dst = (data & 0x01) ? fg : bg; @@ -559,10 +561,10 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, { fb_data *dst, *dst_row; unsigned dmask = 0x00000000; - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; /* clipping */ @@ -578,14 +580,14 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -673,7 +675,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, /* go through the rows and update each pixel */ do { - /* saving current_vp->fg/bg_pattern and lcd_backdrop_offset into these + /* saving lcd_current_viewport->fg/bg_pattern and lcd_backdrop_offset into these * temp vars just before the loop helps gcc to opimize the loop better * (testing showed ~15% speedup) */ unsigned fg, bg; @@ -734,7 +736,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_BG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; do { unsigned px = FB_UNPACK_SCALAR_LCD(*dst); @@ -757,7 +759,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_FG: - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { unsigned px = FB_UNPACK_SCALAR_LCD(*dst); @@ -769,7 +771,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, break; case DRMODE_SOLID|DRMODE_INT_BD: bo = lcd_backdrop_offset; - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { unsigned c = FB_UNPACK_SCALAR_LCD(*(fb_data *)((uintptr_t)dst + bo)); @@ -780,7 +782,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_SOLID|DRMODE_INT_IMG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; img_offset = image - dst; do { @@ -805,8 +807,8 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_SOLID: - bg = current_vp->bg_pattern; - fg = current_vp->fg_pattern; + bg = lcd_current_viewport->bg_pattern; + fg = lcd_current_viewport->fg_pattern; do { *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); @@ -855,7 +857,7 @@ void lcd_hline(int x1, int x2, int y) { int x, width; fb_data *dst, *dst_end; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; /* direction flip */ if (x2 < x1) @@ -867,20 +869,20 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || - (x1 >= current_vp->width) || + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || + (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* Adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -912,7 +914,7 @@ void lcd_vline(int x, int y1, int y2) { int y; fb_data *dst, *dst_end; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; /* direction flip */ if (y2 < y1) @@ -924,20 +926,20 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || - (y1 >= current_vp->height) || + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || + (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - x += current_vp->x; - y1 += current_vp->y; - y2 += current_vp->y; + x += lcd_current_viewport->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -973,8 +975,8 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -990,14 +992,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1047,8 +1049,8 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -1064,14 +1066,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1104,7 +1106,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, transparent = FB_SCALARPACK(TRANSPARENT_COLOR); replacewithfg = FB_SCALARPACK(REPLACEWITHFG_COLOR); - fg = FB_SCALARPACK(current_vp->fg_pattern); + fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern); #define CMP(c1, c2) (c1.r == c2.r && c1.g == c2.g && c1.b == c2.b) do diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c index 1d256e5f58..35a2be5b2c 100644 --- a/firmware/drivers/lcd-2bit-horz.c +++ b/firmware/drivers/lcd-2bit-horz.c @@ -39,8 +39,8 @@ /*** globals ***/ -unsigned char lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; -unsigned char *lcd_framebuffer = &lcd_static_framebuffer[0][0]; +static unsigned char lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; +static void *lcd_frameaddress_default(int x, int y); static const unsigned char pixmask[4] ICONST_ATTR = { 0xC0, 0x30, 0x0C, 0x03 @@ -49,6 +49,15 @@ static const unsigned char pixmask[4] ICONST_ATTR = { static fb_data* lcd_backdrop = NULL; static long lcd_backdrop_offset IDATA_ATTR = 0; +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t lcd_framebuffer_default = +{ + .fb_ptr = &lcd_static_framebuffer[0][0], + .get_address_fn = &lcd_frameaddress_default, + .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT), + .elems = (LCD_FBWIDTH*LCD_FBHEIGHT), +}; + static struct viewport default_vp = { .x = 0, @@ -57,18 +66,32 @@ static struct viewport default_vp = .height = LCD_HEIGHT, .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, + .buffer = NULL, .fg_pattern = LCD_DEFAULT_FG, .bg_pattern = LCD_DEFAULT_BG }; -static struct viewport* current_vp IBSS_ATTR; +struct viewport* lcd_current_viewport IBSS_ATTR; static unsigned fg_pattern IBSS_ATTR; static unsigned bg_pattern IBSS_ATTR; +static void *lcd_frameaddress_default(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = lcd_current_viewport->buffer; + +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y; +#else + size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x; +#endif + return fb->fb_ptr + element;/*(element % fb->elems);*/ +} + /* LCD init */ void lcd_init(void) { - /* Initialise the viewport */ + /* Initialize the viewport */ lcd_set_viewport(NULL); lcd_clear_display(); @@ -81,34 +104,34 @@ void lcd_init(void) void lcd_set_drawmode(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int lcd_get_drawmode(void) { - return current_vp->drawmode; + return lcd_current_viewport->drawmode; } void lcd_set_foreground(unsigned brightness) { - current_vp->fg_pattern = brightness; + lcd_current_viewport->fg_pattern = brightness; fg_pattern = 0x55 * (~brightness & 3); } unsigned lcd_get_foreground(void) { - return current_vp->fg_pattern; + return lcd_current_viewport->fg_pattern; } void lcd_set_background(unsigned brightness) { - current_vp->bg_pattern = brightness; + lcd_current_viewport->bg_pattern = brightness; bg_pattern = 0x55 * (~brightness & 3); } unsigned lcd_get_background(void) { - return current_vp->bg_pattern; + return lcd_current_viewport->bg_pattern; } void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) @@ -120,27 +143,27 @@ void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) int lcd_getwidth(void) { - return current_vp->width; + return lcd_current_viewport->width; } int lcd_getheight(void) { - return current_vp->height; + return lcd_current_viewport->height; } void lcd_setfont(int newfont) { - current_vp->font = newfont; + lcd_current_viewport->font = newfont; } int lcd_getfont(void) { - return current_vp->font; + return lcd_current_viewport->font; } int lcd_getstringsize(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, lcd_current_viewport->font); } /*** low-level drawing functions ***/ @@ -318,7 +341,7 @@ void lcd_set_backdrop(fb_data* backdrop) lcd_backdrop = backdrop; if (backdrop) { - lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; + lcd_backdrop_offset = (long)backdrop - (long)FBADDR(0,0); lcd_pixelfuncs = lcd_pixelfuncs_backdrop; lcd_blockfuncs = lcd_blockfuncs_backdrop; } @@ -349,16 +372,16 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) /* Clear the whole display */ void lcd_clear_display(void) { - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - memset(lcd_framebuffer, fg_pattern, FRAMEBUFFER_SIZE); + memset(FBADDR(0,0), fg_pattern, FRAMEBUFFER_SIZE); } else { if (lcd_backdrop) - memcpy(lcd_framebuffer, lcd_backdrop, FRAMEBUFFER_SIZE); + memcpy(FBADDR(0,0), lcd_backdrop, FRAMEBUFFER_SIZE); else - memset(lcd_framebuffer, bg_pattern, FRAMEBUFFER_SIZE); + memset(FBADDR(0,0), bg_pattern, FRAMEBUFFER_SIZE); } lcd_scroll_info.lines = 0; @@ -369,37 +392,39 @@ void lcd_clear_viewport(void) { int lastmode; - if (current_vp == &default_vp) + if (lcd_current_viewport == &default_vp && + default_vp.buffer == &lcd_framebuffer_default) { lcd_clear_display(); } else { - lastmode = current_vp->drawmode; + lastmode = lcd_current_viewport->drawmode; /* Invert the INVERSEVID bit and set basic mode to SOLID */ - current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | + lcd_current_viewport->drawmode = (~lastmode & DRMODE_INVERSEVID) | DRMODE_SOLID; - lcd_fillrect(0, 0, current_vp->width, current_vp->height); + lcd_fillrect(0, 0, lcd_current_viewport->width, lcd_current_viewport->height); - current_vp->drawmode = lastmode; + lcd_current_viewport->drawmode = lastmode; - lcd_scroll_stop_viewport(current_vp); + lcd_scroll_stop_viewport(lcd_current_viewport); } + lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /* Set a single pixel */ void lcd_drawpixel(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); + lcd_pixelfuncs[lcd_current_viewport->drawmode](lcd_current_viewport->x + x, lcd_current_viewport->y + y); } /* Draw a line */ @@ -411,7 +436,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; + lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode]; deltay = abs(y2 - y1); if (deltay == 0) @@ -467,14 +492,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - pfunc(current_vp->x + x, current_vp->y + y); + pfunc(lcd_current_viewport->x + x, lcd_current_viewport->y + y); if (d < 0) { @@ -509,19 +534,19 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* adjust to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -537,7 +562,7 @@ void lcd_hline(int x1, int x2, int y) x2 = LCD_WIDTH-1; #endif - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x1>>2,y); nx = x2 - (x1 & ~3); mask = 0xFFu >> (2 * (x1 & 3)); @@ -557,6 +582,7 @@ void lcd_vline(int x, int y1, int y2) { int y; unsigned char *dst, *dst_end; + int stride_dst; unsigned mask; lcd_blockfunc_type *bfunc; @@ -570,19 +596,19 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - y1 += current_vp->y; - y2 += current_vp->y; - x += current_vp->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; + x += lcd_current_viewport->x; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -598,15 +624,16 @@ void lcd_vline(int x, int y1, int y2) y2 = LCD_HEIGHT-1; #endif - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x>>2,y1); + stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); mask = pixmask[x & 3]; - dst_end = dst + (y2 - y1) * LCD_FBWIDTH; + dst_end = dst + (y2 - y1) * stride_dst; do { bfunc(dst, mask, 0xFFu); - dst += LCD_FBWIDTH; + dst += stride_dst; } while (dst <= dst_end); } @@ -631,12 +658,13 @@ void lcd_fillrect(int x, int y, int width, int height) { int nx; unsigned char *dst, *dst_end; + int stride_dst; unsigned mask, mask_right; lcd_blockfunc_type *bfunc; /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || (y >= current_vp->height) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; @@ -650,14 +678,14 @@ void lcd_fillrect(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -683,21 +711,22 @@ void lcd_fillrect(int x, int y, int width, int height) height = LCD_HEIGHT - y; #endif - bfunc = lcd_blockfuncs[current_vp->drawmode]; - dst = FBADDR(x>>2,y); - nx = width - 1 + (x & 3); - mask = 0xFFu >> (2 * (x & 3)); + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; + dst = FBADDR(x>>2,y); + stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); + nx = width - 1 + (x & 3); + mask = 0xFFu >> (2 * (x & 3)); mask_right = 0xFFu << (2 * (~nx & 3)); for (; nx >= 4; nx -= 4) { unsigned char *dst_col = dst; - dst_end = dst_col + height * LCD_FBWIDTH; + dst_end = dst_col + height * stride_dst; do { bfunc(dst_col, mask, 0xFFu); - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; } while (dst_col < dst_end); @@ -706,11 +735,11 @@ void lcd_fillrect(int x, int y, int width, int height) } mask &= mask_right; - dst_end = dst + height * LCD_FBWIDTH; + dst_end = dst + height * stride_dst; do { bfunc(dst, mask, 0xFFu); - dst += LCD_FBWIDTH; + dst += stride_dst; } while (dst < dst_end); } @@ -731,14 +760,15 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, { const unsigned char *src_end; fb_data *dst, *dst_end; + int stride_dst; unsigned dmask = 0x100; /* bit 8 == sentinel */ unsigned dst_mask; - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -753,13 +783,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; - x += current_vp->x; /* adjust for viewport */ - y += current_vp->y; /* adjust for viewport */ + x += lcd_current_viewport->x; /* adjust for viewport */ + y += lcd_current_viewport->y; /* adjust for viewport */ #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -792,7 +822,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_end = src + width; dst = FBADDR(x >> 2,y); - dst_end = dst + height * LCD_FBWIDTH; + stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); + dst_end = dst + height * stride_dst; dst_mask = pixmask[x & 3]; if (drmode & DRMODE_INVERSEVID) @@ -825,7 +856,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, if (data & 0x01) *dst_col ^= dst_mask; - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -843,7 +874,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, *dst_col = block ^ ((block ^ *(dst_col + bo)) & dst_mask); } - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -858,7 +889,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, unsigned block = *dst_col; *dst_col = block ^ ((block ^ bg) & dst_mask); } - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -874,7 +905,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, unsigned block = *dst_col; *dst_col = block ^ ((block ^ fg) & dst_mask); } - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -891,7 +922,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, *dst_col = block ^ ((block ^ ((data & 0x01) ? fg : *(dst_col + bo))) & dst_mask); - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -905,7 +936,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, *dst_col = block ^ ((block ^ ((data & 0x01) ? fg : bg)) & dst_mask); - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -945,12 +976,13 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, { int shift, nx; unsigned char *dst, *dst_end; + int stride_dst; unsigned mask, mask_right; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -965,14 +997,14 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1000,12 +1032,13 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, height = LCD_HEIGHT - y; #endif - stride = (stride + 3) >> 2; /* convert to no. of bytes */ + stride = LCD_FBSTRIDE(stride, 0); /* convert to no. of bytes */ src += stride * src_y + (src_x >> 2); /* move starting point */ src_x &= 3; x -= src_x; dst = FBADDR(x>>2,y); + stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); shift = x & 3; nx = width - 1 + shift + src_x; @@ -1013,7 +1046,7 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, mask_right = 0xFFu << (2 * (~nx & 3)); shift *= 2; - dst_end = dst + height * LCD_FBWIDTH; + dst_end = dst + height * stride_dst; do { const unsigned char *src_row = src; @@ -1039,7 +1072,7 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, setblock(dst_row, mask_row & mask_right, data >> shift); src += stride; - dst += LCD_FBWIDTH; + dst += stride_dst; } while (dst < dst_end); } diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c index 501e568a69..a099c45e98 100644 --- a/firmware/drivers/lcd-2bit-vert.c +++ b/firmware/drivers/lcd-2bit-vert.c @@ -36,8 +36,8 @@ /*** globals ***/ -fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; -fb_data *lcd_framebuffer = &lcd_static_framebuffer[0][0]; +static fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; +static void *lcd_frameaddress_default(int x, int y); const unsigned char lcd_dibits[16] ICONST_ATTR = { 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, @@ -51,6 +51,15 @@ static const unsigned char pixmask[4] ICONST_ATTR = { static fb_data* lcd_backdrop = NULL; static long lcd_backdrop_offset IDATA_ATTR = 0; +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t lcd_framebuffer_default = +{ + .fb_ptr = &lcd_static_framebuffer[0][0], + .get_address_fn = &lcd_frameaddress_default, + .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT), + .elems = (LCD_FBWIDTH*LCD_FBHEIGHT), +}; + static struct viewport default_vp = { .x = 0, @@ -59,18 +68,32 @@ static struct viewport default_vp = .height = LCD_HEIGHT, .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, + .buffer = NULL, .fg_pattern = LCD_DEFAULT_FG, .bg_pattern = LCD_DEFAULT_BG }; -static struct viewport* current_vp IBSS_ATTR; +struct viewport* lcd_current_viewport IBSS_ATTR; static unsigned fg_pattern IBSS_ATTR; static unsigned bg_pattern IBSS_ATTR; +static void *lcd_frameaddress_default(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = lcd_current_viewport->buffer; + +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y; +#else + size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x; +#endif + return fb->fb_ptr + element; /*(element % fb->elems);*/ +} + /* LCD init */ void lcd_init(void) { - /* Initialise the viewport */ + /* Initialize the viewport */ lcd_set_viewport(NULL); lcd_clear_display(); @@ -83,34 +106,34 @@ void lcd_init(void) void lcd_set_drawmode(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int lcd_get_drawmode(void) { - return current_vp->drawmode; + return lcd_current_viewport->drawmode; } void lcd_set_foreground(unsigned brightness) { - current_vp->fg_pattern = brightness; + lcd_current_viewport->fg_pattern = brightness; fg_pattern = 0x55 * (~brightness & 3); } unsigned lcd_get_foreground(void) { - return current_vp->fg_pattern; + return lcd_current_viewport->fg_pattern; } void lcd_set_background(unsigned brightness) { - current_vp->bg_pattern = brightness; + lcd_current_viewport->bg_pattern = brightness; bg_pattern = 0x55 * (~brightness & 3); } unsigned lcd_get_background(void) { - return current_vp->bg_pattern; + return lcd_current_viewport->bg_pattern; } void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) @@ -122,27 +145,27 @@ void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) int lcd_getwidth(void) { - return current_vp->width; + return lcd_current_viewport->width; } int lcd_getheight(void) { - return current_vp->height; + return lcd_current_viewport->height; } void lcd_setfont(int newfont) { - current_vp->font = newfont; + lcd_current_viewport->font = newfont; } int lcd_getfont(void) { - return current_vp->font; + return lcd_current_viewport->font; } int lcd_getstringsize(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, lcd_current_viewport->font); } /*** low-level drawing functions ***/ @@ -320,7 +343,7 @@ void lcd_set_backdrop(fb_data* backdrop) lcd_backdrop = backdrop; if (backdrop) { - lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; + lcd_backdrop_offset = (long)backdrop - (long)FBADDR(0,0); lcd_pixelfuncs = lcd_pixelfuncs_backdrop; lcd_blockfuncs = lcd_blockfuncs_backdrop; } @@ -351,16 +374,16 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) /* Clear the whole display */ void lcd_clear_display(void) { - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - memset(lcd_framebuffer, fg_pattern, FRAMEBUFFER_SIZE); + memset(FBADDR(0,0), fg_pattern, FRAMEBUFFER_SIZE); } else { if (lcd_backdrop) - memcpy(lcd_framebuffer, lcd_backdrop, FRAMEBUFFER_SIZE); + memcpy(FBADDR(0,0), lcd_backdrop, FRAMEBUFFER_SIZE); else - memset(lcd_framebuffer, bg_pattern, FRAMEBUFFER_SIZE); + memset(FBADDR(0,0), bg_pattern, FRAMEBUFFER_SIZE); } lcd_scroll_info.lines = 0; @@ -371,37 +394,39 @@ void lcd_clear_viewport(void) { int lastmode; - if (current_vp == &default_vp) + if (lcd_current_viewport == &default_vp && + default_vp.buffer == &lcd_framebuffer_default) { lcd_clear_display(); } else { - lastmode = current_vp->drawmode; + lastmode = lcd_current_viewport->drawmode; /* Invert the INVERSEVID bit and set basic mode to SOLID */ - current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | + lcd_current_viewport->drawmode = (~lastmode & DRMODE_INVERSEVID) | DRMODE_SOLID; - lcd_fillrect(0, 0, current_vp->width, current_vp->height); + lcd_fillrect(0, 0, lcd_current_viewport->width, lcd_current_viewport->height); - current_vp->drawmode = lastmode; + lcd_current_viewport->drawmode = lastmode; - lcd_scroll_stop_viewport(current_vp); + lcd_scroll_stop_viewport(lcd_current_viewport); } + lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /* Set a single pixel */ void lcd_drawpixel(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); + lcd_pixelfuncs[lcd_current_viewport->drawmode](lcd_current_viewport->x + x, lcd_current_viewport->y + y); } /* Draw a line */ @@ -413,7 +438,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; + lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode]; deltax = abs(x2 - x1); if (deltax == 0) @@ -469,14 +494,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - pfunc(current_vp->x + x, current_vp->y + y); + pfunc(lcd_current_viewport->x + x, lcd_current_viewport->y + y); if (d < 0) { @@ -512,19 +537,19 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -542,7 +567,7 @@ void lcd_hline(int x1, int x2, int y) width = x2 - x1 + 1; - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x1,y>>2); mask = pixmask[y & 3]; @@ -557,6 +582,7 @@ void lcd_vline(int x, int y1, int y2) { int ny; fb_data *dst; + int stride_dst; unsigned mask, mask_bottom; lcd_blockfunc_type *bfunc; @@ -570,19 +596,19 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - y1 += current_vp->y; - y2 += current_vp->y; - x += current_vp->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; + x += lcd_current_viewport->x; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -598,8 +624,9 @@ void lcd_vline(int x, int y1, int y2) y2 = LCD_HEIGHT-1; #endif - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x,y1>>2); + stride_dst = lcd_current_viewport->buffer->stride; ny = y2 - (y1 & ~3); mask = 0xFFu << (2 * (y1 & 3)); mask_bottom = 0xFFu >> (2 * (~ny & 3)); @@ -607,7 +634,7 @@ void lcd_vline(int x, int y1, int y2) for (; ny >= 4; ny -= 4) { bfunc(dst, mask, 0xFFu); - dst += LCD_WIDTH; + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -634,6 +661,7 @@ void lcd_fillrect(int x, int y, int width, int height) { int ny; fb_data *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; unsigned bits = 0; lcd_blockfunc_type *bfunc; @@ -641,8 +669,8 @@ void lcd_fillrect(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) + || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -655,14 +683,14 @@ void lcd_fillrect(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -688,9 +716,9 @@ void lcd_fillrect(int x, int y, int width, int height) height = LCD_HEIGHT - y; #endif - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if ((current_vp->drawmode & DRMODE_BG) && !lcd_backdrop) + if ((lcd_current_viewport->drawmode & DRMODE_BG) && !lcd_backdrop) { fillopt = true; bits = bg_pattern; @@ -698,14 +726,15 @@ void lcd_fillrect(int x, int y, int width, int height) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = true; bits = fg_pattern; } } - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x,y>>2); + stride_dst = lcd_current_viewport->buffer->stride; ny = height - 1 + (y & 3); mask = 0xFFu << (2 * (y & 3)); mask_bottom = 0xFFu >> (2 * (~ny & 3)); @@ -724,7 +753,7 @@ void lcd_fillrect(int x, int y, int width, int height) while (dst_row < dst_end); } - dst += LCD_WIDTH; + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -758,13 +787,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, { int shift, ny; fb_data *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; lcd_blockfunc_type *bfunc; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -779,14 +809,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -818,13 +848,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y &= 7; y -= src_y; dst = FBADDR(x,y>>2); + stride_dst = lcd_current_viewport->buffer->stride; shift = y & 3; ny = height - 1 + shift + src_y; mask = 0xFFFFu << (2 * (shift + src_y)); /* Overflowing bits aren't important. */ mask_bottom = 0xFFFFu >> (2 * (~ny & 7)); - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; if (shift == 0) { @@ -836,7 +867,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, for (; ny >= 8; ny -= 8) { const unsigned char *src_row = src; - fb_data *dst_row = dst + LCD_WIDTH; + fb_data *dst_row = dst + stride_dst; dst_end = dst_row + width; @@ -845,7 +876,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, do { data = *src_row++; - bfunc(dst_row - LCD_WIDTH, dmask1, lcd_dibits[data&0x0F]); + bfunc(dst_row - stride_dst, dmask1, lcd_dibits[data&0x0F]); bfunc(dst_row++, dmask2, lcd_dibits[(data>>4)&0x0F]); } while (dst_row < dst_end); @@ -857,7 +888,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, while (dst_row < dst_end); } src += stride; - dst += 2*LCD_WIDTH; + dst += 2*stride_dst; dmask1 = dmask2 = 0xFFu; } dmask1 &= mask_bottom; @@ -873,7 +904,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, { data = *src++; bfunc(dst, dmask1, lcd_dibits[data&0x0F]); - bfunc((dst++) + LCD_WIDTH, dmask2, lcd_dibits[(data>>4)&0x0F]); + bfunc((dst++) + stride_dst, dmask2, lcd_dibits[(data>>4)&0x0F]); } while (dst < dst_end); } @@ -887,7 +918,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, else { do - bfunc((dst++) + LCD_WIDTH, dmask2, lcd_dibits[((*src++)>>4)&0x0F]); + bfunc((dst++) + stride_dst, dmask2, lcd_dibits[((*src++)>>4)&0x0F]); while (dst < dst_end); } } @@ -909,7 +940,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, { if (mask_col & 0xFFu) bfunc(dst_col, mask_col, lcd_dibits[data&0x0F]); - bfunc(dst_col + LCD_WIDTH, mask_col >> 8, + bfunc(dst_col + stride_dst, mask_col >> 8, lcd_dibits[(data>>4)&0x0F]); mask_col = 0xFFFFu; } @@ -917,7 +948,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, mask_col >>= 16; src_col += stride; - dst_col += 2*LCD_WIDTH; + dst_col += 2*stride_dst; data >>= 8; } data |= *src_col << shift; @@ -925,7 +956,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, if (mask_col & 0xFFu) bfunc(dst_col, mask_col, lcd_dibits[data&0x0F]); if (mask_col & 0xFF00u) - bfunc(dst_col + LCD_WIDTH, mask_col >> 8, + bfunc(dst_col + stride_dst, mask_col >> 8, lcd_dibits[(data>>4)&0x0F]); } while (dst < dst_end); @@ -956,12 +987,13 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, { int shift, ny; fb_data *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) + || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -976,14 +1008,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1010,11 +1042,11 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, if (y + height > LCD_HEIGHT) height = LCD_HEIGHT - y; #endif - src += stride * (src_y >> 2) + src_x; /* move starting point */ src_y &= 3; y -= src_y; dst = FBADDR(x,y>>2); + stride_dst = lcd_current_viewport->buffer->stride; shift = y & 3; ny = height - 1 + shift + src_y; @@ -1038,7 +1070,7 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, while (dst_row < dst_end); } src += stride; - dst += LCD_WIDTH; + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -1077,7 +1109,7 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, mask_col >>= 8; src_col += stride; - dst_col += LCD_WIDTH; + dst_col += stride_dst; data >>= 8; } data |= *src_col << shift; diff --git a/firmware/drivers/lcd-2bit-vi.c b/firmware/drivers/lcd-2bit-vi.c index 0608dfaa46..035e8b6d0d 100644 --- a/firmware/drivers/lcd-2bit-vi.c +++ b/firmware/drivers/lcd-2bit-vi.c @@ -46,17 +46,32 @@ #define MAIN_LCD #endif -/*** globals ***/ +#ifdef MAIN_LCD +#define THIS_STRIDE STRIDE_MAIN +#else +#define THIS_STRIDE STRIDE_REMOTE +#endif -FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; -FBFN(data) *LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; +#define CURRENT_VP LCDFN(current_viewport) +/*** globals ***/ +static FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; +static void *LCDFN(frameaddress_default)(int x, int y); static const FBFN(data) patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000}; static FBFN(data) *backdrop = NULL; static long backdrop_offset IDATA_ATTR = 0; +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t LCDFN(framebuffer_default) = +{ + .FBFN(ptr) = &LCDFN(static_framebuffer)[0][0], + .get_address_fn = &LCDFN(frameaddress_default), + .stride = THIS_STRIDE(LCDM(WIDTH), LCDM(HEIGHT)), + .elems = (LCDM(FBWIDTH)*LCDM(FBHEIGHT)), +}; + static struct viewport default_vp = { .x = 0, @@ -65,19 +80,34 @@ static struct viewport default_vp = .height = LCDM(HEIGHT), .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, + .buffer = NULL, .fg_pattern = LCDM(DEFAULT_FG), .bg_pattern = LCDM(DEFAULT_BG) }; -static struct viewport * current_vp IBSS_ATTR; +struct viewport * CURRENT_VP IBSS_ATTR; static unsigned fg_pattern IBSS_ATTR; static unsigned bg_pattern IBSS_ATTR; +static void *LCDFN(frameaddress_default)(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = CURRENT_VP->buffer; +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCDM(NATIVE_STRIDE)(fb->stride)) + y; +#else + size_t element = (y * LCDM(NATIVE_STRIDE)(fb->stride)) + x; +#endif + return fb->FBFN(ptr) + element;/*(element % fb->elems);*/ +} + /* LCD init */ void LCDFN(init)(void) { + /* Initialize the viewport */ LCDFN(set_viewport)(NULL); + LCDFN(clear_display)(); LCDFN(init_device)(); #ifdef MAIN_LCD @@ -105,34 +135,34 @@ unsigned lcd_remote_color_to_native(unsigned color) void LCDFN(set_drawmode)(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + CURRENT_VP->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int LCDFN(get_drawmode)(void) { - return current_vp->drawmode; + return CURRENT_VP->drawmode; } void LCDFN(set_foreground)(unsigned brightness) { - current_vp->fg_pattern = brightness; + CURRENT_VP->fg_pattern = brightness; fg_pattern = patterns[brightness & 3]; } unsigned LCDFN(get_foreground)(void) { - return current_vp->fg_pattern; + return CURRENT_VP->fg_pattern; } void LCDFN(set_background)(unsigned brightness) { - current_vp->bg_pattern = brightness; + CURRENT_VP->bg_pattern = brightness; bg_pattern = patterns[brightness & 3]; } unsigned LCDFN(get_background)(void) { - return current_vp->bg_pattern; + return CURRENT_VP->bg_pattern; } void LCDFN(set_drawinfo)(int mode, unsigned fg_brightness, @@ -145,26 +175,26 @@ void LCDFN(set_drawinfo)(int mode, unsigned fg_brightness, int LCDFN(getwidth)(void) { - return current_vp->width; + return CURRENT_VP->width; } int LCDFN(getheight)(void) { - return current_vp->height; + return CURRENT_VP->height; } void LCDFN(setfont)(int newfont) { - current_vp->font = newfont; + CURRENT_VP->font = newfont; } int LCDFN(getfont)(void) { - return current_vp->font; + return CURRENT_VP->font; } int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, CURRENT_VP->font); } /*** low-level drawing functions ***/ @@ -345,7 +375,7 @@ void LCDFN(set_backdrop)(FBFN(data) *bd) backdrop = bd; if (bd) { - backdrop_offset = (long)bd - (long)LCDFN(framebuffer); + backdrop_offset = (long)bd - (long)LCDFB(0, 0); LCDFN(pixelfuncs) = LCDFN(pixelfuncs_backdrop); LCDFN(blockfuncs) = LCDFN(blockfuncs_backdrop); } @@ -377,15 +407,15 @@ void LCDFN(clear_display)(void) { if (default_vp.drawmode & DRMODE_INVERSEVID) { - memset(LCDFN(framebuffer), patterns[default_vp.fg_pattern & 3], + memset(LCDFB(0, 0), patterns[default_vp.fg_pattern & 3], FBSIZE); } else { if (backdrop) - memcpy(LCDFN(framebuffer), backdrop, FBSIZE); + memcpy(LCDFB(0, 0), backdrop, FBSIZE); else - memset(LCDFN(framebuffer), patterns[default_vp.bg_pattern & 3], + memset(LCDFB(0, 0), patterns[default_vp.bg_pattern & 3], FBSIZE); } @@ -397,37 +427,39 @@ void LCDFN(clear_viewport)(void) { int lastmode; - if (current_vp == &default_vp) + if (CURRENT_VP == &default_vp && + default_vp.buffer == &LCDFN(framebuffer_default)) { LCDFN(clear_display)(); } else { - lastmode = current_vp->drawmode; + lastmode = CURRENT_VP->drawmode; /* Invert the INVERSEVID bit and set basic mode to SOLID */ - current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | + CURRENT_VP->drawmode = (~lastmode & DRMODE_INVERSEVID) | DRMODE_SOLID; - LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); + LCDFN(fillrect)(0, 0, CURRENT_VP->width, CURRENT_VP->height); - current_vp->drawmode = lastmode; + CURRENT_VP->drawmode = lastmode; - LCDFN(scroll_stop_viewport)(current_vp); + LCDFN(scroll_stop_viewport)(CURRENT_VP); } + CURRENT_VP->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /* Set a single pixel */ void LCDFN(drawpixel)(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)CURRENT_VP->width) + && ((unsigned)y < (unsigned)CURRENT_VP->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCDM(WIDTH)) && ((unsigned)y < (unsigned)LCDM(HEIGHT)) #endif ) - LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x+x, current_vp->y+y); + LCDFN(pixelfuncs)[CURRENT_VP->drawmode](CURRENT_VP->x+x, CURRENT_VP->y+y); } /* Draw a line */ @@ -439,7 +471,7 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[current_vp->drawmode]; + LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode]; deltax = abs(x2 - x1); if (deltax == 0) @@ -495,14 +527,14 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)CURRENT_VP->width) + && ((unsigned)y < (unsigned)CURRENT_VP->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCDM(WIDTH)) && ((unsigned)y < (unsigned)LCDM(HEIGHT)) #endif ) - pfunc(current_vp->x + x, current_vp->y + y); + pfunc(CURRENT_VP->x + x, CURRENT_VP->y + y); if (d < 0) { @@ -538,19 +570,19 @@ void LCDFN(hline)(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) + if (((unsigned)y >= (unsigned)CURRENT_VP->height) || (x1 >= CURRENT_VP->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= CURRENT_VP->width) + x2 = CURRENT_VP->width-1; /* adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += CURRENT_VP->x; + x2 += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -568,7 +600,7 @@ void LCDFN(hline)(int x1, int x2, int y) width = x2 - x1 + 1; - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x1,y>>3); mask = 0x0101 << (y & 7); @@ -583,6 +615,7 @@ void LCDFN(vline)(int x, int y1, int y2) { int ny; FBFN(data) *dst; + int stride_dst; unsigned mask, mask_bottom; LCDFN(blockfunc_type) *bfunc; @@ -596,19 +629,19 @@ void LCDFN(vline)(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) + if (((unsigned)x >= (unsigned)CURRENT_VP->width) || (y1 >= CURRENT_VP->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= CURRENT_VP->height) + y2 = CURRENT_VP->height-1; /* adjust for viewport */ - y1 += current_vp->y; - y2 += current_vp->y; - x += current_vp->x; + y1 += CURRENT_VP->y; + y2 += CURRENT_VP->y; + x += CURRENT_VP->x; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -624,8 +657,9 @@ void LCDFN(vline)(int x, int y1, int y2) y2 = LCDM(HEIGHT)-1; #endif - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x,y1>>3); + stride_dst = CURRENT_VP->buffer->stride; ny = y2 - (y1 & ~7); mask = (0xFFu << (y1 & 7)) & 0xFFu; mask |= mask << 8; @@ -635,7 +669,7 @@ void LCDFN(vline)(int x, int y1, int y2) for (; ny >= 8; ny -= 8) { bfunc(dst, mask, 0xFFFFu); - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFFFu; } mask &= mask_bottom; @@ -662,6 +696,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height) { int ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; unsigned bits = 0; LCDFN(blockfunc_type) *bfunc; @@ -669,8 +704,8 @@ void LCDFN(fillrect)(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) + || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -683,14 +718,14 @@ void LCDFN(fillrect)(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -717,9 +752,9 @@ void LCDFN(fillrect)(int x, int y, int width, int height) #endif - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (CURRENT_VP->drawmode & DRMODE_INVERSEVID) { - if ((current_vp->drawmode & DRMODE_BG) && !backdrop) + if ((CURRENT_VP->drawmode & DRMODE_BG) && !backdrop) { fillopt = true; bits = bg_pattern; @@ -727,14 +762,15 @@ void LCDFN(fillrect)(int x, int y, int width, int height) } else { - if (current_vp->drawmode & DRMODE_FG) + if (CURRENT_VP->drawmode & DRMODE_FG) { fillopt = true; bits = fg_pattern; } } - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x,y>>3); + stride_dst = CURRENT_VP->buffer->stride; ny = height - 1 + (y & 7); mask = (0xFFu << (y & 7)) & 0xFFu; mask |= mask << 8; @@ -755,7 +791,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height) while (dst_row < dst_end); } - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFFFu; } mask &= mask_bottom; @@ -789,13 +825,14 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, { int shift, ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned data, mask, mask_bottom; LCDFN(blockfunc_type) *bfunc; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) || + (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -810,14 +847,14 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -849,10 +886,11 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, src_y &= 7; y -= src_y; dst = LCDFB(x,y>>3); + stride_dst = CURRENT_VP->buffer->stride; shift = y & 7; ny = height - 1 + shift + src_y; - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; mask = 0xFFu << (shift + src_y); /* not byte-doubled here because shift+src_y can be > 7 */ mask_bottom = 0xFFu >> (~ny & 7); @@ -877,7 +915,7 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, while (dst_row < dst_end); src += stride; - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFFFu; } mask &= mask_bottom; @@ -921,7 +959,7 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, } src_col += stride; - dst_col += LCDM(WIDTH); + dst_col += stride_dst; data >>= 8; } data |= *src_col << shift; @@ -958,12 +996,13 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, { int shift, ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) + || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -978,14 +1017,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1017,6 +1056,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, src_y &= 7; y -= src_y; dst = LCDFB(x,y>>3); + stride_dst = CURRENT_VP->buffer->stride; shift = y & 7; ny = height - 1 + shift + src_y; @@ -1045,7 +1085,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, while (dst_row < dst_end); } src += stride; - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFFFu; } mask &= mask_bottom; @@ -1092,7 +1132,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, mask_col |= mask_col << 8; } src_col += stride; - dst_col += LCDM(WIDTH); + dst_col += stride_dst; olddata = data >> 8; } data = *src_col << shift; diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index 8c38e513c6..94829b5d0c 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c @@ -40,43 +40,70 @@ #define MAIN_LCD #endif -void LCDFN(set_framebuffer)(FBFN(data) *fb) -{ - if (fb) - LCDFN(framebuffer) = fb; - else - LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; -} +#ifdef MAIN_LCD +#define THIS_STRIDE STRIDE_MAIN +#else +#define THIS_STRIDE STRIDE_REMOTE +#endif +extern void viewport_set_buffer(struct viewport *vp, + struct frame_buffer_t *buffer, + const enum screen_type screen); /* viewport.c */ /* * draws the borders of the current viewport **/ void LCDFN(draw_border_viewport)(void) { - LCDFN(drawrect)(0, 0, current_vp->width, current_vp->height); + LCDFN(drawrect)(0, 0, LCDFN(current_viewport)->width, LCDFN(current_viewport)->height); } /* - * fills the rectangle formed by current_vp + * fills the rectangle formed by LCDFN(current_viewport) **/ void LCDFN(fill_viewport)(void) { - LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); + LCDFN(fillrect)(0, 0, LCDFN(current_viewport)->width, LCDFN(current_viewport)->height); } /*** Viewports ***/ - -void LCDFN(set_viewport)(struct viewport* vp) +/* init_viewport Notes: When a viewport is initialized + * if vp->buffer is NULL the default frame_buffer is assigned + * likewise the actual buffer, stride, get_address_fn + * are all filled with values from the default buffer if they are not set + * RETURNS either the viewport you passed or the default viewport if vp == NULL + */ +struct viewport* LCDFN(init_viewport)(struct viewport* vp) { - if (vp == NULL) - current_vp = &default_vp; + struct frame_buffer_t *fb_default = &LCDFN(framebuffer_default); + if (!vp) /* NULL vp grabs default viewport */ + vp = &default_vp; + + /* use defaults if no buffer is provided */ + if (vp->buffer == NULL || vp->buffer->elems == 0) + vp->buffer = fb_default; else - current_vp = vp; + { + if (vp->buffer->stride == 0) + vp->buffer->stride = fb_default->stride; + + if (vp->buffer->data == NULL) + vp->buffer->data = fb_default->data; + + if (vp->buffer->get_address_fn == NULL) + vp->buffer->get_address_fn = fb_default->get_address_fn; + } + return vp; +} +struct viewport* LCDFN(set_viewport_ex)(struct viewport* vp, int flags) +{ + vp = LCDFN(init_viewport)(vp); + struct viewport* last_vp = LCDFN(current_viewport); + LCDFN(current_viewport) = vp; #if LCDM(DEPTH) > 1 - LCDFN(set_foreground)(current_vp->fg_pattern); - LCDFN(set_background)(current_vp->bg_pattern); + LCDFN(set_foreground)(vp->fg_pattern); + LCDFN(set_background)(vp->bg_pattern); #endif #if defined(SIMULATOR) @@ -84,10 +111,11 @@ void LCDFN(set_viewport)(struct viewport* vp) * be considered an error - the viewport will not draw as it might be * expected. */ - if((unsigned) current_vp->x > (unsigned) LCDM(WIDTH) - || (unsigned) current_vp->y > (unsigned) LCDM(HEIGHT) - || current_vp->x + current_vp->width > LCDM(WIDTH) - || current_vp->y + current_vp->height > LCDM(HEIGHT)) + + if((unsigned) vp->x > (unsigned) LCDM(WIDTH) + || (unsigned) vp->y > (unsigned) LCDM(HEIGHT) + || vp->x + vp->width > LCDM(WIDTH) + || vp->y + vp->height > LCDM(HEIGHT)) { #if !defined(HAVE_VIEWPORT_CLIP) DEBUGF("ERROR: " @@ -95,27 +123,68 @@ void LCDFN(set_viewport)(struct viewport* vp) DEBUGF("NOTE: " #endif "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", - current_vp->x, current_vp->y, - current_vp->width, current_vp->height); + vp->x, vp->y, vp->width, vp->height); } #endif + if(last_vp) + { + if ((flags & VP_FLAG_CLEAR_FLAG) == VP_FLAG_CLEAR_FLAG) + last_vp->flags &= ~flags; + else + last_vp->flags |= flags; + } + + return last_vp; +} + +struct viewport* LCDFN(set_viewport)(struct viewport* vp) +{ + return LCDFN(set_viewport_ex)(vp, VP_FLAG_VP_DIRTY); } struct viewport *LCDFN(get_viewport)(bool *is_default) { - *is_default = (current_vp == &default_vp); - return current_vp; +#if 0 + *is_default = memcmp(LCDFN(current_viewport), + &default_vp, sizeof(struct viewport)) == 0; +#else + *is_default = LCDFN(current_viewport) == &default_vp; +#endif + + return LCDFN(current_viewport); } void LCDFN(update_viewport)(void) { - LCDFN(update_rect)(current_vp->x, current_vp->y, - current_vp->width, current_vp->height); + struct viewport* vp = LCDFN(current_viewport); + if (vp->buffer->stride != LCDFN(framebuffer_default.stride)) + { + LCDFN(update_viewport_rect)(0,0, vp->width, vp->height); + return; + } + LCDFN(update_rect)(vp->x, vp->y, vp->width, vp->height); } void LCDFN(update_viewport_rect)(int x, int y, int width, int height) { - LCDFN(update_rect)(current_vp->x + x, current_vp->y + y, width, height); + struct viewport* vp = LCDFN(current_viewport); + + /* handle the case of viewport with differing stride from main screen */ + if (vp->buffer->stride != LCDFN(framebuffer_default.stride)) + { + struct frame_buffer_t *fb = vp->buffer; + viewport_set_buffer(vp, NULL, 0); + + LCDFN(bitmap_part) + (fb->FBFN(ptr), vp->x, vp->y, fb->stride, + vp->x + x, vp->y + y, width, height); + + LCDFN(update_rect)(vp->x + x, vp->y + y, width, height); + viewport_set_buffer(vp, fb, 0); + return; + } + + LCDFN(update_rect)(vp->x + x, vp->y + y, width, height); } #ifndef BOOTLOADER @@ -123,9 +192,9 @@ void LCDFN(update_viewport_rect)(int x, int y, int width, int height) static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) { unsigned short *ucs; - font_lock(current_vp->font, true); - struct font* pf = font_get(current_vp->font); - int vp_flags = current_vp->flags; + font_lock(LCDFN(current_viewport)->font, true); + struct font* pf = font_get(LCDFN(current_viewport)->font); + int vp_flags = LCDFN(current_viewport)->flags; int rtl_next_non_diac_width, last_non_diacritic_width; if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0) @@ -136,13 +205,13 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) /* center takes precedence */ if (vp_flags & VP_FLAG_ALIGN_CENTER) { - x = ((current_vp->width - w)/ 2) + x; + x = ((LCDFN(current_viewport)->width - w)/ 2) + x; if (x < 0) x = 0; } else { - x = current_vp->width - w - x; + x = LCDFN(current_viewport)->width - w - x; x += ofs; ofs = 0; } @@ -158,7 +227,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) int width, base_width, drawmode = 0, base_ofs = 0; const unsigned short next_ch = ucs[1]; - if (x >= current_vp->width) + if (x >= LCDFN(current_viewport)->width) break; is_diac = is_diacritic(*ucs, &is_rtl); @@ -219,8 +288,8 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) * buffer using OR, and then draw the final bitmap instead of the * chars, without touching the drawmode **/ - drawmode = current_vp->drawmode; - current_vp->drawmode = DRMODE_FG; + drawmode = LCDFN(current_viewport)->drawmode; + LCDFN(current_viewport)->drawmode = DRMODE_FG; base_ofs = (base_width - width) / 2; } @@ -237,7 +306,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) y, width - ofs, pf->height); if (is_diac) { - current_vp->drawmode = drawmode; + LCDFN(current_viewport)->drawmode = drawmode; } if (next_ch) @@ -256,7 +325,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) } } } - font_lock(current_vp->font, false); + font_lock(LCDFN(current_viewport)->font, false); } #else /* BOOTLOADER */ /* put a string at a given pixel position, skipping first ofs pixel columns */ @@ -375,7 +444,7 @@ static struct scrollinfo* find_scrolling_line(int x, int y) for(i=0; ix == x && s->y == y && s->vp == current_vp) + if (s->x == x && s->y == y && s->vp == LCDFN(current_viewport)) return s; } return NULL; @@ -411,13 +480,13 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, /* prepare rectangle for scrolling. x and y must be calculated early * for find_scrolling_line() to work */ - cwidth = font_get(current_vp->font)->maxwidth; - height = font_get(current_vp->font)->height; + cwidth = font_get(LCDFN(current_viewport)->font)->maxwidth; + height = font_get(LCDFN(current_viewport)->font)->height; y = y * (linebased ? height : 1); x = x * (linebased ? cwidth : 1); - width = current_vp->width - x; + width = LCDFN(current_viewport)->width - x; - if (y >= current_vp->height) + if (y >= LCDFN(current_viewport)->height) return false; s = find_scrolling_line(x, y); @@ -430,7 +499,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, * the string width is too small to scroll the scrolling line is * cleared as well */ if (w < width || restart) { - LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height); + LCDFN(scroll_stop_viewport_rect)(LCDFN(current_viewport), x, y, width, height); LCDFN(putsxyofs)(x, y, x_offset, string); /* nothing to scroll, or out of scrolling lines. Either way, get out */ if (w < width || LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) @@ -443,7 +512,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, strlcpy(s->linebuffer, string, sizeof(s->linebuffer)); /* scroll bidirectional or forward only depending on the string width */ if ( LCDFN(scroll_info).bidir_limit ) { - s->bidir = w < (current_vp->width) * + s->bidir = w < (LCDFN(current_viewport)->width) * (100 + LCDFN(scroll_info).bidir_limit) / 100; } else @@ -457,7 +526,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, s->y = y; s->width = width; s->height = height; - s->vp = current_vp; + s->vp = LCDFN(current_viewport); s->start_tick = current_tick + LCDFN(scroll_info).delay; LCDFN(scroll_info).lines++; } else { @@ -497,11 +566,6 @@ bool LCDFN(puts_scroll)(int x, int y, const unsigned char *string) #if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD) /* see lcd-16bit-common.c for others */ -#ifdef MAIN_LCD -#define THIS_STRIDE STRIDE_MAIN -#else -#define THIS_STRIDE STRIDE_REMOTE -#endif void LCDFN(bmp_part)(const struct bitmap* bm, int src_x, int src_y, int x, int y, int width, int height) diff --git a/firmware/drivers/lcd-color-common.c b/firmware/drivers/lcd-color-common.c index c8bfd2d6b3..60e95a25ca 100644 --- a/firmware/drivers/lcd-color-common.c +++ b/firmware/drivers/lcd-color-common.c @@ -36,13 +36,23 @@ enum fill_opt { }; /*** globals ***/ -fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] +static fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16); -fb_data *lcd_framebuffer = &lcd_static_framebuffer[0][0]; + +static void *lcd_frameaddress_default(int x, int y); static fb_data* lcd_backdrop = NULL; static long lcd_backdrop_offset IDATA_ATTR = 0; +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t lcd_framebuffer_default = +{ + .fb_ptr = &lcd_static_framebuffer[0][0], + .get_address_fn = &lcd_frameaddress_default, + .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT), + .elems = (LCD_FBWIDTH*LCD_FBHEIGHT), +}; + static struct viewport default_vp = { .x = 0, @@ -51,15 +61,32 @@ static struct viewport default_vp = .height = LCD_HEIGHT, .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, - .fg_pattern = LCD_DEFAULT_FG, - .bg_pattern = LCD_DEFAULT_BG, + .buffer = NULL, + .fg_pattern = LCD_DEFAULT_FG, + .bg_pattern = LCD_DEFAULT_BG, }; -static struct viewport* current_vp IDATA_ATTR = &default_vp; +struct viewport* lcd_current_viewport IDATA_ATTR; + +static void *lcd_frameaddress_default(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = lcd_current_viewport->buffer; + +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y; +#else + size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x; +#endif + return fb->fb_ptr + element;/*(element % fb->elems);*/ +} /* LCD init */ void lcd_init(void) { + /* Initialize the viewport */ + lcd_set_viewport(NULL); + lcd_clear_display(); /* Call device specific init */ @@ -70,77 +97,77 @@ void lcd_init(void) /* Clear the whole display */ void lcd_clear_display(void) { - struct viewport* old_vp = current_vp; + struct viewport* old_vp = lcd_current_viewport; - current_vp = &default_vp; + lcd_current_viewport = &default_vp; lcd_clear_viewport(); - current_vp = old_vp; + lcd_current_viewport = old_vp; } /*** parameter handling ***/ void lcd_set_drawmode(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int lcd_get_drawmode(void) { - return current_vp->drawmode; + return lcd_current_viewport->drawmode; } void lcd_set_foreground(unsigned color) { - current_vp->fg_pattern = color; + lcd_current_viewport->fg_pattern = color; } unsigned lcd_get_foreground(void) { - return current_vp->fg_pattern; + return lcd_current_viewport->fg_pattern; } void lcd_set_background(unsigned color) { - current_vp->bg_pattern = color; + lcd_current_viewport->bg_pattern = color; } unsigned lcd_get_background(void) { - return current_vp->bg_pattern; + return lcd_current_viewport->bg_pattern; } void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color) { lcd_set_drawmode(mode); - current_vp->fg_pattern = fg_color; - current_vp->bg_pattern = bg_color; + lcd_current_viewport->fg_pattern = fg_color; + lcd_current_viewport->bg_pattern = bg_color; } int lcd_getwidth(void) { - return current_vp->width; + return lcd_current_viewport->width; } int lcd_getheight(void) { - return current_vp->height; + return lcd_current_viewport->height; } void lcd_setfont(int newfont) { - current_vp->font = newfont; + lcd_current_viewport->font = newfont; } int lcd_getfont(void) { - return current_vp->font; + return lcd_current_viewport->font; } int lcd_getstringsize(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, lcd_current_viewport->font); } void lcd_set_backdrop(fb_data* backdrop) @@ -148,7 +175,7 @@ void lcd_set_backdrop(fb_data* backdrop) lcd_backdrop = backdrop; if (backdrop) { - lcd_backdrop_offset = (intptr_t)backdrop - (intptr_t)lcd_framebuffer; + lcd_backdrop_offset = (intptr_t)backdrop - (intptr_t)FBADDR(0,0); lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop; } else @@ -166,14 +193,14 @@ fb_data* lcd_get_backdrop(void) /* Set a single pixel */ void lcd_drawpixel(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - lcd_fastpixelfuncs[current_vp->drawmode](FBADDR(current_vp->x+x, current_vp->y+y)); + lcd_fastpixelfuncs[lcd_current_viewport->drawmode](FBADDR(lcd_current_viewport->x+x, lcd_current_viewport->y+y)); } /* Draw a line */ @@ -185,7 +212,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; deltay = abs(y2 - y1); if (deltay == 0) @@ -241,14 +268,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - pfunc(FBADDR(x + current_vp->x, y + current_vp->y)); + pfunc(FBADDR(x + lcd_current_viewport->x, y + lcd_current_viewport->y)); if (d < 0) { @@ -307,9 +334,9 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x, void ICODE_ATTR lcd_bmp_part(const struct bitmap* bm, int src_x, int src_y, int x, int y, int width, int height) { - int bitmap_stride = STRIDE_MAIN(bm->width, bm->height); + int bitmap_stride = LCD_FBSTRIDE(bm->width, bm->height); if (bm->format == FORMAT_MONO) - lcd_mono_bitmap_part(bm->data, src_x, src_y, bitmap_stride, x, y, width, height); + lcd_mono_bitmap_part(bm->data, src_x, src_y, bm->width, x, y, width, height); else if (bm->alpha_offset > 0) lcd_alpha_bitmap_part_mix((fb_data*)bm->data, bm->data+bm->alpha_offset, src_x, src_y, x, y, width, height, @@ -554,7 +581,7 @@ void lcd_blit_yuv(unsigned char * const src[3], 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) { - int old_pattern = current_vp->fg_pattern; + int old_pattern = lcd_current_viewport->fg_pattern; int step_mul, i; int x1, x2; x1 = x; @@ -581,14 +608,14 @@ void lcd_gradient_fillrect_part(int x, int y, int width, int height, } for(i = y; i < y + height; i++) { - current_vp->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); + lcd_current_viewport->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); lcd_hline(x1, x2, i); h_r -= rstep; h_g -= gstep; h_b -= bstep; } - current_vp->fg_pattern = old_pattern; + lcd_current_viewport->fg_pattern = old_pattern; } /* Fill a rectangle with a gradient. The gradient's color will fade from diff --git a/firmware/drivers/lcd-scroll.c b/firmware/drivers/lcd-scroll.c index 5d66788093..d8bfd72dde 100644 --- a/firmware/drivers/lcd-scroll.c +++ b/firmware/drivers/lcd-scroll.c @@ -156,8 +156,9 @@ bool LCDFN(scroll_now)(struct scrollinfo *s) } } - /* Stash and restore these three, so that the scroll_func + /* Stash and restore these four, so that the scroll_func * can do whatever it likes without destroying the state */ + struct frame_buffer_t *framebuf = s->vp->buffer; unsigned drawmode; #if LCD_DEPTH > 1 unsigned fg_pattern, bg_pattern; @@ -174,6 +175,7 @@ bool LCDFN(scroll_now)(struct scrollinfo *s) s->vp->bg_pattern = bg_pattern; #endif s->vp->drawmode = drawmode; + s->vp->buffer = framebuf; return ended; } @@ -205,7 +207,7 @@ static void LCDFN(scroll_worker)(void) * be switched early so that lcd_getstringsize() picks the * correct font */ vp = LCDFN(get_viewport)(&is_default); - LCDFN(set_viewport)(s->vp); + LCDFN(set_viewport_ex)(s->vp, 0); /* don't mark the last vp as dirty */ makedelay = false; step = si->step; @@ -218,7 +220,7 @@ static void LCDFN(scroll_worker)(void) /* put the line onto the display now */ makedelay = LCDFN(scroll_now(s)); - LCDFN(set_viewport)(vp); + LCDFN(set_viewport_ex)(vp, 0); /* don't mark the last vp as dirty */ if (makedelay) s->start_tick += si->delay + si->ticks; -- cgit