From 3237ae4a4ff9296a377ff9194a11038da161208f Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Wed, 7 Oct 2020 02:01:35 -0400 Subject: LCD core move buf ptr and address look up function viewport struct I'm currently running up against the limitations of the lcd_draw functions I want these functions to be able to be used on any size buffer not just buffers with a stride matching the underlying device [DONE] allow the framebuffer to be decoupled from the device framebuffer [DONE need examples] allow for some simple blit like transformations [DONE] remove the device framebuffer from the plugin api [DONE}ditto remote framebuffer [DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr while remote lcds may compile (and work in the sim) its not been tested on targets [FIXED] backdrops need work to be screen agnostic [FIXED] screen statusbar is not being combined into the main viewport correctly yet [FIXED] screen elements are displayed incorrectly after switch to void* [FIXED] core didn't restore proper viewport on splash etc. [NEEDS TESTING] remote lcd garbled data [FIXED] osd lib garbled screen on bmp_part [FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport [FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer [FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw) [UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear scrolling viewports no longer trigger wps refresh also fixed a bug where guisyncyesno was displaying and then disappearing [ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes (LCD_ and LCD_REMOTE_) LCD_STRIDE(w, h) same as STRIDE_MAIN LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH) test_viewports.c has an example of usage [FIXED!!] 2bit targets don't respect non-native strides [FIXED] Few define snags Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af --- apps/alarm_menu.c | 5 +- apps/gui/bitmap/list.c | 4 +- apps/gui/color_picker.c | 8 +- apps/gui/pitchscreen.c | 5 +- apps/gui/quickscreen.c | 4 +- apps/gui/skin_engine/skin_backdrops.c | 25 +- apps/gui/skin_engine/skin_engine.c | 6 +- apps/gui/skin_engine/skin_engine.h | 2 +- apps/gui/skin_engine/skin_parser.c | 8 +- apps/gui/skin_engine/skin_render.c | 45 ++-- apps/gui/skin_engine/wps_internals.h | 1 + apps/gui/splash.c | 4 +- apps/gui/statusbar.c | 5 +- apps/gui/usb_screen.c | 5 +- apps/gui/viewport.c | 26 +- apps/gui/viewport.h | 3 + apps/gui/yesno.c | 9 +- apps/menus/time_menu.c | 4 +- apps/misc.c | 4 +- apps/onplay.c | 11 +- apps/plugin.c | 12 +- apps/plugin.h | 7 +- apps/plugins/doom/i_video.c | 10 +- apps/plugins/fire.c | 5 +- apps/plugins/imageviewer/imageviewer.c | 11 +- apps/plugins/imageviewer/jpeg/yuv2rgb.c | 12 +- apps/plugins/invadrox.c | 12 +- apps/plugins/lib/grey.h | 2 +- apps/plugins/lib/grey_core.c | 13 +- apps/plugins/lib/grey_parm.c | 4 +- apps/plugins/lib/osd.c | 27 +- apps/plugins/lib/xlcd.h | 2 + apps/plugins/lib/xlcd_core.c | 9 + apps/plugins/lib/xlcd_draw.c | 14 +- apps/plugins/lib/xlcd_scroll.c | 107 ++++++-- apps/plugins/lua/rocklib_img.c | 8 +- apps/plugins/mpegplayer/mpegplayer.c | 12 +- apps/plugins/oscilloscope.c | 4 +- apps/plugins/pacbox/pacbox.c | 6 +- apps/plugins/pictureflow/pictureflow.c | 6 +- apps/plugins/plasma.c | 11 +- apps/plugins/puzzles/rockbox.c | 17 +- apps/plugins/rockboy/lcd.c | 15 +- apps/plugins/rockboy/sys_rockbox.c | 10 +- .../sdl/src/video/rockbox/SDL_rockboxvideo.c | 11 +- apps/plugins/test_resize.c | 4 +- apps/plugins/test_viewports.c | 27 +- apps/plugins/xworld/sys.c | 21 +- apps/plugins/zxbox/zxvid_16bpp.c | 11 +- apps/plugins/zxbox/zxvid_2bpp.c | 13 +- apps/recorder/keyboard.c | 4 +- apps/screen_access.c | 21 +- apps/screen_access.h | 7 +- apps/screens.c | 5 +- firmware/drivers/lcd-16bit-common.c | 112 ++++----- firmware/drivers/lcd-16bit-vert.c | 98 ++++---- firmware/drivers/lcd-16bit.c | 93 +++---- firmware/drivers/lcd-1bit-vert.c | 176 ++++++++----- firmware/drivers/lcd-24bit.c | 180 +++++++------- firmware/drivers/lcd-2bit-horz.c | 215 +++++++++------- firmware/drivers/lcd-2bit-vert.c | 210 +++++++++------- firmware/drivers/lcd-2bit-vi.c | 202 +++++++++------ firmware/drivers/lcd-bitmap-common.c | 166 +++++++++---- firmware/drivers/lcd-color-common.c | 95 +++++--- firmware/drivers/lcd-scroll.c | 8 +- firmware/export/lcd-remote.h | 74 +++--- firmware/export/lcd.h | 271 +++++++++++++-------- firmware/target/arm/as3525/lcd-fuze.c | 2 +- .../arm/tms320dm320/creative-zvm/lcd-creativezvm.c | 2 +- .../target/arm/tms320dm320/mrobe-500/lcd-mr500.c | 4 +- firmware/target/coldfire/iriver/h300/lcd-h300.c | 2 +- firmware/target/coldfire/mpio/hd200/lcd-hd200.c | 2 +- firmware/target/hosted/android/lcd-android.c | 4 +- firmware/target/hosted/sdl/lcd-sdl.c | 2 +- 74 files changed, 1595 insertions(+), 967 deletions(-) diff --git a/apps/alarm_menu.c b/apps/alarm_menu.c index 497747bd7b..62b54a84bb 100644 --- a/apps/alarm_menu.c +++ b/apps/alarm_menu.c @@ -60,6 +60,7 @@ int alarm_screen(void) bool update = true; bool hour_wrapped = false; struct viewport vp[NB_SCREENS]; + struct viewport * last_vp; rtc_get_alarm(&h, &m); @@ -91,11 +92,11 @@ int alarm_screen(void) FOR_NB_SCREENS(i) { - screens[i].set_viewport(&vp[i]); + last_vp = screens[i].set_viewport(&vp[i]); screens[i].putsf(0, 1, str(LANG_ALARM_MOD_TIME)); screens[i].putsf(0, 2, "%02d:%02d", h, m); screens[i].update_viewport(); - screens[i].set_viewport(NULL); + screens[i].set_viewport(last_vp); } button = get_action(CONTEXT_SETTINGS,HZ); diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index 2d3141b8cc..27121eac56 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c @@ -146,7 +146,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) struct viewport *list_text_vp = &list_text[screen]; int indent = 0; - display->set_viewport(parent); + struct viewport * last_vp = display->set_viewport(parent); display->clear_viewport(); display->scroll_stop_viewport(list_text_vp); *list_text_vp = *parent; @@ -332,7 +332,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) } display->set_viewport(parent); display->update_viewport(); - display->set_viewport(NULL); + display->set_viewport(last_vp); } #if defined(HAVE_TOUCHSCREEN) diff --git a/apps/gui/color_picker.c b/apps/gui/color_picker.c index 03096e5589..a32f1ee179 100644 --- a/apps/gui/color_picker.c +++ b/apps/gui/color_picker.c @@ -164,7 +164,7 @@ static void draw_screen(struct screen *display, char *title, struct viewport vp; viewport_set_defaults(&vp, display->screen_type); - display->set_viewport(&vp); + struct viewport * last_vp = display->set_viewport(&vp); display->clear_viewport(); @@ -323,7 +323,7 @@ static void draw_screen(struct screen *display, char *title, } display->update_viewport(); - display->set_viewport(NULL); + display->set_viewport(last_vp); } #ifdef HAVE_TOUCHSCREEN @@ -341,7 +341,7 @@ static int touchscreen_slider(struct screen *display, struct viewport vp; viewport_set_defaults(&vp, display->screen_type); - display->set_viewport(&vp); + struct viewport *last_vp = display->set_viewport(&vp); button = action_get_touchscreen_press_in_vp(&x, &y, &vp); if (button == ACTION_UNKNOWN || button == BUTTON_NONE) @@ -373,7 +373,7 @@ static int touchscreen_slider(struct screen *display, char_height*2 + /* + margins for bottom */ MARGIN_BOTTOM; /* colored rectangle */ - display->set_viewport(NULL); + display->set_viewport(last_vp); if (y < text_top) { diff --git a/apps/gui/pitchscreen.c b/apps/gui/pitchscreen.c index 0d31193fa6..b5b719ef02 100644 --- a/apps/gui/pitchscreen.c +++ b/apps/gui/pitchscreen.c @@ -239,6 +239,7 @@ static void pitchscreen_draw(struct screen *display, int max_lines, char buf[32]; int w, h; bool show_lang_pitch; + struct viewport *last_vp = NULL; /* "Pitch up/Pitch down" - hide for a small screen, * the text is drawn centered automatically @@ -249,7 +250,7 @@ static void pitchscreen_draw(struct screen *display, int max_lines, { int w, h; struct viewport *vp = &pitch_viewports[PITCH_TOP]; - display->set_viewport(vp); + last_vp = display->set_viewport(vp); display->clear_viewport(); #ifdef HAVE_TOUCHSCREEN /* two arrows in the top row, left and right column */ @@ -405,7 +406,7 @@ static void pitchscreen_draw(struct screen *display, int max_lines, rightlabel); } display->update_viewport(); - display->set_viewport(NULL); + display->set_viewport(last_vp); } static int32_t pitch_increase(int32_t pitch, int32_t pitch_delta, bool allow_cutoff diff --git a/apps/gui/quickscreen.c b/apps/gui/quickscreen.c index 704133c1c4..421cc267ca 100644 --- a/apps/gui/quickscreen.c +++ b/apps/gui/quickscreen.c @@ -172,7 +172,7 @@ static void gui_quickscreen_draw(const struct gui_quickscreen *qs, char buf[MAX_PATH]; unsigned const char *title, *value; int temp; - display->set_viewport(parent); + struct viewport *last_vp = display->set_viewport(parent); display->clear_viewport(); for (i = 0; i < QUICKSCREEN_ITEM_COUNT; i++) @@ -225,7 +225,7 @@ static void gui_quickscreen_draw(const struct gui_quickscreen *qs, display->set_viewport(parent); display->update_viewport(); - display->set_viewport(NULL); + display->set_viewport(last_vp); } static void talk_qs_option(const struct settings_list *opt, bool enqueue) diff --git a/apps/gui/skin_engine/skin_backdrops.c b/apps/gui/skin_engine/skin_backdrops.c index 243fc30a3a..caf705af54 100644 --- a/apps/gui/skin_engine/skin_backdrops.c +++ b/apps/gui/skin_engine/skin_backdrops.c @@ -204,11 +204,28 @@ bool skin_backdrops_preload(void) return retval; } -void* skin_backdrop_get_buffer(int backdrop_id) +void skin_backdrop_set_buffer(int backdrop_id, struct skin_viewport *svp) { - if (backdrop_id < 0) - return NULL; - return backdrops[backdrop_id].buffer; + if (UNLIKELY(!svp)) + return; + else if (backdrop_id < 0) + { + svp->vp.buffer = NULL; /*Default*/ + return; + } + + enum screen_type screen = backdrops[backdrop_id].screen; + svp->framebuf.ch_ptr = backdrops[backdrop_id].buffer; +#if defined(HAVE_REMOTE_LCD) + if (screen == SCREEN_REMOTE) + svp->framebuf.elems = REMOTE_LCD_BACKDROP_BYTES / sizeof(fb_remote_data); + else +#endif + { + svp->framebuf.elems = LCD_BACKDROP_BYTES / sizeof(fb_data); + } + svp->framebuf.get_address_fn = NULL; /*Default iterator*/ + screens[screen].viewport_set_buffer(&svp->vp, &svp->framebuf); } void skin_backdrop_show(int backdrop_id) diff --git a/apps/gui/skin_engine/skin_engine.c b/apps/gui/skin_engine/skin_engine.c index cd763def1c..049629b181 100644 --- a/apps/gui/skin_engine/skin_engine.c +++ b/apps/gui/skin_engine/skin_engine.c @@ -312,7 +312,11 @@ struct wps_state *skin_get_global_state(void) bool skin_do_full_update(enum skinnable_screens skin, enum screen_type screen) { - bool ret = skins[skin][screen].needs_full_update; + struct viewport *vp = *(screens[screen].current_viewport); + + bool vp_is_dirty = ((vp->flags & VP_FLAG_VP_SET_CLEAN) == VP_FLAG_VP_DIRTY); + + bool ret = (skins[skin][screen].needs_full_update || vp_is_dirty); skins[skin][screen].needs_full_update = false; return ret; } diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h index 55839608be..3b757a5f8b 100644 --- a/apps/gui/skin_engine/skin_engine.h +++ b/apps/gui/skin_engine/skin_engine.h @@ -70,7 +70,7 @@ void skin_backdrop_show(int backdrop_id); void skin_backdrop_load_setting(void); void skin_backdrop_unload(int backdrop_id); #define BACKDROP_BUFFERNAME "#backdrop_buffer#" -void* skin_backdrop_get_buffer(int backdrop_id); +void skin_backdrop_set_buffer(int backdrop_id, struct skin_viewport *svp); /* do the button loop as often as required for the peak meters to update * with a good refresh rate. diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index f3a23377ef..e1a8118190 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -259,7 +259,7 @@ static int parse_statusbar_tags(struct skin_element* element, } else { - struct skin_viewport *default_vp = SKINOFFSETTOPTR(skin_buffer, first_viewport->data); + struct skin_viewport *skin_default = SKINOFFSETTOPTR(skin_buffer, first_viewport->data); if (first_viewport->params_count == 0) { wps_data->wps_sb_tag = true; @@ -267,11 +267,11 @@ static int parse_statusbar_tags(struct skin_element* element, } if (wps_data->show_sb_on_wps) { - viewport_set_defaults(&default_vp->vp, curr_screen); + viewport_set_defaults(&skin_default->vp, curr_screen); } else { - viewport_set_fullscreen(&default_vp->vp, curr_screen); + viewport_set_fullscreen(&skin_default->vp, curr_screen); } #ifdef HAVE_REMOTE_LCD /* This parser requires viewports which will use the settings font to @@ -279,7 +279,7 @@ static int parse_statusbar_tags(struct skin_element* element, * the current real font id. So force 1 here it will be set correctly * at the end */ - default_vp->vp.font = 1; + skin_default->vp.font = 1; #endif } return 0; diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c index 51c58fc196..00981f5b67 100644 --- a/apps/gui/skin_engine/skin_render.c +++ b/apps/gui/skin_engine/skin_render.c @@ -349,6 +349,8 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch, { struct gui_wps *gwps = info->gwps; struct wps_data *data = gwps->data; + struct viewport *last_vp; + /* Tags here are ones which need to be "turned off" or cleared * if they are in a conditional branch which isnt being used */ if (branch->type == LINE_ALTERNATOR) @@ -420,22 +422,23 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch, #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) if (skin_viewport->output_to_backdrop_buffer) { - void *backdrop = skin_backdrop_get_buffer(data->backdrop_id); - gwps->display->set_framebuffer(backdrop); + skin_backdrop_set_buffer(data->backdrop_id, skin_viewport); skin_backdrop_show(-1); } #endif - gwps->display->set_viewport(&skin_viewport->vp); + last_vp = gwps->display->set_viewport(&skin_viewport->vp); gwps->display->clear_viewport(); - gwps->display->set_viewport(&info->skin_vp->vp); + gwps->display->set_viewport_ex(&info->skin_vp->vp, 0); skin_viewport->hidden_flags |= VP_DRAW_HIDDEN; #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) if (skin_viewport->output_to_backdrop_buffer) { - gwps->display->set_framebuffer(NULL); + gwps->display->set_viewport_ex(last_vp, 0); skin_backdrop_show(data->backdrop_id); } +#else + (void)last_vp; #endif } } @@ -792,6 +795,7 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps, void skin_render(struct gui_wps *gwps, unsigned refresh_mode) { + const int vp_is_appearing = (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE); struct wps_data *data = gwps->data; struct screen *display = gwps->display; @@ -801,7 +805,20 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) int old_refresh_mode = refresh_mode; skin_buffer = get_skin_buffer(gwps->data); - + + struct viewport* first_vp; + /* should already be the default buffer */ + first_vp = display->set_viewport(NULL); + + /* Framebuffer is likely dirty */ + if ((refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL) + { + if ((first_vp->flags & VP_FLAG_VP_SET_CLEAN) == VP_FLAG_VP_DIRTY && + get_current_activity() == ACTIVITY_WPS) /* only clear if in WPS */ + { + display->clear_viewport(); + } + } viewport = SKINOFFSETTOPTR(skin_buffer, data->tree); skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data); @@ -822,12 +839,12 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) if (skin_viewport->output_to_backdrop_buffer) { - display->set_framebuffer(skin_backdrop_get_buffer(data->backdrop_id)); + skin_backdrop_set_buffer(data->backdrop_id, skin_viewport); skin_backdrop_show(-1); } else { - display->set_framebuffer(NULL); + skin_backdrop_set_buffer(-1, skin_viewport); skin_backdrop_show(data->backdrop_id); } #endif @@ -842,15 +859,14 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN; continue; } - else if (((skin_viewport->hidden_flags& - (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)) - == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))) + else if ((skin_viewport->hidden_flags & vp_is_appearing) == vp_is_appearing) { vp_refresh_mode = SKIN_REFRESH_ALL; skin_viewport->hidden_flags = VP_DRAW_HIDEABLE; } - display->set_viewport(&skin_viewport->vp); + display->set_viewport_ex(&skin_viewport->vp, VP_FLAG_VP_SET_CLEAN); + if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL) { display->clear_viewport(); @@ -862,7 +878,6 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) refresh_mode = old_refresh_mode; } #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) - display->set_framebuffer(NULL); skin_backdrop_show(data->backdrop_id); #endif @@ -872,8 +887,8 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) * to redraw itself */ send_event(GUI_EVENT_NEED_UI_UPDATE, NULL); } - /* Restore the default viewport */ - display->set_viewport(NULL); + /* Restore the first viewport */ + display->set_viewport_ex(first_vp, VP_FLAG_VP_SET_CLEAN); display->update(); } diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index b7d7ff35d0..bf7f52bdbf 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -175,6 +175,7 @@ struct gradient_config { #define VP_DEFAULT_LABEL_STRING "|" struct skin_viewport { struct viewport vp; /* The LCD viewport struct */ + struct frame_buffer_t framebuf; char hidden_flags; bool is_infovp; OFFSETTYPE(char*) label; diff --git a/apps/gui/splash.c b/apps/gui/splash.c index 5bcac80169..1415d47a70 100644 --- a/apps/gui/splash.c +++ b/apps/gui/splash.c @@ -53,7 +53,7 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) int maxw = 0; viewport_set_defaults(&vp, screen->screen_type); - screen->set_viewport(&vp); + struct viewport *last_vp = screen->set_viewport(&vp); screen->getstringsize(" ", &space_w, &h); y = h; @@ -157,7 +157,7 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) } screen->update_viewport(); end: - screen->set_viewport(NULL); + screen->set_viewport(last_vp); } void splashf(int ticks, const char *fmt, ...) diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c index cf70b7bb39..708624b23e 100644 --- a/apps/gui/statusbar.c +++ b/apps/gui/statusbar.c @@ -183,6 +183,7 @@ static void gui_statusbar_init(struct gui_statusbar * bar) void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw, struct viewport *vp) { struct screen * display = bar->display; + struct viewport *last_vp = NULL; if (!display) return; @@ -267,7 +268,7 @@ void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw, struct vi #endif memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info))) { - display->set_viewport(vp); + last_vp = display->set_viewport(vp); display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); display->fill_viewport(); display->set_drawmode(DRMODE_SOLID); @@ -343,7 +344,7 @@ void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw, struct vi gui_statusbar_led(display); #endif display->update_viewport(); - display->set_viewport(NULL); + display->set_viewport(last_vp); bar->lastinfo = bar->info; } } diff --git a/apps/gui/usb_screen.c b/apps/gui/usb_screen.c index 3169831322..31321ec005 100644 --- a/apps/gui/usb_screen.c +++ b/apps/gui/usb_screen.c @@ -179,6 +179,7 @@ static void usb_screen_fix_viewports(struct screen *screen, static void usb_screens_draw(struct usb_screen_vps_t *usb_screen_vps_ar) { + struct viewport *last_vp; static const struct bitmap* logos[NB_SCREENS] = { &bm_usblogo, #ifdef HAVE_REMOTE_LCD @@ -194,7 +195,7 @@ static void usb_screens_draw(struct usb_screen_vps_t *usb_screen_vps_ar) struct viewport *parent = &usb_screen_vps->parent; struct viewport *logo = &usb_screen_vps->logo; - screen->set_viewport(parent); + last_vp = screen->set_viewport(parent); screen->clear_viewport(); screen->backlight_on(); @@ -217,7 +218,7 @@ static void usb_screens_draw(struct usb_screen_vps_t *usb_screen_vps_ar) } screen->set_viewport(parent); - screen->set_viewport(NULL); + screen->set_viewport(last_vp); screen->update_viewport(); } } diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c index db58b5d72d..9fdf88e8f0 100644 --- a/apps/gui/viewport.c +++ b/apps/gui/viewport.c @@ -31,6 +31,7 @@ #include "settings.h" #include "misc.h" #include "list.h" + /*some short cuts for fg/bg/line selector handling */ #ifdef HAVE_LCD_COLOR #define FG_FALLBACK global_settings.fg_color @@ -44,7 +45,6 @@ #define REMOTE_BG_FALLBACK LCD_REMOTE_DEFAULT_BG #endif - /* all below isn't needed for pc tools (i.e. checkwps/wps editor) * only viewport_parse_viewport() is */ #ifndef __PCTOOL__ @@ -101,6 +101,7 @@ static void toggle_theme(enum screen_type screen, bool force) bool enable_event = false; static bool was_enabled[NB_SCREENS] = {false}; static bool after_boot[NB_SCREENS] = {false}; + struct viewport *last_vp; FOR_NB_SCREENS(i) { @@ -111,6 +112,7 @@ static void toggle_theme(enum screen_type screen, bool force) if (is_theme_enabled(screen)) { + last_vp = screens[screen].set_viewport(NULL); bool first_boot = theme_stack_top[screen] == 0; /* remove the left overs from the previous screen. * could cause a tiny flicker. Redo your screen code if that happens */ @@ -162,7 +164,7 @@ static void toggle_theme(enum screen_type screen, bool force) screens[screen].clear_viewport(); screens[screen].update_viewport(); } - screens[screen].set_viewport(NULL); + screens[screen].set_viewport(last_vp); } intptr_t force = first_boot?0:1; @@ -282,11 +284,11 @@ static void set_default_align_flags(struct viewport *vp) void viewport_set_fullscreen(struct viewport *vp, const enum screen_type screen) { + screens[screen].init_viewport(vp); vp->x = 0; vp->y = 0; vp->width = screens[screen].lcdwidth; vp->height = screens[screen].lcdheight; - #ifndef __PCTOOL__ set_default_align_flags(vp); #endif @@ -312,9 +314,25 @@ void viewport_set_fullscreen(struct viewport *vp, #endif } +void viewport_set_buffer(struct viewport *vp, struct frame_buffer_t *buffer, + const enum screen_type screen) +{ + if (!vp) /* NULL vp grabs current framebuffer */ + vp = *(screens[screen].current_viewport); + + /* NULL sets default buffer */ + if (buffer && buffer->elems == 0) + vp->buffer = NULL; + else + vp->buffer = buffer; + screens[screen].init_viewport(vp); +} + void viewport_set_defaults(struct viewport *vp, const enum screen_type screen) { + vp->buffer = NULL; /* use default frame_buffer */ + #if !defined(__PCTOOL__) struct viewport *sbs_area = NULL; if (!is_theme_enabled(screen)) @@ -323,7 +341,7 @@ void viewport_set_defaults(struct viewport *vp, return; } sbs_area = sb_skin_get_info_vp(screen); - + if (sbs_area) *vp = *sbs_area; else diff --git a/apps/gui/viewport.h b/apps/gui/viewport.h index 683c36fe76..be80e44721 100644 --- a/apps/gui/viewport.h +++ b/apps/gui/viewport.h @@ -63,6 +63,9 @@ void viewportmanager_theme_undo(enum screen_type screen, bool force_redraw); /* call this when a theme changed */ void viewportmanager_theme_changed(const int); +void viewport_set_buffer(struct viewport *vp, struct frame_buffer_t *buffer, + const enum screen_type screen); + #ifdef HAVE_TOUCHSCREEN bool viewport_point_within_vp(const struct viewport *vp, const int x, const int y); diff --git a/apps/gui/yesno.c b/apps/gui/yesno.c index 1a1645047a..d70b66f230 100644 --- a/apps/gui/yesno.c +++ b/apps/gui/yesno.c @@ -78,8 +78,9 @@ static void gui_yesno_draw(struct gui_yesno * yn) struct screen * display=yn->display; struct viewport *vp = yn->vp; int nb_lines, vp_lines, line_shift=0; + struct viewport *last_vp; - display->set_viewport(vp); + last_vp = display->set_viewport(vp); display->clear_viewport(); nb_lines = yn->main_message->nb_lines; vp_lines = viewport_get_nb_lines(vp); @@ -116,7 +117,7 @@ static void gui_yesno_draw(struct gui_yesno * yn) } #endif display->update_viewport(); - display->set_viewport(NULL); + display->set_viewport(last_vp); } /* @@ -133,11 +134,11 @@ static bool gui_yesno_draw_result(struct gui_yesno * yn, enum yesno_res result) struct screen * display=yn->display; if(message==NULL) return false; - display->set_viewport(vp); + struct viewport *last_vp = display->set_viewport(vp); display->clear_viewport(); put_message(yn->display, message, 0, viewport_get_nb_lines(vp)); display->update_viewport(); - display->set_viewport(NULL); + display->set_viewport(last_vp); return(true); } diff --git a/apps/menus/time_menu.c b/apps/menus/time_menu.c index 6ebf005ffd..edd2e19a2b 100644 --- a/apps/menus/time_menu.c +++ b/apps/menus/time_menu.c @@ -169,7 +169,7 @@ static void draw_timedate(struct viewport *vp, struct screen *display) const char *t = time, *d = date; if (vp->height == 0) return; - display->set_viewport(vp); + struct viewport *last_vp = display->set_viewport(vp); display->clear_viewport(); if (viewport_get_nb_lines(vp) >= 4) line = 1; @@ -200,7 +200,7 @@ static void draw_timedate(struct viewport *vp, struct screen *display) display->puts(0, line, d); display->update_viewport(); - display->set_viewport(NULL); + display->set_viewport(last_vp); } diff --git a/apps/misc.c b/apps/misc.c index 7d4ca97ff8..3a8798fec0 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -769,7 +769,9 @@ int show_logo( void ) lcd_remote_setfont(FONT_UI); lcd_remote_update(); #endif - +#ifdef SIMULATOR + sleep(HZ); /* sim is too fast to see logo */ +#endif return 0; } diff --git a/apps/onplay.c b/apps/onplay.c index f2ebd47630..ded2994c97 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -795,33 +795,34 @@ static int cat_playlist_callback(int action, static void draw_slider(void) { + struct viewport *last_vp; FOR_NB_SCREENS(i) { struct viewport vp; int slider_height = 2*screens[i].getcharheight(); viewport_set_defaults(&vp, i); - screens[i].set_viewport(&vp); + last_vp = screens[i].set_viewport(&vp); show_busy_slider(&screens[i], 1, vp.height - slider_height, vp.width-2, slider_height-1); screens[i].update_viewport(); - screens[i].set_viewport(NULL); + screens[i].set_viewport(last_vp); } } static void clear_display(bool update) { struct viewport vp; - + struct viewport *last_vp; FOR_NB_SCREENS(i) { struct screen * screen = &screens[i]; viewport_set_defaults(&vp, screen->screen_type); - screen->set_viewport(&vp); + last_vp = screen->set_viewport(&vp); screen->clear_viewport(); if (update) { screen->update_viewport(); } - screen->set_viewport(NULL); + screen->set_viewport(last_vp); } } diff --git a/apps/plugin.c b/apps/plugin.c index 48f9dac487..4a50c2b3a3 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -194,9 +194,7 @@ static const struct plugin_api rockbox_api = { lcd_putsf, lcd_puts_scroll, lcd_scroll_stop, - &lcd_framebuffer, lcd_set_viewport, - lcd_set_framebuffer, lcd_bmp_part, lcd_update_rect, lcd_set_drawmode, @@ -281,7 +279,6 @@ static const struct plugin_api rockbox_api = { lcd_remote_mono_bitmap_part, lcd_remote_mono_bitmap, lcd_remote_putsxy, - &lcd_remote_framebuffer; lcd_remote_update, lcd_remote_update_rect, #if (LCD_REMOTE_DEPTH > 1) @@ -303,6 +300,7 @@ static const struct plugin_api rockbox_api = { viewportmanager_theme_enable, viewportmanager_theme_undo, viewport_set_fullscreen, + viewport_set_buffer, #ifdef HAVE_BACKLIGHT /* lcd backlight */ @@ -869,11 +867,12 @@ int plugin_load(const char* plugin, const void* parameter) #endif *(p_hdr->api) = &rockbox_api; - + lcd_set_viewport(NULL); lcd_clear_display(); lcd_update(); #ifdef HAVE_REMOTE_LCD + lcd_remote_set_viewport(NULL); lcd_remote_clear_display(); lcd_remote_update(); #endif @@ -914,7 +913,8 @@ int plugin_load(const char* plugin, const void* parameter) #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(global_settings.touch_mode); #endif - + /* restore default vp */ + lcd_set_viewport(NULL); screen_helper_setfont(FONT_UI); #if LCD_DEPTH > 1 #ifdef HAVE_LCD_COLOR @@ -928,6 +928,8 @@ int plugin_load(const char* plugin, const void* parameter) #endif /* LCD_DEPTH */ #ifdef HAVE_REMOTE_LCD + lcd_remote_set_viewport(NULL); + #if LCD_REMOTE_DEPTH > 1 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG, LCD_REMOTE_DEFAULT_BG); diff --git a/apps/plugin.h b/apps/plugin.h index 12fc5424f1..395caaddc0 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -204,9 +204,7 @@ struct plugin_api { void (*lcd_putsf)(int x, int y, const unsigned char *fmt, ...); bool (*lcd_puts_scroll)(int x, int y, const unsigned char* string); void (*lcd_scroll_stop)(void); - fb_data** lcd_framebuffer; - void (*lcd_set_viewport)(struct viewport* vp); - void (*lcd_set_framebuffer)(fb_data *fb); + struct viewport* (*lcd_set_viewport)(struct viewport* vp); void (*lcd_bmp_part)(const struct bitmap *bm, int src_x, int src_y, int x, int y, int width, int height); void (*lcd_update_rect)(int x, int y, int width, int height); @@ -314,7 +312,6 @@ struct plugin_api { void (*lcd_remote_mono_bitmap)(const unsigned char *src, int x, int y, int width, int height); void (*lcd_remote_putsxy)(int x, int y, const unsigned char *string); - fb_remote_data** lcd_remote_framebuffer; void (*lcd_remote_update)(void); void (*lcd_remote_update_rect)(int x, int y, int width, int height); #if (LCD_REMOTE_DEPTH > 1) @@ -338,6 +335,8 @@ struct plugin_api { void (*viewportmanager_theme_undo)(enum screen_type screen, bool force_redraw); void (*viewport_set_fullscreen)(struct viewport *vp, const enum screen_type screen); + void (*viewport_set_buffer)(struct viewport *vp, struct frame_buffer_t *buffer, + const enum screen_type screen); #ifdef HAVE_BACKLIGHT /* lcd backlight */ diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c index 3186fac16d..99b4de827d 100644 --- a/apps/plugins/doom/i_video.c +++ b/apps/plugins/doom/i_video.c @@ -1052,6 +1052,12 @@ void I_FinishUpdate (void) rb->lcd_blit_pal256(src, 0, 0, 0, 0, LCD_WIDTH, LCD_HEIGHT); #endif #elif defined(HAVE_LCD_COLOR) + static fb_data *lcd_fb = NULL; + if (!lcd_fb) + { + struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); + lcd_fb = vp_main->buffer->fb_ptr; + } #if(LCD_HEIGHT>LCD_WIDTH) if(rotate_screen) { @@ -1059,7 +1065,7 @@ void I_FinishUpdate (void) for (y = 1; y <= SCREENHEIGHT; y++) { - fb_data *dst = *rb->lcd_framebuffer + LCD_WIDTH - y; + fb_data *dst = lcd_fb + LCD_WIDTH - y; count = SCREENWIDTH; do @@ -1073,7 +1079,7 @@ void I_FinishUpdate (void) else #endif { - fb_data *dst = *rb->lcd_framebuffer; + fb_data *dst = lcd_fb; count = SCREENWIDTH*SCREENHEIGHT; do diff --git a/apps/plugins/fire.c b/apps/plugins/fire.c index 95edbf37c4..f3e6fb35e4 100644 --- a/apps/plugins/fire.c +++ b/apps/plugins/fire.c @@ -30,6 +30,7 @@ #ifndef HAVE_LCD_COLOR #include "lib/grey.h" #endif +static fb_data *lcd_fb = NULL; #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) /* Archos has not enough plugin RAM for full-width fire :( */ @@ -251,7 +252,7 @@ static inline void fire_draw(struct fire* fire) #ifndef HAVE_LCD_COLOR dest = draw_buffer; #else - dest = *rb->lcd_framebuffer + LCD_WIDTH * y + FIRE_XPOS; + dest = lcd_fb + LCD_WIDTH * y + FIRE_XPOS; #endif end = dest + FIRE_WIDTH; @@ -379,6 +380,8 @@ enum plugin_status plugin_start(const void* parameter) rb->lcd_set_mode(LCD_MODE_PAL256); #endif + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; ret = main(); #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) diff --git a/apps/plugins/imageviewer/imageviewer.c b/apps/plugins/imageviewer/imageviewer.c index 37c5838d73..4b1a982438 100644 --- a/apps/plugins/imageviewer/imageviewer.c +++ b/apps/plugins/imageviewer/imageviewer.c @@ -509,6 +509,13 @@ static void pan_view_up(struct image_info *info) the bottom */ static void pan_view_down(struct image_info *info) { + static fb_data *lcd_fb = NULL; + if (!lcd_fb) + { + struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); + lcd_fb = vp_main->buffer->fb_ptr; + } + int move; move = MIN(VSCROLL, info->height - info->y - LCD_HEIGHT); @@ -526,7 +533,7 @@ static void pan_view_down(struct image_info *info) */ move++, info->y--; rb->memcpy(rgb_linebuf, - *rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, + lcd_fb + (LCD_HEIGHT - move)*LCD_WIDTH, LCD_WIDTH*sizeof (fb_data)); } #endif @@ -539,7 +546,7 @@ static void pan_view_down(struct image_info *info) && settings.jpeg_dither_mode == DITHER_DIFFUSION) { /* Cover the first row drawn with previous image data. */ - rb->memcpy(*rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, + rb->memcpy(lcd_fb + (LCD_HEIGHT - move)*LCD_WIDTH, rgb_linebuf, LCD_WIDTH*sizeof (fb_data)); info->y++; } diff --git a/apps/plugins/imageviewer/jpeg/yuv2rgb.c b/apps/plugins/imageviewer/jpeg/yuv2rgb.c index 5504e425e6..d0d5cb683b 100644 --- a/apps/plugins/imageviewer/jpeg/yuv2rgb.c +++ b/apps/plugins/imageviewer/jpeg/yuv2rgb.c @@ -236,15 +236,15 @@ static fb_data (* const pixel_funcs[COLOUR_NUM_MODES][DITHER_NUM_MODES])(void) = [DITHER_DIFFUSION] = pixel_fsdither_to_lcd, }, }; - +static fb_data *lcd_fb = NULL; /* These defines are used fornormal horizontal strides and vertical strides. */ #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE -#define LCDADDR(x, y) (*rb->lcd_framebuffer + LCD_HEIGHT*(x) + (y)) +#define LCDADDR(x, y) (lcd_fb + LCD_HEIGHT*(x) + (y)) #define ROWENDOFFSET (width*LCD_HEIGHT) #define ROWOFFSET (1) #define COLOFFSET (LCD_HEIGHT) #else -#define LCDADDR(x, y) (*rb->lcd_framebuffer + LCD_WIDTH*(y) + (x)) +#define LCDADDR(x, y) (lcd_fb + LCD_WIDTH*(y) + (x)) #define ROWENDOFFSET (width) #define ROWOFFSET (LCD_WIDTH) #define COLOFFSET (1) @@ -261,6 +261,12 @@ void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y, int x, int y, int width, int height, int colour_mode, int dither_mode) { + if (!lcd_fb) + { + struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); + lcd_fb = vp_main->buffer->fb_ptr; + } + fb_data *dst, *dst_end; fb_data (*pixel_func)(void); struct rgb_pixel px; diff --git a/apps/plugins/invadrox.c b/apps/plugins/invadrox.c index 0b26581b30..1c39a01c87 100644 --- a/apps/plugins/invadrox.c +++ b/apps/plugins/invadrox.c @@ -768,7 +768,7 @@ int curr_alien, aliens_paralyzed, gamespeed; int ufo_state, ufo_x; bool level_finished; bool aliens_down, aliens_right, hit_left_border, hit_right_border; - +static fb_data *lcd_fb; /* No standard get_pixel function yet, use this hack instead */ #if (LCD_DEPTH >= 8) @@ -776,12 +776,12 @@ bool aliens_down, aliens_right, hit_left_border, hit_right_border; #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE static inline fb_data get_pixel(int x, int y) { - return *rb->lcd_framebuffer[x*LCD_HEIGHT+y]; + return lcd_fb[x*LCD_HEIGHT+y]; } #else static inline fb_data get_pixel(int x, int y) { - return *rb->lcd_framebuffer[ytab[y] + x]; + return lcd_fb[ytab[y] + x]; } #endif @@ -794,7 +794,7 @@ static const unsigned char shifts[4] = { /* Horizontal packing */ static inline fb_data get_pixel(int x, int y) { - return (*rb->lcd_framebuffer[ytab[y] + (x >> 2)] >> shifts[x & 3]) & 3; + return (lcd_fb[ytab[y] + (x >> 2)] >> shifts[x & 3]) & 3; } #else /* Vertical packing */ @@ -803,7 +803,7 @@ static const unsigned char shifts[4] = { }; static inline fb_data get_pixel(int x, int y) { - return (*rb->lcd_framebuffer[ytab[y] + x] >> shifts[y & 3]) & 3; + return (lcd_fb[ytab[y] + x] >> shifts[y & 3]) & 3; } #endif /* Horizontal/Vertical packing */ @@ -1902,6 +1902,8 @@ enum plugin_status plugin_start(UNUSED const void* parameter) #ifdef HAVE_BACKLIGHT backlight_ignore_timeout(); #endif + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; /* now go ahead and have fun! */ game_loop(); diff --git a/apps/plugins/lib/grey.h b/apps/plugins/lib/grey.h index 0e064f46b2..5cafc6a83e 100644 --- a/apps/plugins/lib/grey.h +++ b/apps/plugins/lib/grey.h @@ -62,7 +62,7 @@ void grey_deferred_lcd_update(void); /* Viewports and framebuffers */ void grey_clear_viewport(void); -void grey_set_viewport(struct viewport *vp); +struct viewport *grey_set_viewport(struct viewport *vp); void grey_viewport_set_fullscreen(struct viewport *vp, const enum screen_type screen); void grey_viewport_set_pos(struct viewport *vp, diff --git a/apps/plugins/lib/grey_core.c b/apps/plugins/lib/grey_core.c index 9686f1d021..e3543aeba2 100644 --- a/apps/plugins/lib/grey_core.c +++ b/apps/plugins/lib/grey_core.c @@ -765,6 +765,11 @@ static const unsigned char colorindex[4] = {128, 85, 43, 0}; content (b&w and greyscale overlay) to an 8-bit BMP file. */ static void grey_screendump_hook(int fd) { + fb_data *lcd_fb; + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + rb->viewport_set_fullscreen(vp_main, SCREEN_MAIN); + lcd_fb = vp_main->buffer->fb_ptr; + int i; int y, gx, gy; #if LCD_PIXELFORMAT == VERTICAL_PACKING @@ -845,7 +850,7 @@ static void grey_screendump_hook(int fd) gsrc = _grey_info.values + _GREY_MULUQ(_grey_info.width, gy); #if LCD_DEPTH == 2 - src = *rb->lcd_framebuffer + _GREY_MULUQ(LCD_FBWIDTH, y); + src = lcd_fb + _GREY_MULUQ(LCD_FBWIDTH, y); do { @@ -876,7 +881,7 @@ static void grey_screendump_hook(int fd) #if LCD_DEPTH == 1 mask = BIT_N(y & 7); - src = *rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3); + src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 3); do { @@ -908,7 +913,7 @@ static void grey_screendump_hook(int fd) #elif LCD_DEPTH == 2 shift = 2 * (y & 3); - src = *rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 2); + src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 2); do { @@ -933,7 +938,7 @@ static void grey_screendump_hook(int fd) #if LCD_DEPTH == 2 shift = y & 7; - src = *rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3); + src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 3); do { diff --git a/apps/plugins/lib/grey_parm.c b/apps/plugins/lib/grey_parm.c index d2dfde42f1..700b6f0026 100644 --- a/apps/plugins/lib/grey_parm.c +++ b/apps/plugins/lib/grey_parm.c @@ -154,8 +154,9 @@ static void grey_update_clip_rect(void) } /* Set current grey viewport for draw routines */ -void grey_set_viewport(struct viewport *vp) +struct viewport *grey_set_viewport(struct viewport *vp) { + struct viewport *last_vp = _grey_info.vp; if (vp == NULL) vp = &_grey_default_vp; @@ -164,6 +165,7 @@ void grey_set_viewport(struct viewport *vp) _grey_info.vp = vp; grey_update_clip_rect(); } + return last_vp; } /* Set viewport to default settings */ diff --git a/apps/plugins/lib/osd.c b/apps/plugins/lib/osd.c index 97db09cc1e..7d6e10a410 100644 --- a/apps/plugins/lib/osd.c +++ b/apps/plugins/lib/osd.c @@ -52,6 +52,7 @@ struct osd OSD_ERASED, /* Erased in preparation for regular drawing */ } status; /* View status */ struct viewport vp; /* Clipping viewport */ + struct frame_buffer_t framebuf; /* Holds framebuffer reference */ int lcd_bitmap_stride; /* Stride of LCD bitmap */ void *lcd_bitmap_data; /* Backbuffer framebuffer data */ int back_bitmap_stride; /* Stride of backbuffer bitmap */ @@ -68,7 +69,7 @@ struct osd int height); void (*lcd_update)(void); void (*lcd_update_rect)(int x, int y, int width, int height); - void (*lcd_set_viewport)(struct viewport *vp); + struct viewport *(*lcd_set_viewport)(struct viewport *vp); void (*lcd_set_framebuffer)(void *buf); void (*lcd_framebuffer_set_pos)(int x, int y, int width, int height); void (*lcd_bitmap_part)(const void *src, int src_x, int src_y, @@ -227,7 +228,8 @@ static void * _osd_lcd_init_buffers(struct osd *osd, unsigned flags, osd->back_bitmap_stride = w; #endif /* end stride type selection */ - osd->lcd_bitmap_data = (void *)*rb->lcd_framebuffer; + /* vp is currently initialized to the default framebuffer */ + osd->lcd_bitmap_data = osd->vp.buffer->data; osd->back_bitmap_data = buf; osd->maxwidth = w; @@ -686,6 +688,25 @@ static void _osd_lcd_update_rect(struct osd *osd, osd->lcd_update_rect(x, y, width, height); } +static void _osd_lcd_viewport_set_buffer(void *buffer) +{ + if (buffer) + { + native_osd.framebuf.data = buffer; + native_osd.framebuf.elems = native_osd.maxheight * native_osd.maxwidth; + native_osd.framebuf.get_address_fn = NULL; /*Default iterator*/ + + if (buffer == native_osd.back_bitmap_data) + native_osd.framebuf.stride = (native_osd.back_bitmap_stride); + else + native_osd.framebuf.stride = (native_osd.lcd_bitmap_stride); + + rb->viewport_set_buffer(NULL, &native_osd.framebuf, SCREEN_MAIN); + } + else + rb->viewport_set_buffer(NULL, NULL, SCREEN_MAIN); +} + /* Native LCD, public */ bool osd_init(unsigned flags, void *backbuf, size_t backbuf_size, osd_draw_cb_fn_t draw_cb, int *width, int *height, @@ -696,7 +717,7 @@ bool osd_init(unsigned flags, void *backbuf, size_t backbuf_size, native_osd.lcd_update = rb->lcd_update; native_osd.lcd_update_rect = rb->lcd_update_rect; native_osd.lcd_set_viewport = rb->lcd_set_viewport; - native_osd.lcd_set_framebuffer = (void *)rb->lcd_set_framebuffer; + native_osd.lcd_set_framebuffer = (void *)_osd_lcd_viewport_set_buffer; #if LCD_DEPTH < 4 native_osd.lcd_framebuffer_set_pos = NULL; #endif /* LCD_DEPTH < 4 */ diff --git a/apps/plugins/lib/xlcd.h b/apps/plugins/lib/xlcd.h index 963c7c4831..069cc00508 100644 --- a/apps/plugins/lib/xlcd.h +++ b/apps/plugins/lib/xlcd.h @@ -34,6 +34,8 @@ void xlcd_fillcircle_screen(struct screen* display, int cx, int cy, int radius); void xlcd_drawcircle(int cx, int cy, int radius); void xlcd_drawcircle_screen(struct screen* display, int cx, int cy, int radius); +fb_data* get_framebuffer(struct viewport *vp, size_t *stride); /*CORE*/ + #if LCD_DEPTH >= 8 void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, int stride, int x, int y, int width, int height); diff --git a/apps/plugins/lib/xlcd_core.c b/apps/plugins/lib/xlcd_core.c index 47875a51a9..9a274cb48d 100644 --- a/apps/plugins/lib/xlcd_core.c +++ b/apps/plugins/lib/xlcd_core.c @@ -26,3 +26,12 @@ #include "xlcd.h" +fb_data* get_framebuffer(struct viewport *vp, size_t *stride) +{ + struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); + if (vp) + *vp = *vp_main; + if (stride) + *stride = vp_main->buffer->stride; + return vp_main->buffer->fb_ptr; +} diff --git a/apps/plugins/lib/xlcd_draw.c b/apps/plugins/lib/xlcd_draw.c index b6ed403353..0bd1c7a9e2 100644 --- a/apps/plugins/lib/xlcd_draw.c +++ b/apps/plugins/lib/xlcd_draw.c @@ -349,6 +349,9 @@ static const fb_data graylut[256] = { void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, int stride, int x, int y, int width, int height) { + size_t dst_stride; + fb_data *lcd_fb = get_framebuffer(NULL, &dst_stride); + const unsigned char *src_end; fb_data *dst; @@ -377,7 +380,7 @@ void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, src += stride * src_y + src_x; /* move starting point */ src_end = src + stride * height; - dst = *rb->lcd_framebuffer + LCD_WIDTH * y + x; + dst = lcd_fb + dst_stride * y + x; do { @@ -398,7 +401,7 @@ void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, #endif src += stride; - dst += LCD_WIDTH; + dst += dst_stride; } while (src < src_end); } @@ -416,6 +419,9 @@ void xlcd_gray_bitmap(const unsigned char *src, int x, int y, int width, void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y, int stride, int x, int y, int width, int height) { + size_t dst_stride; + fb_data *lcd_fb = get_framebuffer(NULL, &dst_stride); + const unsigned char *src_end; fb_data *dst; @@ -444,7 +450,7 @@ void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y, src += 3 * (stride * src_y + src_x); /* move starting point */ src_end = src + 3 * stride * height; - dst = *rb->lcd_framebuffer + LCD_WIDTH * y + x; + dst = lcd_fb + dst_stride * y + x; do { @@ -471,7 +477,7 @@ void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y, while (src_row < row_end); src += 3 * stride; - dst += LCD_WIDTH; + dst += dst_stride; } while (src < src_end); } diff --git a/apps/plugins/lib/xlcd_scroll.c b/apps/plugins/lib/xlcd_scroll.c index ab9ee1c4cb..89427b6118 100644 --- a/apps/plugins/lib/xlcd_scroll.c +++ b/apps/plugins/lib/xlcd_scroll.c @@ -33,6 +33,11 @@ static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000}; #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE void xlcd_scroll_left(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + + int length, oldmode; if ((unsigned)count >= LCD_WIDTH) @@ -43,8 +48,7 @@ void xlcd_scroll_left(int count) length = (LCD_WIDTH-count)*LCD_FBHEIGHT; - rb->memmove(*rb->lcd_framebuffer, *rb->lcd_framebuffer + LCD_HEIGHT*count, - length * sizeof(fb_data)); + rb->memmove(lcd_fb, lcd_fb + LCD_HEIGHT*count, length * sizeof(fb_data)); oldmode = rb->lcd_get_drawmode(); rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); @@ -55,6 +59,11 @@ void xlcd_scroll_left(int count) /* Scroll right */ void xlcd_scroll_right(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + + int length, oldmode; if ((unsigned)count >= LCD_WIDTH) @@ -65,8 +74,8 @@ void xlcd_scroll_right(int count) length = (LCD_WIDTH-count)*LCD_FBHEIGHT; - rb->memmove(*rb->lcd_framebuffer + LCD_HEIGHT*count, - *rb->lcd_framebuffer, length * sizeof(fb_data)); + rb->memmove(lcd_fb + LCD_HEIGHT*count, + lcd_fb, length * sizeof(fb_data)); oldmode = rb->lcd_get_drawmode(); rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); @@ -77,6 +86,11 @@ void xlcd_scroll_right(int count) /* Scroll up */ void xlcd_scroll_up(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + + int width, length, oldmode; fb_data *data; @@ -90,7 +104,7 @@ void xlcd_scroll_up(int count) length = LCD_HEIGHT - count; width = LCD_WIDTH-1; - data = *rb->lcd_framebuffer; + data = lcd_fb; do { rb->memmove(data,data + count,length * sizeof(fb_data)); @@ -106,6 +120,11 @@ void xlcd_scroll_up(int count) /* Scroll down */ void xlcd_scroll_down(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + + int width, length, oldmode; fb_data *data; @@ -119,7 +138,7 @@ void xlcd_scroll_down(int count) length = LCD_HEIGHT - count; width = LCD_WIDTH-1; - data = *rb->lcd_framebuffer; + data = lcd_fb; do { rb->memmove(data + count, data, length * sizeof(fb_data)); @@ -138,6 +157,11 @@ void xlcd_scroll_down(int count) /* Scroll left */ void xlcd_scroll_left(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + + int bitcount=0, oldmode; int blockcount=0, blocklen; @@ -155,7 +179,7 @@ void xlcd_scroll_left(int count) if (blockcount) { - unsigned char *data = *rb->lcd_framebuffer; + unsigned char *data = lcd_fb; unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT; do @@ -168,7 +192,7 @@ void xlcd_scroll_left(int count) if (bitcount) { int bx, y; - unsigned char *addr = *rb->lcd_framebuffer + blocklen; + unsigned char *addr = lcd_fb + blocklen; #if LCD_DEPTH == 2 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount; #endif @@ -196,6 +220,11 @@ void xlcd_scroll_left(int count) /* Scroll right */ void xlcd_scroll_right(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + + int bitcount=0, oldmode; int blockcount=0, blocklen; @@ -213,7 +242,7 @@ void xlcd_scroll_right(int count) if (blockcount) { - unsigned char *data = *rb->lcd_framebuffer; + unsigned char *data = lcd_fb; unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT; do @@ -226,7 +255,7 @@ void xlcd_scroll_right(int count) if (bitcount) { int bx, y; - unsigned char *addr = *rb->lcd_framebuffer + blockcount; + unsigned char *addr = lcd_fb + blockcount; #if LCD_DEPTH == 2 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3); #endif @@ -256,6 +285,11 @@ void xlcd_scroll_right(int count) /* Scroll left */ void xlcd_scroll_left(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + + fb_data *data, *data_end; int length, oldmode; @@ -265,7 +299,7 @@ void xlcd_scroll_left(int count) return; } - data = *rb->lcd_framebuffer; + data = lcd_fb; data_end = data + LCD_WIDTH*LCD_FBHEIGHT; length = LCD_WIDTH - count; @@ -285,6 +319,11 @@ void xlcd_scroll_left(int count) /* Scroll right */ void xlcd_scroll_right(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + + fb_data *data, *data_end; int length, oldmode; @@ -294,7 +333,7 @@ void xlcd_scroll_right(int count) return; } - data = *rb->lcd_framebuffer; + data = lcd_fb; data_end = data + LCD_WIDTH*LCD_FBHEIGHT; length = LCD_WIDTH - count; @@ -318,6 +357,10 @@ void xlcd_scroll_right(int count) /* Scroll up */ void xlcd_scroll_up(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + int length, oldmode; if ((unsigned)count >= LCD_HEIGHT) @@ -328,8 +371,8 @@ void xlcd_scroll_up(int count) length = LCD_HEIGHT - count; - rb->memmove(*rb->lcd_framebuffer, - *rb->lcd_framebuffer + count * LCD_FBWIDTH, + rb->memmove(lcd_fb, + lcd_fb + count * LCD_FBWIDTH, length * LCD_FBWIDTH * sizeof(fb_data)); oldmode = rb->lcd_get_drawmode(); @@ -341,6 +384,10 @@ void xlcd_scroll_up(int count) /* Scroll down */ void xlcd_scroll_down(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + int length, oldmode; if ((unsigned)count >= LCD_HEIGHT) @@ -351,8 +398,8 @@ void xlcd_scroll_down(int count) length = LCD_HEIGHT - count; - rb->memmove(*rb->lcd_framebuffer + count * LCD_FBWIDTH, - *rb->lcd_framebuffer, + rb->memmove(lcd_fb + count * LCD_FBWIDTH, + lcd_fb, length * LCD_FBWIDTH * sizeof(fb_data)); oldmode = rb->lcd_get_drawmode(); @@ -367,6 +414,10 @@ void xlcd_scroll_down(int count) /* Scroll up */ void xlcd_scroll_up(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + int bitcount=0, oldmode; int blockcount=0, blocklen; @@ -388,8 +439,8 @@ void xlcd_scroll_up(int count) if (blockcount) { - rb->memmove(*rb->lcd_framebuffer, - *rb->lcd_framebuffer + blockcount * LCD_FBWIDTH, + rb->memmove(lcd_fb, + lcd_fb + blockcount * LCD_FBWIDTH, blocklen * LCD_FBWIDTH * sizeof(fb_data)); } if (bitcount) @@ -424,7 +475,7 @@ void xlcd_scroll_up(int count) : /* inputs */ [wide]"r"(LCD_FBWIDTH), [rows]"r"(blocklen), - [addr]"a"(*rb->lcd_framebuffer + blocklen * LCD_FBWIDTH), + [addr]"a"(lcd_fb + blocklen * LCD_FBWIDTH), [cnt] "d"(bitcount), [bkg] "d"(0x55 * (~rb->lcd_get_background() & 3)) : /* clobbers */ @@ -432,7 +483,7 @@ void xlcd_scroll_up(int count) ); #else /* C version */ int x, by; - unsigned char *addr = *rb->lcd_framebuffer + blocklen * LCD_FBWIDTH; + unsigned char *addr = lcd_fb + blocklen * LCD_FBWIDTH; #if LCD_DEPTH == 2 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3); #else @@ -457,7 +508,7 @@ void xlcd_scroll_up(int count) #if LCD_DEPTH == 2 int x, by; - fb_data *addr = *rb->lcd_framebuffer + blocklen * LCD_FBWIDTH; + fb_data *addr = lcd_fb + blocklen * LCD_FBWIDTH; unsigned fill, mask; fill = patterns[rb->lcd_get_background() & 3] << 8; @@ -491,6 +542,10 @@ void xlcd_scroll_up(int count) /* Scroll up */ void xlcd_scroll_down(int count) { + /*size_t dst_stride;*/ + /*struct viewport *vp_main = NULL;*/ + fb_data *lcd_fb = get_framebuffer(NULL, NULL); + int bitcount=0, oldmode; int blockcount=0, blocklen; @@ -512,8 +567,8 @@ void xlcd_scroll_down(int count) if (blockcount) { - rb->memmove(*rb->lcd_framebuffer + blockcount * LCD_FBWIDTH, - *rb->lcd_framebuffer, + rb->memmove(lcd_fb + blockcount * LCD_FBWIDTH, + lcd_fb, blocklen * LCD_FBWIDTH * sizeof(fb_data)); } if (bitcount) @@ -548,7 +603,7 @@ void xlcd_scroll_down(int count) : /* inputs */ [wide]"r"(LCD_WIDTH), [rows]"r"(blocklen), - [addr]"a"(*rb->lcd_framebuffer + blockcount * LCD_FBWIDTH), + [addr]"a"(lcd_fb + blockcount * LCD_FBWIDTH), [cnt] "d"(bitcount), [bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount) : /* clobbers */ @@ -556,7 +611,7 @@ void xlcd_scroll_down(int count) ); #else /* C version */ int x, by; - unsigned char *addr = *rb->lcd_framebuffer + blockcount * LCD_FBWIDTH; + unsigned char *addr = lcd_fb + blockcount * LCD_FBWIDTH; #if LCD_DEPTH == 2 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount; #else @@ -581,7 +636,7 @@ void xlcd_scroll_down(int count) #if LCD_DEPTH == 2 int x, by; - fb_data *addr = *rb->lcd_framebuffer + blockcount * LCD_FBWIDTH; + fb_data *addr = lcd_fb + blockcount * LCD_FBWIDTH; unsigned fill, mask; fill = patterns[rb->lcd_get_background() & 3] >> (8 - bitcount); diff --git a/apps/plugins/lua/rocklib_img.c b/apps/plugins/lua/rocklib_img.c index da3ef4b52c..887ef984d0 100644 --- a/apps/plugins/lua/rocklib_img.c +++ b/apps/plugins/lua/rocklib_img.c @@ -1242,6 +1242,7 @@ static int get_screen(lua_State *L, int narg) return screen; } #else /* only SCREEN_MAIN exists */ +#define get_screen(a,b) (SCREEN_MAIN) #define RB_SCREEN_STRUCT(luastate, narg) \ rb->screens[SCREEN_MAIN] #define RB_SCREENS(luastate, narg, func, ...) \ @@ -1379,7 +1380,12 @@ RB_WRAP(font_getstringsize) RB_WRAP(lcd_framebuffer) { - rli_wrap(L, *rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT); + int screen = get_screen(L, 1); + static struct viewport vp; + rb->viewport_set_fullscreen(&vp, screen); + rli_wrap(L, vp.buffer->data, + RB_SCREEN_STRUCT(L, 1)->lcdwidth, + RB_SCREEN_STRUCT(L, 1)->lcdheight); return 1; } diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index e72d2828e3..619be8f1ef 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -620,6 +620,14 @@ struct fps static struct osd osd; static struct fps fps NOCACHEBSS_ATTR; /* Accessed on other processor */ +#ifdef LCD_PORTRAIT +static fb_data* get_framebuffer(void) +{ + struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); + return vp_main->buffer->fb_ptr; +} +#endif + static void osd_show(unsigned show); #ifdef LCD_LANDSCAPE @@ -821,7 +829,7 @@ static void draw_oriented_mono_bitmap_part(const unsigned char *src, src_y &= 7; src_end = src + width; - dst = *rb->lcd_framebuffer + (LCD_WIDTH - y) + x*LCD_WIDTH; + dst = get_framebuffer() + (LCD_WIDTH - y) + x*LCD_WIDTH; do { const unsigned char *src_col = src++; @@ -953,7 +961,7 @@ static void draw_oriented_alpha_bitmap_part(const unsigned char *src, fg_pattern = rb->lcd_get_foreground(); /*bg_pattern=*/ rb->lcd_get_background(); - dst_start = *rb->lcd_framebuffer + (LCD_WIDTH - y - 1) + x*LCD_WIDTH; + dst_start = get_framebuffer() + (LCD_WIDTH - y - 1) + x*LCD_WIDTH; int col, row = height; unsigned data, pixels; unsigned skip_end = (stride - width); diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c index d8bef0ae7f..62c11b91c9 100644 --- a/apps/plugins/oscilloscope.c +++ b/apps/plugins/oscilloscope.c @@ -838,10 +838,10 @@ static void osc_osd_show_message(int id, int val) int width, height; int maxwidth, maxheight; - rb->lcd_set_viewport(osd_get_viewport()); + struct viewport *last_vp = rb->lcd_set_viewport(osd_get_viewport()); osd_get_max_dims(&maxwidth, &maxheight); rb->lcd_getstringsize(osc_osd_message, &width, &height); - rb->lcd_set_viewport(NULL); /* to regular viewport */ + rb->lcd_set_viewport(last_vp); /* to regular viewport */ width += 2 + 2*OSC_OSD_MARGIN_SIZE; if (width > maxwidth) diff --git a/apps/plugins/pacbox/pacbox.c b/apps/plugins/pacbox/pacbox.c index 262ab3e836..71c9751cad 100755 --- a/apps/plugins/pacbox/pacbox.c +++ b/apps/plugins/pacbox/pacbox.c @@ -35,6 +35,7 @@ #include "lib/configfile.h" #include "lib/playback_control.h" #include "lib/helper.h" +static fb_data *lcd_fb; /*Allows split screen jump and makes pacman invincible if you start at 18 credits (for testing purposes)*/ //#define CHEATS 1 @@ -704,7 +705,7 @@ static int gameProc( void ) rb->lcd_blit_pal256( video_buffer, 0, 0, XOFS, YOFS, ScreenWidth, ScreenHeight); #else - blit_display(*rb->lcd_framebuffer,video_buffer); + blit_display(lcd_fb ,video_buffer); #endif if (settings.showfps) { @@ -743,6 +744,9 @@ enum plugin_status plugin_start(const void* parameter) rb->lcd_clear_display(); rb->lcd_update(); + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; + /* Set the default settings */ settings.difficulty = 0; /* Normal */ settings.numlives = 2; /* 3 lives */ diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c index eadf9c3d0a..5f700aac83 100644 --- a/apps/plugins/pictureflow/pictureflow.c +++ b/apps/plugins/pictureflow/pictureflow.c @@ -35,6 +35,7 @@ #include "lib/feature_wrappers.h" /******************************* Globals ***********************************/ +static fb_data *lcd_fb; /* * Targets which use plugin_get_audio_buffer() can't have playback from @@ -190,7 +191,7 @@ GREY_INFO_STRUCT #define BUFFER_HEIGHT _grey_info.height typedef unsigned char pix_t; #else /* LCD_DEPTH >= 8 */ -#define LCD_BUF *rb->lcd_framebuffer +#define LCD_BUF lcd_fb #define G_PIX LCD_RGBPACK #define N_PIX LCD_RGBPACK #define G_BRIGHT(y) LCD_RGBPACK(y,y,y) @@ -3847,6 +3848,9 @@ static int pictureflow_main(void) enum plugin_status plugin_start(const void *parameter) { + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; + int ret; (void) parameter; diff --git a/apps/plugins/plasma.c b/apps/plugins/plasma.c index 9e2e3832a3..f944d3d775 100644 --- a/apps/plugins/plasma.c +++ b/apps/plugins/plasma.c @@ -36,6 +36,8 @@ /******************************* Globals ***********************************/ +static fb_data *lcd_fb; + static unsigned char wave_array[256]; /* Pre calculated wave array */ #ifdef HAVE_LCD_COLOR @@ -201,9 +203,9 @@ int main(void) #ifdef HAVE_LCD_COLOR shades_generate(time++); /* dynamically */ #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) - ptr = (unsigned char*)*rb->lcd_framebuffer; + ptr = (unsigned char*)lcd_fb; #else - ptr = *rb->lcd_framebuffer; + ptr = lcd_fb; #endif #else @@ -237,7 +239,7 @@ int main(void) p4-=sp4; #ifdef HAVE_LCD_COLOR #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) - rb->lcd_blit_pal256( (unsigned char*)*rb->lcd_framebuffer, + rb->lcd_blit_pal256( (unsigned char*)lcd_fb, 0,0,0,0,LCD_WIDTH,LCD_HEIGHT); #else rb->lcd_update(); @@ -326,5 +328,8 @@ enum plugin_status plugin_start(const void* parameter) #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) rb->lcd_set_mode(LCD_MODE_PAL256); #endif + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; + return main(); } diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c index ed58bd900a..08581db1c6 100644 --- a/apps/plugins/puzzles/rockbox.c +++ b/apps/plugins/puzzles/rockbox.c @@ -310,6 +310,7 @@ static int help_times = 0; #endif /* clipping stuff */ +static fb_data *lcd_fb; static struct viewport clip_rect; static bool clipped = false, zoom_enabled = false, view_mode = true, mouse_mode = false; @@ -1016,7 +1017,7 @@ static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2, } else #endif - draw_antialiased_line(*rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); + draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); } else { @@ -1294,7 +1295,7 @@ static void rb_draw_poly(void *handle, int *coords, int npoints, x2, y2); } else - draw_antialiased_line(*rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); + draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); #ifdef DEBUG_MENU if(debug_settings.polyanim) @@ -1319,7 +1320,7 @@ static void rb_draw_poly(void *handle, int *coords, int npoints, x2, y2); } else - draw_antialiased_line(*rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); + draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); } else { @@ -1474,7 +1475,7 @@ static void rb_blitter_save(void *handle, blitter *bl, int x, int y) trim_rect(&x, &y, &w, &h); - fb_data *fb = zoom_enabled ? zoom_fb : *rb->lcd_framebuffer; + fb_data *fb = zoom_enabled ? zoom_fb : lcd_fb; LOGF("rb_blitter_save(%d, %d, %d, %d)", x, y, w, h); for(int i = 0; i < h; ++i) { @@ -1778,9 +1779,9 @@ static void timer_cb(void) static bool what = false; what = !what; if(what) - *rb->lcd_framebuffer[0] = LCD_BLACK; + lcd_fb[0] = LCD_BLACK; else - *rb->lcd_framebuffer[0] = LCD_WHITE; + lcd_fb[0] = LCD_WHITE; rb->lcd_update(); } #endif @@ -2909,7 +2910,7 @@ static void bench_aa(void) int i = 0; while(*rb->current_tick < next) { - draw_antialiased_line(*rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, 0, 0, 20, 31); + draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, 0, 0, 20, 31); ++i; } rb->splashf(HZ, "%d AA lines/sec", i); @@ -3843,6 +3844,8 @@ enum plugin_status plugin_start(const void *param) giant_buffer = rb->plugin_get_buffer(&giant_buffer_len); init_tlsf(); + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; if(!strcmp(thegame.name, "Solo")) { diff --git a/apps/plugins/rockboy/lcd.c b/apps/plugins/rockboy/lcd.c index 387a88c3df..92db851ee8 100644 --- a/apps/plugins/rockboy/lcd.c +++ b/apps/plugins/rockboy/lcd.c @@ -64,6 +64,12 @@ unsigned char *vdest; fb_data *vdest; #endif +static fb_data* get_framebuffer(void) +{ + struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); + return vp_main->buffer->fb_ptr; +} + #ifndef ASM_UPDATEPATPIX static void updatepatpix(void) ICODE_ATTR; static void updatepatpix(void) @@ -741,10 +747,11 @@ static void spr_scan(void) void lcd_begin(void) { + fb_data *lcd_fb = get_framebuffer(); #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) - vdest=(unsigned char*)*rb->lcd_framebuffer; + vdest=(unsigned char*)lcd_fb; #else - vdest=*rb->lcd_framebuffer; + vdest=lcd_fb; #endif #ifdef HAVE_LCD_COLOR @@ -975,9 +982,9 @@ void lcd_refreshline(void) #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) if(options.scaling==3) { - rb->lcd_blit_pal256((unsigned char*)*rb->lcd_framebuffer,(LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, (LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, 160, 144); + rb->lcd_blit_pal256((unsigned char*)lcd_fb,(LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, (LCD_WIDTH-160)/2, (LCD_HEIGHT-144)/2, 160, 144); } else { - rb->lcd_blit_pal256((unsigned char*)*rb->lcd_framebuffer,0,0,0,0,LCD_WIDTH,LCD_HEIGHT); + rb->lcd_blit_pal256((unsigned char*)lcd_fb,0,0,0,0,LCD_WIDTH,LCD_HEIGHT); } #else if(options.scaling==3) { diff --git a/apps/plugins/rockboy/sys_rockbox.c b/apps/plugins/rockboy/sys_rockbox.c index 364176ce2d..64acd37563 100644 --- a/apps/plugins/rockboy/sys_rockbox.c +++ b/apps/plugins/rockboy/sys_rockbox.c @@ -282,6 +282,12 @@ fb_data *frameb; void vid_update(int scanline) { register int cnt=0; + static fb_data *lcd_fb = NULL; + if (!lcd_fb) + { + struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); + lcd_fb = vp_main->buffer->fb_ptr; + } int scanline_remapped; #if (LCD_HEIGHT == 64) && (LCD_DEPTH == 1) /* Archos, Clip, m200v4 */ int balance = 0; @@ -290,7 +296,7 @@ void vid_update(int scanline) else if (fb.mode==2) scanline-=8; scanline_remapped = scanline / 16; - frameb = *rb->lcd_framebuffer + scanline_remapped * LCD_WIDTH; + frameb = lcd_fb + scanline_remapped * LCD_WIDTH; while (cnt < 160) { balance += LCD_WIDTH; if (balance > 0) @@ -316,7 +322,7 @@ void vid_update(int scanline) else if (fb.mode==2) scanline-=8; scanline_remapped = scanline / 4; - frameb = *rb->lcd_framebuffer + scanline_remapped * LCD_WIDTH; + frameb = lcd_fb + scanline_remapped * LCD_WIDTH; while (cnt < 160) { *(frameb++) = (scan.buf[0][cnt]&0x3) | ((scan.buf[1][cnt]&0x3)<<2) | diff --git a/apps/plugins/sdl/src/video/rockbox/SDL_rockboxvideo.c b/apps/plugins/sdl/src/video/rockbox/SDL_rockboxvideo.c index 5e0ccfb167..85c245ed9c 100644 --- a/apps/plugins/sdl/src/video/rockbox/SDL_rockboxvideo.c +++ b/apps/plugins/sdl/src/video/rockbox/SDL_rockboxvideo.c @@ -67,6 +67,7 @@ #define RBSDL_EXTRA0 SDLK_0 /* Initialization/Query functions */ +static fb_data *lcd_fb; static int ROCKBOX_VideoInit(_THIS, SDL_PixelFormat *vformat); static SDL_Rect **ROCKBOX_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); static SDL_Surface *ROCKBOX_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); @@ -447,6 +448,8 @@ static void rb_pixelformat(SDL_PixelFormat *vformat) int ROCKBOX_VideoInit(_THIS, SDL_PixelFormat *vformat) { + struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport); + lcd_fb = vp_main->buffer->fb_ptr; /* we change this during the SDL_SetVideoMode implementation... */ rb_pixelformat(vformat); @@ -639,7 +642,7 @@ SDL_Surface *ROCKBOX_SetVideoMode(_THIS, SDL_Surface *current, this->hidden->w = current->w = width; this->hidden->h = current->h = height; current->pitch = current->w * (bpp / 8); - current->pixels = this->hidden->direct ? *rb->lcd_framebuffer : this->hidden->buffer; + current->pixels = this->hidden->direct ? lcd_fb : this->hidden->buffer; /* We're done */ return(current); @@ -674,7 +677,7 @@ static void flip_pixels(int x, int y, int w, int h) for(int x_0 = x; x_0 < x + w; ++x_0) { /* swap pixels directly in the framebuffer */ - *rb->lcd_framebuffer[y_0 * LCD_WIDTH + x_0] = swap16(*rb->lcd_framebuffer[y_0 * LCD_WIDTH + x_0]); + lcd_fb[y_0 * LCD_WIDTH + x_0] = swap16(lcd_fb[y_0 * LCD_WIDTH + x_0]); } } } @@ -684,7 +687,7 @@ static void blit_rotated(fb_data *src, int x, int y, int w, int h) { for(int y_0 = y; y_0 < y + h; ++y_0) for(int x_0 = x; x_0 < x + w; ++x_0) - *rb->lcd_framebuffer[x_0 * LCD_WIDTH + y_0] = src[(LCD_WIDTH - y_0) * LCD_HEIGHT + x_0]; + lcd_fb[x_0 * LCD_WIDTH + y_0] = src[(LCD_WIDTH - y_0) * LCD_HEIGHT + x_0]; } static void ROCKBOX_UpdateRects(_THIS, int numrects, SDL_Rect *rects) @@ -720,7 +723,7 @@ static void ROCKBOX_UpdateRects(_THIS, int numrects, SDL_Rect *rects) out_bmp.width = LCD_WIDTH; out_bmp.height = LCD_HEIGHT; - out_bmp.data = (char*)*rb->lcd_framebuffer; + out_bmp.data = (char*)lcd_fb; simple_resize_bitmap(&in_bmp, &out_bmp); } else diff --git a/apps/plugins/test_resize.c b/apps/plugins/test_resize.c index 3e50bdc8cc..443067c7e1 100644 --- a/apps/plugins/test_resize.c +++ b/apps/plugins/test_resize.c @@ -64,8 +64,8 @@ static fb_data output_bmp_data[MAX_OUTPUT_WIDTH*MAX_OUTPUT_HEIGHT]; enum plugin_status plugin_start(const void* parameter) { (void)parameter; - - b = *rb->lcd_framebuffer; + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + b = vp_main->buffer->fb_ptr; rb->lcd_set_background(LCD_RGBPACK(0,0,0)); rb->lcd_clear_display(); // TODO: Optimizes this by e.g. invalidating rects diff --git a/apps/plugins/test_viewports.c b/apps/plugins/test_viewports.c index 465a832399..60c6672456 100644 --- a/apps/plugins/test_viewports.c +++ b/apps/plugins/test_viewports.c @@ -35,7 +35,7 @@ static struct viewport vp0 = { .x = 0, .y = 0, - .width = LCD_WIDTH, + .width = LCD_WIDTH/ 2 + LCD_WIDTH / 3, .height = 20, .font = FONT_UI, .drawmode = DRMODE_SOLID, @@ -120,15 +120,37 @@ static struct viewport rvp1 = #endif +static void *test_address_fn(int x, int y) +{ + struct frame_buffer_t *fb = vp0.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 % fb->elems); +} enum plugin_status plugin_start(const void* parameter) { (void)parameter; char buf[80]; int i,y; + fb_data vp_buffer[LCD_NBELEMS(vp0.width, vp0.height)]; + struct frame_buffer_t fb; + + fb.stride = STRIDE_MAIN(vp0.width, vp0.height); + + fb.fb_ptr = vp_buffer; + fb.elems = LCD_NBELEMS(vp0.width, vp0.height); + fb.get_address_fn = &test_address_fn; + + rb->viewport_set_buffer(&vp0, &fb, SCREEN_MAIN); rb->screens[SCREEN_MAIN]->set_viewport(&vp0); rb->screens[SCREEN_MAIN]->clear_viewport(); + rb->screens[SCREEN_MAIN]->puts_scroll(0,0,"Viewport testing plugin - this is a scrolling title"); rb->screens[SCREEN_MAIN]->set_viewport(&vp1); @@ -192,6 +214,9 @@ enum plugin_status plugin_start(const void* parameter) rb->screens[SCREEN_REMOTE]->update(); #endif + rb->button_clear_queue(); + while(rb->button_get(true) <= BUTTON_NONE) + ;; rb->button_get(true); diff --git a/apps/plugins/xworld/sys.c b/apps/plugins/xworld/sys.c index 0bd1e0dc08..c57da9456b 100644 --- a/apps/plugins/xworld/sys.c +++ b/apps/plugins/xworld/sys.c @@ -40,6 +40,7 @@ #include "engine.h" static struct System* save_sys; +static fb_data *lcd_fb = NULL; static bool sys_save_settings(struct System* sys) { @@ -438,6 +439,8 @@ void sys_init(struct System* sys, const char* title) { sys_reset_settings(sys); } + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; } void sys_destroy(struct System* sys) @@ -584,7 +587,7 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16 struct bitmap out_bmp; out_bmp.width = LCD_WIDTH; out_bmp.height = LCD_HEIGHT; - out_bmp.data = (unsigned char*) *rb->lcd_framebuffer; + out_bmp.data = (unsigned char*) lcd_fb; #ifdef HAVE_LCD_COLOR if(sys->settings.scaling_quality == 1) @@ -631,25 +634,25 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16 { #ifdef HAVE_LCD_COLOR int r, g, b; - fb_data pix = *rb->lcd_framebuffer[y * LCD_WIDTH + x]; + fb_data pix = lcd_fb[y * LCD_WIDTH + x]; #if (LCD_DEPTH > 24) r = 0xff - pix.r; g = 0xff - pix.g; b = 0xff - pix.b; - *rb->lcd_framebuffer[y * LCD_WIDTH + x] = (fb_data) { b, g, r, 255 }; + lcd_fb[y * LCD_WIDTH + x] = (fb_data) { b, g, r, 255 }; #elif (LCD_DEPTH == 24) r = 0xff - pix.r; g = 0xff - pix.g; b = 0xff - pix.b; - *rb->lcd_framebuffer[y * LCD_WIDTH + x] = (fb_data) { b, g, r }; + lcd_fb[y * LCD_WIDTH + x] = (fb_data) { b, g, r }; #else r = RGB_UNPACK_RED (pix); g = RGB_UNPACK_GREEN(pix); b = RGB_UNPACK_BLUE (pix); - *rb->lcd_framebuffer[y * LCD_WIDTH + x] = LCD_RGBPACK(0xff - r, 0xff - g, 0xff - b); + lcd_fb[y * LCD_WIDTH + x] = LCD_RGBPACK(0xff - r, 0xff - g, 0xff - b); #endif #else - *rb->lcd_framebuffer[y * LCD_WIDTH + x] = LCD_BRIGHTNESS(0xff - *rb->lcd_framebuffer[y * LCD_WIDTH + x]); + lcd_fb[y * LCD_WIDTH + x] = LCD_BRIGHTNESS(0xff - lcd_fb[y * LCD_WIDTH + x]); #endif } } @@ -671,14 +674,14 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16 if(prev_frames && orig_fb) { - rb->memcpy(orig_fb, *rb->lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT); + rb->memcpy(orig_fb, lcd_fb, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT); /* fancy useless slow motion blur */ for(int y = 0; y < LCD_HEIGHT; ++y) { for(int x = 0; x < LCD_WIDTH; ++x) { int r, g, b; - fb_data pix = *rb->lcd_framebuffer[y * LCD_WIDTH + x]; + fb_data pix = lcd_fb[y * LCD_WIDTH + x]; r = RGB_UNPACK_RED (pix); g = RGB_UNPACK_GREEN(pix); b = RGB_UNPACK_BLUE (pix); @@ -695,7 +698,7 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16 r /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1); g /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1); b /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1); - *rb->lcd_framebuffer[y * LCD_WIDTH + x] = LCD_RGBPACK(r, g, b); + lcd_fb[y * LCD_WIDTH + x] = LCD_RGBPACK(r, g, b); } } prev_baseidx -= LCD_WIDTH * LCD_HEIGHT; diff --git a/apps/plugins/zxbox/zxvid_16bpp.c b/apps/plugins/zxbox/zxvid_16bpp.c index f8482e3147..f0e2cee5ac 100644 --- a/apps/plugins/zxbox/zxvid_16bpp.c +++ b/apps/plugins/zxbox/zxvid_16bpp.c @@ -33,6 +33,8 @@ static const unsigned _16bpp_colors[32] = { LCD_RGBPACK(IB1, IB1, IB0), LCD_RGBPACK(IB1, IB1, IB1), }; +static fb_data *lcd_fb = NULL; + void init_spect_scr(void) { int i; @@ -49,6 +51,11 @@ void init_spect_scr(void) void update_screen(void) { + if (!lcd_fb) + { + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; + } fb_data *frameb; int y=0; @@ -58,7 +65,7 @@ void update_screen(void) byte *scrptr; scrptr = (byte *) SPNM(image); */ - frameb = *rb->lcd_framebuffer; + frameb = lcd_fb; for ( y = 0 ; y < HEIGHT*WIDTH; y++ ){ frameb[y] = FB_SCALARPACK(_16bpp_colors[(unsigned)sp_image[y]]); } @@ -68,7 +75,7 @@ void update_screen(void) int srcx, srcy=0; /* x / y coordinates in source image */ unsigned char* image; image = sp_image + ( (Y_OFF)*(WIDTH) ) + X_OFF; - frameb = *rb->lcd_framebuffer; + frameb = lcd_fb; for(y = 0; y < LCD_HEIGHT; y++) { srcx = 0; /* reset our x counter before each row... */ diff --git a/apps/plugins/zxbox/zxvid_2bpp.c b/apps/plugins/zxbox/zxvid_2bpp.c index 9772625387..97e6a5de76 100644 --- a/apps/plugins/zxbox/zxvid_2bpp.c +++ b/apps/plugins/zxbox/zxvid_2bpp.c @@ -26,6 +26,8 @@ static const unsigned char graylevels[16] = { 0, 1, 1, 1, 2, 2, 3, 3 }; +static fb_data *lcd_fb = NULL; + void init_spect_scr(void) { int i; @@ -41,6 +43,11 @@ void init_spect_scr(void) } void update_screen(void) { + if (!lcd_fb) + { + struct viewport *vp_main = rb->lcd_set_viewport(NULL); + lcd_fb = vp_main->buffer->fb_ptr; + } fb_data *frameb; int y=0; int x=0; @@ -51,7 +58,7 @@ void update_screen(void) #if LCD_PIXELFORMAT == HORIZONTAL_PACKING for(y = 0; y < LCD_HEIGHT; y++) { - frameb = *rb->lcd_framebuffer + (y) * FB_WIDTH; + frameb = lcd_fb + (y) * FB_WIDTH; srcx = 0; /* reset our x counter before each row... */ for(x = 0; x < LCD_WIDTH; x++) { @@ -67,7 +74,7 @@ void update_screen(void) int shift; for(y = 0; y < LCD_HEIGHT; y++) { - frameb = *rb->lcd_framebuffer + (y/4) * LCD_WIDTH; + frameb = lcd_fb + (y/4) * LCD_WIDTH; srcx = 0; /* reset our x counter before each row... */ shift = ((y & 3 ) * 2 ); mask = ~pixmask[y & 3]; @@ -84,7 +91,7 @@ void update_screen(void) int shift; for(y = 0; y < LCD_HEIGHT; y++) { - frameb = *rb->lcd_framebuffer + (y/8) * LCD_WIDTH; + frameb = lcd_fb + (y/8) * LCD_WIDTH; srcx = 0; /* reset our x counter before each row... */ shift = (y & 7); mask = ~pixmask[y & 7]; diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c index f735afe84d..b211fad331 100644 --- a/apps/recorder/keyboard.c +++ b/apps/recorder/keyboard.c @@ -1009,7 +1009,7 @@ static void kbd_draw_buttons(struct keyboard_parameters *pm, struct screen *sc) int sc_w = sc->getwidth(), sc_h = sc->getheight(); viewport_set_defaults(&vp, sc->screen_type); vp.flags |= VP_FLAG_ALIGN_CENTER; - sc->set_viewport(&vp); + struct viewport *last_vp = sc->set_viewport(&vp); text_h = sc->getcharheight(); button_h = GRID_SIZE(sc->screen_type, text_h); text_y = (button_h - text_h) / 2 + 1; @@ -1039,7 +1039,7 @@ static void kbd_draw_buttons(struct keyboard_parameters *pm, struct screen *sc) vp.x += vp.width; sc->vline(0, 0, button_h); sc->putsxy(0, text_y, str(LANG_KBD_CANCEL)); - sc->set_viewport(NULL); + sc->set_viewport(last_vp); } static int keyboard_touchscreen(struct keyboard_parameters *pm, diff --git a/apps/screen_access.c b/apps/screen_access.c index 44e90742b0..390fb2ad4e 100644 --- a/apps/screen_access.c +++ b/apps/screen_access.c @@ -35,6 +35,7 @@ #include "backlight.h" #include "screen_access.h" #include "backdrop.h" +#include "viewport.h" /* some helper functions to calculate metrics on the fly */ static int screen_helper_getcharwidth(void) @@ -87,7 +88,17 @@ static void screen_helper_put_line(int x, int y, struct line_desc *line, va_end(ap); } +void screen_helper_lcd_viewport_set_buffer(struct viewport *vp, struct frame_buffer_t *buffer) +{ + viewport_set_buffer(vp, buffer, SCREEN_MAIN); +} + #if NB_SCREENS == 2 +void screen_helper_lcd_remote_viewport_set_buffer(struct viewport *vp, struct frame_buffer_t *buffer) +{ + viewport_set_buffer(vp, buffer, SCREEN_REMOTE); +} + static int screen_helper_remote_getcharwidth(void) { return font_get(lcd_remote_getfont())->maxwidth; @@ -156,7 +167,11 @@ struct screen screens[NB_SCREENS] = .has_disk_led=true, #endif .set_drawmode=&screen_helper_set_drawmode, + .init_viewport=&lcd_init_viewport, .set_viewport=&lcd_set_viewport, + .set_viewport_ex=&lcd_set_viewport_ex, + .viewport_set_buffer = &screen_helper_lcd_viewport_set_buffer, + .current_viewport = &lcd_current_viewport, .getwidth=&lcd_getwidth, .getheight=&lcd_getheight, .getstringsize=&lcd_getstringsize, @@ -221,7 +236,6 @@ struct screen screens[NB_SCREENS] = .backdrop_load=&backdrop_load, .backdrop_show=&backdrop_show, #endif - .set_framebuffer = (void*)lcd_set_framebuffer, #if defined(HAVE_LCD_COLOR) .gradient_fillrect = lcd_gradient_fillrect, .gradient_fillrect_part = lcd_gradient_fillrect_part, @@ -241,7 +255,11 @@ struct screen screens[NB_SCREENS] = .getcharheight=screen_helper_remote_getcharheight, .has_disk_led=false, .set_drawmode=&lcd_remote_set_drawmode, + .init_viewport=&lcd_remote_init_viewport, .set_viewport=&lcd_remote_set_viewport, + .set_viewport_ex=&lcd_remote_set_viewport_ex, + .viewport_set_buffer = &screen_helper_lcd_remote_viewport_set_buffer, + .current_viewport = &lcd_remote_current_viewport, .getwidth=&lcd_remote_getwidth, .getheight=&lcd_remote_getheight, .getstringsize=&lcd_remote_getstringsize, @@ -307,7 +325,6 @@ struct screen screens[NB_SCREENS] = .backdrop_load=&remote_backdrop_load, .backdrop_show=&remote_backdrop_show, #endif - .set_framebuffer = (void*)lcd_remote_set_framebuffer, .put_line = screen_helper_remote_put_line, } #endif /* NB_SCREENS == 2 */ diff --git a/apps/screen_access.h b/apps/screen_access.h index 79ad79c153..81c7cb2a85 100644 --- a/apps/screen_access.h +++ b/apps/screen_access.h @@ -58,7 +58,11 @@ struct screen bool has_disk_led; #endif void (*set_drawmode)(int mode); - void (*set_viewport)(struct viewport* vp); + struct viewport* (*init_viewport)(struct viewport* vp); + struct viewport* (*set_viewport)(struct viewport* vp); + struct viewport* (*set_viewport_ex)(struct viewport* vp, int flags); + void (*viewport_set_buffer)(struct viewport *vp, struct frame_buffer_t *buffer); + struct viewport** current_viewport; int (*getwidth)(void); int (*getheight)(void); int (*getstringsize)(const unsigned char *str, int *w, int *h); @@ -126,7 +130,6 @@ struct screen bool (*backdrop_load)(const char *filename, char* backdrop_buffer); void (*backdrop_show)(char* backdrop_buffer); #endif - void (*set_framebuffer)(void *framebuffer); #if defined(HAVE_LCD_COLOR) void (*gradient_fillrect)(int x, int y, int width, int height, unsigned start, unsigned end); diff --git a/apps/screens.c b/apps/screens.c index 020d0a3021..fde99912d5 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -207,12 +207,13 @@ bool set_time_screen(const char* title, struct tm *tm) /* 6 possible cursor possitions, 2 values stored for each: x, y */ unsigned int cursor[6][2]; struct viewport *vp = &viewports[s]; + struct viewport *last_vp; struct screen *screen = &screens[s]; static unsigned char rtl_idx[] = { IDX_SECONDS, IDX_MINUTES, IDX_HOURS, IDX_DAY, IDX_MONTH, IDX_YEAR }; viewport_set_defaults(vp, s); - screen->set_viewport(vp); + last_vp = screen->set_viewport(vp); nb_lines = viewport_get_nb_lines(vp); /* minimum lines needed is 2 + title line */ @@ -283,7 +284,7 @@ bool set_time_screen(const char* title, struct tm *tm) if (nb_lines > 5) screen->puts(0, 5, str(LANG_TIME_REVERT)); screen->update_viewport(); - screen->set_viewport(NULL); + screen->set_viewport(last_vp); } /* set the most common numbers */ diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c index a7e80c7244..7c766dab8a 100644 --- a/firmware/drivers/lcd-16bit-common.c +++ b/firmware/drivers/lcd-16bit-common.c @@ -35,10 +35,10 @@ void lcd_clear_viewport(void) int x, y, width, height; int len, step; - x = current_vp->x; - y = current_vp->y; - width = current_vp->width; - height = current_vp->height; + x = lcd_current_viewport->x; + y = lcd_current_viewport->y; + width = lcd_current_viewport->width; + height = lcd_current_viewport->height; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -70,11 +70,11 @@ void lcd_clear_viewport(void) dst = FBADDR(x, y); dst_end = FBADDR(x + width - 1 , y + height - 1); - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { do { - memset16(dst, current_vp->fg_pattern, len); + memset16(dst, lcd_current_viewport->fg_pattern, len); dst += step; } while (dst <= dst_end); @@ -85,7 +85,7 @@ void lcd_clear_viewport(void) { do { - memset16(dst, current_vp->bg_pattern, len); + memset16(dst, lcd_current_viewport->bg_pattern, len); dst += step; } while (dst <= dst_end); @@ -102,22 +102,24 @@ void lcd_clear_viewport(void) } } - if (current_vp == &default_vp) + if (lcd_current_viewport == &default_vp) lcd_scroll_stop(); else - lcd_scroll_stop_viewport(current_vp); + lcd_scroll_stop_viewport(lcd_current_viewport); + + lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /*** low-level drawing functions ***/ static void ICODE_ATTR setpixel(fb_data *address) { - *address = current_vp->fg_pattern; + *address = lcd_current_viewport->fg_pattern; } static void ICODE_ATTR clearpixel(fb_data *address) { - *address = current_vp->bg_pattern; + *address = lcd_current_viewport->bg_pattern; } static void ICODE_ATTR clearimgpixel(fb_data *address) @@ -157,8 +159,8 @@ void lcd_fillrect(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -171,14 +173,14 @@ void lcd_fillrect(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -205,14 +207,14 @@ void lcd_fillrect(int x, int y, int width, int height) #endif /* drawmode and optimisation */ - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (lcd_current_viewport->drawmode & DRMODE_BG) { if (!lcd_backdrop) { fillopt = OPT_SET; - bits = current_vp->bg_pattern; + bits = lcd_current_viewport->bg_pattern; } else fillopt = OPT_COPY; @@ -220,13 +222,13 @@ void lcd_fillrect(int x, int y, int width, int height) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = OPT_SET; - bits = current_vp->fg_pattern; + bits = lcd_current_viewport->fg_pattern; } } - if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) + if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT) return; dst = FBADDR(x, y); @@ -284,13 +286,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, const unsigned char *src_end; fb_data *dst, *dst_col; unsigned dmask = 0x100; /* bit 8 == sentinel */ - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; int row; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -305,14 +307,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -404,7 +406,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_BG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; do { if (!(data & 0x01)) @@ -417,7 +419,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_FG: - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { if (data & 0x01) @@ -430,7 +432,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_SOLID|DRMODE_INT_BD: - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; bo = lcd_backdrop_offset; do { @@ -443,8 +445,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_SOLID: - fg = current_vp->fg_pattern; - bg = current_vp->bg_pattern; + fg = lcd_current_viewport->fg_pattern; + bg = lcd_current_viewport->bg_pattern; do { *dst = (data & 0x01) ? fg : bg; @@ -549,10 +551,10 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, { fb_data *dst, *dst_row; unsigned dmask = 0x00000000; - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; /* initialize blending */ BLEND_INIT; @@ -570,14 +572,14 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -668,7 +670,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, /* go through the rows and update each pixel */ do { - /* saving current_vp->fg/bg_pattern and lcd_backdrop_offset into these + /* saving lcd_current_viewport->fg/bg_pattern and lcd_backdrop_offset into these * temp vars just before the loop helps gcc to opimize the loop better * (testing showed ~15% speedup) */ unsigned fg, bg; @@ -727,7 +729,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_BG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; do { *dst = blend_two_colors(bg, *dst, data & ALPHA_COLOR_LOOKUP_SIZE ); @@ -747,7 +749,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_FG: - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { *dst = blend_two_colors(*dst, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); @@ -758,7 +760,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, break; case DRMODE_SOLID|DRMODE_INT_BD: bo = lcd_backdrop_offset; - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { fb_data *c = (fb_data *)((uintptr_t)dst + bo); @@ -769,7 +771,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_SOLID|DRMODE_INT_IMG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; img_offset = image - dst; do { @@ -792,8 +794,8 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_SOLID: - bg = current_vp->bg_pattern; - fg = current_vp->fg_pattern; + bg = lcd_current_viewport->bg_pattern; + fg = lcd_current_viewport->fg_pattern; do { *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); diff --git a/firmware/drivers/lcd-16bit-vert.c b/firmware/drivers/lcd-16bit-vert.c index ffe2b85b3c..b336e78c78 100644 --- a/firmware/drivers/lcd-16bit-vert.c +++ b/firmware/drivers/lcd-16bit-vert.c @@ -39,7 +39,7 @@ #include "scroll_engine.h" #define ROW_INC 1 -#define COL_INC LCD_HEIGHT +#define COL_INC lcd_current_viewport->buffer->stride extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[]; @@ -61,7 +61,9 @@ void lcd_hline(int x1, int x2, int y) { int x; fb_data *dst, *dst_end; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + int stride_dst; + + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; /* direction flip */ if (x2 < x1) @@ -73,20 +75,20 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || - (x1 >= current_vp->width) || + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || + (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* Adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -103,12 +105,13 @@ void lcd_hline(int x1, int x2, int y) #endif dst = FBADDR(x1 , y ); - dst_end = dst + (x2 - x1) * LCD_HEIGHT; + stride_dst = lcd_current_viewport->buffer->stride; + dst_end = dst + (x2 - x1) * stride_dst; do { pfunc(dst); - dst += LCD_HEIGHT; + dst += stride_dst; } while (dst <= dst_end); } @@ -131,20 +134,20 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || - (y1 >= current_vp->height) || + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || + (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - x += current_vp->x; - y1 += current_vp->y; - y2 += current_vp->y; + x += lcd_current_viewport->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -163,14 +166,14 @@ void lcd_vline(int x, int y1, int y2) height = y2 - y1 + 1; /* drawmode and optimisation */ - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (lcd_current_viewport->drawmode & DRMODE_BG) { if (!lcd_backdrop) { fillopt = OPT_SET; - bits = current_vp->bg_pattern; + bits = lcd_current_viewport->bg_pattern; } else fillopt = OPT_COPY; @@ -178,13 +181,13 @@ void lcd_vline(int x, int y1, int y2) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = OPT_SET; - bits = current_vp->fg_pattern; + bits = lcd_current_viewport->fg_pattern; } } - if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) + if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT) return; dst = FBADDR(x, y1); @@ -215,11 +218,11 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, int height) { fb_data *dst; - + int stride_dst; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -235,14 +238,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -272,13 +275,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, src += stride * src_x + src_y; /* move starting point */ dst = FBADDR(x, y); - fb_data *dst_end = dst + width * LCD_HEIGHT; + stride_dst = lcd_current_viewport->buffer->stride; + fb_data *dst_end = dst + width * stride_dst; do { memcpy(dst, src, height * sizeof(fb_data)); src += stride; - dst += LCD_HEIGHT; + dst += stride_dst; } while (dst < dst_end); } @@ -289,11 +293,12 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, int y, int width, int height) { fb_data *dst, *dst_end; + int stride_dst; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -309,14 +314,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -346,7 +351,8 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, src += stride * src_x + src_y; /* move starting point */ dst = FBADDR(x, y); - dst_end = dst + width * LCD_HEIGHT; + stride_dst = lcd_current_viewport->buffer->stride; + dst_end = dst + width * stride_dst; do { @@ -354,12 +360,12 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, for(i = 0;i < height;i++) { if (src[i] == REPLACEWITHFG_COLOR) - dst[i] = current_vp->fg_pattern; + dst[i] = lcd_current_viewport->fg_pattern; else if(src[i] != TRANSPARENT_COLOR) dst[i] = src[i]; } src += stride; - dst += LCD_HEIGHT; + dst += stride_dst; } while (dst < dst_end); } diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index b792be4e02..03c50f8ebf 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c @@ -38,7 +38,7 @@ #include "bidi.h" #include "scroll_engine.h" -#define ROW_INC LCD_WIDTH +#define ROW_INC lcd_current_viewport->buffer->stride #define COL_INC 1 extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; @@ -74,20 +74,20 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || - (x1 >= current_vp->width) || + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || + (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* Adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -106,14 +106,14 @@ void lcd_hline(int x1, int x2, int y) width = x2 - x1 + 1; /* drawmode and optimisation */ - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (lcd_current_viewport->drawmode & DRMODE_BG) { if (!lcd_backdrop) { fillopt = OPT_SET; - bits = current_vp->bg_pattern; + bits = lcd_current_viewport->bg_pattern; } else fillopt = OPT_COPY; @@ -121,13 +121,13 @@ void lcd_hline(int x1, int x2, int y) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = OPT_SET; - bits = current_vp->fg_pattern; + bits = lcd_current_viewport->fg_pattern; } } - if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) + if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT) return; dst = FBADDR(x1, y); @@ -157,7 +157,8 @@ void lcd_vline(int x, int y1, int y2) { int y; fb_data *dst, *dst_end; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + int stride_dst; + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; /* direction flip */ if (y2 < y1) @@ -169,20 +170,20 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || - (y1 >= current_vp->height) || + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || + (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - x += current_vp->x; - y1 += current_vp->y; - y2 += current_vp->y; + x += lcd_current_viewport->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -199,12 +200,13 @@ void lcd_vline(int x, int y1, int y2) #endif dst = FBADDR(x , y1); - dst_end = dst + (y2 - y1) * LCD_WIDTH; + stride_dst = lcd_current_viewport->buffer->stride; + dst_end = dst + (y2 - y1) * stride_dst; do { pfunc(dst); - dst += LCD_WIDTH; + dst += stride_dst; } while (dst <= dst_end); } @@ -215,11 +217,12 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, int height) { fb_data *dst; + int stride_dst; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -235,14 +238,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -272,12 +275,13 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, src += stride * src_y + src_x; /* move starting point */ dst = FBADDR(x, y); + stride_dst = lcd_current_viewport->buffer->stride; do { memcpy(dst, src, width * sizeof(fb_data)); src += stride; - dst += LCD_WIDTH; + dst += stride_dst; } while (--height > 0); } @@ -288,12 +292,13 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, int y, int width, int height) { fb_data *dst; - unsigned fg = current_vp->fg_pattern; + unsigned fg = lcd_current_viewport->fg_pattern; + int stride_dst = lcd_current_viewport->buffer->stride; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -309,14 +314,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -371,7 +376,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, [s]"+&r"(src), [d]"+&r"(dst) : [width]"r"(width), [sstp]"r"(stride - width), - [dstp]"r"(LCD_WIDTH - width), + [dstp]"r"(stride_dst - width), [transcolor]"r"(TRANSPARENT_COLOR), [fgcolor]"r"(REPLACEWITHFG_COLOR), [fgpat]"r"(fg) @@ -395,7 +400,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, } while (++dst_row < row_end); src += stride; - dst += LCD_WIDTH; + dst += stride_dst; } while (--height > 0); #endif diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c index 668c685187..57abdb91a6 100644 --- a/firmware/drivers/lcd-1bit-vert.c +++ b/firmware/drivers/lcd-1bit-vert.c @@ -44,9 +44,26 @@ #define MAIN_LCD #endif +#ifdef MAIN_LCD +#define THIS_STRIDE STRIDE_MAIN +#else +#define THIS_STRIDE STRIDE_REMOTE +#endif + +#define CURRENT_VP LCDFN(current_viewport) /*** globals ***/ -FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; -FBFN(data) *LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; +static FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; + +static void *LCDFN(frameaddress_default)(int x, int y); + +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t LCDFN(framebuffer_default) = +{ + .FBFN(ptr) = &LCDFN(static_framebuffer)[0][0], + .get_address_fn = &LCDFN(frameaddress_default), + .stride = THIS_STRIDE(LCDM(WIDTH), LCDM(HEIGHT)), + .elems = (LCDM(FBWIDTH)*LCDM(FBHEIGHT)), +}; static struct viewport default_vp = { @@ -56,55 +73,73 @@ static struct viewport default_vp = .height = LCDM(HEIGHT), .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, + .buffer = NULL, }; -static struct viewport* current_vp = &default_vp; +struct viewport* CURRENT_VP; + +static void *LCDFN(frameaddress_default)(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = CURRENT_VP->buffer; +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCDM(NATIVE_STRIDE)(fb->stride)) + y; +#else + size_t element = (y * LCDM(NATIVE_STRIDE)(fb->stride)) + x; +#endif + + return fb->FBFN(ptr) + element;/*(element % fb->elems);*/ +} /* LCD init */ void LCDFN(init)(void) { + + /* Initialize the viewport */ + LCDFN(set_viewport)(NULL); LCDFN(clear_display)(); LCDFN(init_device)(); #ifdef MAIN_LCD scroll_init(); #endif + } /*** parameter handling ***/ void LCDFN(set_drawmode)(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + CURRENT_VP->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int LCDFN(get_drawmode)(void) { - return current_vp->drawmode; + return CURRENT_VP->drawmode; } int LCDFN(getwidth)(void) { - return current_vp->width; + return CURRENT_VP->width; } int LCDFN(getheight)(void) { - return current_vp->height; + return CURRENT_VP->height; } void LCDFN(setfont)(int newfont) { - current_vp->font = newfont; + CURRENT_VP->font = newfont; } int LCDFN(getfont)(void) { - return current_vp->font; + return CURRENT_VP->font; } int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, CURRENT_VP->font); } /*** low-level drawing functions ***/ @@ -134,7 +169,7 @@ LCDFN(pixelfunc_type)* const LCDFN(pixelfuncs)[8] = { flippixel, nopixel, setpixel, setpixel, nopixel, clearpixel, nopixel, clearpixel }; - + static void ICODE_ATTR flipblock(FBFN(data) *address, unsigned mask, unsigned bits) { @@ -199,9 +234,9 @@ LCDFN(blockfunc_type)* const LCDFN(blockfuncs)[8] = { /* Clear the whole display */ void LCDFN(clear_display)(void) { - unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; + unsigned bits = (CURRENT_VP->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; - memset(LCDFN(framebuffer), bits, FBSIZE); + memset(LCDFB(0, 0), bits, FBSIZE); LCDFN(scroll_info).lines = 0; } @@ -210,37 +245,40 @@ void LCDFN(clear_viewport)(void) { int oldmode; - if (current_vp == &default_vp) + if (CURRENT_VP == &default_vp && + default_vp.buffer == &LCDFN(framebuffer_default)) { LCDFN(clear_display)(); } else { - oldmode = current_vp->drawmode; + oldmode = CURRENT_VP->drawmode; /* Invert the INVERSEVID bit and set basic mode to SOLID */ - current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) | + CURRENT_VP->drawmode = (~CURRENT_VP->drawmode & DRMODE_INVERSEVID) | DRMODE_SOLID; - LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); + LCDFN(fillrect)(0, 0, CURRENT_VP->width, CURRENT_VP->height); - current_vp->drawmode = oldmode; + CURRENT_VP->drawmode = oldmode; - LCDFN(scroll_stop_viewport)(current_vp); + LCDFN(scroll_stop_viewport)(CURRENT_VP); } + + CURRENT_VP->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /* Set a single pixel */ void LCDFN(drawpixel)(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)CURRENT_VP->width) + && ((unsigned)y < (unsigned)CURRENT_VP->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCDM(WIDTH)) && ((unsigned)y < (unsigned)LCDM(HEIGHT)) #endif ) - LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x + x, current_vp->y + y); + LCDFN(pixelfuncs)[CURRENT_VP->drawmode](CURRENT_VP->x + x, CURRENT_VP->y + y); } /* Draw a line */ @@ -252,7 +290,7 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[current_vp->drawmode]; + LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode]; deltax = abs(x2 - x1); if (deltax == 0) @@ -308,14 +346,14 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)CURRENT_VP->width) + && ((unsigned)y < (unsigned)CURRENT_VP->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCDM(WIDTH)) && ((unsigned)y < (unsigned)LCDM(HEIGHT)) #endif ) - pfunc(current_vp->x + x, current_vp->y + y); + pfunc(CURRENT_VP->x + x, CURRENT_VP->y + y); if (d < 0) { @@ -350,19 +388,19 @@ void LCDFN(hline)(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) + if (((unsigned)y >= (unsigned)CURRENT_VP->height) || (x1 >= CURRENT_VP->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= CURRENT_VP->width) + x2 = CURRENT_VP->width-1; /* adjust to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += CURRENT_VP->x; + x2 += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -380,7 +418,7 @@ void LCDFN(hline)(int x1, int x2, int y) width = x2 - x1 + 1; - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x1,y>>3); mask = BIT_N(y & 7); @@ -395,6 +433,7 @@ void LCDFN(vline)(int x, int y1, int y2) { int ny; FBFN(data) *dst; + int stride_dst; unsigned mask, mask_bottom; LCDFN(blockfunc_type) *bfunc; @@ -408,19 +447,19 @@ void LCDFN(vline)(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) + if (((unsigned)x >= (unsigned)CURRENT_VP->width) || (y1 >= CURRENT_VP->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= CURRENT_VP->height) + y2 = CURRENT_VP->height-1; /* adjust for viewport */ - y1 += current_vp->y; - y2 += current_vp->y; - x += current_vp->x; + y1 += CURRENT_VP->y; + y2 += CURRENT_VP->y; + x += CURRENT_VP->x; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -436,16 +475,17 @@ void LCDFN(vline)(int x, int y1, int y2) y2 = LCDM(HEIGHT)-1; #endif - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x,y1>>3); ny = y2 - (y1 & ~7); mask = 0xFFu << (y1 & 7); mask_bottom = 0xFFu >> (~ny & 7); + stride_dst = CURRENT_VP->buffer->stride; for (; ny >= 8; ny -= 8) { bfunc(dst, mask, 0xFFu); - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -472,6 +512,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height) { int ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; unsigned bits = 0; LCDFN(blockfunc_type) *bfunc; @@ -479,8 +520,8 @@ void LCDFN(fillrect)(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) + || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -493,14 +534,14 @@ void LCDFN(fillrect)(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -526,26 +567,27 @@ void LCDFN(fillrect)(int x, int y, int width, int height) height = LCDM(HEIGHT) - y; #endif - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (CURRENT_VP->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (CURRENT_VP->drawmode & DRMODE_BG) { fillopt = true; } } else { - if (current_vp->drawmode & DRMODE_FG) + if (CURRENT_VP->drawmode & DRMODE_FG) { fillopt = true; bits = 0xFFu; } } - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x,y>>3); ny = height - 1 + (y & 7); mask = 0xFFu << (y & 7); mask_bottom = 0xFFu >> (~ny & 7); + stride_dst = CURRENT_VP->buffer->stride; for (; ny >= 8; ny -= 8) { @@ -561,7 +603,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height) while (dst_row < dst_end); } - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -595,13 +637,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, { int shift, ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; LCDFN(blockfunc_type) *bfunc; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) + || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; /* clip image in viewport */ @@ -617,14 +660,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -656,16 +699,17 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, src_y &= 7; y -= src_y; dst = LCDFB(x,y>>3); + stride_dst = CURRENT_VP->buffer->stride; shift = y & 7; ny = height - 1 + shift + src_y; - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; mask = 0xFFu << (shift + src_y); mask_bottom = 0xFFu >> (~ny & 7); if (shift == 0) { - bool copyopt = (current_vp->drawmode == DRMODE_SOLID); + bool copyopt = (CURRENT_VP->drawmode == DRMODE_SOLID); for (; ny >= 8; ny -= 8) { @@ -683,7 +727,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, } src += stride; - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -721,7 +765,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x, mask_col >>= 8; src_col += stride; - dst_col += LCDM(WIDTH); + dst_col += stride_dst; data >>= 8; } data |= *src_col << shift; diff --git a/firmware/drivers/lcd-24bit.c b/firmware/drivers/lcd-24bit.c index 8820e632d4..65fa01f37f 100644 --- a/firmware/drivers/lcd-24bit.c +++ b/firmware/drivers/lcd-24bit.c @@ -39,7 +39,7 @@ #include "bidi.h" #include "scroll_engine.h" -#define ROW_INC LCD_WIDTH +#define ROW_INC lcd_current_viewport->buffer->stride #define COL_INC 1 extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; @@ -62,10 +62,10 @@ void lcd_clear_viewport(void) int x, y, width, height; int len, step; - x = current_vp->x; - y = current_vp->y; - width = current_vp->width; - height = current_vp->height; + x = lcd_current_viewport->x; + y = lcd_current_viewport->y; + width = lcd_current_viewport->width; + height = lcd_current_viewport->height; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -97,9 +97,9 @@ void lcd_clear_viewport(void) dst = FBADDR(x, y); dst_end = FBADDR(x + width - 1 , y + height - 1); - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - fb_data px = FB_SCALARPACK(current_vp->fg_pattern); + fb_data px = FB_SCALARPACK(lcd_current_viewport->fg_pattern); do { fb_data *end = dst + len; @@ -114,7 +114,7 @@ void lcd_clear_viewport(void) { if (!lcd_backdrop) { - fb_data px = FB_SCALARPACK(current_vp->bg_pattern); + fb_data px = FB_SCALARPACK(lcd_current_viewport->bg_pattern); do { fb_data *end = dst + len; @@ -137,22 +137,24 @@ void lcd_clear_viewport(void) } } - if (current_vp == &default_vp) + if (lcd_current_viewport == &default_vp) lcd_scroll_stop(); else - lcd_scroll_stop_viewport(current_vp); + lcd_scroll_stop_viewport(lcd_current_viewport); + + lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /*** low-level drawing functions ***/ static void ICODE_ATTR setpixel(fb_data *address) { - *address = FB_SCALARPACK(current_vp->fg_pattern); + *address = FB_SCALARPACK(lcd_current_viewport->fg_pattern); } static void ICODE_ATTR clearpixel(fb_data *address) { - *address = FB_SCALARPACK(current_vp->bg_pattern); + *address = FB_SCALARPACK(lcd_current_viewport->bg_pattern); } static void ICODE_ATTR clearimgpixel(fb_data *address) @@ -194,8 +196,8 @@ void lcd_fillrect(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -208,14 +210,14 @@ void lcd_fillrect(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -242,14 +244,14 @@ void lcd_fillrect(int x, int y, int width, int height) #endif /* drawmode and optimisation */ - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if (current_vp->drawmode & DRMODE_BG) + if (lcd_current_viewport->drawmode & DRMODE_BG) { if (!lcd_backdrop) { fillopt = OPT_SET; - bits = FB_SCALARPACK(current_vp->bg_pattern); + bits = FB_SCALARPACK(lcd_current_viewport->bg_pattern); } else fillopt = OPT_COPY; @@ -257,13 +259,13 @@ void lcd_fillrect(int x, int y, int width, int height) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = OPT_SET; - bits = FB_SCALARPACK(current_vp->fg_pattern); + bits = FB_SCALARPACK(lcd_current_viewport->fg_pattern); } } - if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) + if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT) return; dst = FBADDR(x, y); @@ -327,13 +329,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, const unsigned char *src_end; fb_data *dst, *dst_col; unsigned dmask = 0x100; /* bit 8 == sentinel */ - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; int row; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -348,14 +350,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -447,7 +449,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_BG: - bg = FB_SCALARPACK(current_vp->bg_pattern); + bg = FB_SCALARPACK(lcd_current_viewport->bg_pattern); do { if (!(data & 0x01)) @@ -460,7 +462,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_FG: - fg = FB_SCALARPACK(current_vp->fg_pattern); + fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern); do { if (data & 0x01) @@ -473,7 +475,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_SOLID|DRMODE_INT_BD: - fg = FB_SCALARPACK(current_vp->fg_pattern); + fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern); bo = lcd_backdrop_offset; do { @@ -486,8 +488,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, break; case DRMODE_SOLID: - fg = FB_SCALARPACK(current_vp->fg_pattern); - bg = FB_SCALARPACK(current_vp->bg_pattern); + fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern); + bg = FB_SCALARPACK(lcd_current_viewport->bg_pattern); do { *dst = (data & 0x01) ? fg : bg; @@ -559,10 +561,10 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, { fb_data *dst, *dst_row; unsigned dmask = 0x00000000; - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; /* clipping */ @@ -578,14 +580,14 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -673,7 +675,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, /* go through the rows and update each pixel */ do { - /* saving current_vp->fg/bg_pattern and lcd_backdrop_offset into these + /* saving lcd_current_viewport->fg/bg_pattern and lcd_backdrop_offset into these * temp vars just before the loop helps gcc to opimize the loop better * (testing showed ~15% speedup) */ unsigned fg, bg; @@ -734,7 +736,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_BG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; do { unsigned px = FB_UNPACK_SCALAR_LCD(*dst); @@ -757,7 +759,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_FG: - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { unsigned px = FB_UNPACK_SCALAR_LCD(*dst); @@ -769,7 +771,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, break; case DRMODE_SOLID|DRMODE_INT_BD: bo = lcd_backdrop_offset; - fg = current_vp->fg_pattern; + fg = lcd_current_viewport->fg_pattern; do { unsigned c = FB_UNPACK_SCALAR_LCD(*(fb_data *)((uintptr_t)dst + bo)); @@ -780,7 +782,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_SOLID|DRMODE_INT_IMG: - bg = current_vp->bg_pattern; + bg = lcd_current_viewport->bg_pattern; img_offset = image - dst; do { @@ -805,8 +807,8 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, while (--col); break; case DRMODE_SOLID: - bg = current_vp->bg_pattern; - fg = current_vp->fg_pattern; + bg = lcd_current_viewport->bg_pattern; + fg = lcd_current_viewport->fg_pattern; do { *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); @@ -855,7 +857,7 @@ void lcd_hline(int x1, int x2, int y) { int x, width; fb_data *dst, *dst_end; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; /* direction flip */ if (x2 < x1) @@ -867,20 +869,20 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || - (x1 >= current_vp->width) || + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || + (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* Adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -912,7 +914,7 @@ void lcd_vline(int x, int y1, int y2) { int y; fb_data *dst, *dst_end; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; /* direction flip */ if (y2 < y1) @@ -924,20 +926,20 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || - (y1 >= current_vp->height) || + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || + (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - x += current_vp->x; - y1 += current_vp->y; - y2 += current_vp->y; + x += lcd_current_viewport->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -973,8 +975,8 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -990,14 +992,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1047,8 +1049,8 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -1064,14 +1066,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1104,7 +1106,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, transparent = FB_SCALARPACK(TRANSPARENT_COLOR); replacewithfg = FB_SCALARPACK(REPLACEWITHFG_COLOR); - fg = FB_SCALARPACK(current_vp->fg_pattern); + fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern); #define CMP(c1, c2) (c1.r == c2.r && c1.g == c2.g && c1.b == c2.b) do diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c index 1d256e5f58..35a2be5b2c 100644 --- a/firmware/drivers/lcd-2bit-horz.c +++ b/firmware/drivers/lcd-2bit-horz.c @@ -39,8 +39,8 @@ /*** globals ***/ -unsigned char lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; -unsigned char *lcd_framebuffer = &lcd_static_framebuffer[0][0]; +static unsigned char lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; +static void *lcd_frameaddress_default(int x, int y); static const unsigned char pixmask[4] ICONST_ATTR = { 0xC0, 0x30, 0x0C, 0x03 @@ -49,6 +49,15 @@ static const unsigned char pixmask[4] ICONST_ATTR = { static fb_data* lcd_backdrop = NULL; static long lcd_backdrop_offset IDATA_ATTR = 0; +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t lcd_framebuffer_default = +{ + .fb_ptr = &lcd_static_framebuffer[0][0], + .get_address_fn = &lcd_frameaddress_default, + .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT), + .elems = (LCD_FBWIDTH*LCD_FBHEIGHT), +}; + static struct viewport default_vp = { .x = 0, @@ -57,18 +66,32 @@ static struct viewport default_vp = .height = LCD_HEIGHT, .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, + .buffer = NULL, .fg_pattern = LCD_DEFAULT_FG, .bg_pattern = LCD_DEFAULT_BG }; -static struct viewport* current_vp IBSS_ATTR; +struct viewport* lcd_current_viewport IBSS_ATTR; static unsigned fg_pattern IBSS_ATTR; static unsigned bg_pattern IBSS_ATTR; +static void *lcd_frameaddress_default(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = lcd_current_viewport->buffer; + +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y; +#else + size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x; +#endif + return fb->fb_ptr + element;/*(element % fb->elems);*/ +} + /* LCD init */ void lcd_init(void) { - /* Initialise the viewport */ + /* Initialize the viewport */ lcd_set_viewport(NULL); lcd_clear_display(); @@ -81,34 +104,34 @@ void lcd_init(void) void lcd_set_drawmode(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int lcd_get_drawmode(void) { - return current_vp->drawmode; + return lcd_current_viewport->drawmode; } void lcd_set_foreground(unsigned brightness) { - current_vp->fg_pattern = brightness; + lcd_current_viewport->fg_pattern = brightness; fg_pattern = 0x55 * (~brightness & 3); } unsigned lcd_get_foreground(void) { - return current_vp->fg_pattern; + return lcd_current_viewport->fg_pattern; } void lcd_set_background(unsigned brightness) { - current_vp->bg_pattern = brightness; + lcd_current_viewport->bg_pattern = brightness; bg_pattern = 0x55 * (~brightness & 3); } unsigned lcd_get_background(void) { - return current_vp->bg_pattern; + return lcd_current_viewport->bg_pattern; } void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) @@ -120,27 +143,27 @@ void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) int lcd_getwidth(void) { - return current_vp->width; + return lcd_current_viewport->width; } int lcd_getheight(void) { - return current_vp->height; + return lcd_current_viewport->height; } void lcd_setfont(int newfont) { - current_vp->font = newfont; + lcd_current_viewport->font = newfont; } int lcd_getfont(void) { - return current_vp->font; + return lcd_current_viewport->font; } int lcd_getstringsize(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, lcd_current_viewport->font); } /*** low-level drawing functions ***/ @@ -318,7 +341,7 @@ void lcd_set_backdrop(fb_data* backdrop) lcd_backdrop = backdrop; if (backdrop) { - lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; + lcd_backdrop_offset = (long)backdrop - (long)FBADDR(0,0); lcd_pixelfuncs = lcd_pixelfuncs_backdrop; lcd_blockfuncs = lcd_blockfuncs_backdrop; } @@ -349,16 +372,16 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) /* Clear the whole display */ void lcd_clear_display(void) { - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - memset(lcd_framebuffer, fg_pattern, FRAMEBUFFER_SIZE); + memset(FBADDR(0,0), fg_pattern, FRAMEBUFFER_SIZE); } else { if (lcd_backdrop) - memcpy(lcd_framebuffer, lcd_backdrop, FRAMEBUFFER_SIZE); + memcpy(FBADDR(0,0), lcd_backdrop, FRAMEBUFFER_SIZE); else - memset(lcd_framebuffer, bg_pattern, FRAMEBUFFER_SIZE); + memset(FBADDR(0,0), bg_pattern, FRAMEBUFFER_SIZE); } lcd_scroll_info.lines = 0; @@ -369,37 +392,39 @@ void lcd_clear_viewport(void) { int lastmode; - if (current_vp == &default_vp) + if (lcd_current_viewport == &default_vp && + default_vp.buffer == &lcd_framebuffer_default) { lcd_clear_display(); } else { - lastmode = current_vp->drawmode; + lastmode = lcd_current_viewport->drawmode; /* Invert the INVERSEVID bit and set basic mode to SOLID */ - current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | + lcd_current_viewport->drawmode = (~lastmode & DRMODE_INVERSEVID) | DRMODE_SOLID; - lcd_fillrect(0, 0, current_vp->width, current_vp->height); + lcd_fillrect(0, 0, lcd_current_viewport->width, lcd_current_viewport->height); - current_vp->drawmode = lastmode; + lcd_current_viewport->drawmode = lastmode; - lcd_scroll_stop_viewport(current_vp); + lcd_scroll_stop_viewport(lcd_current_viewport); } + lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /* Set a single pixel */ void lcd_drawpixel(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); + lcd_pixelfuncs[lcd_current_viewport->drawmode](lcd_current_viewport->x + x, lcd_current_viewport->y + y); } /* Draw a line */ @@ -411,7 +436,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; + lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode]; deltay = abs(y2 - y1); if (deltay == 0) @@ -467,14 +492,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - pfunc(current_vp->x + x, current_vp->y + y); + pfunc(lcd_current_viewport->x + x, lcd_current_viewport->y + y); if (d < 0) { @@ -509,19 +534,19 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* adjust to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -537,7 +562,7 @@ void lcd_hline(int x1, int x2, int y) x2 = LCD_WIDTH-1; #endif - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x1>>2,y); nx = x2 - (x1 & ~3); mask = 0xFFu >> (2 * (x1 & 3)); @@ -557,6 +582,7 @@ void lcd_vline(int x, int y1, int y2) { int y; unsigned char *dst, *dst_end; + int stride_dst; unsigned mask; lcd_blockfunc_type *bfunc; @@ -570,19 +596,19 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - y1 += current_vp->y; - y2 += current_vp->y; - x += current_vp->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; + x += lcd_current_viewport->x; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -598,15 +624,16 @@ void lcd_vline(int x, int y1, int y2) y2 = LCD_HEIGHT-1; #endif - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x>>2,y1); + stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); mask = pixmask[x & 3]; - dst_end = dst + (y2 - y1) * LCD_FBWIDTH; + dst_end = dst + (y2 - y1) * stride_dst; do { bfunc(dst, mask, 0xFFu); - dst += LCD_FBWIDTH; + dst += stride_dst; } while (dst <= dst_end); } @@ -631,12 +658,13 @@ void lcd_fillrect(int x, int y, int width, int height) { int nx; unsigned char *dst, *dst_end; + int stride_dst; unsigned mask, mask_right; lcd_blockfunc_type *bfunc; /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || (y >= current_vp->height) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; @@ -650,14 +678,14 @@ void lcd_fillrect(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -683,21 +711,22 @@ void lcd_fillrect(int x, int y, int width, int height) height = LCD_HEIGHT - y; #endif - bfunc = lcd_blockfuncs[current_vp->drawmode]; - dst = FBADDR(x>>2,y); - nx = width - 1 + (x & 3); - mask = 0xFFu >> (2 * (x & 3)); + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; + dst = FBADDR(x>>2,y); + stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); + nx = width - 1 + (x & 3); + mask = 0xFFu >> (2 * (x & 3)); mask_right = 0xFFu << (2 * (~nx & 3)); for (; nx >= 4; nx -= 4) { unsigned char *dst_col = dst; - dst_end = dst_col + height * LCD_FBWIDTH; + dst_end = dst_col + height * stride_dst; do { bfunc(dst_col, mask, 0xFFu); - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; } while (dst_col < dst_end); @@ -706,11 +735,11 @@ void lcd_fillrect(int x, int y, int width, int height) } mask &= mask_right; - dst_end = dst + height * LCD_FBWIDTH; + dst_end = dst + height * stride_dst; do { bfunc(dst, mask, 0xFFu); - dst += LCD_FBWIDTH; + dst += stride_dst; } while (dst < dst_end); } @@ -731,14 +760,15 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, { const unsigned char *src_end; fb_data *dst, *dst_end; + int stride_dst; unsigned dmask = 0x100; /* bit 8 == sentinel */ unsigned dst_mask; - int drmode = current_vp->drawmode; + int drmode = lcd_current_viewport->drawmode; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -753,13 +783,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; - x += current_vp->x; /* adjust for viewport */ - y += current_vp->y; /* adjust for viewport */ + x += lcd_current_viewport->x; /* adjust for viewport */ + y += lcd_current_viewport->y; /* adjust for viewport */ #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -792,7 +822,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_end = src + width; dst = FBADDR(x >> 2,y); - dst_end = dst + height * LCD_FBWIDTH; + stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); + dst_end = dst + height * stride_dst; dst_mask = pixmask[x & 3]; if (drmode & DRMODE_INVERSEVID) @@ -825,7 +856,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, if (data & 0x01) *dst_col ^= dst_mask; - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -843,7 +874,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, *dst_col = block ^ ((block ^ *(dst_col + bo)) & dst_mask); } - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -858,7 +889,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, unsigned block = *dst_col; *dst_col = block ^ ((block ^ bg) & dst_mask); } - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -874,7 +905,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, unsigned block = *dst_col; *dst_col = block ^ ((block ^ fg) & dst_mask); } - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -891,7 +922,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, *dst_col = block ^ ((block ^ ((data & 0x01) ? fg : *(dst_col + bo))) & dst_mask); - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -905,7 +936,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, *dst_col = block ^ ((block ^ ((data & 0x01) ? fg : bg)) & dst_mask); - dst_col += LCD_FBWIDTH; + dst_col += stride_dst; UPDATE_SRC; } while (dst_col < dst_end); @@ -945,12 +976,13 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, { int shift, nx; unsigned char *dst, *dst_end; + int stride_dst; unsigned mask, mask_right; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -965,14 +997,14 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1000,12 +1032,13 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, height = LCD_HEIGHT - y; #endif - stride = (stride + 3) >> 2; /* convert to no. of bytes */ + stride = LCD_FBSTRIDE(stride, 0); /* convert to no. of bytes */ src += stride * src_y + (src_x >> 2); /* move starting point */ src_x &= 3; x -= src_x; dst = FBADDR(x>>2,y); + stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0); shift = x & 3; nx = width - 1 + shift + src_x; @@ -1013,7 +1046,7 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, mask_right = 0xFFu << (2 * (~nx & 3)); shift *= 2; - dst_end = dst + height * LCD_FBWIDTH; + dst_end = dst + height * stride_dst; do { const unsigned char *src_row = src; @@ -1039,7 +1072,7 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x, setblock(dst_row, mask_row & mask_right, data >> shift); src += stride; - dst += LCD_FBWIDTH; + dst += stride_dst; } while (dst < dst_end); } diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c index 501e568a69..a099c45e98 100644 --- a/firmware/drivers/lcd-2bit-vert.c +++ b/firmware/drivers/lcd-2bit-vert.c @@ -36,8 +36,8 @@ /*** globals ***/ -fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; -fb_data *lcd_framebuffer = &lcd_static_framebuffer[0][0]; +static fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; +static void *lcd_frameaddress_default(int x, int y); const unsigned char lcd_dibits[16] ICONST_ATTR = { 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, @@ -51,6 +51,15 @@ static const unsigned char pixmask[4] ICONST_ATTR = { static fb_data* lcd_backdrop = NULL; static long lcd_backdrop_offset IDATA_ATTR = 0; +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t lcd_framebuffer_default = +{ + .fb_ptr = &lcd_static_framebuffer[0][0], + .get_address_fn = &lcd_frameaddress_default, + .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT), + .elems = (LCD_FBWIDTH*LCD_FBHEIGHT), +}; + static struct viewport default_vp = { .x = 0, @@ -59,18 +68,32 @@ static struct viewport default_vp = .height = LCD_HEIGHT, .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, + .buffer = NULL, .fg_pattern = LCD_DEFAULT_FG, .bg_pattern = LCD_DEFAULT_BG }; -static struct viewport* current_vp IBSS_ATTR; +struct viewport* lcd_current_viewport IBSS_ATTR; static unsigned fg_pattern IBSS_ATTR; static unsigned bg_pattern IBSS_ATTR; +static void *lcd_frameaddress_default(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = lcd_current_viewport->buffer; + +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y; +#else + size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x; +#endif + return fb->fb_ptr + element; /*(element % fb->elems);*/ +} + /* LCD init */ void lcd_init(void) { - /* Initialise the viewport */ + /* Initialize the viewport */ lcd_set_viewport(NULL); lcd_clear_display(); @@ -83,34 +106,34 @@ void lcd_init(void) void lcd_set_drawmode(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int lcd_get_drawmode(void) { - return current_vp->drawmode; + return lcd_current_viewport->drawmode; } void lcd_set_foreground(unsigned brightness) { - current_vp->fg_pattern = brightness; + lcd_current_viewport->fg_pattern = brightness; fg_pattern = 0x55 * (~brightness & 3); } unsigned lcd_get_foreground(void) { - return current_vp->fg_pattern; + return lcd_current_viewport->fg_pattern; } void lcd_set_background(unsigned brightness) { - current_vp->bg_pattern = brightness; + lcd_current_viewport->bg_pattern = brightness; bg_pattern = 0x55 * (~brightness & 3); } unsigned lcd_get_background(void) { - return current_vp->bg_pattern; + return lcd_current_viewport->bg_pattern; } void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) @@ -122,27 +145,27 @@ void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) int lcd_getwidth(void) { - return current_vp->width; + return lcd_current_viewport->width; } int lcd_getheight(void) { - return current_vp->height; + return lcd_current_viewport->height; } void lcd_setfont(int newfont) { - current_vp->font = newfont; + lcd_current_viewport->font = newfont; } int lcd_getfont(void) { - return current_vp->font; + return lcd_current_viewport->font; } int lcd_getstringsize(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, lcd_current_viewport->font); } /*** low-level drawing functions ***/ @@ -320,7 +343,7 @@ void lcd_set_backdrop(fb_data* backdrop) lcd_backdrop = backdrop; if (backdrop) { - lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; + lcd_backdrop_offset = (long)backdrop - (long)FBADDR(0,0); lcd_pixelfuncs = lcd_pixelfuncs_backdrop; lcd_blockfuncs = lcd_blockfuncs_backdrop; } @@ -351,16 +374,16 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits) /* Clear the whole display */ void lcd_clear_display(void) { - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - memset(lcd_framebuffer, fg_pattern, FRAMEBUFFER_SIZE); + memset(FBADDR(0,0), fg_pattern, FRAMEBUFFER_SIZE); } else { if (lcd_backdrop) - memcpy(lcd_framebuffer, lcd_backdrop, FRAMEBUFFER_SIZE); + memcpy(FBADDR(0,0), lcd_backdrop, FRAMEBUFFER_SIZE); else - memset(lcd_framebuffer, bg_pattern, FRAMEBUFFER_SIZE); + memset(FBADDR(0,0), bg_pattern, FRAMEBUFFER_SIZE); } lcd_scroll_info.lines = 0; @@ -371,37 +394,39 @@ void lcd_clear_viewport(void) { int lastmode; - if (current_vp == &default_vp) + if (lcd_current_viewport == &default_vp && + default_vp.buffer == &lcd_framebuffer_default) { lcd_clear_display(); } else { - lastmode = current_vp->drawmode; + lastmode = lcd_current_viewport->drawmode; /* Invert the INVERSEVID bit and set basic mode to SOLID */ - current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | + lcd_current_viewport->drawmode = (~lastmode & DRMODE_INVERSEVID) | DRMODE_SOLID; - lcd_fillrect(0, 0, current_vp->width, current_vp->height); + lcd_fillrect(0, 0, lcd_current_viewport->width, lcd_current_viewport->height); - current_vp->drawmode = lastmode; + lcd_current_viewport->drawmode = lastmode; - lcd_scroll_stop_viewport(current_vp); + lcd_scroll_stop_viewport(lcd_current_viewport); } + lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /* Set a single pixel */ void lcd_drawpixel(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); + lcd_pixelfuncs[lcd_current_viewport->drawmode](lcd_current_viewport->x + x, lcd_current_viewport->y + y); } /* Draw a line */ @@ -413,7 +438,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; + lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode]; deltax = abs(x2 - x1); if (deltax == 0) @@ -469,14 +494,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - pfunc(current_vp->x + x, current_vp->y + y); + pfunc(lcd_current_viewport->x + x, lcd_current_viewport->y + y); if (d < 0) { @@ -512,19 +537,19 @@ void lcd_hline(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) + if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || (x1 >= lcd_current_viewport->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= lcd_current_viewport->width) + x2 = lcd_current_viewport->width-1; /* adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += lcd_current_viewport->x; + x2 += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -542,7 +567,7 @@ void lcd_hline(int x1, int x2, int y) width = x2 - x1 + 1; - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x1,y>>2); mask = pixmask[y & 3]; @@ -557,6 +582,7 @@ void lcd_vline(int x, int y1, int y2) { int ny; fb_data *dst; + int stride_dst; unsigned mask, mask_bottom; lcd_blockfunc_type *bfunc; @@ -570,19 +596,19 @@ void lcd_vline(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) + if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || (y1 >= lcd_current_viewport->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= lcd_current_viewport->height) + y2 = lcd_current_viewport->height-1; /* adjust for viewport */ - y1 += current_vp->y; - y2 += current_vp->y; - x += current_vp->x; + y1 += lcd_current_viewport->y; + y2 += lcd_current_viewport->y; + x += lcd_current_viewport->x; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -598,8 +624,9 @@ void lcd_vline(int x, int y1, int y2) y2 = LCD_HEIGHT-1; #endif - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x,y1>>2); + stride_dst = lcd_current_viewport->buffer->stride; ny = y2 - (y1 & ~3); mask = 0xFFu << (2 * (y1 & 3)); mask_bottom = 0xFFu >> (2 * (~ny & 3)); @@ -607,7 +634,7 @@ void lcd_vline(int x, int y1, int y2) for (; ny >= 4; ny -= 4) { bfunc(dst, mask, 0xFFu); - dst += LCD_WIDTH; + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -634,6 +661,7 @@ void lcd_fillrect(int x, int y, int width, int height) { int ny; fb_data *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; unsigned bits = 0; lcd_blockfunc_type *bfunc; @@ -641,8 +669,8 @@ void lcd_fillrect(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) + || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -655,14 +683,14 @@ void lcd_fillrect(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -688,9 +716,9 @@ void lcd_fillrect(int x, int y, int width, int height) height = LCD_HEIGHT - y; #endif - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID) { - if ((current_vp->drawmode & DRMODE_BG) && !lcd_backdrop) + if ((lcd_current_viewport->drawmode & DRMODE_BG) && !lcd_backdrop) { fillopt = true; bits = bg_pattern; @@ -698,14 +726,15 @@ void lcd_fillrect(int x, int y, int width, int height) } else { - if (current_vp->drawmode & DRMODE_FG) + if (lcd_current_viewport->drawmode & DRMODE_FG) { fillopt = true; bits = fg_pattern; } } - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; dst = FBADDR(x,y>>2); + stride_dst = lcd_current_viewport->buffer->stride; ny = height - 1 + (y & 3); mask = 0xFFu << (2 * (y & 3)); mask_bottom = 0xFFu >> (2 * (~ny & 3)); @@ -724,7 +753,7 @@ void lcd_fillrect(int x, int y, int width, int height) while (dst_row < dst_end); } - dst += LCD_WIDTH; + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -758,13 +787,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, { int shift, ny; fb_data *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; lcd_blockfunc_type *bfunc; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || + (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -779,14 +809,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -818,13 +848,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, src_y &= 7; y -= src_y; dst = FBADDR(x,y>>2); + stride_dst = lcd_current_viewport->buffer->stride; shift = y & 3; ny = height - 1 + shift + src_y; mask = 0xFFFFu << (2 * (shift + src_y)); /* Overflowing bits aren't important. */ mask_bottom = 0xFFFFu >> (2 * (~ny & 7)); - bfunc = lcd_blockfuncs[current_vp->drawmode]; + bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode]; if (shift == 0) { @@ -836,7 +867,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, for (; ny >= 8; ny -= 8) { const unsigned char *src_row = src; - fb_data *dst_row = dst + LCD_WIDTH; + fb_data *dst_row = dst + stride_dst; dst_end = dst_row + width; @@ -845,7 +876,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, do { data = *src_row++; - bfunc(dst_row - LCD_WIDTH, dmask1, lcd_dibits[data&0x0F]); + bfunc(dst_row - stride_dst, dmask1, lcd_dibits[data&0x0F]); bfunc(dst_row++, dmask2, lcd_dibits[(data>>4)&0x0F]); } while (dst_row < dst_end); @@ -857,7 +888,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, while (dst_row < dst_end); } src += stride; - dst += 2*LCD_WIDTH; + dst += 2*stride_dst; dmask1 = dmask2 = 0xFFu; } dmask1 &= mask_bottom; @@ -873,7 +904,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, { data = *src++; bfunc(dst, dmask1, lcd_dibits[data&0x0F]); - bfunc((dst++) + LCD_WIDTH, dmask2, lcd_dibits[(data>>4)&0x0F]); + bfunc((dst++) + stride_dst, dmask2, lcd_dibits[(data>>4)&0x0F]); } while (dst < dst_end); } @@ -887,7 +918,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, else { do - bfunc((dst++) + LCD_WIDTH, dmask2, lcd_dibits[((*src++)>>4)&0x0F]); + bfunc((dst++) + stride_dst, dmask2, lcd_dibits[((*src++)>>4)&0x0F]); while (dst < dst_end); } } @@ -909,7 +940,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, { if (mask_col & 0xFFu) bfunc(dst_col, mask_col, lcd_dibits[data&0x0F]); - bfunc(dst_col + LCD_WIDTH, mask_col >> 8, + bfunc(dst_col + stride_dst, mask_col >> 8, lcd_dibits[(data>>4)&0x0F]); mask_col = 0xFFFFu; } @@ -917,7 +948,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, mask_col >>= 16; src_col += stride; - dst_col += 2*LCD_WIDTH; + dst_col += 2*stride_dst; data >>= 8; } data |= *src_col << shift; @@ -925,7 +956,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, if (mask_col & 0xFFu) bfunc(dst_col, mask_col, lcd_dibits[data&0x0F]); if (mask_col & 0xFF00u) - bfunc(dst_col + LCD_WIDTH, mask_col >> 8, + bfunc(dst_col + stride_dst, mask_col >> 8, lcd_dibits[(data>>4)&0x0F]); } while (dst < dst_end); @@ -956,12 +987,13 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, { int shift, ny; fb_data *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) + || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -976,14 +1008,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > lcd_current_viewport->width) + width = lcd_current_viewport->width - x; + if (y + height > lcd_current_viewport->height) + height = lcd_current_viewport->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += lcd_current_viewport->x; + y += lcd_current_viewport->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1010,11 +1042,11 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, if (y + height > LCD_HEIGHT) height = LCD_HEIGHT - y; #endif - src += stride * (src_y >> 2) + src_x; /* move starting point */ src_y &= 3; y -= src_y; dst = FBADDR(x,y>>2); + stride_dst = lcd_current_viewport->buffer->stride; shift = y & 3; ny = height - 1 + shift + src_y; @@ -1038,7 +1070,7 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, while (dst_row < dst_end); } src += stride; - dst += LCD_WIDTH; + dst += stride_dst; mask = 0xFFu; } mask &= mask_bottom; @@ -1077,7 +1109,7 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, mask_col >>= 8; src_col += stride; - dst_col += LCD_WIDTH; + dst_col += stride_dst; data >>= 8; } data |= *src_col << shift; diff --git a/firmware/drivers/lcd-2bit-vi.c b/firmware/drivers/lcd-2bit-vi.c index 0608dfaa46..035e8b6d0d 100644 --- a/firmware/drivers/lcd-2bit-vi.c +++ b/firmware/drivers/lcd-2bit-vi.c @@ -46,17 +46,32 @@ #define MAIN_LCD #endif -/*** globals ***/ +#ifdef MAIN_LCD +#define THIS_STRIDE STRIDE_MAIN +#else +#define THIS_STRIDE STRIDE_REMOTE +#endif -FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; -FBFN(data) *LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; +#define CURRENT_VP LCDFN(current_viewport) +/*** globals ***/ +static FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; +static void *LCDFN(frameaddress_default)(int x, int y); static const FBFN(data) patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000}; static FBFN(data) *backdrop = NULL; static long backdrop_offset IDATA_ATTR = 0; +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t LCDFN(framebuffer_default) = +{ + .FBFN(ptr) = &LCDFN(static_framebuffer)[0][0], + .get_address_fn = &LCDFN(frameaddress_default), + .stride = THIS_STRIDE(LCDM(WIDTH), LCDM(HEIGHT)), + .elems = (LCDM(FBWIDTH)*LCDM(FBHEIGHT)), +}; + static struct viewport default_vp = { .x = 0, @@ -65,19 +80,34 @@ static struct viewport default_vp = .height = LCDM(HEIGHT), .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, + .buffer = NULL, .fg_pattern = LCDM(DEFAULT_FG), .bg_pattern = LCDM(DEFAULT_BG) }; -static struct viewport * current_vp IBSS_ATTR; +struct viewport * CURRENT_VP IBSS_ATTR; static unsigned fg_pattern IBSS_ATTR; static unsigned bg_pattern IBSS_ATTR; +static void *LCDFN(frameaddress_default)(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = CURRENT_VP->buffer; +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCDM(NATIVE_STRIDE)(fb->stride)) + y; +#else + size_t element = (y * LCDM(NATIVE_STRIDE)(fb->stride)) + x; +#endif + return fb->FBFN(ptr) + element;/*(element % fb->elems);*/ +} + /* LCD init */ void LCDFN(init)(void) { + /* Initialize the viewport */ LCDFN(set_viewport)(NULL); + LCDFN(clear_display)(); LCDFN(init_device)(); #ifdef MAIN_LCD @@ -105,34 +135,34 @@ unsigned lcd_remote_color_to_native(unsigned color) void LCDFN(set_drawmode)(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + CURRENT_VP->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int LCDFN(get_drawmode)(void) { - return current_vp->drawmode; + return CURRENT_VP->drawmode; } void LCDFN(set_foreground)(unsigned brightness) { - current_vp->fg_pattern = brightness; + CURRENT_VP->fg_pattern = brightness; fg_pattern = patterns[brightness & 3]; } unsigned LCDFN(get_foreground)(void) { - return current_vp->fg_pattern; + return CURRENT_VP->fg_pattern; } void LCDFN(set_background)(unsigned brightness) { - current_vp->bg_pattern = brightness; + CURRENT_VP->bg_pattern = brightness; bg_pattern = patterns[brightness & 3]; } unsigned LCDFN(get_background)(void) { - return current_vp->bg_pattern; + return CURRENT_VP->bg_pattern; } void LCDFN(set_drawinfo)(int mode, unsigned fg_brightness, @@ -145,26 +175,26 @@ void LCDFN(set_drawinfo)(int mode, unsigned fg_brightness, int LCDFN(getwidth)(void) { - return current_vp->width; + return CURRENT_VP->width; } int LCDFN(getheight)(void) { - return current_vp->height; + return CURRENT_VP->height; } void LCDFN(setfont)(int newfont) { - current_vp->font = newfont; + CURRENT_VP->font = newfont; } int LCDFN(getfont)(void) { - return current_vp->font; + return CURRENT_VP->font; } int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, CURRENT_VP->font); } /*** low-level drawing functions ***/ @@ -345,7 +375,7 @@ void LCDFN(set_backdrop)(FBFN(data) *bd) backdrop = bd; if (bd) { - backdrop_offset = (long)bd - (long)LCDFN(framebuffer); + backdrop_offset = (long)bd - (long)LCDFB(0, 0); LCDFN(pixelfuncs) = LCDFN(pixelfuncs_backdrop); LCDFN(blockfuncs) = LCDFN(blockfuncs_backdrop); } @@ -377,15 +407,15 @@ void LCDFN(clear_display)(void) { if (default_vp.drawmode & DRMODE_INVERSEVID) { - memset(LCDFN(framebuffer), patterns[default_vp.fg_pattern & 3], + memset(LCDFB(0, 0), patterns[default_vp.fg_pattern & 3], FBSIZE); } else { if (backdrop) - memcpy(LCDFN(framebuffer), backdrop, FBSIZE); + memcpy(LCDFB(0, 0), backdrop, FBSIZE); else - memset(LCDFN(framebuffer), patterns[default_vp.bg_pattern & 3], + memset(LCDFB(0, 0), patterns[default_vp.bg_pattern & 3], FBSIZE); } @@ -397,37 +427,39 @@ void LCDFN(clear_viewport)(void) { int lastmode; - if (current_vp == &default_vp) + if (CURRENT_VP == &default_vp && + default_vp.buffer == &LCDFN(framebuffer_default)) { LCDFN(clear_display)(); } else { - lastmode = current_vp->drawmode; + lastmode = CURRENT_VP->drawmode; /* Invert the INVERSEVID bit and set basic mode to SOLID */ - current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | + CURRENT_VP->drawmode = (~lastmode & DRMODE_INVERSEVID) | DRMODE_SOLID; - LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); + LCDFN(fillrect)(0, 0, CURRENT_VP->width, CURRENT_VP->height); - current_vp->drawmode = lastmode; + CURRENT_VP->drawmode = lastmode; - LCDFN(scroll_stop_viewport)(current_vp); + LCDFN(scroll_stop_viewport)(CURRENT_VP); } + CURRENT_VP->flags &= ~(VP_FLAG_VP_SET_CLEAN); } /* Set a single pixel */ void LCDFN(drawpixel)(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)CURRENT_VP->width) + && ((unsigned)y < (unsigned)CURRENT_VP->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCDM(WIDTH)) && ((unsigned)y < (unsigned)LCDM(HEIGHT)) #endif ) - LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x+x, current_vp->y+y); + LCDFN(pixelfuncs)[CURRENT_VP->drawmode](CURRENT_VP->x+x, CURRENT_VP->y+y); } /* Draw a line */ @@ -439,7 +471,7 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[current_vp->drawmode]; + LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode]; deltax = abs(x2 - x1); if (deltax == 0) @@ -495,14 +527,14 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)CURRENT_VP->width) + && ((unsigned)y < (unsigned)CURRENT_VP->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCDM(WIDTH)) && ((unsigned)y < (unsigned)LCDM(HEIGHT)) #endif ) - pfunc(current_vp->x + x, current_vp->y + y); + pfunc(CURRENT_VP->x + x, CURRENT_VP->y + y); if (d < 0) { @@ -538,19 +570,19 @@ void LCDFN(hline)(int x1, int x2, int y) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) + if (((unsigned)y >= (unsigned)CURRENT_VP->height) || (x1 >= CURRENT_VP->width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; - if (x2 >= current_vp->width) - x2 = current_vp->width-1; + if (x2 >= CURRENT_VP->width) + x2 = CURRENT_VP->width-1; /* adjust x1 and y to viewport */ - x1 += current_vp->x; - x2 += current_vp->x; - y += current_vp->y; + x1 += CURRENT_VP->x; + x2 += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -568,7 +600,7 @@ void LCDFN(hline)(int x1, int x2, int y) width = x2 - x1 + 1; - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x1,y>>3); mask = 0x0101 << (y & 7); @@ -583,6 +615,7 @@ void LCDFN(vline)(int x, int y1, int y2) { int ny; FBFN(data) *dst; + int stride_dst; unsigned mask, mask_bottom; LCDFN(blockfunc_type) *bfunc; @@ -596,19 +629,19 @@ void LCDFN(vline)(int x, int y1, int y2) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) + if (((unsigned)x >= (unsigned)CURRENT_VP->width) || (y1 >= CURRENT_VP->height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; - if (y2 >= current_vp->height) - y2 = current_vp->height-1; + if (y2 >= CURRENT_VP->height) + y2 = CURRENT_VP->height-1; /* adjust for viewport */ - y1 += current_vp->y; - y2 += current_vp->y; - x += current_vp->x; + y1 += CURRENT_VP->y; + y2 += CURRENT_VP->y; + x += CURRENT_VP->x; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -624,8 +657,9 @@ void LCDFN(vline)(int x, int y1, int y2) y2 = LCDM(HEIGHT)-1; #endif - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x,y1>>3); + stride_dst = CURRENT_VP->buffer->stride; ny = y2 - (y1 & ~7); mask = (0xFFu << (y1 & 7)) & 0xFFu; mask |= mask << 8; @@ -635,7 +669,7 @@ void LCDFN(vline)(int x, int y1, int y2) for (; ny >= 8; ny -= 8) { bfunc(dst, mask, 0xFFFFu); - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFFFu; } mask &= mask_bottom; @@ -662,6 +696,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height) { int ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; unsigned bits = 0; LCDFN(blockfunc_type) *bfunc; @@ -669,8 +704,8 @@ void LCDFN(fillrect)(int x, int y, int width, int height) /******************** In viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) + || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -683,14 +718,14 @@ void LCDFN(fillrect)(int x, int y, int width, int height) height += y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -717,9 +752,9 @@ void LCDFN(fillrect)(int x, int y, int width, int height) #endif - if (current_vp->drawmode & DRMODE_INVERSEVID) + if (CURRENT_VP->drawmode & DRMODE_INVERSEVID) { - if ((current_vp->drawmode & DRMODE_BG) && !backdrop) + if ((CURRENT_VP->drawmode & DRMODE_BG) && !backdrop) { fillopt = true; bits = bg_pattern; @@ -727,14 +762,15 @@ void LCDFN(fillrect)(int x, int y, int width, int height) } else { - if (current_vp->drawmode & DRMODE_FG) + if (CURRENT_VP->drawmode & DRMODE_FG) { fillopt = true; bits = fg_pattern; } } - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; dst = LCDFB(x,y>>3); + stride_dst = CURRENT_VP->buffer->stride; ny = height - 1 + (y & 7); mask = (0xFFu << (y & 7)) & 0xFFu; mask |= mask << 8; @@ -755,7 +791,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height) while (dst_row < dst_end); } - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFFFu; } mask &= mask_bottom; @@ -789,13 +825,14 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, { int shift, ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned data, mask, mask_bottom; LCDFN(blockfunc_type) *bfunc; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || - (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) || + (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -810,14 +847,14 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -849,10 +886,11 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, src_y &= 7; y -= src_y; dst = LCDFB(x,y>>3); + stride_dst = CURRENT_VP->buffer->stride; shift = y & 7; ny = height - 1 + shift + src_y; - bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; + bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode]; mask = 0xFFu << (shift + src_y); /* not byte-doubled here because shift+src_y can be > 7 */ mask_bottom = 0xFFu >> (~ny & 7); @@ -877,7 +915,7 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, while (dst_row < dst_end); src += stride; - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFFFu; } mask &= mask_bottom; @@ -921,7 +959,7 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x, } src_col += stride; - dst_col += LCDM(WIDTH); + dst_col += stride_dst; data >>= 8; } data |= *src_col << shift; @@ -958,12 +996,13 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, { int shift, ny; FBFN(data) *dst, *dst_end; + int stride_dst; unsigned mask, mask_bottom; /******************** Image in viewport clipping **********************/ /* nothing to draw? */ - if ((width <= 0) || (height <= 0) || (x >= current_vp->width) - || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) + if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) + || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0)) return; if (x < 0) @@ -978,14 +1017,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, src_y -= y; y = 0; } - if (x + width > current_vp->width) - width = current_vp->width - x; - if (y + height > current_vp->height) - height = current_vp->height - y; + if (x + width > CURRENT_VP->width) + width = CURRENT_VP->width - x; + if (y + height > CURRENT_VP->height) + height = CURRENT_VP->height - y; /* adjust for viewport */ - x += current_vp->x; - y += current_vp->y; + x += CURRENT_VP->x; + y += CURRENT_VP->y; #if defined(HAVE_VIEWPORT_CLIP) /********************* Viewport on screen clipping ********************/ @@ -1017,6 +1056,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, src_y &= 7; y -= src_y; dst = LCDFB(x,y>>3); + stride_dst = CURRENT_VP->buffer->stride; shift = y & 7; ny = height - 1 + shift + src_y; @@ -1045,7 +1085,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, while (dst_row < dst_end); } src += stride; - dst += LCDM(WIDTH); + dst += stride_dst; mask = 0xFFFFu; } mask &= mask_bottom; @@ -1092,7 +1132,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x, mask_col |= mask_col << 8; } src_col += stride; - dst_col += LCDM(WIDTH); + dst_col += stride_dst; olddata = data >> 8; } data = *src_col << shift; diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index 8c38e513c6..94829b5d0c 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c @@ -40,43 +40,70 @@ #define MAIN_LCD #endif -void LCDFN(set_framebuffer)(FBFN(data) *fb) -{ - if (fb) - LCDFN(framebuffer) = fb; - else - LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; -} +#ifdef MAIN_LCD +#define THIS_STRIDE STRIDE_MAIN +#else +#define THIS_STRIDE STRIDE_REMOTE +#endif +extern void viewport_set_buffer(struct viewport *vp, + struct frame_buffer_t *buffer, + const enum screen_type screen); /* viewport.c */ /* * draws the borders of the current viewport **/ void LCDFN(draw_border_viewport)(void) { - LCDFN(drawrect)(0, 0, current_vp->width, current_vp->height); + LCDFN(drawrect)(0, 0, LCDFN(current_viewport)->width, LCDFN(current_viewport)->height); } /* - * fills the rectangle formed by current_vp + * fills the rectangle formed by LCDFN(current_viewport) **/ void LCDFN(fill_viewport)(void) { - LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); + LCDFN(fillrect)(0, 0, LCDFN(current_viewport)->width, LCDFN(current_viewport)->height); } /*** Viewports ***/ - -void LCDFN(set_viewport)(struct viewport* vp) +/* init_viewport Notes: When a viewport is initialized + * if vp->buffer is NULL the default frame_buffer is assigned + * likewise the actual buffer, stride, get_address_fn + * are all filled with values from the default buffer if they are not set + * RETURNS either the viewport you passed or the default viewport if vp == NULL + */ +struct viewport* LCDFN(init_viewport)(struct viewport* vp) { - if (vp == NULL) - current_vp = &default_vp; + struct frame_buffer_t *fb_default = &LCDFN(framebuffer_default); + if (!vp) /* NULL vp grabs default viewport */ + vp = &default_vp; + + /* use defaults if no buffer is provided */ + if (vp->buffer == NULL || vp->buffer->elems == 0) + vp->buffer = fb_default; else - current_vp = vp; + { + if (vp->buffer->stride == 0) + vp->buffer->stride = fb_default->stride; + + if (vp->buffer->data == NULL) + vp->buffer->data = fb_default->data; + + if (vp->buffer->get_address_fn == NULL) + vp->buffer->get_address_fn = fb_default->get_address_fn; + } + return vp; +} +struct viewport* LCDFN(set_viewport_ex)(struct viewport* vp, int flags) +{ + vp = LCDFN(init_viewport)(vp); + struct viewport* last_vp = LCDFN(current_viewport); + LCDFN(current_viewport) = vp; #if LCDM(DEPTH) > 1 - LCDFN(set_foreground)(current_vp->fg_pattern); - LCDFN(set_background)(current_vp->bg_pattern); + LCDFN(set_foreground)(vp->fg_pattern); + LCDFN(set_background)(vp->bg_pattern); #endif #if defined(SIMULATOR) @@ -84,10 +111,11 @@ void LCDFN(set_viewport)(struct viewport* vp) * be considered an error - the viewport will not draw as it might be * expected. */ - if((unsigned) current_vp->x > (unsigned) LCDM(WIDTH) - || (unsigned) current_vp->y > (unsigned) LCDM(HEIGHT) - || current_vp->x + current_vp->width > LCDM(WIDTH) - || current_vp->y + current_vp->height > LCDM(HEIGHT)) + + if((unsigned) vp->x > (unsigned) LCDM(WIDTH) + || (unsigned) vp->y > (unsigned) LCDM(HEIGHT) + || vp->x + vp->width > LCDM(WIDTH) + || vp->y + vp->height > LCDM(HEIGHT)) { #if !defined(HAVE_VIEWPORT_CLIP) DEBUGF("ERROR: " @@ -95,27 +123,68 @@ void LCDFN(set_viewport)(struct viewport* vp) DEBUGF("NOTE: " #endif "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", - current_vp->x, current_vp->y, - current_vp->width, current_vp->height); + vp->x, vp->y, vp->width, vp->height); } #endif + if(last_vp) + { + if ((flags & VP_FLAG_CLEAR_FLAG) == VP_FLAG_CLEAR_FLAG) + last_vp->flags &= ~flags; + else + last_vp->flags |= flags; + } + + return last_vp; +} + +struct viewport* LCDFN(set_viewport)(struct viewport* vp) +{ + return LCDFN(set_viewport_ex)(vp, VP_FLAG_VP_DIRTY); } struct viewport *LCDFN(get_viewport)(bool *is_default) { - *is_default = (current_vp == &default_vp); - return current_vp; +#if 0 + *is_default = memcmp(LCDFN(current_viewport), + &default_vp, sizeof(struct viewport)) == 0; +#else + *is_default = LCDFN(current_viewport) == &default_vp; +#endif + + return LCDFN(current_viewport); } void LCDFN(update_viewport)(void) { - LCDFN(update_rect)(current_vp->x, current_vp->y, - current_vp->width, current_vp->height); + struct viewport* vp = LCDFN(current_viewport); + if (vp->buffer->stride != LCDFN(framebuffer_default.stride)) + { + LCDFN(update_viewport_rect)(0,0, vp->width, vp->height); + return; + } + LCDFN(update_rect)(vp->x, vp->y, vp->width, vp->height); } void LCDFN(update_viewport_rect)(int x, int y, int width, int height) { - LCDFN(update_rect)(current_vp->x + x, current_vp->y + y, width, height); + struct viewport* vp = LCDFN(current_viewport); + + /* handle the case of viewport with differing stride from main screen */ + if (vp->buffer->stride != LCDFN(framebuffer_default.stride)) + { + struct frame_buffer_t *fb = vp->buffer; + viewport_set_buffer(vp, NULL, 0); + + LCDFN(bitmap_part) + (fb->FBFN(ptr), vp->x, vp->y, fb->stride, + vp->x + x, vp->y + y, width, height); + + LCDFN(update_rect)(vp->x + x, vp->y + y, width, height); + viewport_set_buffer(vp, fb, 0); + return; + } + + LCDFN(update_rect)(vp->x + x, vp->y + y, width, height); } #ifndef BOOTLOADER @@ -123,9 +192,9 @@ void LCDFN(update_viewport_rect)(int x, int y, int width, int height) static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) { unsigned short *ucs; - font_lock(current_vp->font, true); - struct font* pf = font_get(current_vp->font); - int vp_flags = current_vp->flags; + font_lock(LCDFN(current_viewport)->font, true); + struct font* pf = font_get(LCDFN(current_viewport)->font); + int vp_flags = LCDFN(current_viewport)->flags; int rtl_next_non_diac_width, last_non_diacritic_width; if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0) @@ -136,13 +205,13 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) /* center takes precedence */ if (vp_flags & VP_FLAG_ALIGN_CENTER) { - x = ((current_vp->width - w)/ 2) + x; + x = ((LCDFN(current_viewport)->width - w)/ 2) + x; if (x < 0) x = 0; } else { - x = current_vp->width - w - x; + x = LCDFN(current_viewport)->width - w - x; x += ofs; ofs = 0; } @@ -158,7 +227,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) int width, base_width, drawmode = 0, base_ofs = 0; const unsigned short next_ch = ucs[1]; - if (x >= current_vp->width) + if (x >= LCDFN(current_viewport)->width) break; is_diac = is_diacritic(*ucs, &is_rtl); @@ -219,8 +288,8 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) * buffer using OR, and then draw the final bitmap instead of the * chars, without touching the drawmode **/ - drawmode = current_vp->drawmode; - current_vp->drawmode = DRMODE_FG; + drawmode = LCDFN(current_viewport)->drawmode; + LCDFN(current_viewport)->drawmode = DRMODE_FG; base_ofs = (base_width - width) / 2; } @@ -237,7 +306,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) y, width - ofs, pf->height); if (is_diac) { - current_vp->drawmode = drawmode; + LCDFN(current_viewport)->drawmode = drawmode; } if (next_ch) @@ -256,7 +325,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) } } } - font_lock(current_vp->font, false); + font_lock(LCDFN(current_viewport)->font, false); } #else /* BOOTLOADER */ /* put a string at a given pixel position, skipping first ofs pixel columns */ @@ -375,7 +444,7 @@ static struct scrollinfo* find_scrolling_line(int x, int y) for(i=0; ix == x && s->y == y && s->vp == current_vp) + if (s->x == x && s->y == y && s->vp == LCDFN(current_viewport)) return s; } return NULL; @@ -411,13 +480,13 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, /* prepare rectangle for scrolling. x and y must be calculated early * for find_scrolling_line() to work */ - cwidth = font_get(current_vp->font)->maxwidth; - height = font_get(current_vp->font)->height; + cwidth = font_get(LCDFN(current_viewport)->font)->maxwidth; + height = font_get(LCDFN(current_viewport)->font)->height; y = y * (linebased ? height : 1); x = x * (linebased ? cwidth : 1); - width = current_vp->width - x; + width = LCDFN(current_viewport)->width - x; - if (y >= current_vp->height) + if (y >= LCDFN(current_viewport)->height) return false; s = find_scrolling_line(x, y); @@ -430,7 +499,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, * the string width is too small to scroll the scrolling line is * cleared as well */ if (w < width || restart) { - LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height); + LCDFN(scroll_stop_viewport_rect)(LCDFN(current_viewport), x, y, width, height); LCDFN(putsxyofs)(x, y, x_offset, string); /* nothing to scroll, or out of scrolling lines. Either way, get out */ if (w < width || LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) @@ -443,7 +512,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, strlcpy(s->linebuffer, string, sizeof(s->linebuffer)); /* scroll bidirectional or forward only depending on the string width */ if ( LCDFN(scroll_info).bidir_limit ) { - s->bidir = w < (current_vp->width) * + s->bidir = w < (LCDFN(current_viewport)->width) * (100 + LCDFN(scroll_info).bidir_limit) / 100; } else @@ -457,7 +526,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, s->y = y; s->width = width; s->height = height; - s->vp = current_vp; + s->vp = LCDFN(current_viewport); s->start_tick = current_tick + LCDFN(scroll_info).delay; LCDFN(scroll_info).lines++; } else { @@ -497,11 +566,6 @@ bool LCDFN(puts_scroll)(int x, int y, const unsigned char *string) #if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD) /* see lcd-16bit-common.c for others */ -#ifdef MAIN_LCD -#define THIS_STRIDE STRIDE_MAIN -#else -#define THIS_STRIDE STRIDE_REMOTE -#endif void LCDFN(bmp_part)(const struct bitmap* bm, int src_x, int src_y, int x, int y, int width, int height) diff --git a/firmware/drivers/lcd-color-common.c b/firmware/drivers/lcd-color-common.c index c8bfd2d6b3..60e95a25ca 100644 --- a/firmware/drivers/lcd-color-common.c +++ b/firmware/drivers/lcd-color-common.c @@ -36,13 +36,23 @@ enum fill_opt { }; /*** globals ***/ -fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] +static fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16); -fb_data *lcd_framebuffer = &lcd_static_framebuffer[0][0]; + +static void *lcd_frameaddress_default(int x, int y); static fb_data* lcd_backdrop = NULL; static long lcd_backdrop_offset IDATA_ATTR = 0; +/* shouldn't be changed unless you want system-wide framebuffer changes! */ +struct frame_buffer_t lcd_framebuffer_default = +{ + .fb_ptr = &lcd_static_framebuffer[0][0], + .get_address_fn = &lcd_frameaddress_default, + .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT), + .elems = (LCD_FBWIDTH*LCD_FBHEIGHT), +}; + static struct viewport default_vp = { .x = 0, @@ -51,15 +61,32 @@ static struct viewport default_vp = .height = LCD_HEIGHT, .font = FONT_SYSFIXED, .drawmode = DRMODE_SOLID, - .fg_pattern = LCD_DEFAULT_FG, - .bg_pattern = LCD_DEFAULT_BG, + .buffer = NULL, + .fg_pattern = LCD_DEFAULT_FG, + .bg_pattern = LCD_DEFAULT_BG, }; -static struct viewport* current_vp IDATA_ATTR = &default_vp; +struct viewport* lcd_current_viewport IDATA_ATTR; + +static void *lcd_frameaddress_default(int x, int y) +{ + /* the default expects a buffer the same size as the screen */ + struct frame_buffer_t *fb = lcd_current_viewport->buffer; + +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE + size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y; +#else + size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x; +#endif + return fb->fb_ptr + element;/*(element % fb->elems);*/ +} /* LCD init */ void lcd_init(void) { + /* Initialize the viewport */ + lcd_set_viewport(NULL); + lcd_clear_display(); /* Call device specific init */ @@ -70,77 +97,77 @@ void lcd_init(void) /* Clear the whole display */ void lcd_clear_display(void) { - struct viewport* old_vp = current_vp; + struct viewport* old_vp = lcd_current_viewport; - current_vp = &default_vp; + lcd_current_viewport = &default_vp; lcd_clear_viewport(); - current_vp = old_vp; + lcd_current_viewport = old_vp; } /*** parameter handling ***/ void lcd_set_drawmode(int mode) { - current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); + lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); } int lcd_get_drawmode(void) { - return current_vp->drawmode; + return lcd_current_viewport->drawmode; } void lcd_set_foreground(unsigned color) { - current_vp->fg_pattern = color; + lcd_current_viewport->fg_pattern = color; } unsigned lcd_get_foreground(void) { - return current_vp->fg_pattern; + return lcd_current_viewport->fg_pattern; } void lcd_set_background(unsigned color) { - current_vp->bg_pattern = color; + lcd_current_viewport->bg_pattern = color; } unsigned lcd_get_background(void) { - return current_vp->bg_pattern; + return lcd_current_viewport->bg_pattern; } void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color) { lcd_set_drawmode(mode); - current_vp->fg_pattern = fg_color; - current_vp->bg_pattern = bg_color; + lcd_current_viewport->fg_pattern = fg_color; + lcd_current_viewport->bg_pattern = bg_color; } int lcd_getwidth(void) { - return current_vp->width; + return lcd_current_viewport->width; } int lcd_getheight(void) { - return current_vp->height; + return lcd_current_viewport->height; } void lcd_setfont(int newfont) { - current_vp->font = newfont; + lcd_current_viewport->font = newfont; } int lcd_getfont(void) { - return current_vp->font; + return lcd_current_viewport->font; } int lcd_getstringsize(const unsigned char *str, int *w, int *h) { - return font_getstringsize(str, w, h, current_vp->font); + return font_getstringsize(str, w, h, lcd_current_viewport->font); } void lcd_set_backdrop(fb_data* backdrop) @@ -148,7 +175,7 @@ void lcd_set_backdrop(fb_data* backdrop) lcd_backdrop = backdrop; if (backdrop) { - lcd_backdrop_offset = (intptr_t)backdrop - (intptr_t)lcd_framebuffer; + lcd_backdrop_offset = (intptr_t)backdrop - (intptr_t)FBADDR(0,0); lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop; } else @@ -166,14 +193,14 @@ fb_data* lcd_get_backdrop(void) /* Set a single pixel */ void lcd_drawpixel(int x, int y) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - lcd_fastpixelfuncs[current_vp->drawmode](FBADDR(current_vp->x+x, current_vp->y+y)); + lcd_fastpixelfuncs[lcd_current_viewport->drawmode](FBADDR(lcd_current_viewport->x+x, lcd_current_viewport->y+y)); } /* Draw a line */ @@ -185,7 +212,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) int d, dinc1, dinc2; int x, xinc1, xinc2; int y, yinc1, yinc2; - lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; + lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode]; deltay = abs(y2 - y1); if (deltay == 0) @@ -241,14 +268,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2) for (i = 0; i < numpixels; i++) { - if ( ((unsigned)x < (unsigned)current_vp->width) - && ((unsigned)y < (unsigned)current_vp->height) + if ( ((unsigned)x < (unsigned)lcd_current_viewport->width) + && ((unsigned)y < (unsigned)lcd_current_viewport->height) #if defined(HAVE_VIEWPORT_CLIP) && ((unsigned)x < (unsigned)LCD_WIDTH) && ((unsigned)y < (unsigned)LCD_HEIGHT) #endif ) - pfunc(FBADDR(x + current_vp->x, y + current_vp->y)); + pfunc(FBADDR(x + lcd_current_viewport->x, y + lcd_current_viewport->y)); if (d < 0) { @@ -307,9 +334,9 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x, void ICODE_ATTR lcd_bmp_part(const struct bitmap* bm, int src_x, int src_y, int x, int y, int width, int height) { - int bitmap_stride = STRIDE_MAIN(bm->width, bm->height); + int bitmap_stride = LCD_FBSTRIDE(bm->width, bm->height); if (bm->format == FORMAT_MONO) - lcd_mono_bitmap_part(bm->data, src_x, src_y, bitmap_stride, x, y, width, height); + lcd_mono_bitmap_part(bm->data, src_x, src_y, bm->width, x, y, width, height); else if (bm->alpha_offset > 0) lcd_alpha_bitmap_part_mix((fb_data*)bm->data, bm->data+bm->alpha_offset, src_x, src_y, x, y, width, height, @@ -554,7 +581,7 @@ void lcd_blit_yuv(unsigned char * const src[3], void lcd_gradient_fillrect_part(int x, int y, int width, int height, unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip) { - int old_pattern = current_vp->fg_pattern; + int old_pattern = lcd_current_viewport->fg_pattern; int step_mul, i; int x1, x2; x1 = x; @@ -581,14 +608,14 @@ void lcd_gradient_fillrect_part(int x, int y, int width, int height, } for(i = y; i < y + height; i++) { - current_vp->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); + lcd_current_viewport->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); lcd_hline(x1, x2, i); h_r -= rstep; h_g -= gstep; h_b -= bstep; } - current_vp->fg_pattern = old_pattern; + lcd_current_viewport->fg_pattern = old_pattern; } /* Fill a rectangle with a gradient. The gradient's color will fade from diff --git a/firmware/drivers/lcd-scroll.c b/firmware/drivers/lcd-scroll.c index 5d66788093..d8bfd72dde 100644 --- a/firmware/drivers/lcd-scroll.c +++ b/firmware/drivers/lcd-scroll.c @@ -156,8 +156,9 @@ bool LCDFN(scroll_now)(struct scrollinfo *s) } } - /* Stash and restore these three, so that the scroll_func + /* Stash and restore these four, so that the scroll_func * can do whatever it likes without destroying the state */ + struct frame_buffer_t *framebuf = s->vp->buffer; unsigned drawmode; #if LCD_DEPTH > 1 unsigned fg_pattern, bg_pattern; @@ -174,6 +175,7 @@ bool LCDFN(scroll_now)(struct scrollinfo *s) s->vp->bg_pattern = bg_pattern; #endif s->vp->drawmode = drawmode; + s->vp->buffer = framebuf; return ended; } @@ -205,7 +207,7 @@ static void LCDFN(scroll_worker)(void) * be switched early so that lcd_getstringsize() picks the * correct font */ vp = LCDFN(get_viewport)(&is_default); - LCDFN(set_viewport)(s->vp); + LCDFN(set_viewport_ex)(s->vp, 0); /* don't mark the last vp as dirty */ makedelay = false; step = si->step; @@ -218,7 +220,7 @@ static void LCDFN(scroll_worker)(void) /* put the line onto the display now */ makedelay = LCDFN(scroll_now(s)); - LCDFN(set_viewport)(vp); + LCDFN(set_viewport_ex)(vp, 0); /* don't mark the last vp as dirty */ if (makedelay) s->start_tick += si->delay + si->ticks; diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h index 1819a4de72..030b01c736 100644 --- a/firmware/export/lcd-remote.h +++ b/firmware/export/lcd-remote.h @@ -34,29 +34,12 @@ #define REMOTETYPE_H100_LCD 1 #define REMOTETYPE_H300_LCD 2 #define REMOTETYPE_H300_NONLCD 3 -int remote_type(void); -#endif - -#if LCD_REMOTE_DEPTH <= 8 -#if (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) \ - || (LCD_REMOTE_PIXELFORMAT == HORIZONTAL_INTERLEAVED) -typedef unsigned short fb_remote_data; -#define FB_RDATA_SZ 2 -#else -typedef unsigned char fb_remote_data; -#define FB_RDATA_SZ 1 -#endif -#elif LCD_DEPTH <= 16 -typedef unsigned short fb_remote_data; -#define FB_RDATA_SZ 2 -#else -typedef unsigned long fb_remote_data; -#define FB_RDATA_SZ 4 + int remote_type(void); #endif #if LCD_REMOTE_DEPTH > 1 /* greyscale - 8 bit max */ #ifdef HAVE_LCD_COLOR -extern unsigned lcd_remote_color_to_native(unsigned color); + extern unsigned lcd_remote_color_to_native(unsigned color); #endif #define LCD_REMOTE_MAX_LEVEL ((1 << LCD_REMOTE_DEPTH) - 1) @@ -77,12 +60,19 @@ extern unsigned lcd_remote_color_to_native(unsigned color); /* Frame buffer dimensions (format checks only cover existing targets!) */ #if LCD_REMOTE_DEPTH == 1 -#define LCD_REMOTE_FBHEIGHT ((LCD_REMOTE_HEIGHT+7)/8) +#define LCD_REMOTE_STRIDE(w, h) (h) +#define LCD_REMOTE_FBSTRIDE(w, h) ((h+7)/8) +#define LCD_REMOTE_FBHEIGHT LCD_REMOTE_FBSTRIDE(LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT) +#define LCD_REMOTE_NBELEMS(w, h) (((w*LCD_REMOTE_FBSTRIDE(w, h)) + h) / sizeof(fb_remote_data)) #elif LCD_REMOTE_DEPTH == 2 #if LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED -#define LCD_REMOTE_FBHEIGHT ((LCD_REMOTE_HEIGHT+7)/8) +#define LCD_REMOTE_STRIDE(w, h) (h) +#define LCD_REMOTE_FBSTRIDE(w, h) ((h+7)/8) +#define LCD_REMOTE_FBHEIGHT LCD_REMOTE_FBSTRIDE(LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT) +#define LCD_REMOTE_NBELEMS(w, h) (((w*LCD_REMOTE_FBSTRIDE(w, h)) + h) / sizeof(fb_remote_data)) #endif #endif /* LCD_REMOTE_DEPTH */ + /* Set defaults if not defined different yet. The defaults apply to both * dimensions for LCD_REMOTE_DEPTH >= 8 */ #ifndef LCD_REMOTE_FBWIDTH @@ -92,11 +82,20 @@ extern unsigned lcd_remote_color_to_native(unsigned color); #define LCD_REMOTE_FBHEIGHT LCD_REMOTE_HEIGHT #endif -/* The actual framebuffer */ -extern fb_remote_data *lcd_remote_framebuffer; -extern fb_remote_data lcd_remote_static_framebuffer[LCD_REMOTE_FBHEIGHT][LCD_REMOTE_FBWIDTH]; -#define FBREMOTEADDR(x, y) (lcd_remote_framebuffer + ((y) * LCD_REMOTE_FBWIDTH) + (x)) -#define FRAMEBUFFER_REMOTE_SIZE (sizeof(lcd_remote_static_framebuffer)) +#ifndef LCD_REMOTE_NBELEMS +/* At this time (2020) known remote screens only have vertical stride */ +#define LCD_REMOTE_NBELEMS(w, h) ((w*STRIDE_REMOTE(w, h)) + h) / sizeof(fb_remote_data)) +#define LCD_REMOTE_STRIDE(w, h) STRIDE_REMOTE(w, h) +#define LCD_REMOTE_FBSTRIDE(w, h) STRIDE_REMOTE(w, h) +#endif + +#ifndef LCD_REMOTE_NATIVE_STRIDE +#define LCD_REMOTE_NATIVE_STRIDE(s) (s) +#endif + +extern struct viewport* lcd_remote_current_viewport; +#define FBREMOTEADDR(x,y) (fb_remote_data *)(lcd_remote_current_viewport->buffer->get_address_fn(x, y)) +#define FRAMEBUFFER_REMOTE_SIZE (sizeof(fb_remote_data)*LCD_REMOTE_FBWIDTH*LCD_REMOTE_FBHEIGHT) #if LCD_REMOTE_DEPTH > 1 extern void lcd_remote_set_foreground(unsigned foreground); @@ -112,13 +111,13 @@ extern void lcd_remote_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, int stride, int x, int y, int width, int height); extern void lcd_remote_mono_bitmap(const unsigned char *src, int x, int y, - int width, int height); + int width, int height); extern void lcd_remote_bitmap_transparent_part(const fb_remote_data *src, int src_x, int src_y, int stride, int x, int y, int width, int height); extern void lcd_bitmap_remote_transparent(const fb_remote_data *src, int x, - int y, int width, int height); + int y, int width, int height); #else /* LCD_REMOTE_DEPTH == 1 */ #define lcd_remote_mono_bitmap lcd_remote_bitmap #define lcd_remote_mono_bitmap_part lcd_remote_bitmap_part @@ -137,7 +136,7 @@ extern void lcd_remote_bitmap_part(const fb_remote_data *src, int src_x, extern void lcd_remote_bitmap(const fb_remote_data *src, int x, int y, int width, int height); extern void lcd_remote_nine_segment_bmp(const struct bitmap* bm, int x, int y, - int width, int height); + int width, int height); /* Low-level drawing function types */ typedef void lcd_remote_pixelfunc_type(int x, int y); @@ -146,17 +145,17 @@ typedef void lcd_remote_blockfunc_type(fb_remote_data *address, unsigned mask, /* low level drawing function pointer arrays */ #if LCD_REMOTE_DEPTH > 1 -extern lcd_remote_pixelfunc_type* const *lcd_remote_pixelfuncs; -extern lcd_remote_blockfunc_type* const *lcd_remote_blockfuncs; + extern lcd_remote_pixelfunc_type* const *lcd_remote_pixelfuncs; + extern lcd_remote_blockfunc_type* const *lcd_remote_blockfuncs; #else -extern lcd_remote_pixelfunc_type* const lcd_remote_pixelfuncs[8]; -extern lcd_remote_blockfunc_type* const lcd_remote_blockfuncs[8]; + extern lcd_remote_pixelfunc_type* const lcd_remote_pixelfuncs[8]; + extern lcd_remote_blockfunc_type* const lcd_remote_blockfuncs[8]; #endif #endif /* HAVE_LCD_REMOTE */ #ifdef HAVE_REMOTE_LCD_TICKING -void lcd_remote_emireduce(bool state); + void lcd_remote_emireduce(bool state); #endif void lcd_remote_init_device(void); @@ -170,7 +169,10 @@ extern void lcd_remote_init(void); extern int lcd_remote_default_contrast(void); extern void lcd_remote_set_contrast(int val); -extern void lcd_remote_set_viewport(struct viewport* vp); +extern struct viewport* lcd_remote_init_viewport(struct viewport* vp); +extern struct viewport* lcd_remote_set_viewport(struct viewport* vp); +extern struct viewport* lcd_remote_set_viewport_ex(struct viewport* vp, int flags); + extern void lcd_remote_clear_display(void); extern void lcd_remote_clear_viewport(void); extern void lcd_remote_puts(int x, int y, const unsigned char *str); @@ -212,7 +214,7 @@ extern void lcd_remote_bidir_scroll(int threshold); extern void lcd_remote_scroll_step(int pixels); extern void lcd_remote_bmp_part(const struct bitmap* bm, int src_x, int src_y, - int x, int y, int width, int height); + int x, int y, int width, int height); extern void lcd_remote_bmp(const struct bitmap* bm, int x, int y); #endif /* __LCD_REMOTE_H__ */ diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index ae06307dca..af734da913 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -23,30 +23,11 @@ #define __LCD_H__ #include +#include #include "cpu.h" #include "config.h" #include "events.h" -#define VP_FLAG_ALIGN_RIGHT 0x01 -#define VP_FLAG_ALIGN_CENTER 0x02 - -#define VP_FLAG_ALIGNMENT_MASK \ - (VP_FLAG_ALIGN_RIGHT|VP_FLAG_ALIGN_CENTER) - -#define VP_IS_RTL(vp) (((vp)->flags & VP_FLAG_ALIGNMENT_MASK) == VP_FLAG_ALIGN_RIGHT) - -struct viewport { - int x; - int y; - int width; - int height; - int flags; - int font; - int drawmode; - /* needed for even for mono displays to support greylib */ - unsigned fg_pattern; - unsigned bg_pattern; -}; /* Frame buffer stride * @@ -101,7 +82,7 @@ enum screen_type { struct scrollinfo; -#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE +#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE #define STRIDE_MAIN(w, h) (h) #else #define STRIDE_MAIN(w, h) (w) @@ -115,46 +96,105 @@ struct scrollinfo; #if LCD_DEPTH <=8 #if (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) \ || (LCD_PIXELFORMAT == HORIZONTAL_INTERLEAVED) -typedef unsigned short fb_data; + typedef unsigned short fb_data; #define FB_DATA_SZ 2 #else -typedef unsigned char fb_data; + typedef unsigned char fb_data; #define FB_DATA_SZ 1 #endif #elif LCD_DEPTH <= 16 -typedef unsigned short fb_data; + typedef unsigned short fb_data; #define FB_DATA_SZ 2 #elif LCD_DEPTH <= 24 -struct _fb_pixel { - unsigned char b, g, r; -}; -typedef struct _fb_pixel fb_data; + struct _fb_pixel { + unsigned char b, g, r; + }; + typedef struct _fb_pixel fb_data; #define FB_DATA_SZ 3 #else /* LCD_DEPTH > 24 */ #if (LCD_PIXELFORMAT == XRGB8888) -struct _fb_pixel { - unsigned char b, g, r, x; -}; -typedef struct _fb_pixel fb_data; + struct _fb_pixel { + unsigned char b, g, r, x; + }; + typedef struct _fb_pixel fb_data; #else -typedef unsigned long fb_data; + typedef unsigned long fb_data; #endif #define FB_DATA_SZ 4 #endif /* LCD_DEPTH */ +#ifdef HAVE_REMOTE_LCD +#if LCD_REMOTE_DEPTH <= 8 +#if (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) \ + || (LCD_REMOTE_PIXELFORMAT == HORIZONTAL_INTERLEAVED) + typedef unsigned short fb_remote_data; +#define FB_RDATA_SZ 2 +#else + typedef unsigned char fb_remote_data; +#define FB_RDATA_SZ 1 +#endif +#elif LCD_DEPTH <= 16 + typedef unsigned short fb_remote_data; +#define FB_RDATA_SZ 2 +#else + typedef unsigned long fb_remote_data; +#define FB_RDATA_SZ 4 +#endif +#endif + #if defined(HAVE_LCD_MODES) -void lcd_set_mode(int mode); + void lcd_set_mode(int mode); #define LCD_MODE_RGB565 0x00000001 #define LCD_MODE_YUV 0x00000002 #define LCD_MODE_PAL256 0x00000004 #if HAVE_LCD_MODES & LCD_MODE_PAL256 - void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, + void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, int width, int height); - void lcd_pal256_update_pal(fb_data *palette); + void lcd_pal256_update_pal(fb_data *palette); #endif #endif +struct frame_buffer_t { + union + { + void *data; + char *ch_ptr; + fb_data *fb_ptr; +#ifdef HAVE_REMOTE_LCD + fb_remote_data *fb_remote_ptr; +#endif + }; + void *(*get_address_fn)(int x, int y); + ptrdiff_t stride; + size_t elems; +}; + +#define VP_FLAG_ALIGN_RIGHT 0x01 +#define VP_FLAG_ALIGN_CENTER 0x02 + +#define VP_FLAG_ALIGNMENT_MASK \ + (VP_FLAG_ALIGN_RIGHT|VP_FLAG_ALIGN_CENTER) + +#define VP_IS_RTL(vp) (((vp)->flags & VP_FLAG_ALIGNMENT_MASK) == VP_FLAG_ALIGN_RIGHT) + +#define VP_FLAG_VP_DIRTY 0x4000 +#define VP_FLAG_CLEAR_FLAG 0x8000 +#define VP_FLAG_VP_SET_CLEAN (VP_FLAG_CLEAR_FLAG | VP_FLAG_VP_DIRTY) + +struct viewport { + int x; + int y; + int width; + int height; + int flags; + int font; + int drawmode; + struct frame_buffer_t *buffer; + /* needed for even for mono displays to support greylib */ + unsigned fg_pattern; + unsigned bg_pattern; +}; /* common functions */ extern void lcd_write_command(int byte); @@ -171,7 +211,10 @@ extern int lcd_getwidth(void); extern int lcd_getheight(void); extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); -extern void lcd_set_viewport(struct viewport* vp); +extern struct viewport* lcd_init_viewport(struct viewport* vp); +extern struct viewport* lcd_set_viewport(struct viewport* vp); +extern struct viewport* lcd_set_viewport_ex(struct viewport* vp, int flags); + extern void lcd_update(void); extern void lcd_update_viewport(void); extern void lcd_update_viewport_rect(int x, int y, int width, int height); @@ -193,15 +236,15 @@ extern bool lcd_putsxy_scroll_func(int x, int y, const unsigned char *string, #if defined(HAVE_LCD_COLOR) #if MEMORYSIZE > 2 #define LCD_YUV_DITHER 0x1 -extern void lcd_yuv_set_options(unsigned options); -extern void lcd_blit_yuv(unsigned char * const src[3], + extern void lcd_yuv_set_options(unsigned options); + extern void lcd_blit_yuv(unsigned char * const src[3], int src_x, int src_y, int stride, int x, int y, int width, int height); #endif /* MEMORYSIZE > 2 */ #else -extern void lcd_blit_mono(const unsigned char *data, int x, int by, int width, + extern void lcd_blit_mono(const unsigned char *data, int x, int by, int width, int bheight, int stride); -extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, + extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, int bx, int by, int bwidth, int bheight, int stride); #endif @@ -211,9 +254,9 @@ extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, extern void lcd_update_rect(int x, int y, int width, int height); #ifdef HAVE_REMOTE_LCD -extern void lcd_remote_update(void); -/* update a fraction of the screen */ -extern void lcd_remote_update_rect(int x, int y, int width, int height); + extern void lcd_remote_update(void); + /* update a fraction of the screen */ + extern void lcd_remote_update_rect(int x, int y, int width, int height); #endif /* HAVE_REMOTE_LCD */ /* Bitmap formats */ @@ -239,13 +282,13 @@ enum typedef void lcd_pixelfunc_type(int x, int y); typedef void lcd_blockfunc_type(fb_data *address, unsigned mask, unsigned bits); #if LCD_DEPTH >= 8 -typedef void lcd_fastpixelfunc_type(fb_data *address); + typedef void lcd_fastpixelfunc_type(fb_data *address); #endif #if defined(HAVE_LCD_COLOR) && defined(LCD_REMOTE_DEPTH) && \ LCD_REMOTE_DEPTH > 1 /* Just return color for screens use */ -static inline unsigned lcd_color_to_native(unsigned color) + static inline unsigned lcd_color_to_native(unsigned color) { return color; } #define SCREEN_COLOR_TO_NATIVE(screen, color) (screen)->color_to_native(color) #else @@ -286,7 +329,7 @@ static inline unsigned lcd_color_to_native(unsigned color) (((b) >> 3) << 8) ) /* swap color once - not currenly used in static inits */ #define _SWAPUNPACK(x, _unp_) \ - ({ typeof (x) _x_ = swap16(x); _unp_(_x_); }) + ({ typeof (x) _x_ = swap16(x); _unp_(_x_); }) #define RGB_UNPACK_RED(x) _SWAPUNPACK((x), _RGB_UNPACK_RED) #define RGB_UNPACK_GREEN(x) _SWAPUNPACK((x), _RGB_UNPACK_GREEN) #define RGB_UNPACK_BLUE(x) _SWAPUNPACK((x), _RGB_UNPACK_BLUE) @@ -374,16 +417,16 @@ static inline unsigned lcd_color_to_native(unsigned color) * format, so it's the reverse of FB_SCALARPACK_LCD */ #if LCD_DEPTH >= 24 -static inline fb_data scalar_to_fb(unsigned p) -{ - union { fb_data st; unsigned sc; } convert; - convert.sc = p; return convert.st; -} -static inline unsigned fb_to_scalar(fb_data p) -{ - union { fb_data st; unsigned sc; } convert; - convert.st = p; return convert.sc; -} + static inline fb_data scalar_to_fb(unsigned p) + { + union { fb_data st; unsigned sc; } convert; + convert.sc = p; return convert.st; + } + static inline unsigned fb_to_scalar(fb_data p) + { + union { fb_data st; unsigned sc; } convert; + convert.st = p; return convert.sc; + } #define FB_RGBPACK(r_, g_, b_) ((fb_data){.r = r_, .g = g_, .b = b_}) #define FB_RGBPACK_LCD(r_, g_, b_) FB_RGBPACK(r_, g_, b_) #define FB_UNPACK_RED(fb) ((fb).r) @@ -411,17 +454,28 @@ static inline unsigned fb_to_scalar(fb_data p) /* Frame buffer dimensions */ #if LCD_DEPTH == 1 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING -#define LCD_FBWIDTH ((LCD_WIDTH+7)/8) +#define LCD_FBSTRIDE(w, h) ((w+7)/8) +#define LCD_FBWIDTH LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((h*LCD_FBSTRIDE(w, h)) + w) / sizeof(fb_data)) #else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ -#define LCD_FBHEIGHT ((LCD_HEIGHT+7)/8) +#define LCD_FBSTRIDE(w, h) ((h+7)/8) +#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data)) #endif /* LCD_PIXELFORMAT */ #elif LCD_DEPTH == 2 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING -#define LCD_FBWIDTH ((LCD_WIDTH+3)/4) +#define LCD_FBSTRIDE(w, h) ((w+3)>>2) +#define LCD_NATIVE_STRIDE(s) LCD_FBSTRIDE(s, s) +#define LCD_FBWIDTH LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((h*LCD_FBSTRIDE(w, h)) + w) / sizeof(fb_data)) #elif LCD_PIXELFORMAT == VERTICAL_PACKING -#define LCD_FBHEIGHT ((LCD_HEIGHT+3)/4) +#define LCD_FBSTRIDE(w, h) ((h+3)/4) +#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data)) #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED -#define LCD_FBHEIGHT ((LCD_HEIGHT+7)/8) +#define LCD_FBSTRIDE(w, h) ((h+7)/8) +#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT) +#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data)) #endif /* LCD_PIXELFORMAT */ #endif /* LCD_DEPTH */ /* Set defaults if not defined different yet. The defaults apply to both @@ -432,13 +486,29 @@ static inline unsigned fb_to_scalar(fb_data p) #ifndef LCD_FBHEIGHT #define LCD_FBHEIGHT LCD_HEIGHT #endif -/* The actual framebuffer */ -extern fb_data *lcd_framebuffer; + +#ifndef LCD_NATIVE_STRIDE +/* 2-bit Horz is the only display that actually defines this */ +#define LCD_NATIVE_STRIDE(s) (s) +#endif + +#ifndef LCD_NBELEMS #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE -#define FBADDR(x, y) (lcd_framebuffer + ((x) * LCD_FBHEIGHT) + (y)) +#define LCD_NBELEMS(w, h) ((w*STRIDE_MAIN(w, h)) + h) #else -#define FBADDR(x, y) (lcd_framebuffer + ((y) * LCD_FBWIDTH) + (x)) +#define LCD_NBELEMS(w, h) ((h*STRIDE_MAIN(w, h)) + w) #endif +#define LCD_FBSTRIDE(w, h) STRIDE_MAIN(w, h) +#endif + +#ifndef LCD_STRIDE + #define LCD_STRIDE(w, h) STRIDE_MAIN(w, h) +#endif + +extern struct viewport* lcd_current_viewport; + +#define FBADDR(x,y) ((fb_data*) lcd_current_viewport->buffer->get_address_fn(x, y)) + #define FRAMEBUFFER_SIZE (sizeof(fb_data)*LCD_FBWIDTH*LCD_FBHEIGHT) /** Port-specific functions. Enable in port config file. **/ @@ -499,7 +569,7 @@ struct bitmap { extern void lcd_set_invert_display(bool yesno); #ifdef HAVE_BACKLIGHT_INVERSION -extern void lcd_set_backlight_inversion(bool yesno); + extern void lcd_set_backlight_inversion(bool yesno); #endif /* HAVE_BACKLIGHT_INVERSION */ extern void lcd_set_flip(bool yesno); @@ -510,13 +580,13 @@ extern int lcd_getfont(void); /* low level drawing function pointer arrays */ #if LCD_DEPTH >= 8 -extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; + extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; #elif LCD_DEPTH > 1 -extern lcd_pixelfunc_type* const *lcd_pixelfuncs; -extern lcd_blockfunc_type* const *lcd_blockfuncs; + extern lcd_pixelfunc_type* const *lcd_pixelfuncs; + extern lcd_blockfunc_type* const *lcd_blockfuncs; #else /* LCD_DEPTH == 1*/ -extern lcd_pixelfunc_type* const lcd_pixelfuncs[8]; -extern lcd_blockfunc_type* const lcd_blockfuncs[8]; + extern lcd_pixelfunc_type* const lcd_pixelfuncs[8]; + extern lcd_blockfunc_type* const lcd_blockfuncs[8]; #endif /* LCD_DEPTH */ extern void lcd_drawpixel(int x, int y); @@ -526,45 +596,44 @@ extern void lcd_vline(int x, int y1, int y2); extern void lcd_drawrect(int x, int y, int width, int height); extern void lcd_fillrect(int x, int y, int width, int height); extern void lcd_gradient_fillrect(int x, int y, int width, int height, - unsigned start_rgb, unsigned end_rgb); + unsigned start_rgb, unsigned end_rgb); extern void lcd_gradient_fillrect_part(int x, int y, int width, int height, - unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip); + unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip); extern void lcd_draw_border_viewport(void); extern void lcd_fill_viewport(void); extern void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, int stride, int x, int y, int width, int height); extern void lcd_bitmap(const fb_data *src, int x, int y, int width, int height); -extern void lcd_set_framebuffer(fb_data *fb); extern void lcd_scroll_step(int pixels); #if LCD_DEPTH > 1 -extern void lcd_set_foreground(unsigned foreground); -extern unsigned lcd_get_foreground(void); -extern void lcd_set_background(unsigned background); -extern unsigned lcd_get_background(void); + extern void lcd_set_foreground(unsigned foreground); + extern unsigned lcd_get_foreground(void); + extern void lcd_set_background(unsigned background); + extern unsigned lcd_get_background(void); #ifdef HAVE_LCD_COLOR -extern void lcd_set_selector_start(unsigned selector); -extern void lcd_set_selector_end(unsigned selector); -extern void lcd_set_selector_text(unsigned selector_text); + extern void lcd_set_selector_start(unsigned selector); + extern void lcd_set_selector_end(unsigned selector); + extern void lcd_set_selector_text(unsigned selector_text); #endif -extern void lcd_set_drawinfo(int mode, unsigned foreground, - unsigned background); -void lcd_set_backdrop(fb_data* backdrop); - -fb_data* lcd_get_backdrop(void); - -extern void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, - int stride, int x, int y, int width, int height); -extern void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, - int height); -extern void lcd_bitmap_transparent_part(const fb_data *src, - int src_x, int src_y, - int stride, int x, int y, int width, - int height); -extern void lcd_bitmap_transparent(const fb_data *src, int x, int y, - int width, int height); + extern void lcd_set_drawinfo(int mode, unsigned foreground, + unsigned background); + void lcd_set_backdrop(fb_data* backdrop); + + fb_data* lcd_get_backdrop(void); + + extern void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height); + extern void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, + int height); + extern void lcd_bitmap_transparent_part(const fb_data *src, + int src_x, int src_y, + int stride, int x, int y, int width, + int height); + extern void lcd_bitmap_transparent(const fb_data *src, int x, int y, + int width, int height); #else /* LCD_DEPTH == 1 */ #define lcd_mono_bitmap lcd_bitmap #define lcd_mono_bitmap_part lcd_bitmap_part @@ -577,10 +646,10 @@ extern void lcd_nine_segment_bmp(const struct bitmap* bm, int x, int y, /* TODO: Impement this for remote displays if ever needed */ #if defined(LCD_DPI) && (LCD_DPI > 0) -/* returns the pixel density of the display */ -static inline int lcd_get_dpi(void) { return LCD_DPI; } + /* returns the pixel density of the display */ + static inline int lcd_get_dpi(void) { return LCD_DPI; } #else -extern int lcd_get_dpi(void); + extern int lcd_get_dpi(void); #endif /* LCD_DPI */ #endif /* __LCD_H__ */ diff --git a/firmware/target/arm/as3525/lcd-fuze.c b/firmware/target/arm/as3525/lcd-fuze.c index df4d668ab0..a1ccea348d 100644 --- a/firmware/target/arm/as3525/lcd-fuze.c +++ b/firmware/target/arm/as3525/lcd-fuze.c @@ -291,7 +291,7 @@ void lcd_update(void) lcd_write_cmd(R_WRITE_DATA_2_GRAM); - dbop_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); + dbop_write_data(FBADDR(0,0), LCD_WIDTH*LCD_HEIGHT); } /* Update a fraction of the display. */ diff --git a/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c index 5f623dc239..9621b532fe 100644 --- a/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c +++ b/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c @@ -251,7 +251,7 @@ void lcd_set_direct_fb(bool yes) unsigned int addr; direct_fb_access = yes; if(yes) - addr = ((unsigned int)&lcd_framebuffer-CONFIG_SDRAM_START) / 32; + addr = ((unsigned int)FBADDR(0,0)-CONFIG_SDRAM_START) / 32; else addr = ((unsigned int)FRAME-CONFIG_SDRAM_START) / 32; IO_OSD_OSDWINADH = addr >> 16; diff --git a/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c index c3a96a3efd..d952d3d40d 100644 --- a/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c +++ b/firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c @@ -489,7 +489,7 @@ void lcd_update_rect(int x, int y, int width, int height) #if CONFIG_ORIENTATION == SCREEN_PORTRAIT #if defined(LCD_USE_DMA) - dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_WIDTH, + dma_start_transfer16( (char *)FBADDR(0,0), x, y, LCD_WIDTH, x, y, width, height, 2); #else register fb_data *dst; @@ -514,7 +514,7 @@ void lcd_update_rect(int x, int y, int width, int height) #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE #if defined(LCD_USE_DMA) - dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_HEIGHT, + dma_start_transfer16( (char *)FBADDR(0,0), x, y, LCD_HEIGHT, x, y, width, height, 2); #else fb_data *src; diff --git a/firmware/target/coldfire/iriver/h300/lcd-h300.c b/firmware/target/coldfire/iriver/h300/lcd-h300.c index 191c769c97..312bd70ccc 100644 --- a/firmware/target/coldfire/iriver/h300/lcd-h300.c +++ b/firmware/target/coldfire/iriver/h300/lcd-h300.c @@ -408,7 +408,7 @@ void lcd_update(void) lcd_begin_write_gram(); dma_count = 1; - SAR3 = (unsigned long)lcd_framebuffer; + SAR3 = (unsigned long)FBADDR(0,0); BCR3 = LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data); DCR3 = DMA_INT | DMA_AA | DMA_BWC(1) | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) diff --git a/firmware/target/coldfire/mpio/hd200/lcd-hd200.c b/firmware/target/coldfire/mpio/hd200/lcd-hd200.c index 3c00959745..967618fce1 100644 --- a/firmware/target/coldfire/mpio/hd200/lcd-hd200.c +++ b/firmware/target/coldfire/mpio/hd200/lcd-hd200.c @@ -218,7 +218,7 @@ void lcd_update(void) dma_len = LCD_WIDTH*2; /* Initialize DMA transfer */ - SAR3 = (unsigned long)lcd_framebuffer; + SAR3 = (unsigned long)FBADDR(0,0); BCR3 = LCD_WIDTH*2; DCR3 = DMA_INT | DMA_AA | DMA_BWC(1) | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c index a161406cc0..12df52c95e 100644 --- a/firmware/target/hosted/android/lcd-android.c +++ b/firmware/target/hosted/android/lcd-android.c @@ -83,7 +83,7 @@ void lcd_update(void) if (display_on) { JNIEnv e = *env_ptr; - jobject buffer = e->NewDirectByteBuffer(env_ptr, lcd_framebuffer, + jobject buffer = e->NewDirectByteBuffer(env_ptr, FBADDR(0,0), (jlong) FRAMEBUFFER_SIZE); e->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, @@ -97,7 +97,7 @@ void lcd_update_rect(int x, int y, int width, int height) if (display_on) { JNIEnv e = *env_ptr; - jobject buffer = e->NewDirectByteBuffer(env_ptr, lcd_framebuffer, + jobject buffer = e->NewDirectByteBuffer(env_ptr, FBADDR(0,0), (jlong) FRAMEBUFFER_SIZE); jobject rect = e->NewObject(env_ptr, AndroidRect_class, AndroidRect_constructor, x, y, x + width, y + height); diff --git a/firmware/target/hosted/sdl/lcd-sdl.c b/firmware/target/hosted/sdl/lcd-sdl.c index 40ba94072b..de19de365a 100644 --- a/firmware/target/hosted/sdl/lcd-sdl.c +++ b/firmware/target/hosted/sdl/lcd-sdl.c @@ -39,7 +39,7 @@ void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width, (void)max_y; (void)getpixel; /* Update complete screen via one blit operation (fast) */ - SDL_Surface *lcd = SDL_CreateRGBSurfaceFrom(lcd_framebuffer, LCD_FBWIDTH, + SDL_Surface *lcd = SDL_CreateRGBSurfaceFrom(FBADDR(0, 0), LCD_FBWIDTH, LCD_FBHEIGHT, LCD_DEPTH, LCD_FBWIDTH * LCD_DEPTH/8, 0, 0, 0, 0); -- cgit v1.2.3