summaryrefslogtreecommitdiffstats
path: root/firmware/drivers
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2020-10-07 02:01:35 -0400
committerWilliam Wilgus <wilgus.william@gmail.com>2020-10-26 12:28:48 -0400
commit3237ae4a4ff9296a377ff9194a11038da161208f (patch)
treeaf4338c78467b9b0845d76c39da1fbe10f25e23e /firmware/drivers
parent12f3ed1699d6bef25bed90ba95cbcc1a6bb4934a (diff)
downloadrockbox-3237ae4a4ff9296a377ff9194a11038da161208f.tar.gz
rockbox-3237ae4a4ff9296a377ff9194a11038da161208f.tar.bz2
rockbox-3237ae4a4ff9296a377ff9194a11038da161208f.zip
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
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/lcd-16bit-common.c112
-rw-r--r--firmware/drivers/lcd-16bit-vert.c98
-rw-r--r--firmware/drivers/lcd-16bit.c93
-rw-r--r--firmware/drivers/lcd-1bit-vert.c176
-rw-r--r--firmware/drivers/lcd-24bit.c180
-rw-r--r--firmware/drivers/lcd-2bit-horz.c215
-rw-r--r--firmware/drivers/lcd-2bit-vert.c210
-rw-r--r--firmware/drivers/lcd-2bit-vi.c202
-rw-r--r--firmware/drivers/lcd-bitmap-common.c166
-rw-r--r--firmware/drivers/lcd-color-common.c95
-rw-r--r--firmware/drivers/lcd-scroll.c8
11 files changed, 906 insertions, 649 deletions
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; i<LCDFN(scroll_info).lines; i++)
{
s = &LCDFN(scroll_info).scroll[i];
- if (s->x == 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;