1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
William Wilgus 2020-10-07 02:01:35 -04:00
parent 12f3ed1699
commit 3237ae4a4f
74 changed files with 1595 additions and 967 deletions

View file

@ -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)