summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2020-10-07 02:01:35 -0400
committerWilliam Wilgus <wilgus.william@gmail.com>2020-10-26 12:28:48 -0400
commit3237ae4a4ff9296a377ff9194a11038da161208f (patch)
treeaf4338c78467b9b0845d76c39da1fbe10f25e23e
parent12f3ed1699d6bef25bed90ba95cbcc1a6bb4934a (diff)
downloadrockbox-3237ae4a4ff9296a377ff9194a11038da161208f.tar.gz
rockbox-3237ae4a4ff9296a377ff9194a11038da161208f.zip
LCD core move buf ptr and address look up function viewport struct
I'm currently running up against the limitations of the lcd_draw functions I want these functions to be able to be used on any size buffer not just buffers with a stride matching the underlying device [DONE] allow the framebuffer to be decoupled from the device framebuffer [DONE need examples] allow for some simple blit like transformations [DONE] remove the device framebuffer from the plugin api [DONE}ditto remote framebuffer [DONE] remove _viewport_get_framebuffer you can call struct *vp = lcd_set_viewport(NULL) and vp->buffer->fb_ptr while remote lcds may compile (and work in the sim) its not been tested on targets [FIXED] backdrops need work to be screen agnostic [FIXED] screen statusbar is not being combined into the main viewport correctly yet [FIXED] screen elements are displayed incorrectly after switch to void* [FIXED] core didn't restore proper viewport on splash etc. [NEEDS TESTING] remote lcd garbled data [FIXED] osd lib garbled screen on bmp_part [FIXED] grey_set_vp needs to return old viewport like lcd_set_viewport [FIXED] Viewport update now handles viewports with differing buffers/strides by copying to the main buffer [FIXED] splash on top of WPS leaves old framebuffer data (doesn't redraw) [UPDATE] refined this a bit more to have clear_viewport set the clean bit and have skin_render do its own screen clear scrolling viewports no longer trigger wps refresh also fixed a bug where guisyncyesno was displaying and then disappearing [ADDED!] New LCD macros that allow you to create properly size frame buffers in you desired size without wasting bytes (LCD_ and LCD_REMOTE_) LCD_STRIDE(w, h) same as STRIDE_MAIN LCD_FBSTRIDE(w, h) returns target specific stride for a buffer W x H LCD_NBELEMS(w, h) returns the number of fb_data sized elemenst needed for a buffer W x H LCD_NATIVE_STRIDE(s) conversion between rockbox native vertical and lcd native stride (2bitH) test_viewports.c has an example of usage [FIXED!!] 2bit targets don't respect non-native strides [FIXED] Few define snags Change-Id: I0d04c3834e464eca84a5a715743a297a0cefd0af
-rw-r--r--apps/alarm_menu.c5
-rw-r--r--apps/gui/bitmap/list.c4
-rw-r--r--apps/gui/color_picker.c8
-rw-r--r--apps/gui/pitchscreen.c5
-rw-r--r--apps/gui/quickscreen.c4
-rw-r--r--apps/gui/skin_engine/skin_backdrops.c25
-rw-r--r--apps/gui/skin_engine/skin_engine.c6
-rw-r--r--apps/gui/skin_engine/skin_engine.h2
-rw-r--r--apps/gui/skin_engine/skin_parser.c8
-rw-r--r--apps/gui/skin_engine/skin_render.c45
-rw-r--r--apps/gui/skin_engine/wps_internals.h1
-rw-r--r--apps/gui/splash.c4
-rw-r--r--apps/gui/statusbar.c5
-rw-r--r--apps/gui/usb_screen.c5
-rw-r--r--apps/gui/viewport.c26
-rw-r--r--apps/gui/viewport.h3
-rw-r--r--apps/gui/yesno.c9
-rw-r--r--apps/menus/time_menu.c4
-rw-r--r--apps/misc.c4
-rw-r--r--apps/onplay.c11
-rw-r--r--apps/plugin.c12
-rw-r--r--apps/plugin.h7
-rw-r--r--apps/plugins/doom/i_video.c10
-rw-r--r--apps/plugins/fire.c5
-rw-r--r--apps/plugins/imageviewer/imageviewer.c11
-rw-r--r--apps/plugins/imageviewer/jpeg/yuv2rgb.c12
-rw-r--r--apps/plugins/invadrox.c12
-rw-r--r--apps/plugins/lib/grey.h2
-rw-r--r--apps/plugins/lib/grey_core.c13
-rw-r--r--apps/plugins/lib/grey_parm.c4
-rw-r--r--apps/plugins/lib/osd.c27
-rw-r--r--apps/plugins/lib/xlcd.h2
-rw-r--r--apps/plugins/lib/xlcd_core.c9
-rw-r--r--apps/plugins/lib/xlcd_draw.c14
-rw-r--r--apps/plugins/lib/xlcd_scroll.c107
-rw-r--r--apps/plugins/lua/rocklib_img.c8
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c12
-rw-r--r--apps/plugins/oscilloscope.c4
-rwxr-xr-xapps/plugins/pacbox/pacbox.c6
-rw-r--r--apps/plugins/pictureflow/pictureflow.c6
-rw-r--r--apps/plugins/plasma.c11
-rw-r--r--apps/plugins/puzzles/rockbox.c17
-rw-r--r--apps/plugins/rockboy/lcd.c15
-rw-r--r--apps/plugins/rockboy/sys_rockbox.c10
-rw-r--r--apps/plugins/sdl/src/video/rockbox/SDL_rockboxvideo.c11
-rw-r--r--apps/plugins/test_resize.c4
-rw-r--r--apps/plugins/test_viewports.c27
-rw-r--r--apps/plugins/xworld/sys.c21
-rw-r--r--apps/plugins/zxbox/zxvid_16bpp.c11
-rw-r--r--apps/plugins/zxbox/zxvid_2bpp.c13
-rw-r--r--apps/recorder/keyboard.c4
-rw-r--r--apps/screen_access.c21
-rw-r--r--apps/screen_access.h7
-rw-r--r--apps/screens.c5
-rw-r--r--firmware/drivers/lcd-16bit-common.c112
-rw-r--r--firmware/drivers/lcd-16bit-vert.c98
-rw-r--r--firmware/drivers/lcd-16bit.c93
-rw-r--r--firmware/drivers/lcd-1bit-vert.c176
-rw-r--r--firmware/drivers/lcd-24bit.c180
-rw-r--r--firmware/drivers/lcd-2bit-horz.c215
-rw-r--r--firmware/drivers/lcd-2bit-vert.c210
-rw-r--r--firmware/drivers/lcd-2bit-vi.c202
-rw-r--r--firmware/drivers/lcd-bitmap-common.c166
-rw-r--r--firmware/drivers/lcd-color-common.c95
-rw-r--r--firmware/drivers/lcd-scroll.c8
-rw-r--r--firmware/export/lcd-remote.h74
-rw-r--r--firmware/export/lcd.h271
-rw-r--r--firmware/target/arm/as3525/lcd-fuze.c2
-rw-r--r--firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c2
-rw-r--r--firmware/target/arm/tms320dm320/mrobe-500/lcd-mr500.c4
-rw-r--r--firmware/target/coldfire/iriver/h300/lcd-h300.c2
-rw-r--r--firmware/target/coldfire/mpio/hd200/lcd-hd200.c2
-rw-r--r--firmware/target/hosted/android/lcd-android.c4
-rw-r--r--firmware/target/hosted/sdl/lcd-sdl.c2
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)
60 bool update = true; 60 bool update = true;
61 bool hour_wrapped = false; 61 bool hour_wrapped = false;
62 struct viewport vp[NB_SCREENS]; 62 struct viewport vp[NB_SCREENS];
63 struct viewport * last_vp;
63 64
64 rtc_get_alarm(&h, &m); 65 rtc_get_alarm(&h, &m);
65 66
@@ -91,11 +92,11 @@ int alarm_screen(void)
91 92
92 FOR_NB_SCREENS(i) 93 FOR_NB_SCREENS(i)
93 { 94 {
94 screens[i].set_viewport(&vp[i]); 95 last_vp = screens[i].set_viewport(&vp[i]);
95 screens[i].putsf(0, 1, str(LANG_ALARM_MOD_TIME)); 96 screens[i].putsf(0, 1, str(LANG_ALARM_MOD_TIME));
96 screens[i].putsf(0, 2, "%02d:%02d", h, m); 97 screens[i].putsf(0, 2, "%02d:%02d", h, m);
97 screens[i].update_viewport(); 98 screens[i].update_viewport();
98 screens[i].set_viewport(NULL); 99 screens[i].set_viewport(last_vp);
99 } 100 }
100 button = get_action(CONTEXT_SETTINGS,HZ); 101 button = get_action(CONTEXT_SETTINGS,HZ);
101 102
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)
146 struct viewport *list_text_vp = &list_text[screen]; 146 struct viewport *list_text_vp = &list_text[screen];
147 int indent = 0; 147 int indent = 0;
148 148
149 display->set_viewport(parent); 149 struct viewport * last_vp = display->set_viewport(parent);
150 display->clear_viewport(); 150 display->clear_viewport();
151 display->scroll_stop_viewport(list_text_vp); 151 display->scroll_stop_viewport(list_text_vp);
152 *list_text_vp = *parent; 152 *list_text_vp = *parent;
@@ -332,7 +332,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
332 } 332 }
333 display->set_viewport(parent); 333 display->set_viewport(parent);
334 display->update_viewport(); 334 display->update_viewport();
335 display->set_viewport(NULL); 335 display->set_viewport(last_vp);
336} 336}
337 337
338#if defined(HAVE_TOUCHSCREEN) 338#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,
164 struct viewport vp; 164 struct viewport vp;
165 165
166 viewport_set_defaults(&vp, display->screen_type); 166 viewport_set_defaults(&vp, display->screen_type);
167 display->set_viewport(&vp); 167 struct viewport * last_vp = display->set_viewport(&vp);
168 168
169 display->clear_viewport(); 169 display->clear_viewport();
170 170
@@ -323,7 +323,7 @@ static void draw_screen(struct screen *display, char *title,
323 } 323 }
324 324
325 display->update_viewport(); 325 display->update_viewport();
326 display->set_viewport(NULL); 326 display->set_viewport(last_vp);
327} 327}
328 328
329#ifdef HAVE_TOUCHSCREEN 329#ifdef HAVE_TOUCHSCREEN
@@ -341,7 +341,7 @@ static int touchscreen_slider(struct screen *display,
341 struct viewport vp; 341 struct viewport vp;
342 342
343 viewport_set_defaults(&vp, display->screen_type); 343 viewport_set_defaults(&vp, display->screen_type);
344 display->set_viewport(&vp); 344 struct viewport *last_vp = display->set_viewport(&vp);
345 345
346 button = action_get_touchscreen_press_in_vp(&x, &y, &vp); 346 button = action_get_touchscreen_press_in_vp(&x, &y, &vp);
347 if (button == ACTION_UNKNOWN || button == BUTTON_NONE) 347 if (button == ACTION_UNKNOWN || button == BUTTON_NONE)
@@ -373,7 +373,7 @@ static int touchscreen_slider(struct screen *display,
373 char_height*2 + /* + margins for bottom */ 373 char_height*2 + /* + margins for bottom */
374 MARGIN_BOTTOM; /* colored rectangle */ 374 MARGIN_BOTTOM; /* colored rectangle */
375 375
376 display->set_viewport(NULL); 376 display->set_viewport(last_vp);
377 377
378 if (y < text_top) 378 if (y < text_top)
379 { 379 {
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,
239 char buf[32]; 239 char buf[32];
240 int w, h; 240 int w, h;
241 bool show_lang_pitch; 241 bool show_lang_pitch;
242 struct viewport *last_vp = NULL;
242 243
243 /* "Pitch up/Pitch down" - hide for a small screen, 244 /* "Pitch up/Pitch down" - hide for a small screen,
244 * the text is drawn centered automatically 245 * the text is drawn centered automatically
@@ -249,7 +250,7 @@ static void pitchscreen_draw(struct screen *display, int max_lines,
249 { 250 {
250 int w, h; 251 int w, h;
251 struct viewport *vp = &pitch_viewports[PITCH_TOP]; 252 struct viewport *vp = &pitch_viewports[PITCH_TOP];
252 display->set_viewport(vp); 253 last_vp = display->set_viewport(vp);
253 display->clear_viewport(); 254 display->clear_viewport();
254#ifdef HAVE_TOUCHSCREEN 255#ifdef HAVE_TOUCHSCREEN
255 /* two arrows in the top row, left and right column */ 256 /* two arrows in the top row, left and right column */
@@ -405,7 +406,7 @@ static void pitchscreen_draw(struct screen *display, int max_lines,
405 rightlabel); 406 rightlabel);
406 } 407 }
407 display->update_viewport(); 408 display->update_viewport();
408 display->set_viewport(NULL); 409 display->set_viewport(last_vp);
409} 410}
410 411
411static int32_t pitch_increase(int32_t pitch, int32_t pitch_delta, bool allow_cutoff 412static 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,
172 char buf[MAX_PATH]; 172 char buf[MAX_PATH];
173 unsigned const char *title, *value; 173 unsigned const char *title, *value;
174 int temp; 174 int temp;
175 display->set_viewport(parent); 175 struct viewport *last_vp = display->set_viewport(parent);
176 display->clear_viewport(); 176 display->clear_viewport();
177 177
178 for (i = 0; i < QUICKSCREEN_ITEM_COUNT; i++) 178 for (i = 0; i < QUICKSCREEN_ITEM_COUNT; i++)
@@ -225,7 +225,7 @@ static void gui_quickscreen_draw(const struct gui_quickscreen *qs,
225 225
226 display->set_viewport(parent); 226 display->set_viewport(parent);
227 display->update_viewport(); 227 display->update_viewport();
228 display->set_viewport(NULL); 228 display->set_viewport(last_vp);
229} 229}
230 230
231static void talk_qs_option(const struct settings_list *opt, bool enqueue) 231static 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)
204 return retval; 204 return retval;
205} 205}
206 206
207void* skin_backdrop_get_buffer(int backdrop_id) 207void skin_backdrop_set_buffer(int backdrop_id, struct skin_viewport *svp)
208{ 208{
209 if (backdrop_id < 0) 209 if (UNLIKELY(!svp))
210 return NULL; 210 return;
211 return backdrops[backdrop_id].buffer; 211 else if (backdrop_id < 0)
212 {
213 svp->vp.buffer = NULL; /*Default*/
214 return;
215 }
216
217 enum screen_type screen = backdrops[backdrop_id].screen;
218 svp->framebuf.ch_ptr = backdrops[backdrop_id].buffer;
219#if defined(HAVE_REMOTE_LCD)
220 if (screen == SCREEN_REMOTE)
221 svp->framebuf.elems = REMOTE_LCD_BACKDROP_BYTES / sizeof(fb_remote_data);
222 else
223#endif
224 {
225 svp->framebuf.elems = LCD_BACKDROP_BYTES / sizeof(fb_data);
226 }
227 svp->framebuf.get_address_fn = NULL; /*Default iterator*/
228 screens[screen].viewport_set_buffer(&svp->vp, &svp->framebuf);
212} 229}
213 230
214void skin_backdrop_show(int backdrop_id) 231void 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)
312bool skin_do_full_update(enum skinnable_screens skin, 312bool skin_do_full_update(enum skinnable_screens skin,
313 enum screen_type screen) 313 enum screen_type screen)
314{ 314{
315 bool ret = skins[skin][screen].needs_full_update; 315 struct viewport *vp = *(screens[screen].current_viewport);
316
317 bool vp_is_dirty = ((vp->flags & VP_FLAG_VP_SET_CLEAN) == VP_FLAG_VP_DIRTY);
318
319 bool ret = (skins[skin][screen].needs_full_update || vp_is_dirty);
316 skins[skin][screen].needs_full_update = false; 320 skins[skin][screen].needs_full_update = false;
317 return ret; 321 return ret;
318} 322}
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);
70void skin_backdrop_load_setting(void); 70void skin_backdrop_load_setting(void);
71void skin_backdrop_unload(int backdrop_id); 71void skin_backdrop_unload(int backdrop_id);
72#define BACKDROP_BUFFERNAME "#backdrop_buffer#" 72#define BACKDROP_BUFFERNAME "#backdrop_buffer#"
73void* skin_backdrop_get_buffer(int backdrop_id); 73void skin_backdrop_set_buffer(int backdrop_id, struct skin_viewport *svp);
74 74
75/* do the button loop as often as required for the peak meters to update 75/* do the button loop as often as required for the peak meters to update
76 * with a good refresh rate. 76 * 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,
259 } 259 }
260 else 260 else
261 { 261 {
262 struct skin_viewport *default_vp = SKINOFFSETTOPTR(skin_buffer, first_viewport->data); 262 struct skin_viewport *skin_default = SKINOFFSETTOPTR(skin_buffer, first_viewport->data);
263 if (first_viewport->params_count == 0) 263 if (first_viewport->params_count == 0)
264 { 264 {
265 wps_data->wps_sb_tag = true; 265 wps_data->wps_sb_tag = true;
@@ -267,11 +267,11 @@ static int parse_statusbar_tags(struct skin_element* element,
267 } 267 }
268 if (wps_data->show_sb_on_wps) 268 if (wps_data->show_sb_on_wps)
269 { 269 {
270 viewport_set_defaults(&default_vp->vp, curr_screen); 270 viewport_set_defaults(&skin_default->vp, curr_screen);
271 } 271 }
272 else 272 else
273 { 273 {
274 viewport_set_fullscreen(&default_vp->vp, curr_screen); 274 viewport_set_fullscreen(&skin_default->vp, curr_screen);
275 } 275 }
276#ifdef HAVE_REMOTE_LCD 276#ifdef HAVE_REMOTE_LCD
277 /* This parser requires viewports which will use the settings font to 277 /* This parser requires viewports which will use the settings font to
@@ -279,7 +279,7 @@ static int parse_statusbar_tags(struct skin_element* element,
279 * the current real font id. So force 1 here it will be set correctly 279 * the current real font id. So force 1 here it will be set correctly
280 * at the end 280 * at the end
281 */ 281 */
282 default_vp->vp.font = 1; 282 skin_default->vp.font = 1;
283#endif 283#endif
284 } 284 }
285 return 0; 285 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,
349{ 349{
350 struct gui_wps *gwps = info->gwps; 350 struct gui_wps *gwps = info->gwps;
351 struct wps_data *data = gwps->data; 351 struct wps_data *data = gwps->data;
352 struct viewport *last_vp;
353
352 /* Tags here are ones which need to be "turned off" or cleared 354 /* Tags here are ones which need to be "turned off" or cleared
353 * if they are in a conditional branch which isnt being used */ 355 * if they are in a conditional branch which isnt being used */
354 if (branch->type == LINE_ALTERNATOR) 356 if (branch->type == LINE_ALTERNATOR)
@@ -420,22 +422,23 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch,
420#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) 422#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
421 if (skin_viewport->output_to_backdrop_buffer) 423 if (skin_viewport->output_to_backdrop_buffer)
422 { 424 {
423 void *backdrop = skin_backdrop_get_buffer(data->backdrop_id); 425 skin_backdrop_set_buffer(data->backdrop_id, skin_viewport);
424 gwps->display->set_framebuffer(backdrop);
425 skin_backdrop_show(-1); 426 skin_backdrop_show(-1);
426 } 427 }
427#endif 428#endif
428 gwps->display->set_viewport(&skin_viewport->vp); 429 last_vp = gwps->display->set_viewport(&skin_viewport->vp);
429 gwps->display->clear_viewport(); 430 gwps->display->clear_viewport();
430 gwps->display->set_viewport(&info->skin_vp->vp); 431 gwps->display->set_viewport_ex(&info->skin_vp->vp, 0);
431 skin_viewport->hidden_flags |= VP_DRAW_HIDDEN; 432 skin_viewport->hidden_flags |= VP_DRAW_HIDDEN;
432 433
433#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) 434#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
434 if (skin_viewport->output_to_backdrop_buffer) 435 if (skin_viewport->output_to_backdrop_buffer)
435 { 436 {
436 gwps->display->set_framebuffer(NULL); 437 gwps->display->set_viewport_ex(last_vp, 0);
437 skin_backdrop_show(data->backdrop_id); 438 skin_backdrop_show(data->backdrop_id);
438 } 439 }
440#else
441 (void)last_vp;
439#endif 442#endif
440 } 443 }
441 } 444 }
@@ -792,6 +795,7 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
792 795
793void skin_render(struct gui_wps *gwps, unsigned refresh_mode) 796void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
794{ 797{
798 const int vp_is_appearing = (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE);
795 struct wps_data *data = gwps->data; 799 struct wps_data *data = gwps->data;
796 struct screen *display = gwps->display; 800 struct screen *display = gwps->display;
797 801
@@ -801,7 +805,20 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
801 805
802 int old_refresh_mode = refresh_mode; 806 int old_refresh_mode = refresh_mode;
803 skin_buffer = get_skin_buffer(gwps->data); 807 skin_buffer = get_skin_buffer(gwps->data);
804 808
809 struct viewport* first_vp;
810 /* should already be the default buffer */
811 first_vp = display->set_viewport(NULL);
812
813 /* Framebuffer is likely dirty */
814 if ((refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL)
815 {
816 if ((first_vp->flags & VP_FLAG_VP_SET_CLEAN) == VP_FLAG_VP_DIRTY &&
817 get_current_activity() == ACTIVITY_WPS) /* only clear if in WPS */
818 {
819 display->clear_viewport();
820 }
821 }
805 822
806 viewport = SKINOFFSETTOPTR(skin_buffer, data->tree); 823 viewport = SKINOFFSETTOPTR(skin_buffer, data->tree);
807 skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data); 824 skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data);
@@ -822,12 +839,12 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
822#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) 839#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
823 if (skin_viewport->output_to_backdrop_buffer) 840 if (skin_viewport->output_to_backdrop_buffer)
824 { 841 {
825 display->set_framebuffer(skin_backdrop_get_buffer(data->backdrop_id)); 842 skin_backdrop_set_buffer(data->backdrop_id, skin_viewport);
826 skin_backdrop_show(-1); 843 skin_backdrop_show(-1);
827 } 844 }
828 else 845 else
829 { 846 {
830 display->set_framebuffer(NULL); 847 skin_backdrop_set_buffer(-1, skin_viewport);
831 skin_backdrop_show(data->backdrop_id); 848 skin_backdrop_show(data->backdrop_id);
832 } 849 }
833#endif 850#endif
@@ -842,15 +859,14 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
842 skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN; 859 skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN;
843 continue; 860 continue;
844 } 861 }
845 else if (((skin_viewport->hidden_flags& 862 else if ((skin_viewport->hidden_flags & vp_is_appearing) == vp_is_appearing)
846 (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))
847 == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)))
848 { 863 {
849 vp_refresh_mode = SKIN_REFRESH_ALL; 864 vp_refresh_mode = SKIN_REFRESH_ALL;
850 skin_viewport->hidden_flags = VP_DRAW_HIDEABLE; 865 skin_viewport->hidden_flags = VP_DRAW_HIDEABLE;
851 } 866 }
852 867
853 display->set_viewport(&skin_viewport->vp); 868 display->set_viewport_ex(&skin_viewport->vp, VP_FLAG_VP_SET_CLEAN);
869
854 if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL) 870 if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL)
855 { 871 {
856 display->clear_viewport(); 872 display->clear_viewport();
@@ -862,7 +878,6 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
862 refresh_mode = old_refresh_mode; 878 refresh_mode = old_refresh_mode;
863 } 879 }
864#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) 880#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
865 display->set_framebuffer(NULL);
866 skin_backdrop_show(data->backdrop_id); 881 skin_backdrop_show(data->backdrop_id);
867#endif 882#endif
868 883
@@ -872,8 +887,8 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
872 * to redraw itself */ 887 * to redraw itself */
873 send_event(GUI_EVENT_NEED_UI_UPDATE, NULL); 888 send_event(GUI_EVENT_NEED_UI_UPDATE, NULL);
874 } 889 }
875 /* Restore the default viewport */ 890 /* Restore the first viewport */
876 display->set_viewport(NULL); 891 display->set_viewport_ex(first_vp, VP_FLAG_VP_SET_CLEAN);
877 display->update(); 892 display->update();
878} 893}
879 894
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 {
175#define VP_DEFAULT_LABEL_STRING "|" 175#define VP_DEFAULT_LABEL_STRING "|"
176struct skin_viewport { 176struct skin_viewport {
177 struct viewport vp; /* The LCD viewport struct */ 177 struct viewport vp; /* The LCD viewport struct */
178 struct frame_buffer_t framebuf;
178 char hidden_flags; 179 char hidden_flags;
179 bool is_infovp; 180 bool is_infovp;
180 OFFSETTYPE(char*) label; 181 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)
53 int maxw = 0; 53 int maxw = 0;
54 54
55 viewport_set_defaults(&vp, screen->screen_type); 55 viewport_set_defaults(&vp, screen->screen_type);
56 screen->set_viewport(&vp); 56 struct viewport *last_vp = screen->set_viewport(&vp);
57 57
58 screen->getstringsize(" ", &space_w, &h); 58 screen->getstringsize(" ", &space_w, &h);
59 y = h; 59 y = h;
@@ -157,7 +157,7 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap)
157 } 157 }
158 screen->update_viewport(); 158 screen->update_viewport();
159end: 159end:
160 screen->set_viewport(NULL); 160 screen->set_viewport(last_vp);
161} 161}
162 162
163void splashf(int ticks, const char *fmt, ...) 163void 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)
183void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw, struct viewport *vp) 183void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw, struct viewport *vp)
184{ 184{
185 struct screen * display = bar->display; 185 struct screen * display = bar->display;
186 struct viewport *last_vp = NULL;
186 187
187 if (!display) 188 if (!display)
188 return; 189 return;
@@ -267,7 +268,7 @@ void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw, struct vi
267#endif 268#endif
268 memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info))) 269 memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info)))
269 { 270 {
270 display->set_viewport(vp); 271 last_vp = display->set_viewport(vp);
271 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 272 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
272 display->fill_viewport(); 273 display->fill_viewport();
273 display->set_drawmode(DRMODE_SOLID); 274 display->set_drawmode(DRMODE_SOLID);
@@ -343,7 +344,7 @@ void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw, struct vi
343 gui_statusbar_led(display); 344 gui_statusbar_led(display);
344#endif 345#endif
345 display->update_viewport(); 346 display->update_viewport();
346 display->set_viewport(NULL); 347 display->set_viewport(last_vp);
347 bar->lastinfo = bar->info; 348 bar->lastinfo = bar->info;
348 } 349 }
349} 350}
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,
179 179
180static void usb_screens_draw(struct usb_screen_vps_t *usb_screen_vps_ar) 180static void usb_screens_draw(struct usb_screen_vps_t *usb_screen_vps_ar)
181{ 181{
182 struct viewport *last_vp;
182 static const struct bitmap* logos[NB_SCREENS] = { 183 static const struct bitmap* logos[NB_SCREENS] = {
183 &bm_usblogo, 184 &bm_usblogo,
184#ifdef HAVE_REMOTE_LCD 185#ifdef HAVE_REMOTE_LCD
@@ -194,7 +195,7 @@ static void usb_screens_draw(struct usb_screen_vps_t *usb_screen_vps_ar)
194 struct viewport *parent = &usb_screen_vps->parent; 195 struct viewport *parent = &usb_screen_vps->parent;
195 struct viewport *logo = &usb_screen_vps->logo; 196 struct viewport *logo = &usb_screen_vps->logo;
196 197
197 screen->set_viewport(parent); 198 last_vp = screen->set_viewport(parent);
198 screen->clear_viewport(); 199 screen->clear_viewport();
199 screen->backlight_on(); 200 screen->backlight_on();
200 201
@@ -217,7 +218,7 @@ static void usb_screens_draw(struct usb_screen_vps_t *usb_screen_vps_ar)
217 } 218 }
218 screen->set_viewport(parent); 219 screen->set_viewport(parent);
219 220
220 screen->set_viewport(NULL); 221 screen->set_viewport(last_vp);
221 screen->update_viewport(); 222 screen->update_viewport();
222 } 223 }
223} 224}
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 @@
31#include "settings.h" 31#include "settings.h"
32#include "misc.h" 32#include "misc.h"
33#include "list.h" 33#include "list.h"
34
34/*some short cuts for fg/bg/line selector handling */ 35/*some short cuts for fg/bg/line selector handling */
35#ifdef HAVE_LCD_COLOR 36#ifdef HAVE_LCD_COLOR
36#define FG_FALLBACK global_settings.fg_color 37#define FG_FALLBACK global_settings.fg_color
@@ -44,7 +45,6 @@
44#define REMOTE_BG_FALLBACK LCD_REMOTE_DEFAULT_BG 45#define REMOTE_BG_FALLBACK LCD_REMOTE_DEFAULT_BG
45#endif 46#endif
46 47
47
48/* all below isn't needed for pc tools (i.e. checkwps/wps editor) 48/* all below isn't needed for pc tools (i.e. checkwps/wps editor)
49 * only viewport_parse_viewport() is */ 49 * only viewport_parse_viewport() is */
50#ifndef __PCTOOL__ 50#ifndef __PCTOOL__
@@ -101,6 +101,7 @@ static void toggle_theme(enum screen_type screen, bool force)
101 bool enable_event = false; 101 bool enable_event = false;
102 static bool was_enabled[NB_SCREENS] = {false}; 102 static bool was_enabled[NB_SCREENS] = {false};
103 static bool after_boot[NB_SCREENS] = {false}; 103 static bool after_boot[NB_SCREENS] = {false};
104 struct viewport *last_vp;
104 105
105 FOR_NB_SCREENS(i) 106 FOR_NB_SCREENS(i)
106 { 107 {
@@ -111,6 +112,7 @@ static void toggle_theme(enum screen_type screen, bool force)
111 112
112 if (is_theme_enabled(screen)) 113 if (is_theme_enabled(screen))
113 { 114 {
115 last_vp = screens[screen].set_viewport(NULL);
114 bool first_boot = theme_stack_top[screen] == 0; 116 bool first_boot = theme_stack_top[screen] == 0;
115 /* remove the left overs from the previous screen. 117 /* remove the left overs from the previous screen.
116 * could cause a tiny flicker. Redo your screen code if that happens */ 118 * 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)
162 screens[screen].clear_viewport(); 164 screens[screen].clear_viewport();
163 screens[screen].update_viewport(); 165 screens[screen].update_viewport();
164 } 166 }
165 screens[screen].set_viewport(NULL); 167 screens[screen].set_viewport(last_vp);
166 } 168 }
167 intptr_t force = first_boot?0:1; 169 intptr_t force = first_boot?0:1;
168 170
@@ -282,11 +284,11 @@ static void set_default_align_flags(struct viewport *vp)
282void viewport_set_fullscreen(struct viewport *vp, 284void viewport_set_fullscreen(struct viewport *vp,
283 const enum screen_type screen) 285 const enum screen_type screen)
284{ 286{
287 screens[screen].init_viewport(vp);
285 vp->x = 0; 288 vp->x = 0;
286 vp->y = 0; 289 vp->y = 0;
287 vp->width = screens[screen].lcdwidth; 290 vp->width = screens[screen].lcdwidth;
288 vp->height = screens[screen].lcdheight; 291 vp->height = screens[screen].lcdheight;
289
290#ifndef __PCTOOL__ 292#ifndef __PCTOOL__
291 set_default_align_flags(vp); 293 set_default_align_flags(vp);
292#endif 294#endif
@@ -312,9 +314,25 @@ void viewport_set_fullscreen(struct viewport *vp,
312#endif 314#endif
313} 315}
314 316
317void viewport_set_buffer(struct viewport *vp, struct frame_buffer_t *buffer,
318 const enum screen_type screen)
319{
320 if (!vp) /* NULL vp grabs current framebuffer */
321 vp = *(screens[screen].current_viewport);
322
323 /* NULL sets default buffer */
324 if (buffer && buffer->elems == 0)
325 vp->buffer = NULL;
326 else
327 vp->buffer = buffer;
328 screens[screen].init_viewport(vp);
329}
330
315void viewport_set_defaults(struct viewport *vp, 331void viewport_set_defaults(struct viewport *vp,
316 const enum screen_type screen) 332 const enum screen_type screen)
317{ 333{
334 vp->buffer = NULL; /* use default frame_buffer */
335
318#if !defined(__PCTOOL__) 336#if !defined(__PCTOOL__)
319 struct viewport *sbs_area = NULL; 337 struct viewport *sbs_area = NULL;
320 if (!is_theme_enabled(screen)) 338 if (!is_theme_enabled(screen))
@@ -323,7 +341,7 @@ void viewport_set_defaults(struct viewport *vp,
323 return; 341 return;
324 } 342 }
325 sbs_area = sb_skin_get_info_vp(screen); 343 sbs_area = sb_skin_get_info_vp(screen);
326 344
327 if (sbs_area) 345 if (sbs_area)
328 *vp = *sbs_area; 346 *vp = *sbs_area;
329 else 347 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);
63/* call this when a theme changed */ 63/* call this when a theme changed */
64void viewportmanager_theme_changed(const int); 64void viewportmanager_theme_changed(const int);
65 65
66void viewport_set_buffer(struct viewport *vp, struct frame_buffer_t *buffer,
67 const enum screen_type screen);
68
66#ifdef HAVE_TOUCHSCREEN 69#ifdef HAVE_TOUCHSCREEN
67bool viewport_point_within_vp(const struct viewport *vp, 70bool viewport_point_within_vp(const struct viewport *vp,
68 const int x, const int y); 71 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)
78 struct screen * display=yn->display; 78 struct screen * display=yn->display;
79 struct viewport *vp = yn->vp; 79 struct viewport *vp = yn->vp;
80 int nb_lines, vp_lines, line_shift=0; 80 int nb_lines, vp_lines, line_shift=0;
81 struct viewport *last_vp;
81 82
82 display->set_viewport(vp); 83 last_vp = display->set_viewport(vp);
83 display->clear_viewport(); 84 display->clear_viewport();
84 nb_lines = yn->main_message->nb_lines; 85 nb_lines = yn->main_message->nb_lines;
85 vp_lines = viewport_get_nb_lines(vp); 86 vp_lines = viewport_get_nb_lines(vp);
@@ -116,7 +117,7 @@ static void gui_yesno_draw(struct gui_yesno * yn)
116 } 117 }
117#endif 118#endif
118 display->update_viewport(); 119 display->update_viewport();
119 display->set_viewport(NULL); 120 display->set_viewport(last_vp);
120} 121}
121 122
122/* 123/*
@@ -133,11 +134,11 @@ static bool gui_yesno_draw_result(struct gui_yesno * yn, enum yesno_res result)
133 struct screen * display=yn->display; 134 struct screen * display=yn->display;
134 if(message==NULL) 135 if(message==NULL)
135 return false; 136 return false;
136 display->set_viewport(vp); 137 struct viewport *last_vp = display->set_viewport(vp);
137 display->clear_viewport(); 138 display->clear_viewport();
138 put_message(yn->display, message, 0, viewport_get_nb_lines(vp)); 139 put_message(yn->display, message, 0, viewport_get_nb_lines(vp));
139 display->update_viewport(); 140 display->update_viewport();
140 display->set_viewport(NULL); 141 display->set_viewport(last_vp);
141 return(true); 142 return(true);
142} 143}
143 144
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)
169 const char *t = time, *d = date; 169 const char *t = time, *d = date;
170 if (vp->height == 0) 170 if (vp->height == 0)
171 return; 171 return;
172 display->set_viewport(vp); 172 struct viewport *last_vp = display->set_viewport(vp);
173 display->clear_viewport(); 173 display->clear_viewport();
174 if (viewport_get_nb_lines(vp) >= 4) 174 if (viewport_get_nb_lines(vp) >= 4)
175 line = 1; 175 line = 1;
@@ -200,7 +200,7 @@ static void draw_timedate(struct viewport *vp, struct screen *display)
200 display->puts(0, line, d); 200 display->puts(0, line, d);
201 201
202 display->update_viewport(); 202 display->update_viewport();
203 display->set_viewport(NULL); 203 display->set_viewport(last_vp);
204} 204}
205 205
206 206
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 )
769 lcd_remote_setfont(FONT_UI); 769 lcd_remote_setfont(FONT_UI);
770 lcd_remote_update(); 770 lcd_remote_update();
771#endif 771#endif
772 772#ifdef SIMULATOR
773 sleep(HZ); /* sim is too fast to see logo */
774#endif
773 return 0; 775 return 0;
774} 776}
775 777
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,
795 795
796static void draw_slider(void) 796static void draw_slider(void)
797{ 797{
798 struct viewport *last_vp;
798 FOR_NB_SCREENS(i) 799 FOR_NB_SCREENS(i)
799 { 800 {
800 struct viewport vp; 801 struct viewport vp;
801 int slider_height = 2*screens[i].getcharheight(); 802 int slider_height = 2*screens[i].getcharheight();
802 viewport_set_defaults(&vp, i); 803 viewport_set_defaults(&vp, i);
803 screens[i].set_viewport(&vp); 804 last_vp = screens[i].set_viewport(&vp);
804 show_busy_slider(&screens[i], 1, vp.height - slider_height, 805 show_busy_slider(&screens[i], 1, vp.height - slider_height,
805 vp.width-2, slider_height-1); 806 vp.width-2, slider_height-1);
806 screens[i].update_viewport(); 807 screens[i].update_viewport();
807 screens[i].set_viewport(NULL); 808 screens[i].set_viewport(last_vp);
808 } 809 }
809} 810}
810 811
811static void clear_display(bool update) 812static void clear_display(bool update)
812{ 813{
813 struct viewport vp; 814 struct viewport vp;
814 815 struct viewport *last_vp;
815 FOR_NB_SCREENS(i) 816 FOR_NB_SCREENS(i)
816 { 817 {
817 struct screen * screen = &screens[i]; 818 struct screen * screen = &screens[i];
818 viewport_set_defaults(&vp, screen->screen_type); 819 viewport_set_defaults(&vp, screen->screen_type);
819 screen->set_viewport(&vp); 820 last_vp = screen->set_viewport(&vp);
820 screen->clear_viewport(); 821 screen->clear_viewport();
821 if (update) { 822 if (update) {
822 screen->update_viewport(); 823 screen->update_viewport();
823 } 824 }
824 screen->set_viewport(NULL); 825 screen->set_viewport(last_vp);
825 } 826 }
826} 827}
827 828
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 = {
194 lcd_putsf, 194 lcd_putsf,
195 lcd_puts_scroll, 195 lcd_puts_scroll,
196 lcd_scroll_stop, 196 lcd_scroll_stop,
197 &lcd_framebuffer,
198 lcd_set_viewport, 197 lcd_set_viewport,
199 lcd_set_framebuffer,
200 lcd_bmp_part, 198 lcd_bmp_part,
201 lcd_update_rect, 199 lcd_update_rect,
202 lcd_set_drawmode, 200 lcd_set_drawmode,
@@ -281,7 +279,6 @@ static const struct plugin_api rockbox_api = {
281 lcd_remote_mono_bitmap_part, 279 lcd_remote_mono_bitmap_part,
282 lcd_remote_mono_bitmap, 280 lcd_remote_mono_bitmap,
283 lcd_remote_putsxy, 281 lcd_remote_putsxy,
284 &lcd_remote_framebuffer;
285 lcd_remote_update, 282 lcd_remote_update,
286 lcd_remote_update_rect, 283 lcd_remote_update_rect,
287#if (LCD_REMOTE_DEPTH > 1) 284#if (LCD_REMOTE_DEPTH > 1)
@@ -303,6 +300,7 @@ static const struct plugin_api rockbox_api = {
303 viewportmanager_theme_enable, 300 viewportmanager_theme_enable,
304 viewportmanager_theme_undo, 301 viewportmanager_theme_undo,
305 viewport_set_fullscreen, 302 viewport_set_fullscreen,
303 viewport_set_buffer,
306 304
307#ifdef HAVE_BACKLIGHT 305#ifdef HAVE_BACKLIGHT
308 /* lcd backlight */ 306 /* lcd backlight */
@@ -869,11 +867,12 @@ int plugin_load(const char* plugin, const void* parameter)
869#endif 867#endif
870 868
871 *(p_hdr->api) = &rockbox_api; 869 *(p_hdr->api) = &rockbox_api;
872 870 lcd_set_viewport(NULL);
873 lcd_clear_display(); 871 lcd_clear_display();
874 lcd_update(); 872 lcd_update();
875 873
876#ifdef HAVE_REMOTE_LCD 874#ifdef HAVE_REMOTE_LCD
875 lcd_remote_set_viewport(NULL);
877 lcd_remote_clear_display(); 876 lcd_remote_clear_display();
878 lcd_remote_update(); 877 lcd_remote_update();
879#endif 878#endif
@@ -914,7 +913,8 @@ int plugin_load(const char* plugin, const void* parameter)
914#ifdef HAVE_TOUCHSCREEN 913#ifdef HAVE_TOUCHSCREEN
915 touchscreen_set_mode(global_settings.touch_mode); 914 touchscreen_set_mode(global_settings.touch_mode);
916#endif 915#endif
917 916 /* restore default vp */
917 lcd_set_viewport(NULL);
918 screen_helper_setfont(FONT_UI); 918 screen_helper_setfont(FONT_UI);
919#if LCD_DEPTH > 1 919#if LCD_DEPTH > 1
920#ifdef HAVE_LCD_COLOR 920#ifdef HAVE_LCD_COLOR
@@ -928,6 +928,8 @@ int plugin_load(const char* plugin, const void* parameter)
928#endif /* LCD_DEPTH */ 928#endif /* LCD_DEPTH */
929 929
930#ifdef HAVE_REMOTE_LCD 930#ifdef HAVE_REMOTE_LCD
931 lcd_remote_set_viewport(NULL);
932
931#if LCD_REMOTE_DEPTH > 1 933#if LCD_REMOTE_DEPTH > 1
932 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG, 934 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG,
933 LCD_REMOTE_DEFAULT_BG); 935 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 {
204 void (*lcd_putsf)(int x, int y, const unsigned char *fmt, ...); 204 void (*lcd_putsf)(int x, int y, const unsigned char *fmt, ...);
205 bool (*lcd_puts_scroll)(int x, int y, const unsigned char* string); 205 bool (*lcd_puts_scroll)(int x, int y, const unsigned char* string);
206 void (*lcd_scroll_stop)(void); 206 void (*lcd_scroll_stop)(void);
207 fb_data** lcd_framebuffer; 207 struct viewport* (*lcd_set_viewport)(struct viewport* vp);
208 void (*lcd_set_viewport)(struct viewport* vp);
209 void (*lcd_set_framebuffer)(fb_data *fb);
210 void (*lcd_bmp_part)(const struct bitmap *bm, int src_x, int src_y, 208 void (*lcd_bmp_part)(const struct bitmap *bm, int src_x, int src_y,
211 int x, int y, int width, int height); 209 int x, int y, int width, int height);
212 void (*lcd_update_rect)(int x, int y, int width, int height); 210 void (*lcd_update_rect)(int x, int y, int width, int height);
@@ -314,7 +312,6 @@ struct plugin_api {
314 void (*lcd_remote_mono_bitmap)(const unsigned char *src, int x, int y, 312 void (*lcd_remote_mono_bitmap)(const unsigned char *src, int x, int y,
315 int width, int height); 313 int width, int height);
316 void (*lcd_remote_putsxy)(int x, int y, const unsigned char *string); 314 void (*lcd_remote_putsxy)(int x, int y, const unsigned char *string);
317 fb_remote_data** lcd_remote_framebuffer;
318 void (*lcd_remote_update)(void); 315 void (*lcd_remote_update)(void);
319 void (*lcd_remote_update_rect)(int x, int y, int width, int height); 316 void (*lcd_remote_update_rect)(int x, int y, int width, int height);
320#if (LCD_REMOTE_DEPTH > 1) 317#if (LCD_REMOTE_DEPTH > 1)
@@ -338,6 +335,8 @@ struct plugin_api {
338 void (*viewportmanager_theme_undo)(enum screen_type screen, bool force_redraw); 335 void (*viewportmanager_theme_undo)(enum screen_type screen, bool force_redraw);
339 void (*viewport_set_fullscreen)(struct viewport *vp, 336 void (*viewport_set_fullscreen)(struct viewport *vp,
340 const enum screen_type screen); 337 const enum screen_type screen);
338 void (*viewport_set_buffer)(struct viewport *vp, struct frame_buffer_t *buffer,
339 const enum screen_type screen);
341 340
342#ifdef HAVE_BACKLIGHT 341#ifdef HAVE_BACKLIGHT
343 /* lcd backlight */ 342 /* 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)
1052 rb->lcd_blit_pal256(src, 0, 0, 0, 0, LCD_WIDTH, LCD_HEIGHT); 1052 rb->lcd_blit_pal256(src, 0, 0, 0, 0, LCD_WIDTH, LCD_HEIGHT);
1053#endif 1053#endif
1054#elif defined(HAVE_LCD_COLOR) 1054#elif defined(HAVE_LCD_COLOR)
1055 static fb_data *lcd_fb = NULL;
1056 if (!lcd_fb)
1057 {
1058 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
1059 lcd_fb = vp_main->buffer->fb_ptr;
1060 }
1055#if(LCD_HEIGHT>LCD_WIDTH) 1061#if(LCD_HEIGHT>LCD_WIDTH)
1056 if(rotate_screen) 1062 if(rotate_screen)
1057 { 1063 {
@@ -1059,7 +1065,7 @@ void I_FinishUpdate (void)
1059 1065
1060 for (y = 1; y <= SCREENHEIGHT; y++) 1066 for (y = 1; y <= SCREENHEIGHT; y++)
1061 { 1067 {
1062 fb_data *dst = *rb->lcd_framebuffer + LCD_WIDTH - y; 1068 fb_data *dst = lcd_fb + LCD_WIDTH - y;
1063 count = SCREENWIDTH; 1069 count = SCREENWIDTH;
1064 1070
1065 do 1071 do
@@ -1073,7 +1079,7 @@ void I_FinishUpdate (void)
1073 else 1079 else
1074#endif 1080#endif
1075 { 1081 {
1076 fb_data *dst = *rb->lcd_framebuffer; 1082 fb_data *dst = lcd_fb;
1077 count = SCREENWIDTH*SCREENHEIGHT; 1083 count = SCREENWIDTH*SCREENHEIGHT;
1078 1084
1079 do 1085 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 @@
30#ifndef HAVE_LCD_COLOR 30#ifndef HAVE_LCD_COLOR
31#include "lib/grey.h" 31#include "lib/grey.h"
32#endif 32#endif
33static fb_data *lcd_fb = NULL;
33 34
34#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) 35#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
35/* Archos has not enough plugin RAM for full-width fire :( */ 36/* Archos has not enough plugin RAM for full-width fire :( */
@@ -251,7 +252,7 @@ static inline void fire_draw(struct fire* fire)
251#ifndef HAVE_LCD_COLOR 252#ifndef HAVE_LCD_COLOR
252 dest = draw_buffer; 253 dest = draw_buffer;
253#else 254#else
254 dest = *rb->lcd_framebuffer + LCD_WIDTH * y + FIRE_XPOS; 255 dest = lcd_fb + LCD_WIDTH * y + FIRE_XPOS;
255#endif 256#endif
256 end = dest + FIRE_WIDTH; 257 end = dest + FIRE_WIDTH;
257 258
@@ -379,6 +380,8 @@ enum plugin_status plugin_start(const void* parameter)
379 rb->lcd_set_mode(LCD_MODE_PAL256); 380 rb->lcd_set_mode(LCD_MODE_PAL256);
380#endif 381#endif
381 382
383 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
384 lcd_fb = vp_main->buffer->fb_ptr;
382 ret = main(); 385 ret = main();
383 386
384#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 387#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)
509 the bottom */ 509 the bottom */
510static void pan_view_down(struct image_info *info) 510static void pan_view_down(struct image_info *info)
511{ 511{
512 static fb_data *lcd_fb = NULL;
513 if (!lcd_fb)
514 {
515 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
516 lcd_fb = vp_main->buffer->fb_ptr;
517 }
518
512 int move; 519 int move;
513 520
514 move = MIN(VSCROLL, info->height - info->y - LCD_HEIGHT); 521 move = MIN(VSCROLL, info->height - info->y - LCD_HEIGHT);
@@ -526,7 +533,7 @@ static void pan_view_down(struct image_info *info)
526 */ 533 */
527 move++, info->y--; 534 move++, info->y--;
528 rb->memcpy(rgb_linebuf, 535 rb->memcpy(rgb_linebuf,
529 *rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, 536 lcd_fb + (LCD_HEIGHT - move)*LCD_WIDTH,
530 LCD_WIDTH*sizeof (fb_data)); 537 LCD_WIDTH*sizeof (fb_data));
531 } 538 }
532#endif 539#endif
@@ -539,7 +546,7 @@ static void pan_view_down(struct image_info *info)
539 && settings.jpeg_dither_mode == DITHER_DIFFUSION) 546 && settings.jpeg_dither_mode == DITHER_DIFFUSION)
540 { 547 {
541 /* Cover the first row drawn with previous image data. */ 548 /* Cover the first row drawn with previous image data. */
542 rb->memcpy(*rb->lcd_framebuffer + (LCD_HEIGHT - move)*LCD_WIDTH, 549 rb->memcpy(lcd_fb + (LCD_HEIGHT - move)*LCD_WIDTH,
543 rgb_linebuf, LCD_WIDTH*sizeof (fb_data)); 550 rgb_linebuf, LCD_WIDTH*sizeof (fb_data));
544 info->y++; 551 info->y++;
545 } 552 }
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) =
236 [DITHER_DIFFUSION] = pixel_fsdither_to_lcd, 236 [DITHER_DIFFUSION] = pixel_fsdither_to_lcd,
237 }, 237 },
238}; 238};
239 239static fb_data *lcd_fb = NULL;
240/* These defines are used fornormal horizontal strides and vertical strides. */ 240/* These defines are used fornormal horizontal strides and vertical strides. */
241#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 241#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
242#define LCDADDR(x, y) (*rb->lcd_framebuffer + LCD_HEIGHT*(x) + (y)) 242#define LCDADDR(x, y) (lcd_fb + LCD_HEIGHT*(x) + (y))
243#define ROWENDOFFSET (width*LCD_HEIGHT) 243#define ROWENDOFFSET (width*LCD_HEIGHT)
244#define ROWOFFSET (1) 244#define ROWOFFSET (1)
245#define COLOFFSET (LCD_HEIGHT) 245#define COLOFFSET (LCD_HEIGHT)
246#else 246#else
247#define LCDADDR(x, y) (*rb->lcd_framebuffer + LCD_WIDTH*(y) + (x)) 247#define LCDADDR(x, y) (lcd_fb + LCD_WIDTH*(y) + (x))
248#define ROWENDOFFSET (width) 248#define ROWENDOFFSET (width)
249#define ROWOFFSET (LCD_WIDTH) 249#define ROWOFFSET (LCD_WIDTH)
250#define COLOFFSET (1) 250#define COLOFFSET (1)
@@ -261,6 +261,12 @@ void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y,
261 int x, int y, int width, int height, 261 int x, int y, int width, int height,
262 int colour_mode, int dither_mode) 262 int colour_mode, int dither_mode)
263{ 263{
264 if (!lcd_fb)
265 {
266 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
267 lcd_fb = vp_main->buffer->fb_ptr;
268 }
269
264 fb_data *dst, *dst_end; 270 fb_data *dst, *dst_end;
265 fb_data (*pixel_func)(void); 271 fb_data (*pixel_func)(void);
266 struct rgb_pixel px; 272 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;
768int ufo_state, ufo_x; 768int ufo_state, ufo_x;
769bool level_finished; 769bool level_finished;
770bool aliens_down, aliens_right, hit_left_border, hit_right_border; 770bool aliens_down, aliens_right, hit_left_border, hit_right_border;
771 771static fb_data *lcd_fb;
772 772
773/* No standard get_pixel function yet, use this hack instead */ 773/* No standard get_pixel function yet, use this hack instead */
774#if (LCD_DEPTH >= 8) 774#if (LCD_DEPTH >= 8)
@@ -776,12 +776,12 @@ bool aliens_down, aliens_right, hit_left_border, hit_right_border;
776#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 776#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
777static inline fb_data get_pixel(int x, int y) 777static inline fb_data get_pixel(int x, int y)
778{ 778{
779 return *rb->lcd_framebuffer[x*LCD_HEIGHT+y]; 779 return lcd_fb[x*LCD_HEIGHT+y];
780} 780}
781#else 781#else
782static inline fb_data get_pixel(int x, int y) 782static inline fb_data get_pixel(int x, int y)
783{ 783{
784 return *rb->lcd_framebuffer[ytab[y] + x]; 784 return lcd_fb[ytab[y] + x];
785} 785}
786#endif 786#endif
787 787
@@ -794,7 +794,7 @@ static const unsigned char shifts[4] = {
794/* Horizontal packing */ 794/* Horizontal packing */
795static inline fb_data get_pixel(int x, int y) 795static inline fb_data get_pixel(int x, int y)
796{ 796{
797 return (*rb->lcd_framebuffer[ytab[y] + (x >> 2)] >> shifts[x & 3]) & 3; 797 return (lcd_fb[ytab[y] + (x >> 2)] >> shifts[x & 3]) & 3;
798} 798}
799#else 799#else
800/* Vertical packing */ 800/* Vertical packing */
@@ -803,7 +803,7 @@ static const unsigned char shifts[4] = {
803}; 803};
804static inline fb_data get_pixel(int x, int y) 804static inline fb_data get_pixel(int x, int y)
805{ 805{
806 return (*rb->lcd_framebuffer[ytab[y] + x] >> shifts[y & 3]) & 3; 806 return (lcd_fb[ytab[y] + x] >> shifts[y & 3]) & 3;
807} 807}
808#endif /* Horizontal/Vertical packing */ 808#endif /* Horizontal/Vertical packing */
809 809
@@ -1902,6 +1902,8 @@ enum plugin_status plugin_start(UNUSED const void* parameter)
1902#ifdef HAVE_BACKLIGHT 1902#ifdef HAVE_BACKLIGHT
1903 backlight_ignore_timeout(); 1903 backlight_ignore_timeout();
1904#endif 1904#endif
1905 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
1906 lcd_fb = vp_main->buffer->fb_ptr;
1905 /* now go ahead and have fun! */ 1907 /* now go ahead and have fun! */
1906 game_loop(); 1908 game_loop();
1907 1909
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);
62 62
63/* Viewports and framebuffers */ 63/* Viewports and framebuffers */
64void grey_clear_viewport(void); 64void grey_clear_viewport(void);
65void grey_set_viewport(struct viewport *vp); 65struct viewport *grey_set_viewport(struct viewport *vp);
66void grey_viewport_set_fullscreen(struct viewport *vp, 66void grey_viewport_set_fullscreen(struct viewport *vp,
67 const enum screen_type screen); 67 const enum screen_type screen);
68void grey_viewport_set_pos(struct viewport *vp, 68void 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};
765 content (b&w and greyscale overlay) to an 8-bit BMP file. */ 765 content (b&w and greyscale overlay) to an 8-bit BMP file. */
766static void grey_screendump_hook(int fd) 766static void grey_screendump_hook(int fd)
767{ 767{
768 fb_data *lcd_fb;
769 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
770 rb->viewport_set_fullscreen(vp_main, SCREEN_MAIN);
771 lcd_fb = vp_main->buffer->fb_ptr;
772
768 int i; 773 int i;
769 int y, gx, gy; 774 int y, gx, gy;
770#if LCD_PIXELFORMAT == VERTICAL_PACKING 775#if LCD_PIXELFORMAT == VERTICAL_PACKING
@@ -845,7 +850,7 @@ static void grey_screendump_hook(int fd)
845 gsrc = _grey_info.values + _GREY_MULUQ(_grey_info.width, gy); 850 gsrc = _grey_info.values + _GREY_MULUQ(_grey_info.width, gy);
846 851
847#if LCD_DEPTH == 2 852#if LCD_DEPTH == 2
848 src = *rb->lcd_framebuffer + _GREY_MULUQ(LCD_FBWIDTH, y); 853 src = lcd_fb + _GREY_MULUQ(LCD_FBWIDTH, y);
849 854
850 do 855 do
851 { 856 {
@@ -876,7 +881,7 @@ static void grey_screendump_hook(int fd)
876 881
877#if LCD_DEPTH == 1 882#if LCD_DEPTH == 1
878 mask = BIT_N(y & 7); 883 mask = BIT_N(y & 7);
879 src = *rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3); 884 src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 3);
880 885
881 do 886 do
882 { 887 {
@@ -908,7 +913,7 @@ static void grey_screendump_hook(int fd)
908 913
909#elif LCD_DEPTH == 2 914#elif LCD_DEPTH == 2
910 shift = 2 * (y & 3); 915 shift = 2 * (y & 3);
911 src = *rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 2); 916 src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 2);
912 917
913 do 918 do
914 { 919 {
@@ -933,7 +938,7 @@ static void grey_screendump_hook(int fd)
933 938
934#if LCD_DEPTH == 2 939#if LCD_DEPTH == 2
935 shift = y & 7; 940 shift = y & 7;
936 src = *rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3); 941 src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 3);
937 942
938 do 943 do
939 { 944 {
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)
154} 154}
155 155
156/* Set current grey viewport for draw routines */ 156/* Set current grey viewport for draw routines */
157void grey_set_viewport(struct viewport *vp) 157struct viewport *grey_set_viewport(struct viewport *vp)
158{ 158{
159 struct viewport *last_vp = _grey_info.vp;
159 if (vp == NULL) 160 if (vp == NULL)
160 vp = &_grey_default_vp; 161 vp = &_grey_default_vp;
161 162
@@ -164,6 +165,7 @@ void grey_set_viewport(struct viewport *vp)
164 _grey_info.vp = vp; 165 _grey_info.vp = vp;
165 grey_update_clip_rect(); 166 grey_update_clip_rect();
166 } 167 }
168 return last_vp;
167} 169}
168 170
169/* Set viewport to default settings */ 171/* 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
52 OSD_ERASED, /* Erased in preparation for regular drawing */ 52 OSD_ERASED, /* Erased in preparation for regular drawing */
53 } status; /* View status */ 53 } status; /* View status */
54 struct viewport vp; /* Clipping viewport */ 54 struct viewport vp; /* Clipping viewport */
55 struct frame_buffer_t framebuf; /* Holds framebuffer reference */
55 int lcd_bitmap_stride; /* Stride of LCD bitmap */ 56 int lcd_bitmap_stride; /* Stride of LCD bitmap */
56 void *lcd_bitmap_data; /* Backbuffer framebuffer data */ 57 void *lcd_bitmap_data; /* Backbuffer framebuffer data */
57 int back_bitmap_stride; /* Stride of backbuffer bitmap */ 58 int back_bitmap_stride; /* Stride of backbuffer bitmap */
@@ -68,7 +69,7 @@ struct osd
68 int height); 69 int height);
69 void (*lcd_update)(void); 70 void (*lcd_update)(void);
70 void (*lcd_update_rect)(int x, int y, int width, int height); 71 void (*lcd_update_rect)(int x, int y, int width, int height);
71 void (*lcd_set_viewport)(struct viewport *vp); 72 struct viewport *(*lcd_set_viewport)(struct viewport *vp);
72 void (*lcd_set_framebuffer)(void *buf); 73 void (*lcd_set_framebuffer)(void *buf);
73 void (*lcd_framebuffer_set_pos)(int x, int y, int width, int height); 74 void (*lcd_framebuffer_set_pos)(int x, int y, int width, int height);
74 void (*lcd_bitmap_part)(const void *src, int src_x, int src_y, 75 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,
227 osd->back_bitmap_stride = w; 228 osd->back_bitmap_stride = w;
228#endif /* end stride type selection */ 229#endif /* end stride type selection */
229 230
230 osd->lcd_bitmap_data = (void *)*rb->lcd_framebuffer; 231 /* vp is currently initialized to the default framebuffer */
232 osd->lcd_bitmap_data = osd->vp.buffer->data;
231 osd->back_bitmap_data = buf; 233 osd->back_bitmap_data = buf;
232 234
233 osd->maxwidth = w; 235 osd->maxwidth = w;
@@ -686,6 +688,25 @@ static void _osd_lcd_update_rect(struct osd *osd,
686 osd->lcd_update_rect(x, y, width, height); 688 osd->lcd_update_rect(x, y, width, height);
687} 689}
688 690
691static void _osd_lcd_viewport_set_buffer(void *buffer)
692{
693 if (buffer)
694 {
695 native_osd.framebuf.data = buffer;
696 native_osd.framebuf.elems = native_osd.maxheight * native_osd.maxwidth;
697 native_osd.framebuf.get_address_fn = NULL; /*Default iterator*/
698
699 if (buffer == native_osd.back_bitmap_data)
700 native_osd.framebuf.stride = (native_osd.back_bitmap_stride);
701 else
702 native_osd.framebuf.stride = (native_osd.lcd_bitmap_stride);
703
704 rb->viewport_set_buffer(NULL, &native_osd.framebuf, SCREEN_MAIN);
705 }
706 else
707 rb->viewport_set_buffer(NULL, NULL, SCREEN_MAIN);
708}
709
689/* Native LCD, public */ 710/* Native LCD, public */
690bool osd_init(unsigned flags, void *backbuf, size_t backbuf_size, 711bool osd_init(unsigned flags, void *backbuf, size_t backbuf_size,
691 osd_draw_cb_fn_t draw_cb, int *width, int *height, 712 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,
696 native_osd.lcd_update = rb->lcd_update; 717 native_osd.lcd_update = rb->lcd_update;
697 native_osd.lcd_update_rect = rb->lcd_update_rect; 718 native_osd.lcd_update_rect = rb->lcd_update_rect;
698 native_osd.lcd_set_viewport = rb->lcd_set_viewport; 719 native_osd.lcd_set_viewport = rb->lcd_set_viewport;
699 native_osd.lcd_set_framebuffer = (void *)rb->lcd_set_framebuffer; 720 native_osd.lcd_set_framebuffer = (void *)_osd_lcd_viewport_set_buffer;
700#if LCD_DEPTH < 4 721#if LCD_DEPTH < 4
701 native_osd.lcd_framebuffer_set_pos = NULL; 722 native_osd.lcd_framebuffer_set_pos = NULL;
702#endif /* LCD_DEPTH < 4 */ 723#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);
34void xlcd_drawcircle(int cx, int cy, int radius); 34void xlcd_drawcircle(int cx, int cy, int radius);
35void xlcd_drawcircle_screen(struct screen* display, int cx, int cy, int radius); 35void xlcd_drawcircle_screen(struct screen* display, int cx, int cy, int radius);
36 36
37fb_data* get_framebuffer(struct viewport *vp, size_t *stride); /*CORE*/
38
37#if LCD_DEPTH >= 8 39#if LCD_DEPTH >= 8
38void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, 40void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
39 int stride, int x, int y, int width, int height); 41 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 @@
26 26
27#include "xlcd.h" 27#include "xlcd.h"
28 28
29fb_data* get_framebuffer(struct viewport *vp, size_t *stride)
30{
31 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
32 if (vp)
33 *vp = *vp_main;
34 if (stride)
35 *stride = vp_main->buffer->stride;
36 return vp_main->buffer->fb_ptr;
37}
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] = {
349void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y, 349void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
350 int stride, int x, int y, int width, int height) 350 int stride, int x, int y, int width, int height)
351{ 351{
352 size_t dst_stride;
353 fb_data *lcd_fb = get_framebuffer(NULL, &dst_stride);
354
352 const unsigned char *src_end; 355 const unsigned char *src_end;
353 fb_data *dst; 356 fb_data *dst;
354 357
@@ -377,7 +380,7 @@ void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
377 380
378 src += stride * src_y + src_x; /* move starting point */ 381 src += stride * src_y + src_x; /* move starting point */
379 src_end = src + stride * height; 382 src_end = src + stride * height;
380 dst = *rb->lcd_framebuffer + LCD_WIDTH * y + x; 383 dst = lcd_fb + dst_stride * y + x;
381 384
382 do 385 do
383 { 386 {
@@ -398,7 +401,7 @@ void xlcd_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
398#endif 401#endif
399 402
400 src += stride; 403 src += stride;
401 dst += LCD_WIDTH; 404 dst += dst_stride;
402 } 405 }
403 while (src < src_end); 406 while (src < src_end);
404} 407}
@@ -416,6 +419,9 @@ void xlcd_gray_bitmap(const unsigned char *src, int x, int y, int width,
416void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y, 419void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y,
417 int stride, int x, int y, int width, int height) 420 int stride, int x, int y, int width, int height)
418{ 421{
422 size_t dst_stride;
423 fb_data *lcd_fb = get_framebuffer(NULL, &dst_stride);
424
419 const unsigned char *src_end; 425 const unsigned char *src_end;
420 fb_data *dst; 426 fb_data *dst;
421 427
@@ -444,7 +450,7 @@ void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y,
444 450
445 src += 3 * (stride * src_y + src_x); /* move starting point */ 451 src += 3 * (stride * src_y + src_x); /* move starting point */
446 src_end = src + 3 * stride * height; 452 src_end = src + 3 * stride * height;
447 dst = *rb->lcd_framebuffer + LCD_WIDTH * y + x; 453 dst = lcd_fb + dst_stride * y + x;
448 454
449 do 455 do
450 { 456 {
@@ -471,7 +477,7 @@ void xlcd_color_bitmap_part(const unsigned char *src, int src_x, int src_y,
471 while (src_row < row_end); 477 while (src_row < row_end);
472 478
473 src += 3 * stride; 479 src += 3 * stride;
474 dst += LCD_WIDTH; 480 dst += dst_stride;
475 } 481 }
476 while (src < src_end); 482 while (src < src_end);
477} 483}
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};
33#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 33#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
34void xlcd_scroll_left(int count) 34void xlcd_scroll_left(int count)
35{ 35{
36 /*size_t dst_stride;*/
37 /*struct viewport *vp_main = NULL;*/
38 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
39
40
36 int length, oldmode; 41 int length, oldmode;
37 42
38 if ((unsigned)count >= LCD_WIDTH) 43 if ((unsigned)count >= LCD_WIDTH)
@@ -43,8 +48,7 @@ void xlcd_scroll_left(int count)
43 48
44 length = (LCD_WIDTH-count)*LCD_FBHEIGHT; 49 length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
45 50
46 rb->memmove(*rb->lcd_framebuffer, *rb->lcd_framebuffer + LCD_HEIGHT*count, 51 rb->memmove(lcd_fb, lcd_fb + LCD_HEIGHT*count, length * sizeof(fb_data));
47 length * sizeof(fb_data));
48 52
49 oldmode = rb->lcd_get_drawmode(); 53 oldmode = rb->lcd_get_drawmode();
50 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 54 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
@@ -55,6 +59,11 @@ void xlcd_scroll_left(int count)
55/* Scroll right */ 59/* Scroll right */
56void xlcd_scroll_right(int count) 60void xlcd_scroll_right(int count)
57{ 61{
62 /*size_t dst_stride;*/
63 /*struct viewport *vp_main = NULL;*/
64 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
65
66
58 int length, oldmode; 67 int length, oldmode;
59 68
60 if ((unsigned)count >= LCD_WIDTH) 69 if ((unsigned)count >= LCD_WIDTH)
@@ -65,8 +74,8 @@ void xlcd_scroll_right(int count)
65 74
66 length = (LCD_WIDTH-count)*LCD_FBHEIGHT; 75 length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
67 76
68 rb->memmove(*rb->lcd_framebuffer + LCD_HEIGHT*count, 77 rb->memmove(lcd_fb + LCD_HEIGHT*count,
69 *rb->lcd_framebuffer, length * sizeof(fb_data)); 78 lcd_fb, length * sizeof(fb_data));
70 79
71 oldmode = rb->lcd_get_drawmode(); 80 oldmode = rb->lcd_get_drawmode();
72 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 81 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
@@ -77,6 +86,11 @@ void xlcd_scroll_right(int count)
77/* Scroll up */ 86/* Scroll up */
78void xlcd_scroll_up(int count) 87void xlcd_scroll_up(int count)
79{ 88{
89 /*size_t dst_stride;*/
90 /*struct viewport *vp_main = NULL;*/
91 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
92
93
80 int width, length, oldmode; 94 int width, length, oldmode;
81 95
82 fb_data *data; 96 fb_data *data;
@@ -90,7 +104,7 @@ void xlcd_scroll_up(int count)
90 length = LCD_HEIGHT - count; 104 length = LCD_HEIGHT - count;
91 105
92 width = LCD_WIDTH-1; 106 width = LCD_WIDTH-1;
93 data = *rb->lcd_framebuffer; 107 data = lcd_fb;
94 108
95 do { 109 do {
96 rb->memmove(data,data + count,length * sizeof(fb_data)); 110 rb->memmove(data,data + count,length * sizeof(fb_data));
@@ -106,6 +120,11 @@ void xlcd_scroll_up(int count)
106/* Scroll down */ 120/* Scroll down */
107void xlcd_scroll_down(int count) 121void xlcd_scroll_down(int count)
108{ 122{
123 /*size_t dst_stride;*/
124 /*struct viewport *vp_main = NULL;*/
125 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
126
127
109 int width, length, oldmode; 128 int width, length, oldmode;
110 129
111 fb_data *data; 130 fb_data *data;
@@ -119,7 +138,7 @@ void xlcd_scroll_down(int count)
119 length = LCD_HEIGHT - count; 138 length = LCD_HEIGHT - count;
120 139
121 width = LCD_WIDTH-1; 140 width = LCD_WIDTH-1;
122 data = *rb->lcd_framebuffer; 141 data = lcd_fb;
123 142
124 do { 143 do {
125 rb->memmove(data + count, data, length * sizeof(fb_data)); 144 rb->memmove(data + count, data, length * sizeof(fb_data));
@@ -138,6 +157,11 @@ void xlcd_scroll_down(int count)
138/* Scroll left */ 157/* Scroll left */
139void xlcd_scroll_left(int count) 158void xlcd_scroll_left(int count)
140{ 159{
160 /*size_t dst_stride;*/
161 /*struct viewport *vp_main = NULL;*/
162 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
163
164
141 int bitcount=0, oldmode; 165 int bitcount=0, oldmode;
142 int blockcount=0, blocklen; 166 int blockcount=0, blocklen;
143 167
@@ -155,7 +179,7 @@ void xlcd_scroll_left(int count)
155 179
156 if (blockcount) 180 if (blockcount)
157 { 181 {
158 unsigned char *data = *rb->lcd_framebuffer; 182 unsigned char *data = lcd_fb;
159 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT; 183 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
160 184
161 do 185 do
@@ -168,7 +192,7 @@ void xlcd_scroll_left(int count)
168 if (bitcount) 192 if (bitcount)
169 { 193 {
170 int bx, y; 194 int bx, y;
171 unsigned char *addr = *rb->lcd_framebuffer + blocklen; 195 unsigned char *addr = lcd_fb + blocklen;
172#if LCD_DEPTH == 2 196#if LCD_DEPTH == 2
173 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount; 197 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
174#endif 198#endif
@@ -196,6 +220,11 @@ void xlcd_scroll_left(int count)
196/* Scroll right */ 220/* Scroll right */
197void xlcd_scroll_right(int count) 221void xlcd_scroll_right(int count)
198{ 222{
223 /*size_t dst_stride;*/
224 /*struct viewport *vp_main = NULL;*/
225 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
226
227
199 int bitcount=0, oldmode; 228 int bitcount=0, oldmode;
200 int blockcount=0, blocklen; 229 int blockcount=0, blocklen;
201 230
@@ -213,7 +242,7 @@ void xlcd_scroll_right(int count)
213 242
214 if (blockcount) 243 if (blockcount)
215 { 244 {
216 unsigned char *data = *rb->lcd_framebuffer; 245 unsigned char *data = lcd_fb;
217 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT; 246 unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
218 247
219 do 248 do
@@ -226,7 +255,7 @@ void xlcd_scroll_right(int count)
226 if (bitcount) 255 if (bitcount)
227 { 256 {
228 int bx, y; 257 int bx, y;
229 unsigned char *addr = *rb->lcd_framebuffer + blockcount; 258 unsigned char *addr = lcd_fb + blockcount;
230#if LCD_DEPTH == 2 259#if LCD_DEPTH == 2
231 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3); 260 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
232#endif 261#endif
@@ -256,6 +285,11 @@ void xlcd_scroll_right(int count)
256/* Scroll left */ 285/* Scroll left */
257void xlcd_scroll_left(int count) 286void xlcd_scroll_left(int count)
258{ 287{
288 /*size_t dst_stride;*/
289 /*struct viewport *vp_main = NULL;*/
290 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
291
292
259 fb_data *data, *data_end; 293 fb_data *data, *data_end;
260 int length, oldmode; 294 int length, oldmode;
261 295
@@ -265,7 +299,7 @@ void xlcd_scroll_left(int count)
265 return; 299 return;
266 } 300 }
267 301
268 data = *rb->lcd_framebuffer; 302 data = lcd_fb;
269 data_end = data + LCD_WIDTH*LCD_FBHEIGHT; 303 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
270 length = LCD_WIDTH - count; 304 length = LCD_WIDTH - count;
271 305
@@ -285,6 +319,11 @@ void xlcd_scroll_left(int count)
285/* Scroll right */ 319/* Scroll right */
286void xlcd_scroll_right(int count) 320void xlcd_scroll_right(int count)
287{ 321{
322 /*size_t dst_stride;*/
323 /*struct viewport *vp_main = NULL;*/
324 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
325
326
288 fb_data *data, *data_end; 327 fb_data *data, *data_end;
289 int length, oldmode; 328 int length, oldmode;
290 329
@@ -294,7 +333,7 @@ void xlcd_scroll_right(int count)
294 return; 333 return;
295 } 334 }
296 335
297 data = *rb->lcd_framebuffer; 336 data = lcd_fb;
298 data_end = data + LCD_WIDTH*LCD_FBHEIGHT; 337 data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
299 length = LCD_WIDTH - count; 338 length = LCD_WIDTH - count;
300 339
@@ -318,6 +357,10 @@ void xlcd_scroll_right(int count)
318/* Scroll up */ 357/* Scroll up */
319void xlcd_scroll_up(int count) 358void xlcd_scroll_up(int count)
320{ 359{
360 /*size_t dst_stride;*/
361 /*struct viewport *vp_main = NULL;*/
362 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
363
321 int length, oldmode; 364 int length, oldmode;
322 365
323 if ((unsigned)count >= LCD_HEIGHT) 366 if ((unsigned)count >= LCD_HEIGHT)
@@ -328,8 +371,8 @@ void xlcd_scroll_up(int count)
328 371
329 length = LCD_HEIGHT - count; 372 length = LCD_HEIGHT - count;
330 373
331 rb->memmove(*rb->lcd_framebuffer, 374 rb->memmove(lcd_fb,
332 *rb->lcd_framebuffer + count * LCD_FBWIDTH, 375 lcd_fb + count * LCD_FBWIDTH,
333 length * LCD_FBWIDTH * sizeof(fb_data)); 376 length * LCD_FBWIDTH * sizeof(fb_data));
334 377
335 oldmode = rb->lcd_get_drawmode(); 378 oldmode = rb->lcd_get_drawmode();
@@ -341,6 +384,10 @@ void xlcd_scroll_up(int count)
341/* Scroll down */ 384/* Scroll down */
342void xlcd_scroll_down(int count) 385void xlcd_scroll_down(int count)
343{ 386{
387 /*size_t dst_stride;*/
388 /*struct viewport *vp_main = NULL;*/
389 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
390
344 int length, oldmode; 391 int length, oldmode;
345 392
346 if ((unsigned)count >= LCD_HEIGHT) 393 if ((unsigned)count >= LCD_HEIGHT)
@@ -351,8 +398,8 @@ void xlcd_scroll_down(int count)
351 398
352 length = LCD_HEIGHT - count; 399 length = LCD_HEIGHT - count;
353 400
354 rb->memmove(*rb->lcd_framebuffer + count * LCD_FBWIDTH, 401 rb->memmove(lcd_fb + count * LCD_FBWIDTH,
355 *rb->lcd_framebuffer, 402 lcd_fb,
356 length * LCD_FBWIDTH * sizeof(fb_data)); 403 length * LCD_FBWIDTH * sizeof(fb_data));
357 404
358 oldmode = rb->lcd_get_drawmode(); 405 oldmode = rb->lcd_get_drawmode();
@@ -367,6 +414,10 @@ void xlcd_scroll_down(int count)
367/* Scroll up */ 414/* Scroll up */
368void xlcd_scroll_up(int count) 415void xlcd_scroll_up(int count)
369{ 416{
417 /*size_t dst_stride;*/
418 /*struct viewport *vp_main = NULL;*/
419 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
420
370 int bitcount=0, oldmode; 421 int bitcount=0, oldmode;
371 int blockcount=0, blocklen; 422 int blockcount=0, blocklen;
372 423
@@ -388,8 +439,8 @@ void xlcd_scroll_up(int count)
388 439
389 if (blockcount) 440 if (blockcount)
390 { 441 {
391 rb->memmove(*rb->lcd_framebuffer, 442 rb->memmove(lcd_fb,
392 *rb->lcd_framebuffer + blockcount * LCD_FBWIDTH, 443 lcd_fb + blockcount * LCD_FBWIDTH,
393 blocklen * LCD_FBWIDTH * sizeof(fb_data)); 444 blocklen * LCD_FBWIDTH * sizeof(fb_data));
394 } 445 }
395 if (bitcount) 446 if (bitcount)
@@ -424,7 +475,7 @@ void xlcd_scroll_up(int count)
424 : /* inputs */ 475 : /* inputs */
425 [wide]"r"(LCD_FBWIDTH), 476 [wide]"r"(LCD_FBWIDTH),
426 [rows]"r"(blocklen), 477 [rows]"r"(blocklen),
427 [addr]"a"(*rb->lcd_framebuffer + blocklen * LCD_FBWIDTH), 478 [addr]"a"(lcd_fb + blocklen * LCD_FBWIDTH),
428 [cnt] "d"(bitcount), 479 [cnt] "d"(bitcount),
429 [bkg] "d"(0x55 * (~rb->lcd_get_background() & 3)) 480 [bkg] "d"(0x55 * (~rb->lcd_get_background() & 3))
430 : /* clobbers */ 481 : /* clobbers */
@@ -432,7 +483,7 @@ void xlcd_scroll_up(int count)
432 ); 483 );
433#else /* C version */ 484#else /* C version */
434 int x, by; 485 int x, by;
435 unsigned char *addr = *rb->lcd_framebuffer + blocklen * LCD_FBWIDTH; 486 unsigned char *addr = lcd_fb + blocklen * LCD_FBWIDTH;
436#if LCD_DEPTH == 2 487#if LCD_DEPTH == 2
437 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3); 488 unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
438#else 489#else
@@ -457,7 +508,7 @@ void xlcd_scroll_up(int count)
457 508
458#if LCD_DEPTH == 2 509#if LCD_DEPTH == 2
459 int x, by; 510 int x, by;
460 fb_data *addr = *rb->lcd_framebuffer + blocklen * LCD_FBWIDTH; 511 fb_data *addr = lcd_fb + blocklen * LCD_FBWIDTH;
461 unsigned fill, mask; 512 unsigned fill, mask;
462 513
463 fill = patterns[rb->lcd_get_background() & 3] << 8; 514 fill = patterns[rb->lcd_get_background() & 3] << 8;
@@ -491,6 +542,10 @@ void xlcd_scroll_up(int count)
491/* Scroll up */ 542/* Scroll up */
492void xlcd_scroll_down(int count) 543void xlcd_scroll_down(int count)
493{ 544{
545 /*size_t dst_stride;*/
546 /*struct viewport *vp_main = NULL;*/
547 fb_data *lcd_fb = get_framebuffer(NULL, NULL);
548
494 int bitcount=0, oldmode; 549 int bitcount=0, oldmode;
495 int blockcount=0, blocklen; 550 int blockcount=0, blocklen;
496 551
@@ -512,8 +567,8 @@ void xlcd_scroll_down(int count)
512 567
513 if (blockcount) 568 if (blockcount)
514 { 569 {
515 rb->memmove(*rb->lcd_framebuffer + blockcount * LCD_FBWIDTH, 570 rb->memmove(lcd_fb + blockcount * LCD_FBWIDTH,
516 *rb->lcd_framebuffer, 571 lcd_fb,
517 blocklen * LCD_FBWIDTH * sizeof(fb_data)); 572 blocklen * LCD_FBWIDTH * sizeof(fb_data));
518 } 573 }
519 if (bitcount) 574 if (bitcount)
@@ -548,7 +603,7 @@ void xlcd_scroll_down(int count)
548 : /* inputs */ 603 : /* inputs */
549 [wide]"r"(LCD_WIDTH), 604 [wide]"r"(LCD_WIDTH),
550 [rows]"r"(blocklen), 605 [rows]"r"(blocklen),
551 [addr]"a"(*rb->lcd_framebuffer + blockcount * LCD_FBWIDTH), 606 [addr]"a"(lcd_fb + blockcount * LCD_FBWIDTH),
552 [cnt] "d"(bitcount), 607 [cnt] "d"(bitcount),
553 [bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount) 608 [bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount)
554 : /* clobbers */ 609 : /* clobbers */
@@ -556,7 +611,7 @@ void xlcd_scroll_down(int count)
556 ); 611 );
557#else /* C version */ 612#else /* C version */
558 int x, by; 613 int x, by;
559 unsigned char *addr = *rb->lcd_framebuffer + blockcount * LCD_FBWIDTH; 614 unsigned char *addr = lcd_fb + blockcount * LCD_FBWIDTH;
560#if LCD_DEPTH == 2 615#if LCD_DEPTH == 2
561 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount; 616 unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
562#else 617#else
@@ -581,7 +636,7 @@ void xlcd_scroll_down(int count)
581 636
582#if LCD_DEPTH == 2 637#if LCD_DEPTH == 2
583 int x, by; 638 int x, by;
584 fb_data *addr = *rb->lcd_framebuffer + blockcount * LCD_FBWIDTH; 639 fb_data *addr = lcd_fb + blockcount * LCD_FBWIDTH;
585 unsigned fill, mask; 640 unsigned fill, mask;
586 641
587 fill = patterns[rb->lcd_get_background() & 3] >> (8 - bitcount); 642 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)
1242 return screen; 1242 return screen;
1243} 1243}
1244#else /* only SCREEN_MAIN exists */ 1244#else /* only SCREEN_MAIN exists */
1245#define get_screen(a,b) (SCREEN_MAIN)
1245#define RB_SCREEN_STRUCT(luastate, narg) \ 1246#define RB_SCREEN_STRUCT(luastate, narg) \
1246 rb->screens[SCREEN_MAIN] 1247 rb->screens[SCREEN_MAIN]
1247#define RB_SCREENS(luastate, narg, func, ...) \ 1248#define RB_SCREENS(luastate, narg, func, ...) \
@@ -1379,7 +1380,12 @@ RB_WRAP(font_getstringsize)
1379 1380
1380RB_WRAP(lcd_framebuffer) 1381RB_WRAP(lcd_framebuffer)
1381{ 1382{
1382 rli_wrap(L, *rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT); 1383 int screen = get_screen(L, 1);
1384 static struct viewport vp;
1385 rb->viewport_set_fullscreen(&vp, screen);
1386 rli_wrap(L, vp.buffer->data,
1387 RB_SCREEN_STRUCT(L, 1)->lcdwidth,
1388 RB_SCREEN_STRUCT(L, 1)->lcdheight);
1383 return 1; 1389 return 1;
1384} 1390}
1385 1391
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
620static struct osd osd; 620static struct osd osd;
621static struct fps fps NOCACHEBSS_ATTR; /* Accessed on other processor */ 621static struct fps fps NOCACHEBSS_ATTR; /* Accessed on other processor */
622 622
623#ifdef LCD_PORTRAIT
624static fb_data* get_framebuffer(void)
625{
626 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
627 return vp_main->buffer->fb_ptr;
628}
629#endif
630
623static void osd_show(unsigned show); 631static void osd_show(unsigned show);
624 632
625#ifdef LCD_LANDSCAPE 633#ifdef LCD_LANDSCAPE
@@ -821,7 +829,7 @@ static void draw_oriented_mono_bitmap_part(const unsigned char *src,
821 src_y &= 7; 829 src_y &= 7;
822 src_end = src + width; 830 src_end = src + width;
823 831
824 dst = *rb->lcd_framebuffer + (LCD_WIDTH - y) + x*LCD_WIDTH; 832 dst = get_framebuffer() + (LCD_WIDTH - y) + x*LCD_WIDTH;
825 do 833 do
826 { 834 {
827 const unsigned char *src_col = src++; 835 const unsigned char *src_col = src++;
@@ -953,7 +961,7 @@ static void draw_oriented_alpha_bitmap_part(const unsigned char *src,
953 fg_pattern = rb->lcd_get_foreground(); 961 fg_pattern = rb->lcd_get_foreground();
954 /*bg_pattern=*/ rb->lcd_get_background(); 962 /*bg_pattern=*/ rb->lcd_get_background();
955 963
956 dst_start = *rb->lcd_framebuffer + (LCD_WIDTH - y - 1) + x*LCD_WIDTH; 964 dst_start = get_framebuffer() + (LCD_WIDTH - y - 1) + x*LCD_WIDTH;
957 int col, row = height; 965 int col, row = height;
958 unsigned data, pixels; 966 unsigned data, pixels;
959 unsigned skip_end = (stride - width); 967 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)
838 int width, height; 838 int width, height;
839 int maxwidth, maxheight; 839 int maxwidth, maxheight;
840 840
841 rb->lcd_set_viewport(osd_get_viewport()); 841 struct viewport *last_vp = rb->lcd_set_viewport(osd_get_viewport());
842 osd_get_max_dims(&maxwidth, &maxheight); 842 osd_get_max_dims(&maxwidth, &maxheight);
843 rb->lcd_getstringsize(osc_osd_message, &width, &height); 843 rb->lcd_getstringsize(osc_osd_message, &width, &height);
844 rb->lcd_set_viewport(NULL); /* to regular viewport */ 844 rb->lcd_set_viewport(last_vp); /* to regular viewport */
845 845
846 width += 2 + 2*OSC_OSD_MARGIN_SIZE; 846 width += 2 + 2*OSC_OSD_MARGIN_SIZE;
847 if (width > maxwidth) 847 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 @@
35#include "lib/configfile.h" 35#include "lib/configfile.h"
36#include "lib/playback_control.h" 36#include "lib/playback_control.h"
37#include "lib/helper.h" 37#include "lib/helper.h"
38static fb_data *lcd_fb;
38 39
39/*Allows split screen jump and makes pacman invincible if you start at 18 credits (for testing purposes)*/ 40/*Allows split screen jump and makes pacman invincible if you start at 18 credits (for testing purposes)*/
40//#define CHEATS 1 41//#define CHEATS 1
@@ -704,7 +705,7 @@ static int gameProc( void )
704 rb->lcd_blit_pal256( video_buffer, 0, 0, XOFS, YOFS, 705 rb->lcd_blit_pal256( video_buffer, 0, 0, XOFS, YOFS,
705 ScreenWidth, ScreenHeight); 706 ScreenWidth, ScreenHeight);
706#else 707#else
707 blit_display(*rb->lcd_framebuffer,video_buffer); 708 blit_display(lcd_fb ,video_buffer);
708#endif 709#endif
709 710
710 if (settings.showfps) { 711 if (settings.showfps) {
@@ -743,6 +744,9 @@ enum plugin_status plugin_start(const void* parameter)
743 rb->lcd_clear_display(); 744 rb->lcd_clear_display();
744 rb->lcd_update(); 745 rb->lcd_update();
745 746
747 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
748 lcd_fb = vp_main->buffer->fb_ptr;
749
746 /* Set the default settings */ 750 /* Set the default settings */
747 settings.difficulty = 0; /* Normal */ 751 settings.difficulty = 0; /* Normal */
748 settings.numlives = 2; /* 3 lives */ 752 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 @@
35#include "lib/feature_wrappers.h" 35#include "lib/feature_wrappers.h"
36 36
37/******************************* Globals ***********************************/ 37/******************************* Globals ***********************************/
38static fb_data *lcd_fb;
38 39
39/* 40/*
40 * Targets which use plugin_get_audio_buffer() can't have playback from 41 * Targets which use plugin_get_audio_buffer() can't have playback from
@@ -190,7 +191,7 @@ GREY_INFO_STRUCT
190#define BUFFER_HEIGHT _grey_info.height 191#define BUFFER_HEIGHT _grey_info.height
191typedef unsigned char pix_t; 192typedef unsigned char pix_t;
192#else /* LCD_DEPTH >= 8 */ 193#else /* LCD_DEPTH >= 8 */
193#define LCD_BUF *rb->lcd_framebuffer 194#define LCD_BUF lcd_fb
194#define G_PIX LCD_RGBPACK 195#define G_PIX LCD_RGBPACK
195#define N_PIX LCD_RGBPACK 196#define N_PIX LCD_RGBPACK
196#define G_BRIGHT(y) LCD_RGBPACK(y,y,y) 197#define G_BRIGHT(y) LCD_RGBPACK(y,y,y)
@@ -3847,6 +3848,9 @@ static int pictureflow_main(void)
3847 3848
3848enum plugin_status plugin_start(const void *parameter) 3849enum plugin_status plugin_start(const void *parameter)
3849{ 3850{
3851 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
3852 lcd_fb = vp_main->buffer->fb_ptr;
3853
3850 int ret; 3854 int ret;
3851 (void) parameter; 3855 (void) parameter;
3852 3856
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 @@
36 36
37 37
38/******************************* Globals ***********************************/ 38/******************************* Globals ***********************************/
39static fb_data *lcd_fb;
40
39 41
40static unsigned char wave_array[256]; /* Pre calculated wave array */ 42static unsigned char wave_array[256]; /* Pre calculated wave array */
41#ifdef HAVE_LCD_COLOR 43#ifdef HAVE_LCD_COLOR
@@ -201,9 +203,9 @@ int main(void)
201#ifdef HAVE_LCD_COLOR 203#ifdef HAVE_LCD_COLOR
202 shades_generate(time++); /* dynamically */ 204 shades_generate(time++); /* dynamically */
203#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 205#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
204 ptr = (unsigned char*)*rb->lcd_framebuffer; 206 ptr = (unsigned char*)lcd_fb;
205#else 207#else
206 ptr = *rb->lcd_framebuffer; 208 ptr = lcd_fb;
207#endif 209#endif
208 210
209#else 211#else
@@ -237,7 +239,7 @@ int main(void)
237 p4-=sp4; 239 p4-=sp4;
238#ifdef HAVE_LCD_COLOR 240#ifdef HAVE_LCD_COLOR
239#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 241#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
240 rb->lcd_blit_pal256( (unsigned char*)*rb->lcd_framebuffer, 242 rb->lcd_blit_pal256( (unsigned char*)lcd_fb,
241 0,0,0,0,LCD_WIDTH,LCD_HEIGHT); 243 0,0,0,0,LCD_WIDTH,LCD_HEIGHT);
242#else 244#else
243 rb->lcd_update(); 245 rb->lcd_update();
@@ -326,5 +328,8 @@ enum plugin_status plugin_start(const void* parameter)
326#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 328#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
327 rb->lcd_set_mode(LCD_MODE_PAL256); 329 rb->lcd_set_mode(LCD_MODE_PAL256);
328#endif 330#endif
331 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
332 lcd_fb = vp_main->buffer->fb_ptr;
333
329 return main(); 334 return main();
330} 335}
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;
310#endif 310#endif
311 311
312/* clipping stuff */ 312/* clipping stuff */
313static fb_data *lcd_fb;
313static struct viewport clip_rect; 314static struct viewport clip_rect;
314static bool clipped = false, zoom_enabled = false, view_mode = true, mouse_mode = false; 315static bool clipped = false, zoom_enabled = false, view_mode = true, mouse_mode = false;
315 316
@@ -1016,7 +1017,7 @@ static void rb_draw_line(void *handle, int x1, int y1, int x2, int y2,
1016 } 1017 }
1017 else 1018 else
1018#endif 1019#endif
1019 draw_antialiased_line(*rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); 1020 draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
1020 } 1021 }
1021 else 1022 else
1022 { 1023 {
@@ -1294,7 +1295,7 @@ static void rb_draw_poly(void *handle, int *coords, int npoints,
1294 x2, y2); 1295 x2, y2);
1295 } 1296 }
1296 else 1297 else
1297 draw_antialiased_line(*rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); 1298 draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
1298 1299
1299#ifdef DEBUG_MENU 1300#ifdef DEBUG_MENU
1300 if(debug_settings.polyanim) 1301 if(debug_settings.polyanim)
@@ -1319,7 +1320,7 @@ static void rb_draw_poly(void *handle, int *coords, int npoints,
1319 x2, y2); 1320 x2, y2);
1320 } 1321 }
1321 else 1322 else
1322 draw_antialiased_line(*rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2); 1323 draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, x1, y1, x2, y2);
1323 } 1324 }
1324 else 1325 else
1325 { 1326 {
@@ -1474,7 +1475,7 @@ static void rb_blitter_save(void *handle, blitter *bl, int x, int y)
1474 1475
1475 trim_rect(&x, &y, &w, &h); 1476 trim_rect(&x, &y, &w, &h);
1476 1477
1477 fb_data *fb = zoom_enabled ? zoom_fb : *rb->lcd_framebuffer; 1478 fb_data *fb = zoom_enabled ? zoom_fb : lcd_fb;
1478 LOGF("rb_blitter_save(%d, %d, %d, %d)", x, y, w, h); 1479 LOGF("rb_blitter_save(%d, %d, %d, %d)", x, y, w, h);
1479 for(int i = 0; i < h; ++i) 1480 for(int i = 0; i < h; ++i)
1480 { 1481 {
@@ -1778,9 +1779,9 @@ static void timer_cb(void)
1778 static bool what = false; 1779 static bool what = false;
1779 what = !what; 1780 what = !what;
1780 if(what) 1781 if(what)
1781 *rb->lcd_framebuffer[0] = LCD_BLACK; 1782 lcd_fb[0] = LCD_BLACK;
1782 else 1783 else
1783 *rb->lcd_framebuffer[0] = LCD_WHITE; 1784 lcd_fb[0] = LCD_WHITE;
1784 rb->lcd_update(); 1785 rb->lcd_update();
1785 } 1786 }
1786#endif 1787#endif
@@ -2909,7 +2910,7 @@ static void bench_aa(void)
2909 int i = 0; 2910 int i = 0;
2910 while(*rb->current_tick < next) 2911 while(*rb->current_tick < next)
2911 { 2912 {
2912 draw_antialiased_line(*rb->lcd_framebuffer, LCD_WIDTH, LCD_HEIGHT, 0, 0, 20, 31); 2913 draw_antialiased_line(lcd_fb, LCD_WIDTH, LCD_HEIGHT, 0, 0, 20, 31);
2913 ++i; 2914 ++i;
2914 } 2915 }
2915 rb->splashf(HZ, "%d AA lines/sec", i); 2916 rb->splashf(HZ, "%d AA lines/sec", i);
@@ -3843,6 +3844,8 @@ enum plugin_status plugin_start(const void *param)
3843 3844
3844 giant_buffer = rb->plugin_get_buffer(&giant_buffer_len); 3845 giant_buffer = rb->plugin_get_buffer(&giant_buffer_len);
3845 init_tlsf(); 3846 init_tlsf();
3847 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
3848 lcd_fb = vp_main->buffer->fb_ptr;
3846 3849
3847 if(!strcmp(thegame.name, "Solo")) 3850 if(!strcmp(thegame.name, "Solo"))
3848 { 3851 {
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;
64fb_data *vdest; 64fb_data *vdest;
65#endif 65#endif
66 66
67static fb_data* get_framebuffer(void)
68{
69 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
70 return vp_main->buffer->fb_ptr;
71}
72
67#ifndef ASM_UPDATEPATPIX 73#ifndef ASM_UPDATEPATPIX
68static void updatepatpix(void) ICODE_ATTR; 74static void updatepatpix(void) ICODE_ATTR;
69static void updatepatpix(void) 75static void updatepatpix(void)
@@ -741,10 +747,11 @@ static void spr_scan(void)
741 747
742void lcd_begin(void) 748void lcd_begin(void)
743{ 749{
750 fb_data *lcd_fb = get_framebuffer();
744#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 751#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
745 vdest=(unsigned char*)*rb->lcd_framebuffer; 752 vdest=(unsigned char*)lcd_fb;
746#else 753#else
747 vdest=*rb->lcd_framebuffer; 754 vdest=lcd_fb;
748#endif 755#endif
749 756
750#ifdef HAVE_LCD_COLOR 757#ifdef HAVE_LCD_COLOR
@@ -975,9 +982,9 @@ void lcd_refreshline(void)
975 982
976#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 983#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
977 if(options.scaling==3) { 984 if(options.scaling==3) {
978 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); 985 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);
979 } else { 986 } else {
980 rb->lcd_blit_pal256((unsigned char*)*rb->lcd_framebuffer,0,0,0,0,LCD_WIDTH,LCD_HEIGHT); 987 rb->lcd_blit_pal256((unsigned char*)lcd_fb,0,0,0,0,LCD_WIDTH,LCD_HEIGHT);
981 } 988 }
982#else 989#else
983 if(options.scaling==3) { 990 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;
282void vid_update(int scanline) 282void vid_update(int scanline)
283{ 283{
284 register int cnt=0; 284 register int cnt=0;
285 static fb_data *lcd_fb = NULL;
286 if (!lcd_fb)
287 {
288 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
289 lcd_fb = vp_main->buffer->fb_ptr;
290 }
285 int scanline_remapped; 291 int scanline_remapped;
286#if (LCD_HEIGHT == 64) && (LCD_DEPTH == 1) /* Archos, Clip, m200v4 */ 292#if (LCD_HEIGHT == 64) && (LCD_DEPTH == 1) /* Archos, Clip, m200v4 */
287 int balance = 0; 293 int balance = 0;
@@ -290,7 +296,7 @@ void vid_update(int scanline)
290 else if (fb.mode==2) 296 else if (fb.mode==2)
291 scanline-=8; 297 scanline-=8;
292 scanline_remapped = scanline / 16; 298 scanline_remapped = scanline / 16;
293 frameb = *rb->lcd_framebuffer + scanline_remapped * LCD_WIDTH; 299 frameb = lcd_fb + scanline_remapped * LCD_WIDTH;
294 while (cnt < 160) { 300 while (cnt < 160) {
295 balance += LCD_WIDTH; 301 balance += LCD_WIDTH;
296 if (balance > 0) 302 if (balance > 0)
@@ -316,7 +322,7 @@ void vid_update(int scanline)
316 else if (fb.mode==2) 322 else if (fb.mode==2)
317 scanline-=8; 323 scanline-=8;
318 scanline_remapped = scanline / 4; 324 scanline_remapped = scanline / 4;
319 frameb = *rb->lcd_framebuffer + scanline_remapped * LCD_WIDTH; 325 frameb = lcd_fb + scanline_remapped * LCD_WIDTH;
320 while (cnt < 160) { 326 while (cnt < 160) {
321 *(frameb++) = (scan.buf[0][cnt]&0x3) | 327 *(frameb++) = (scan.buf[0][cnt]&0x3) |
322 ((scan.buf[1][cnt]&0x3)<<2) | 328 ((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 @@
67#define RBSDL_EXTRA0 SDLK_0 67#define RBSDL_EXTRA0 SDLK_0
68 68
69/* Initialization/Query functions */ 69/* Initialization/Query functions */
70static fb_data *lcd_fb;
70static int ROCKBOX_VideoInit(_THIS, SDL_PixelFormat *vformat); 71static int ROCKBOX_VideoInit(_THIS, SDL_PixelFormat *vformat);
71static SDL_Rect **ROCKBOX_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 72static SDL_Rect **ROCKBOX_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
72static SDL_Surface *ROCKBOX_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 73static 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)
447 448
448int ROCKBOX_VideoInit(_THIS, SDL_PixelFormat *vformat) 449int ROCKBOX_VideoInit(_THIS, SDL_PixelFormat *vformat)
449{ 450{
451 struct viewport *vp_main = *(rb->screens[SCREEN_MAIN]->current_viewport);
452 lcd_fb = vp_main->buffer->fb_ptr;
450 /* we change this during the SDL_SetVideoMode implementation... */ 453 /* we change this during the SDL_SetVideoMode implementation... */
451 rb_pixelformat(vformat); 454 rb_pixelformat(vformat);
452 455
@@ -639,7 +642,7 @@ SDL_Surface *ROCKBOX_SetVideoMode(_THIS, SDL_Surface *current,
639 this->hidden->w = current->w = width; 642 this->hidden->w = current->w = width;
640 this->hidden->h = current->h = height; 643 this->hidden->h = current->h = height;
641 current->pitch = current->w * (bpp / 8); 644 current->pitch = current->w * (bpp / 8);
642 current->pixels = this->hidden->direct ? *rb->lcd_framebuffer : this->hidden->buffer; 645 current->pixels = this->hidden->direct ? lcd_fb : this->hidden->buffer;
643 646
644 /* We're done */ 647 /* We're done */
645 return(current); 648 return(current);
@@ -674,7 +677,7 @@ static void flip_pixels(int x, int y, int w, int h)
674 for(int x_0 = x; x_0 < x + w; ++x_0) 677 for(int x_0 = x; x_0 < x + w; ++x_0)
675 { 678 {
676 /* swap pixels directly in the framebuffer */ 679 /* swap pixels directly in the framebuffer */
677 *rb->lcd_framebuffer[y_0 * LCD_WIDTH + x_0] = swap16(*rb->lcd_framebuffer[y_0 * LCD_WIDTH + x_0]); 680 lcd_fb[y_0 * LCD_WIDTH + x_0] = swap16(lcd_fb[y_0 * LCD_WIDTH + x_0]);
678 } 681 }
679 } 682 }
680} 683}
@@ -684,7 +687,7 @@ static void blit_rotated(fb_data *src, int x, int y, int w, int h)
684{ 687{
685 for(int y_0 = y; y_0 < y + h; ++y_0) 688 for(int y_0 = y; y_0 < y + h; ++y_0)
686 for(int x_0 = x; x_0 < x + w; ++x_0) 689 for(int x_0 = x; x_0 < x + w; ++x_0)
687 *rb->lcd_framebuffer[x_0 * LCD_WIDTH + y_0] = src[(LCD_WIDTH - y_0) * LCD_HEIGHT + x_0]; 690 lcd_fb[x_0 * LCD_WIDTH + y_0] = src[(LCD_WIDTH - y_0) * LCD_HEIGHT + x_0];
688} 691}
689 692
690static void ROCKBOX_UpdateRects(_THIS, int numrects, SDL_Rect *rects) 693static void ROCKBOX_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
@@ -720,7 +723,7 @@ static void ROCKBOX_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
720 723
721 out_bmp.width = LCD_WIDTH; 724 out_bmp.width = LCD_WIDTH;
722 out_bmp.height = LCD_HEIGHT; 725 out_bmp.height = LCD_HEIGHT;
723 out_bmp.data = (char*)*rb->lcd_framebuffer; 726 out_bmp.data = (char*)lcd_fb;
724 simple_resize_bitmap(&in_bmp, &out_bmp); 727 simple_resize_bitmap(&in_bmp, &out_bmp);
725 } 728 }
726 else 729 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];
64enum plugin_status plugin_start(const void* parameter) 64enum plugin_status plugin_start(const void* parameter)
65{ 65{
66 (void)parameter; 66 (void)parameter;
67 67 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
68 b = *rb->lcd_framebuffer; 68 b = vp_main->buffer->fb_ptr;
69 69
70 rb->lcd_set_background(LCD_RGBPACK(0,0,0)); 70 rb->lcd_set_background(LCD_RGBPACK(0,0,0));
71 rb->lcd_clear_display(); // TODO: Optimizes this by e.g. invalidating rects 71 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 =
35{ 35{
36 .x = 0, 36 .x = 0,
37 .y = 0, 37 .y = 0,
38 .width = LCD_WIDTH, 38 .width = LCD_WIDTH/ 2 + LCD_WIDTH / 3,
39 .height = 20, 39 .height = 20,
40 .font = FONT_UI, 40 .font = FONT_UI,
41 .drawmode = DRMODE_SOLID, 41 .drawmode = DRMODE_SOLID,
@@ -120,15 +120,37 @@ static struct viewport rvp1 =
120 120
121#endif 121#endif
122 122
123static void *test_address_fn(int x, int y)
124{
125 struct frame_buffer_t *fb = vp0.buffer;
126
127#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
128 size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y;
129#else
130 size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x;
131#endif
132 return fb->fb_ptr + (element % fb->elems);
133}
123 134
124enum plugin_status plugin_start(const void* parameter) 135enum plugin_status plugin_start(const void* parameter)
125{ 136{
126 (void)parameter; 137 (void)parameter;
127 char buf[80]; 138 char buf[80];
128 int i,y; 139 int i,y;
140 fb_data vp_buffer[LCD_NBELEMS(vp0.width, vp0.height)];
129 141
142 struct frame_buffer_t fb;
143
144 fb.stride = STRIDE_MAIN(vp0.width, vp0.height);
145
146 fb.fb_ptr = vp_buffer;
147 fb.elems = LCD_NBELEMS(vp0.width, vp0.height);
148 fb.get_address_fn = &test_address_fn;
149
150 rb->viewport_set_buffer(&vp0, &fb, SCREEN_MAIN);
130 rb->screens[SCREEN_MAIN]->set_viewport(&vp0); 151 rb->screens[SCREEN_MAIN]->set_viewport(&vp0);
131 rb->screens[SCREEN_MAIN]->clear_viewport(); 152 rb->screens[SCREEN_MAIN]->clear_viewport();
153
132 rb->screens[SCREEN_MAIN]->puts_scroll(0,0,"Viewport testing plugin - this is a scrolling title"); 154 rb->screens[SCREEN_MAIN]->puts_scroll(0,0,"Viewport testing plugin - this is a scrolling title");
133 155
134 rb->screens[SCREEN_MAIN]->set_viewport(&vp1); 156 rb->screens[SCREEN_MAIN]->set_viewport(&vp1);
@@ -192,6 +214,9 @@ enum plugin_status plugin_start(const void* parameter)
192 214
193 rb->screens[SCREEN_REMOTE]->update(); 215 rb->screens[SCREEN_REMOTE]->update();
194#endif 216#endif
217 rb->button_clear_queue();
218 while(rb->button_get(true) <= BUTTON_NONE)
219 ;;
195 220
196 rb->button_get(true); 221 rb->button_get(true);
197 222
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 @@
40#include "engine.h" 40#include "engine.h"
41 41
42static struct System* save_sys; 42static struct System* save_sys;
43static fb_data *lcd_fb = NULL;
43 44
44static bool sys_save_settings(struct System* sys) 45static bool sys_save_settings(struct System* sys)
45{ 46{
@@ -438,6 +439,8 @@ void sys_init(struct System* sys, const char* title)
438 { 439 {
439 sys_reset_settings(sys); 440 sys_reset_settings(sys);
440 } 441 }
442 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
443 lcd_fb = vp_main->buffer->fb_ptr;
441} 444}
442 445
443void sys_destroy(struct System* sys) 446void 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
584 struct bitmap out_bmp; 587 struct bitmap out_bmp;
585 out_bmp.width = LCD_WIDTH; 588 out_bmp.width = LCD_WIDTH;
586 out_bmp.height = LCD_HEIGHT; 589 out_bmp.height = LCD_HEIGHT;
587 out_bmp.data = (unsigned char*) *rb->lcd_framebuffer; 590 out_bmp.data = (unsigned char*) lcd_fb;
588 591
589#ifdef HAVE_LCD_COLOR 592#ifdef HAVE_LCD_COLOR
590 if(sys->settings.scaling_quality == 1) 593 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
631 { 634 {
632#ifdef HAVE_LCD_COLOR 635#ifdef HAVE_LCD_COLOR
633 int r, g, b; 636 int r, g, b;
634 fb_data pix = *rb->lcd_framebuffer[y * LCD_WIDTH + x]; 637 fb_data pix = lcd_fb[y * LCD_WIDTH + x];
635#if (LCD_DEPTH > 24) 638#if (LCD_DEPTH > 24)
636 r = 0xff - pix.r; 639 r = 0xff - pix.r;
637 g = 0xff - pix.g; 640 g = 0xff - pix.g;
638 b = 0xff - pix.b; 641 b = 0xff - pix.b;
639 *rb->lcd_framebuffer[y * LCD_WIDTH + x] = (fb_data) { b, g, r, 255 }; 642 lcd_fb[y * LCD_WIDTH + x] = (fb_data) { b, g, r, 255 };
640#elif (LCD_DEPTH == 24) 643#elif (LCD_DEPTH == 24)
641 r = 0xff - pix.r; 644 r = 0xff - pix.r;
642 g = 0xff - pix.g; 645 g = 0xff - pix.g;
643 b = 0xff - pix.b; 646 b = 0xff - pix.b;
644 *rb->lcd_framebuffer[y * LCD_WIDTH + x] = (fb_data) { b, g, r }; 647 lcd_fb[y * LCD_WIDTH + x] = (fb_data) { b, g, r };
645#else 648#else
646 r = RGB_UNPACK_RED (pix); 649 r = RGB_UNPACK_RED (pix);
647 g = RGB_UNPACK_GREEN(pix); 650 g = RGB_UNPACK_GREEN(pix);
648 b = RGB_UNPACK_BLUE (pix); 651 b = RGB_UNPACK_BLUE (pix);
649 *rb->lcd_framebuffer[y * LCD_WIDTH + x] = LCD_RGBPACK(0xff - r, 0xff - g, 0xff - b); 652 lcd_fb[y * LCD_WIDTH + x] = LCD_RGBPACK(0xff - r, 0xff - g, 0xff - b);
650#endif 653#endif
651#else 654#else
652 *rb->lcd_framebuffer[y * LCD_WIDTH + x] = LCD_BRIGHTNESS(0xff - *rb->lcd_framebuffer[y * LCD_WIDTH + x]); 655 lcd_fb[y * LCD_WIDTH + x] = LCD_BRIGHTNESS(0xff - lcd_fb[y * LCD_WIDTH + x]);
653#endif 656#endif
654 } 657 }
655 } 658 }
@@ -671,14 +674,14 @@ void sys_copyRect(struct System* sys, uint16_t x, uint16_t y, uint16_t w, uint16
671 if(prev_frames && orig_fb) 674 if(prev_frames && orig_fb)
672 { 675 {
673 676
674 rb->memcpy(orig_fb, *rb->lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT); 677 rb->memcpy(orig_fb, lcd_fb, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
675 /* fancy useless slow motion blur */ 678 /* fancy useless slow motion blur */
676 for(int y = 0; y < LCD_HEIGHT; ++y) 679 for(int y = 0; y < LCD_HEIGHT; ++y)
677 { 680 {
678 for(int x = 0; x < LCD_WIDTH; ++x) 681 for(int x = 0; x < LCD_WIDTH; ++x)
679 { 682 {
680 int r, g, b; 683 int r, g, b;
681 fb_data pix = *rb->lcd_framebuffer[y * LCD_WIDTH + x]; 684 fb_data pix = lcd_fb[y * LCD_WIDTH + x];
682 r = RGB_UNPACK_RED (pix); 685 r = RGB_UNPACK_RED (pix);
683 g = RGB_UNPACK_GREEN(pix); 686 g = RGB_UNPACK_GREEN(pix);
684 b = RGB_UNPACK_BLUE (pix); 687 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
695 r /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1); 698 r /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
696 g /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1); 699 g /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
697 b /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1); 700 b /= (BLUR_FRAMES + 1) / 2 * (1 + BLUR_FRAMES + 1);
698 *rb->lcd_framebuffer[y * LCD_WIDTH + x] = LCD_RGBPACK(r, g, b); 701 lcd_fb[y * LCD_WIDTH + x] = LCD_RGBPACK(r, g, b);
699 } 702 }
700 } 703 }
701 prev_baseidx -= LCD_WIDTH * LCD_HEIGHT; 704 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] = {
33 LCD_RGBPACK(IB1, IB1, IB0), LCD_RGBPACK(IB1, IB1, IB1), 33 LCD_RGBPACK(IB1, IB1, IB0), LCD_RGBPACK(IB1, IB1, IB1),
34}; 34};
35 35
36static fb_data *lcd_fb = NULL;
37
36void init_spect_scr(void) 38void init_spect_scr(void)
37{ 39{
38 int i; 40 int i;
@@ -49,6 +51,11 @@ void init_spect_scr(void)
49 51
50void update_screen(void) 52void update_screen(void)
51{ 53{
54 if (!lcd_fb)
55 {
56 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
57 lcd_fb = vp_main->buffer->fb_ptr;
58 }
52 fb_data *frameb; 59 fb_data *frameb;
53 60
54 int y=0; 61 int y=0;
@@ -58,7 +65,7 @@ void update_screen(void)
58 byte *scrptr; 65 byte *scrptr;
59 scrptr = (byte *) SPNM(image); 66 scrptr = (byte *) SPNM(image);
60 */ 67 */
61 frameb = *rb->lcd_framebuffer; 68 frameb = lcd_fb;
62 for ( y = 0 ; y < HEIGHT*WIDTH; y++ ){ 69 for ( y = 0 ; y < HEIGHT*WIDTH; y++ ){
63 frameb[y] = FB_SCALARPACK(_16bpp_colors[(unsigned)sp_image[y]]); 70 frameb[y] = FB_SCALARPACK(_16bpp_colors[(unsigned)sp_image[y]]);
64 } 71 }
@@ -68,7 +75,7 @@ void update_screen(void)
68 int srcx, srcy=0; /* x / y coordinates in source image */ 75 int srcx, srcy=0; /* x / y coordinates in source image */
69 unsigned char* image; 76 unsigned char* image;
70 image = sp_image + ( (Y_OFF)*(WIDTH) ) + X_OFF; 77 image = sp_image + ( (Y_OFF)*(WIDTH) ) + X_OFF;
71 frameb = *rb->lcd_framebuffer; 78 frameb = lcd_fb;
72 for(y = 0; y < LCD_HEIGHT; y++) 79 for(y = 0; y < LCD_HEIGHT; y++)
73 { 80 {
74 srcx = 0; /* reset our x counter before each row... */ 81 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] = {
26 0, 1, 1, 1, 2, 2, 3, 3 26 0, 1, 1, 1, 2, 2, 3, 3
27}; 27};
28 28
29static fb_data *lcd_fb = NULL;
30
29void init_spect_scr(void) 31void init_spect_scr(void)
30{ 32{
31 int i; 33 int i;
@@ -41,6 +43,11 @@ void init_spect_scr(void)
41} 43}
42void update_screen(void) 44void update_screen(void)
43{ 45{
46 if (!lcd_fb)
47 {
48 struct viewport *vp_main = rb->lcd_set_viewport(NULL);
49 lcd_fb = vp_main->buffer->fb_ptr;
50 }
44 fb_data *frameb; 51 fb_data *frameb;
45 int y=0; 52 int y=0;
46 int x=0; 53 int x=0;
@@ -51,7 +58,7 @@ void update_screen(void)
51#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 58#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
52 for(y = 0; y < LCD_HEIGHT; y++) 59 for(y = 0; y < LCD_HEIGHT; y++)
53 { 60 {
54 frameb = *rb->lcd_framebuffer + (y) * FB_WIDTH; 61 frameb = lcd_fb + (y) * FB_WIDTH;
55 srcx = 0; /* reset our x counter before each row... */ 62 srcx = 0; /* reset our x counter before each row... */
56 for(x = 0; x < LCD_WIDTH; x++) 63 for(x = 0; x < LCD_WIDTH; x++)
57 { 64 {
@@ -67,7 +74,7 @@ void update_screen(void)
67 int shift; 74 int shift;
68 for(y = 0; y < LCD_HEIGHT; y++) 75 for(y = 0; y < LCD_HEIGHT; y++)
69 { 76 {
70 frameb = *rb->lcd_framebuffer + (y/4) * LCD_WIDTH; 77 frameb = lcd_fb + (y/4) * LCD_WIDTH;
71 srcx = 0; /* reset our x counter before each row... */ 78 srcx = 0; /* reset our x counter before each row... */
72 shift = ((y & 3 ) * 2 ); 79 shift = ((y & 3 ) * 2 );
73 mask = ~pixmask[y & 3]; 80 mask = ~pixmask[y & 3];
@@ -84,7 +91,7 @@ void update_screen(void)
84 int shift; 91 int shift;
85 for(y = 0; y < LCD_HEIGHT; y++) 92 for(y = 0; y < LCD_HEIGHT; y++)
86 { 93 {
87 frameb = *rb->lcd_framebuffer + (y/8) * LCD_WIDTH; 94 frameb = lcd_fb + (y/8) * LCD_WIDTH;
88 srcx = 0; /* reset our x counter before each row... */ 95 srcx = 0; /* reset our x counter before each row... */
89 shift = (y & 7); 96 shift = (y & 7);
90 mask = ~pixmask[y & 7]; 97 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)
1009 int sc_w = sc->getwidth(), sc_h = sc->getheight(); 1009 int sc_w = sc->getwidth(), sc_h = sc->getheight();
1010 viewport_set_defaults(&vp, sc->screen_type); 1010 viewport_set_defaults(&vp, sc->screen_type);
1011 vp.flags |= VP_FLAG_ALIGN_CENTER; 1011 vp.flags |= VP_FLAG_ALIGN_CENTER;
1012 sc->set_viewport(&vp); 1012 struct viewport *last_vp = sc->set_viewport(&vp);
1013 text_h = sc->getcharheight(); 1013 text_h = sc->getcharheight();
1014 button_h = GRID_SIZE(sc->screen_type, text_h); 1014 button_h = GRID_SIZE(sc->screen_type, text_h);
1015 text_y = (button_h - text_h) / 2 + 1; 1015 text_y = (button_h - text_h) / 2 + 1;
@@ -1039,7 +1039,7 @@ static void kbd_draw_buttons(struct keyboard_parameters *pm, struct screen *sc)
1039 vp.x += vp.width; 1039 vp.x += vp.width;
1040 sc->vline(0, 0, button_h); 1040 sc->vline(0, 0, button_h);
1041 sc->putsxy(0, text_y, str(LANG_KBD_CANCEL)); 1041 sc->putsxy(0, text_y, str(LANG_KBD_CANCEL));
1042 sc->set_viewport(NULL); 1042 sc->set_viewport(last_vp);
1043} 1043}
1044 1044
1045static int keyboard_touchscreen(struct keyboard_parameters *pm, 1045static 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 @@
35#include "backlight.h" 35#include "backlight.h"
36#include "screen_access.h" 36#include "screen_access.h"
37#include "backdrop.h" 37#include "backdrop.h"
38#include "viewport.h"
38 39
39/* some helper functions to calculate metrics on the fly */ 40/* some helper functions to calculate metrics on the fly */
40static int screen_helper_getcharwidth(void) 41static int screen_helper_getcharwidth(void)
@@ -87,7 +88,17 @@ static void screen_helper_put_line(int x, int y, struct line_desc *line,
87 va_end(ap); 88 va_end(ap);
88} 89}
89 90
91void screen_helper_lcd_viewport_set_buffer(struct viewport *vp, struct frame_buffer_t *buffer)
92{
93 viewport_set_buffer(vp, buffer, SCREEN_MAIN);
94}
95
90#if NB_SCREENS == 2 96#if NB_SCREENS == 2
97void screen_helper_lcd_remote_viewport_set_buffer(struct viewport *vp, struct frame_buffer_t *buffer)
98{
99 viewport_set_buffer(vp, buffer, SCREEN_REMOTE);
100}
101
91static int screen_helper_remote_getcharwidth(void) 102static int screen_helper_remote_getcharwidth(void)
92{ 103{
93 return font_get(lcd_remote_getfont())->maxwidth; 104 return font_get(lcd_remote_getfont())->maxwidth;
@@ -156,7 +167,11 @@ struct screen screens[NB_SCREENS] =
156 .has_disk_led=true, 167 .has_disk_led=true,
157#endif 168#endif
158 .set_drawmode=&screen_helper_set_drawmode, 169 .set_drawmode=&screen_helper_set_drawmode,
170 .init_viewport=&lcd_init_viewport,
159 .set_viewport=&lcd_set_viewport, 171 .set_viewport=&lcd_set_viewport,
172 .set_viewport_ex=&lcd_set_viewport_ex,
173 .viewport_set_buffer = &screen_helper_lcd_viewport_set_buffer,
174 .current_viewport = &lcd_current_viewport,
160 .getwidth=&lcd_getwidth, 175 .getwidth=&lcd_getwidth,
161 .getheight=&lcd_getheight, 176 .getheight=&lcd_getheight,
162 .getstringsize=&lcd_getstringsize, 177 .getstringsize=&lcd_getstringsize,
@@ -221,7 +236,6 @@ struct screen screens[NB_SCREENS] =
221 .backdrop_load=&backdrop_load, 236 .backdrop_load=&backdrop_load,
222 .backdrop_show=&backdrop_show, 237 .backdrop_show=&backdrop_show,
223#endif 238#endif
224 .set_framebuffer = (void*)lcd_set_framebuffer,
225#if defined(HAVE_LCD_COLOR) 239#if defined(HAVE_LCD_COLOR)
226 .gradient_fillrect = lcd_gradient_fillrect, 240 .gradient_fillrect = lcd_gradient_fillrect,
227 .gradient_fillrect_part = lcd_gradient_fillrect_part, 241 .gradient_fillrect_part = lcd_gradient_fillrect_part,
@@ -241,7 +255,11 @@ struct screen screens[NB_SCREENS] =
241 .getcharheight=screen_helper_remote_getcharheight, 255 .getcharheight=screen_helper_remote_getcharheight,
242 .has_disk_led=false, 256 .has_disk_led=false,
243 .set_drawmode=&lcd_remote_set_drawmode, 257 .set_drawmode=&lcd_remote_set_drawmode,
258 .init_viewport=&lcd_remote_init_viewport,
244 .set_viewport=&lcd_remote_set_viewport, 259 .set_viewport=&lcd_remote_set_viewport,
260 .set_viewport_ex=&lcd_remote_set_viewport_ex,
261 .viewport_set_buffer = &screen_helper_lcd_remote_viewport_set_buffer,
262 .current_viewport = &lcd_remote_current_viewport,
245 .getwidth=&lcd_remote_getwidth, 263 .getwidth=&lcd_remote_getwidth,
246 .getheight=&lcd_remote_getheight, 264 .getheight=&lcd_remote_getheight,
247 .getstringsize=&lcd_remote_getstringsize, 265 .getstringsize=&lcd_remote_getstringsize,
@@ -307,7 +325,6 @@ struct screen screens[NB_SCREENS] =
307 .backdrop_load=&remote_backdrop_load, 325 .backdrop_load=&remote_backdrop_load,
308 .backdrop_show=&remote_backdrop_show, 326 .backdrop_show=&remote_backdrop_show,
309#endif 327#endif
310 .set_framebuffer = (void*)lcd_remote_set_framebuffer,
311 .put_line = screen_helper_remote_put_line, 328 .put_line = screen_helper_remote_put_line,
312 } 329 }
313#endif /* NB_SCREENS == 2 */ 330#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
58 bool has_disk_led; 58 bool has_disk_led;
59#endif 59#endif
60 void (*set_drawmode)(int mode); 60 void (*set_drawmode)(int mode);
61 void (*set_viewport)(struct viewport* vp); 61 struct viewport* (*init_viewport)(struct viewport* vp);
62 struct viewport* (*set_viewport)(struct viewport* vp);
63 struct viewport* (*set_viewport_ex)(struct viewport* vp, int flags);
64 void (*viewport_set_buffer)(struct viewport *vp, struct frame_buffer_t *buffer);
65 struct viewport** current_viewport;
62 int (*getwidth)(void); 66 int (*getwidth)(void);
63 int (*getheight)(void); 67 int (*getheight)(void);
64 int (*getstringsize)(const unsigned char *str, int *w, int *h); 68 int (*getstringsize)(const unsigned char *str, int *w, int *h);
@@ -126,7 +130,6 @@ struct screen
126 bool (*backdrop_load)(const char *filename, char* backdrop_buffer); 130 bool (*backdrop_load)(const char *filename, char* backdrop_buffer);
127 void (*backdrop_show)(char* backdrop_buffer); 131 void (*backdrop_show)(char* backdrop_buffer);
128#endif 132#endif
129 void (*set_framebuffer)(void *framebuffer);
130#if defined(HAVE_LCD_COLOR) 133#if defined(HAVE_LCD_COLOR)
131 void (*gradient_fillrect)(int x, int y, int width, int height, 134 void (*gradient_fillrect)(int x, int y, int width, int height,
132 unsigned start, unsigned end); 135 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)
207 /* 6 possible cursor possitions, 2 values stored for each: x, y */ 207 /* 6 possible cursor possitions, 2 values stored for each: x, y */
208 unsigned int cursor[6][2]; 208 unsigned int cursor[6][2];
209 struct viewport *vp = &viewports[s]; 209 struct viewport *vp = &viewports[s];
210 struct viewport *last_vp;
210 struct screen *screen = &screens[s]; 211 struct screen *screen = &screens[s];
211 static unsigned char rtl_idx[] = 212 static unsigned char rtl_idx[] =
212 { IDX_SECONDS, IDX_MINUTES, IDX_HOURS, IDX_DAY, IDX_MONTH, IDX_YEAR }; 213 { IDX_SECONDS, IDX_MINUTES, IDX_HOURS, IDX_DAY, IDX_MONTH, IDX_YEAR };
213 214
214 viewport_set_defaults(vp, s); 215 viewport_set_defaults(vp, s);
215 screen->set_viewport(vp); 216 last_vp = screen->set_viewport(vp);
216 nb_lines = viewport_get_nb_lines(vp); 217 nb_lines = viewport_get_nb_lines(vp);
217 218
218 /* minimum lines needed is 2 + title line */ 219 /* minimum lines needed is 2 + title line */
@@ -283,7 +284,7 @@ bool set_time_screen(const char* title, struct tm *tm)
283 if (nb_lines > 5) 284 if (nb_lines > 5)
284 screen->puts(0, 5, str(LANG_TIME_REVERT)); 285 screen->puts(0, 5, str(LANG_TIME_REVERT));
285 screen->update_viewport(); 286 screen->update_viewport();
286 screen->set_viewport(NULL); 287 screen->set_viewport(last_vp);
287 } 288 }
288 289
289 /* set the most common numbers */ 290 /* 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)
35 int x, y, width, height; 35 int x, y, width, height;
36 int len, step; 36 int len, step;
37 37
38 x = current_vp->x; 38 x = lcd_current_viewport->x;
39 y = current_vp->y; 39 y = lcd_current_viewport->y;
40 width = current_vp->width; 40 width = lcd_current_viewport->width;
41 height = current_vp->height; 41 height = lcd_current_viewport->height;
42 42
43#if defined(HAVE_VIEWPORT_CLIP) 43#if defined(HAVE_VIEWPORT_CLIP)
44 /********************* Viewport on screen clipping ********************/ 44 /********************* Viewport on screen clipping ********************/
@@ -70,11 +70,11 @@ void lcd_clear_viewport(void)
70 dst = FBADDR(x, y); 70 dst = FBADDR(x, y);
71 dst_end = FBADDR(x + width - 1 , y + height - 1); 71 dst_end = FBADDR(x + width - 1 , y + height - 1);
72 72
73 if (current_vp->drawmode & DRMODE_INVERSEVID) 73 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
74 { 74 {
75 do 75 do
76 { 76 {
77 memset16(dst, current_vp->fg_pattern, len); 77 memset16(dst, lcd_current_viewport->fg_pattern, len);
78 dst += step; 78 dst += step;
79 } 79 }
80 while (dst <= dst_end); 80 while (dst <= dst_end);
@@ -85,7 +85,7 @@ void lcd_clear_viewport(void)
85 { 85 {
86 do 86 do
87 { 87 {
88 memset16(dst, current_vp->bg_pattern, len); 88 memset16(dst, lcd_current_viewport->bg_pattern, len);
89 dst += step; 89 dst += step;
90 } 90 }
91 while (dst <= dst_end); 91 while (dst <= dst_end);
@@ -102,22 +102,24 @@ void lcd_clear_viewport(void)
102 } 102 }
103 } 103 }
104 104
105 if (current_vp == &default_vp) 105 if (lcd_current_viewport == &default_vp)
106 lcd_scroll_stop(); 106 lcd_scroll_stop();
107 else 107 else
108 lcd_scroll_stop_viewport(current_vp); 108 lcd_scroll_stop_viewport(lcd_current_viewport);
109
110 lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN);
109} 111}
110 112
111/*** low-level drawing functions ***/ 113/*** low-level drawing functions ***/
112 114
113static void ICODE_ATTR setpixel(fb_data *address) 115static void ICODE_ATTR setpixel(fb_data *address)
114{ 116{
115 *address = current_vp->fg_pattern; 117 *address = lcd_current_viewport->fg_pattern;
116} 118}
117 119
118static void ICODE_ATTR clearpixel(fb_data *address) 120static void ICODE_ATTR clearpixel(fb_data *address)
119{ 121{
120 *address = current_vp->bg_pattern; 122 *address = lcd_current_viewport->bg_pattern;
121} 123}
122 124
123static void ICODE_ATTR clearimgpixel(fb_data *address) 125static void ICODE_ATTR clearimgpixel(fb_data *address)
@@ -157,8 +159,8 @@ void lcd_fillrect(int x, int y, int width, int height)
157 159
158 /******************** In viewport clipping **********************/ 160 /******************** In viewport clipping **********************/
159 /* nothing to draw? */ 161 /* nothing to draw? */
160 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 162 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
161 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 163 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
162 return; 164 return;
163 165
164 if (x < 0) 166 if (x < 0)
@@ -171,14 +173,14 @@ void lcd_fillrect(int x, int y, int width, int height)
171 height += y; 173 height += y;
172 y = 0; 174 y = 0;
173 } 175 }
174 if (x + width > current_vp->width) 176 if (x + width > lcd_current_viewport->width)
175 width = current_vp->width - x; 177 width = lcd_current_viewport->width - x;
176 if (y + height > current_vp->height) 178 if (y + height > lcd_current_viewport->height)
177 height = current_vp->height - y; 179 height = lcd_current_viewport->height - y;
178 180
179 /* adjust for viewport */ 181 /* adjust for viewport */
180 x += current_vp->x; 182 x += lcd_current_viewport->x;
181 y += current_vp->y; 183 y += lcd_current_viewport->y;
182 184
183#if defined(HAVE_VIEWPORT_CLIP) 185#if defined(HAVE_VIEWPORT_CLIP)
184 /********************* Viewport on screen clipping ********************/ 186 /********************* Viewport on screen clipping ********************/
@@ -205,14 +207,14 @@ void lcd_fillrect(int x, int y, int width, int height)
205#endif 207#endif
206 208
207 /* drawmode and optimisation */ 209 /* drawmode and optimisation */
208 if (current_vp->drawmode & DRMODE_INVERSEVID) 210 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
209 { 211 {
210 if (current_vp->drawmode & DRMODE_BG) 212 if (lcd_current_viewport->drawmode & DRMODE_BG)
211 { 213 {
212 if (!lcd_backdrop) 214 if (!lcd_backdrop)
213 { 215 {
214 fillopt = OPT_SET; 216 fillopt = OPT_SET;
215 bits = current_vp->bg_pattern; 217 bits = lcd_current_viewport->bg_pattern;
216 } 218 }
217 else 219 else
218 fillopt = OPT_COPY; 220 fillopt = OPT_COPY;
@@ -220,13 +222,13 @@ void lcd_fillrect(int x, int y, int width, int height)
220 } 222 }
221 else 223 else
222 { 224 {
223 if (current_vp->drawmode & DRMODE_FG) 225 if (lcd_current_viewport->drawmode & DRMODE_FG)
224 { 226 {
225 fillopt = OPT_SET; 227 fillopt = OPT_SET;
226 bits = current_vp->fg_pattern; 228 bits = lcd_current_viewport->fg_pattern;
227 } 229 }
228 } 230 }
229 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) 231 if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT)
230 return; 232 return;
231 233
232 dst = FBADDR(x, y); 234 dst = FBADDR(x, y);
@@ -284,13 +286,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
284 const unsigned char *src_end; 286 const unsigned char *src_end;
285 fb_data *dst, *dst_col; 287 fb_data *dst, *dst_col;
286 unsigned dmask = 0x100; /* bit 8 == sentinel */ 288 unsigned dmask = 0x100; /* bit 8 == sentinel */
287 int drmode = current_vp->drawmode; 289 int drmode = lcd_current_viewport->drawmode;
288 int row; 290 int row;
289 291
290 /******************** Image in viewport clipping **********************/ 292 /******************** Image in viewport clipping **********************/
291 /* nothing to draw? */ 293 /* nothing to draw? */
292 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 294 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
293 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 295 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
294 return; 296 return;
295 297
296 if (x < 0) 298 if (x < 0)
@@ -305,14 +307,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
305 src_y -= y; 307 src_y -= y;
306 y = 0; 308 y = 0;
307 } 309 }
308 if (x + width > current_vp->width) 310 if (x + width > lcd_current_viewport->width)
309 width = current_vp->width - x; 311 width = lcd_current_viewport->width - x;
310 if (y + height > current_vp->height) 312 if (y + height > lcd_current_viewport->height)
311 height = current_vp->height - y; 313 height = lcd_current_viewport->height - y;
312 314
313 /* adjust for viewport */ 315 /* adjust for viewport */
314 x += current_vp->x; 316 x += lcd_current_viewport->x;
315 y += current_vp->y; 317 y += lcd_current_viewport->y;
316 318
317#if defined(HAVE_VIEWPORT_CLIP) 319#if defined(HAVE_VIEWPORT_CLIP)
318 /********************* Viewport on screen clipping ********************/ 320 /********************* Viewport on screen clipping ********************/
@@ -404,7 +406,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
404 break; 406 break;
405 407
406 case DRMODE_BG: 408 case DRMODE_BG:
407 bg = current_vp->bg_pattern; 409 bg = lcd_current_viewport->bg_pattern;
408 do 410 do
409 { 411 {
410 if (!(data & 0x01)) 412 if (!(data & 0x01))
@@ -417,7 +419,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
417 break; 419 break;
418 420
419 case DRMODE_FG: 421 case DRMODE_FG:
420 fg = current_vp->fg_pattern; 422 fg = lcd_current_viewport->fg_pattern;
421 do 423 do
422 { 424 {
423 if (data & 0x01) 425 if (data & 0x01)
@@ -430,7 +432,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
430 break; 432 break;
431 433
432 case DRMODE_SOLID|DRMODE_INT_BD: 434 case DRMODE_SOLID|DRMODE_INT_BD:
433 fg = current_vp->fg_pattern; 435 fg = lcd_current_viewport->fg_pattern;
434 bo = lcd_backdrop_offset; 436 bo = lcd_backdrop_offset;
435 do 437 do
436 { 438 {
@@ -443,8 +445,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
443 break; 445 break;
444 446
445 case DRMODE_SOLID: 447 case DRMODE_SOLID:
446 fg = current_vp->fg_pattern; 448 fg = lcd_current_viewport->fg_pattern;
447 bg = current_vp->bg_pattern; 449 bg = lcd_current_viewport->bg_pattern;
448 do 450 do
449 { 451 {
450 *dst = (data & 0x01) ? fg : bg; 452 *dst = (data & 0x01) ? fg : bg;
@@ -549,10 +551,10 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
549{ 551{
550 fb_data *dst, *dst_row; 552 fb_data *dst, *dst_row;
551 unsigned dmask = 0x00000000; 553 unsigned dmask = 0x00000000;
552 int drmode = current_vp->drawmode; 554 int drmode = lcd_current_viewport->drawmode;
553 /* nothing to draw? */ 555 /* nothing to draw? */
554 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 556 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
555 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 557 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
556 return; 558 return;
557 /* initialize blending */ 559 /* initialize blending */
558 BLEND_INIT; 560 BLEND_INIT;
@@ -570,14 +572,14 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
570 src_y -= y; 572 src_y -= y;
571 y = 0; 573 y = 0;
572 } 574 }
573 if (x + width > current_vp->width) 575 if (x + width > lcd_current_viewport->width)
574 width = current_vp->width - x; 576 width = lcd_current_viewport->width - x;
575 if (y + height > current_vp->height) 577 if (y + height > lcd_current_viewport->height)
576 height = current_vp->height - y; 578 height = lcd_current_viewport->height - y;
577 579
578 /* adjust for viewport */ 580 /* adjust for viewport */
579 x += current_vp->x; 581 x += lcd_current_viewport->x;
580 y += current_vp->y; 582 y += lcd_current_viewport->y;
581 583
582#if defined(HAVE_VIEWPORT_CLIP) 584#if defined(HAVE_VIEWPORT_CLIP)
583 /********************* Viewport on screen clipping ********************/ 585 /********************* Viewport on screen clipping ********************/
@@ -668,7 +670,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
668 /* go through the rows and update each pixel */ 670 /* go through the rows and update each pixel */
669 do 671 do
670 { 672 {
671 /* saving current_vp->fg/bg_pattern and lcd_backdrop_offset into these 673 /* saving lcd_current_viewport->fg/bg_pattern and lcd_backdrop_offset into these
672 * temp vars just before the loop helps gcc to opimize the loop better 674 * temp vars just before the loop helps gcc to opimize the loop better
673 * (testing showed ~15% speedup) */ 675 * (testing showed ~15% speedup) */
674 unsigned fg, bg; 676 unsigned fg, bg;
@@ -727,7 +729,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
727 while (--col); 729 while (--col);
728 break; 730 break;
729 case DRMODE_BG: 731 case DRMODE_BG:
730 bg = current_vp->bg_pattern; 732 bg = lcd_current_viewport->bg_pattern;
731 do 733 do
732 { 734 {
733 *dst = blend_two_colors(bg, *dst, data & ALPHA_COLOR_LOOKUP_SIZE ); 735 *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,
747 while (--col); 749 while (--col);
748 break; 750 break;
749 case DRMODE_FG: 751 case DRMODE_FG:
750 fg = current_vp->fg_pattern; 752 fg = lcd_current_viewport->fg_pattern;
751 do 753 do
752 { 754 {
753 *dst = blend_two_colors(*dst, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); 755 *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,
758 break; 760 break;
759 case DRMODE_SOLID|DRMODE_INT_BD: 761 case DRMODE_SOLID|DRMODE_INT_BD:
760 bo = lcd_backdrop_offset; 762 bo = lcd_backdrop_offset;
761 fg = current_vp->fg_pattern; 763 fg = lcd_current_viewport->fg_pattern;
762 do 764 do
763 { 765 {
764 fb_data *c = (fb_data *)((uintptr_t)dst + bo); 766 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,
769 while (--col); 771 while (--col);
770 break; 772 break;
771 case DRMODE_SOLID|DRMODE_INT_IMG: 773 case DRMODE_SOLID|DRMODE_INT_IMG:
772 bg = current_vp->bg_pattern; 774 bg = lcd_current_viewport->bg_pattern;
773 img_offset = image - dst; 775 img_offset = image - dst;
774 do 776 do
775 { 777 {
@@ -792,8 +794,8 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
792 while (--col); 794 while (--col);
793 break; 795 break;
794 case DRMODE_SOLID: 796 case DRMODE_SOLID:
795 bg = current_vp->bg_pattern; 797 bg = lcd_current_viewport->bg_pattern;
796 fg = current_vp->fg_pattern; 798 fg = lcd_current_viewport->fg_pattern;
797 do 799 do
798 { 800 {
799 *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); 801 *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 @@
39#include "scroll_engine.h" 39#include "scroll_engine.h"
40 40
41#define ROW_INC 1 41#define ROW_INC 1
42#define COL_INC LCD_HEIGHT 42#define COL_INC lcd_current_viewport->buffer->stride
43 43
44extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; 44extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[];
45extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[]; 45extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[];
@@ -61,7 +61,9 @@ void lcd_hline(int x1, int x2, int y)
61{ 61{
62 int x; 62 int x;
63 fb_data *dst, *dst_end; 63 fb_data *dst, *dst_end;
64 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; 64 int stride_dst;
65
66 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
65 67
66 /* direction flip */ 68 /* direction flip */
67 if (x2 < x1) 69 if (x2 < x1)
@@ -73,20 +75,20 @@ void lcd_hline(int x1, int x2, int y)
73 75
74 /******************** In viewport clipping **********************/ 76 /******************** In viewport clipping **********************/
75 /* nothing to draw? */ 77 /* nothing to draw? */
76 if (((unsigned)y >= (unsigned)current_vp->height) || 78 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) ||
77 (x1 >= current_vp->width) || 79 (x1 >= lcd_current_viewport->width) ||
78 (x2 < 0)) 80 (x2 < 0))
79 return; 81 return;
80 82
81 if (x1 < 0) 83 if (x1 < 0)
82 x1 = 0; 84 x1 = 0;
83 if (x2 >= current_vp->width) 85 if (x2 >= lcd_current_viewport->width)
84 x2 = current_vp->width-1; 86 x2 = lcd_current_viewport->width-1;
85 87
86 /* Adjust x1 and y to viewport */ 88 /* Adjust x1 and y to viewport */
87 x1 += current_vp->x; 89 x1 += lcd_current_viewport->x;
88 x2 += current_vp->x; 90 x2 += lcd_current_viewport->x;
89 y += current_vp->y; 91 y += lcd_current_viewport->y;
90 92
91#if defined(HAVE_VIEWPORT_CLIP) 93#if defined(HAVE_VIEWPORT_CLIP)
92 /********************* Viewport on screen clipping ********************/ 94 /********************* Viewport on screen clipping ********************/
@@ -103,12 +105,13 @@ void lcd_hline(int x1, int x2, int y)
103#endif 105#endif
104 106
105 dst = FBADDR(x1 , y ); 107 dst = FBADDR(x1 , y );
106 dst_end = dst + (x2 - x1) * LCD_HEIGHT; 108 stride_dst = lcd_current_viewport->buffer->stride;
109 dst_end = dst + (x2 - x1) * stride_dst;
107 110
108 do 111 do
109 { 112 {
110 pfunc(dst); 113 pfunc(dst);
111 dst += LCD_HEIGHT; 114 dst += stride_dst;
112 } 115 }
113 while (dst <= dst_end); 116 while (dst <= dst_end);
114} 117}
@@ -131,20 +134,20 @@ void lcd_vline(int x, int y1, int y2)
131 134
132 /******************** In viewport clipping **********************/ 135 /******************** In viewport clipping **********************/
133 /* nothing to draw? */ 136 /* nothing to draw? */
134 if (((unsigned)x >= (unsigned)current_vp->width) || 137 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) ||
135 (y1 >= current_vp->height) || 138 (y1 >= lcd_current_viewport->height) ||
136 (y2 < 0)) 139 (y2 < 0))
137 return; 140 return;
138 141
139 if (y1 < 0) 142 if (y1 < 0)
140 y1 = 0; 143 y1 = 0;
141 if (y2 >= current_vp->height) 144 if (y2 >= lcd_current_viewport->height)
142 y2 = current_vp->height-1; 145 y2 = lcd_current_viewport->height-1;
143 146
144 /* adjust for viewport */ 147 /* adjust for viewport */
145 x += current_vp->x; 148 x += lcd_current_viewport->x;
146 y1 += current_vp->y; 149 y1 += lcd_current_viewport->y;
147 y2 += current_vp->y; 150 y2 += lcd_current_viewport->y;
148 151
149#if defined(HAVE_VIEWPORT_CLIP) 152#if defined(HAVE_VIEWPORT_CLIP)
150 /********************* Viewport on screen clipping ********************/ 153 /********************* Viewport on screen clipping ********************/
@@ -163,14 +166,14 @@ void lcd_vline(int x, int y1, int y2)
163 height = y2 - y1 + 1; 166 height = y2 - y1 + 1;
164 167
165 /* drawmode and optimisation */ 168 /* drawmode and optimisation */
166 if (current_vp->drawmode & DRMODE_INVERSEVID) 169 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
167 { 170 {
168 if (current_vp->drawmode & DRMODE_BG) 171 if (lcd_current_viewport->drawmode & DRMODE_BG)
169 { 172 {
170 if (!lcd_backdrop) 173 if (!lcd_backdrop)
171 { 174 {
172 fillopt = OPT_SET; 175 fillopt = OPT_SET;
173 bits = current_vp->bg_pattern; 176 bits = lcd_current_viewport->bg_pattern;
174 } 177 }
175 else 178 else
176 fillopt = OPT_COPY; 179 fillopt = OPT_COPY;
@@ -178,13 +181,13 @@ void lcd_vline(int x, int y1, int y2)
178 } 181 }
179 else 182 else
180 { 183 {
181 if (current_vp->drawmode & DRMODE_FG) 184 if (lcd_current_viewport->drawmode & DRMODE_FG)
182 { 185 {
183 fillopt = OPT_SET; 186 fillopt = OPT_SET;
184 bits = current_vp->fg_pattern; 187 bits = lcd_current_viewport->fg_pattern;
185 } 188 }
186 } 189 }
187 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) 190 if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT)
188 return; 191 return;
189 192
190 dst = FBADDR(x, y1); 193 dst = FBADDR(x, y1);
@@ -215,11 +218,11 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
215 int height) 218 int height)
216{ 219{
217 fb_data *dst; 220 fb_data *dst;
218 221 int stride_dst;
219 /******************** Image in viewport clipping **********************/ 222 /******************** Image in viewport clipping **********************/
220 /* nothing to draw? */ 223 /* nothing to draw? */
221 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 224 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
222 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 225 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
223 return; 226 return;
224 227
225 if (x < 0) 228 if (x < 0)
@@ -235,14 +238,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
235 y = 0; 238 y = 0;
236 } 239 }
237 240
238 if (x + width > current_vp->width) 241 if (x + width > lcd_current_viewport->width)
239 width = current_vp->width - x; 242 width = lcd_current_viewport->width - x;
240 if (y + height > current_vp->height) 243 if (y + height > lcd_current_viewport->height)
241 height = current_vp->height - y; 244 height = lcd_current_viewport->height - y;
242 245
243 /* adjust for viewport */ 246 /* adjust for viewport */
244 x += current_vp->x; 247 x += lcd_current_viewport->x;
245 y += current_vp->y; 248 y += lcd_current_viewport->y;
246 249
247#if defined(HAVE_VIEWPORT_CLIP) 250#if defined(HAVE_VIEWPORT_CLIP)
248 /********************* Viewport on screen clipping ********************/ 251 /********************* Viewport on screen clipping ********************/
@@ -272,13 +275,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
272 275
273 src += stride * src_x + src_y; /* move starting point */ 276 src += stride * src_x + src_y; /* move starting point */
274 dst = FBADDR(x, y); 277 dst = FBADDR(x, y);
275 fb_data *dst_end = dst + width * LCD_HEIGHT; 278 stride_dst = lcd_current_viewport->buffer->stride;
279 fb_data *dst_end = dst + width * stride_dst;
276 280
277 do 281 do
278 { 282 {
279 memcpy(dst, src, height * sizeof(fb_data)); 283 memcpy(dst, src, height * sizeof(fb_data));
280 src += stride; 284 src += stride;
281 dst += LCD_HEIGHT; 285 dst += stride_dst;
282 } 286 }
283 while (dst < dst_end); 287 while (dst < dst_end);
284} 288}
@@ -289,11 +293,12 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
289 int y, int width, int height) 293 int y, int width, int height)
290{ 294{
291 fb_data *dst, *dst_end; 295 fb_data *dst, *dst_end;
296 int stride_dst;
292 297
293 /******************** Image in viewport clipping **********************/ 298 /******************** Image in viewport clipping **********************/
294 /* nothing to draw? */ 299 /* nothing to draw? */
295 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 300 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
296 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 301 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
297 return; 302 return;
298 303
299 if (x < 0) 304 if (x < 0)
@@ -309,14 +314,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
309 y = 0; 314 y = 0;
310 } 315 }
311 316
312 if (x + width > current_vp->width) 317 if (x + width > lcd_current_viewport->width)
313 width = current_vp->width - x; 318 width = lcd_current_viewport->width - x;
314 if (y + height > current_vp->height) 319 if (y + height > lcd_current_viewport->height)
315 height = current_vp->height - y; 320 height = lcd_current_viewport->height - y;
316 321
317 /* adjust for viewport */ 322 /* adjust for viewport */
318 x += current_vp->x; 323 x += lcd_current_viewport->x;
319 y += current_vp->y; 324 y += lcd_current_viewport->y;
320 325
321#if defined(HAVE_VIEWPORT_CLIP) 326#if defined(HAVE_VIEWPORT_CLIP)
322 /********************* Viewport on screen clipping ********************/ 327 /********************* Viewport on screen clipping ********************/
@@ -346,7 +351,8 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
346 351
347 src += stride * src_x + src_y; /* move starting point */ 352 src += stride * src_x + src_y; /* move starting point */
348 dst = FBADDR(x, y); 353 dst = FBADDR(x, y);
349 dst_end = dst + width * LCD_HEIGHT; 354 stride_dst = lcd_current_viewport->buffer->stride;
355 dst_end = dst + width * stride_dst;
350 356
351 do 357 do
352 { 358 {
@@ -354,12 +360,12 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
354 for(i = 0;i < height;i++) 360 for(i = 0;i < height;i++)
355 { 361 {
356 if (src[i] == REPLACEWITHFG_COLOR) 362 if (src[i] == REPLACEWITHFG_COLOR)
357 dst[i] = current_vp->fg_pattern; 363 dst[i] = lcd_current_viewport->fg_pattern;
358 else if(src[i] != TRANSPARENT_COLOR) 364 else if(src[i] != TRANSPARENT_COLOR)
359 dst[i] = src[i]; 365 dst[i] = src[i];
360 } 366 }
361 src += stride; 367 src += stride;
362 dst += LCD_HEIGHT; 368 dst += stride_dst;
363 } 369 }
364 while (dst < dst_end); 370 while (dst < dst_end);
365} 371}
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 @@
38#include "bidi.h" 38#include "bidi.h"
39#include "scroll_engine.h" 39#include "scroll_engine.h"
40 40
41#define ROW_INC LCD_WIDTH 41#define ROW_INC lcd_current_viewport->buffer->stride
42#define COL_INC 1 42#define COL_INC 1
43 43
44extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; 44extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[];
@@ -74,20 +74,20 @@ void lcd_hline(int x1, int x2, int y)
74 74
75 /******************** In viewport clipping **********************/ 75 /******************** In viewport clipping **********************/
76 /* nothing to draw? */ 76 /* nothing to draw? */
77 if (((unsigned)y >= (unsigned)current_vp->height) || 77 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) ||
78 (x1 >= current_vp->width) || 78 (x1 >= lcd_current_viewport->width) ||
79 (x2 < 0)) 79 (x2 < 0))
80 return; 80 return;
81 81
82 if (x1 < 0) 82 if (x1 < 0)
83 x1 = 0; 83 x1 = 0;
84 if (x2 >= current_vp->width) 84 if (x2 >= lcd_current_viewport->width)
85 x2 = current_vp->width-1; 85 x2 = lcd_current_viewport->width-1;
86 86
87 /* Adjust x1 and y to viewport */ 87 /* Adjust x1 and y to viewport */
88 x1 += current_vp->x; 88 x1 += lcd_current_viewport->x;
89 x2 += current_vp->x; 89 x2 += lcd_current_viewport->x;
90 y += current_vp->y; 90 y += lcd_current_viewport->y;
91 91
92#if defined(HAVE_VIEWPORT_CLIP) 92#if defined(HAVE_VIEWPORT_CLIP)
93 /********************* Viewport on screen clipping ********************/ 93 /********************* Viewport on screen clipping ********************/
@@ -106,14 +106,14 @@ void lcd_hline(int x1, int x2, int y)
106 width = x2 - x1 + 1; 106 width = x2 - x1 + 1;
107 107
108 /* drawmode and optimisation */ 108 /* drawmode and optimisation */
109 if (current_vp->drawmode & DRMODE_INVERSEVID) 109 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
110 { 110 {
111 if (current_vp->drawmode & DRMODE_BG) 111 if (lcd_current_viewport->drawmode & DRMODE_BG)
112 { 112 {
113 if (!lcd_backdrop) 113 if (!lcd_backdrop)
114 { 114 {
115 fillopt = OPT_SET; 115 fillopt = OPT_SET;
116 bits = current_vp->bg_pattern; 116 bits = lcd_current_viewport->bg_pattern;
117 } 117 }
118 else 118 else
119 fillopt = OPT_COPY; 119 fillopt = OPT_COPY;
@@ -121,13 +121,13 @@ void lcd_hline(int x1, int x2, int y)
121 } 121 }
122 else 122 else
123 { 123 {
124 if (current_vp->drawmode & DRMODE_FG) 124 if (lcd_current_viewport->drawmode & DRMODE_FG)
125 { 125 {
126 fillopt = OPT_SET; 126 fillopt = OPT_SET;
127 bits = current_vp->fg_pattern; 127 bits = lcd_current_viewport->fg_pattern;
128 } 128 }
129 } 129 }
130 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) 130 if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT)
131 return; 131 return;
132 132
133 dst = FBADDR(x1, y); 133 dst = FBADDR(x1, y);
@@ -157,7 +157,8 @@ void lcd_vline(int x, int y1, int y2)
157{ 157{
158 int y; 158 int y;
159 fb_data *dst, *dst_end; 159 fb_data *dst, *dst_end;
160 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; 160 int stride_dst;
161 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
161 162
162 /* direction flip */ 163 /* direction flip */
163 if (y2 < y1) 164 if (y2 < y1)
@@ -169,20 +170,20 @@ void lcd_vline(int x, int y1, int y2)
169 170
170 /******************** In viewport clipping **********************/ 171 /******************** In viewport clipping **********************/
171 /* nothing to draw? */ 172 /* nothing to draw? */
172 if (((unsigned)x >= (unsigned)current_vp->width) || 173 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) ||
173 (y1 >= current_vp->height) || 174 (y1 >= lcd_current_viewport->height) ||
174 (y2 < 0)) 175 (y2 < 0))
175 return; 176 return;
176 177
177 if (y1 < 0) 178 if (y1 < 0)
178 y1 = 0; 179 y1 = 0;
179 if (y2 >= current_vp->height) 180 if (y2 >= lcd_current_viewport->height)
180 y2 = current_vp->height-1; 181 y2 = lcd_current_viewport->height-1;
181 182
182 /* adjust for viewport */ 183 /* adjust for viewport */
183 x += current_vp->x; 184 x += lcd_current_viewport->x;
184 y1 += current_vp->y; 185 y1 += lcd_current_viewport->y;
185 y2 += current_vp->y; 186 y2 += lcd_current_viewport->y;
186 187
187#if defined(HAVE_VIEWPORT_CLIP) 188#if defined(HAVE_VIEWPORT_CLIP)
188 /********************* Viewport on screen clipping ********************/ 189 /********************* Viewport on screen clipping ********************/
@@ -199,12 +200,13 @@ void lcd_vline(int x, int y1, int y2)
199#endif 200#endif
200 201
201 dst = FBADDR(x , y1); 202 dst = FBADDR(x , y1);
202 dst_end = dst + (y2 - y1) * LCD_WIDTH; 203 stride_dst = lcd_current_viewport->buffer->stride;
204 dst_end = dst + (y2 - y1) * stride_dst;
203 205
204 do 206 do
205 { 207 {
206 pfunc(dst); 208 pfunc(dst);
207 dst += LCD_WIDTH; 209 dst += stride_dst;
208 } 210 }
209 while (dst <= dst_end); 211 while (dst <= dst_end);
210} 212}
@@ -215,11 +217,12 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
215 int height) 217 int height)
216{ 218{
217 fb_data *dst; 219 fb_data *dst;
220 int stride_dst;
218 221
219 /******************** Image in viewport clipping **********************/ 222 /******************** Image in viewport clipping **********************/
220 /* nothing to draw? */ 223 /* nothing to draw? */
221 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 224 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
222 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 225 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
223 return; 226 return;
224 227
225 if (x < 0) 228 if (x < 0)
@@ -235,14 +238,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
235 y = 0; 238 y = 0;
236 } 239 }
237 240
238 if (x + width > current_vp->width) 241 if (x + width > lcd_current_viewport->width)
239 width = current_vp->width - x; 242 width = lcd_current_viewport->width - x;
240 if (y + height > current_vp->height) 243 if (y + height > lcd_current_viewport->height)
241 height = current_vp->height - y; 244 height = lcd_current_viewport->height - y;
242 245
243 /* adjust for viewport */ 246 /* adjust for viewport */
244 x += current_vp->x; 247 x += lcd_current_viewport->x;
245 y += current_vp->y; 248 y += lcd_current_viewport->y;
246 249
247#if defined(HAVE_VIEWPORT_CLIP) 250#if defined(HAVE_VIEWPORT_CLIP)
248 /********************* Viewport on screen clipping ********************/ 251 /********************* Viewport on screen clipping ********************/
@@ -272,12 +275,13 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
272 275
273 src += stride * src_y + src_x; /* move starting point */ 276 src += stride * src_y + src_x; /* move starting point */
274 dst = FBADDR(x, y); 277 dst = FBADDR(x, y);
278 stride_dst = lcd_current_viewport->buffer->stride;
275 279
276 do 280 do
277 { 281 {
278 memcpy(dst, src, width * sizeof(fb_data)); 282 memcpy(dst, src, width * sizeof(fb_data));
279 src += stride; 283 src += stride;
280 dst += LCD_WIDTH; 284 dst += stride_dst;
281 } 285 }
282 while (--height > 0); 286 while (--height > 0);
283} 287}
@@ -288,12 +292,13 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
288 int y, int width, int height) 292 int y, int width, int height)
289{ 293{
290 fb_data *dst; 294 fb_data *dst;
291 unsigned fg = current_vp->fg_pattern; 295 unsigned fg = lcd_current_viewport->fg_pattern;
296 int stride_dst = lcd_current_viewport->buffer->stride;
292 297
293 /******************** Image in viewport clipping **********************/ 298 /******************** Image in viewport clipping **********************/
294 /* nothing to draw? */ 299 /* nothing to draw? */
295 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 300 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
296 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 301 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
297 return; 302 return;
298 303
299 if (x < 0) 304 if (x < 0)
@@ -309,14 +314,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
309 y = 0; 314 y = 0;
310 } 315 }
311 316
312 if (x + width > current_vp->width) 317 if (x + width > lcd_current_viewport->width)
313 width = current_vp->width - x; 318 width = lcd_current_viewport->width - x;
314 if (y + height > current_vp->height) 319 if (y + height > lcd_current_viewport->height)
315 height = current_vp->height - y; 320 height = lcd_current_viewport->height - y;
316 321
317 /* adjust for viewport */ 322 /* adjust for viewport */
318 x += current_vp->x; 323 x += lcd_current_viewport->x;
319 y += current_vp->y; 324 y += lcd_current_viewport->y;
320 325
321#if defined(HAVE_VIEWPORT_CLIP) 326#if defined(HAVE_VIEWPORT_CLIP)
322 /********************* Viewport on screen clipping ********************/ 327 /********************* Viewport on screen clipping ********************/
@@ -371,7 +376,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
371 [s]"+&r"(src), [d]"+&r"(dst) 376 [s]"+&r"(src), [d]"+&r"(dst)
372 : [width]"r"(width), 377 : [width]"r"(width),
373 [sstp]"r"(stride - width), 378 [sstp]"r"(stride - width),
374 [dstp]"r"(LCD_WIDTH - width), 379 [dstp]"r"(stride_dst - width),
375 [transcolor]"r"(TRANSPARENT_COLOR), 380 [transcolor]"r"(TRANSPARENT_COLOR),
376 [fgcolor]"r"(REPLACEWITHFG_COLOR), 381 [fgcolor]"r"(REPLACEWITHFG_COLOR),
377 [fgpat]"r"(fg) 382 [fgpat]"r"(fg)
@@ -395,7 +400,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
395 } 400 }
396 while (++dst_row < row_end); 401 while (++dst_row < row_end);
397 src += stride; 402 src += stride;
398 dst += LCD_WIDTH; 403 dst += stride_dst;
399 } 404 }
400 while (--height > 0); 405 while (--height > 0);
401#endif 406#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 @@
44#define MAIN_LCD 44#define MAIN_LCD
45#endif 45#endif
46 46
47#ifdef MAIN_LCD
48#define THIS_STRIDE STRIDE_MAIN
49#else
50#define THIS_STRIDE STRIDE_REMOTE
51#endif
52
53#define CURRENT_VP LCDFN(current_viewport)
47/*** globals ***/ 54/*** globals ***/
48FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; 55static FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER;
49FBFN(data) *LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; 56
57static void *LCDFN(frameaddress_default)(int x, int y);
58
59/* shouldn't be changed unless you want system-wide framebuffer changes! */
60struct frame_buffer_t LCDFN(framebuffer_default) =
61{
62 .FBFN(ptr) = &LCDFN(static_framebuffer)[0][0],
63 .get_address_fn = &LCDFN(frameaddress_default),
64 .stride = THIS_STRIDE(LCDM(WIDTH), LCDM(HEIGHT)),
65 .elems = (LCDM(FBWIDTH)*LCDM(FBHEIGHT)),
66};
50 67
51static struct viewport default_vp = 68static struct viewport default_vp =
52{ 69{
@@ -56,55 +73,73 @@ static struct viewport default_vp =
56 .height = LCDM(HEIGHT), 73 .height = LCDM(HEIGHT),
57 .font = FONT_SYSFIXED, 74 .font = FONT_SYSFIXED,
58 .drawmode = DRMODE_SOLID, 75 .drawmode = DRMODE_SOLID,
76 .buffer = NULL,
59}; 77};
60 78
61static struct viewport* current_vp = &default_vp; 79struct viewport* CURRENT_VP;
80
81static void *LCDFN(frameaddress_default)(int x, int y)
82{
83 /* the default expects a buffer the same size as the screen */
84 struct frame_buffer_t *fb = CURRENT_VP->buffer;
85#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
86 size_t element = (x * LCDM(NATIVE_STRIDE)(fb->stride)) + y;
87#else
88 size_t element = (y * LCDM(NATIVE_STRIDE)(fb->stride)) + x;
89#endif
90
91 return fb->FBFN(ptr) + element;/*(element % fb->elems);*/
92}
62 93
63/* LCD init */ 94/* LCD init */
64void LCDFN(init)(void) 95void LCDFN(init)(void)
65{ 96{
97
98 /* Initialize the viewport */
99 LCDFN(set_viewport)(NULL);
66 LCDFN(clear_display)(); 100 LCDFN(clear_display)();
67 LCDFN(init_device)(); 101 LCDFN(init_device)();
68#ifdef MAIN_LCD 102#ifdef MAIN_LCD
69 scroll_init(); 103 scroll_init();
70#endif 104#endif
105
71} 106}
72 107
73/*** parameter handling ***/ 108/*** parameter handling ***/
74 109
75void LCDFN(set_drawmode)(int mode) 110void LCDFN(set_drawmode)(int mode)
76{ 111{
77 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 112 CURRENT_VP->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
78} 113}
79 114
80int LCDFN(get_drawmode)(void) 115int LCDFN(get_drawmode)(void)
81{ 116{
82 return current_vp->drawmode; 117 return CURRENT_VP->drawmode;
83} 118}
84 119
85int LCDFN(getwidth)(void) 120int LCDFN(getwidth)(void)
86{ 121{
87 return current_vp->width; 122 return CURRENT_VP->width;
88} 123}
89 124
90int LCDFN(getheight)(void) 125int LCDFN(getheight)(void)
91{ 126{
92 return current_vp->height; 127 return CURRENT_VP->height;
93} 128}
94 129
95void LCDFN(setfont)(int newfont) 130void LCDFN(setfont)(int newfont)
96{ 131{
97 current_vp->font = newfont; 132 CURRENT_VP->font = newfont;
98} 133}
99 134
100int LCDFN(getfont)(void) 135int LCDFN(getfont)(void)
101{ 136{
102 return current_vp->font; 137 return CURRENT_VP->font;
103} 138}
104 139
105int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h) 140int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h)
106{ 141{
107 return font_getstringsize(str, w, h, current_vp->font); 142 return font_getstringsize(str, w, h, CURRENT_VP->font);
108} 143}
109 144
110/*** low-level drawing functions ***/ 145/*** low-level drawing functions ***/
@@ -134,7 +169,7 @@ LCDFN(pixelfunc_type)* const LCDFN(pixelfuncs)[8] = {
134 flippixel, nopixel, setpixel, setpixel, 169 flippixel, nopixel, setpixel, setpixel,
135 nopixel, clearpixel, nopixel, clearpixel 170 nopixel, clearpixel, nopixel, clearpixel
136}; 171};
137 172
138static void ICODE_ATTR flipblock(FBFN(data) *address, unsigned mask, 173static void ICODE_ATTR flipblock(FBFN(data) *address, unsigned mask,
139 unsigned bits) 174 unsigned bits)
140{ 175{
@@ -199,9 +234,9 @@ LCDFN(blockfunc_type)* const LCDFN(blockfuncs)[8] = {
199/* Clear the whole display */ 234/* Clear the whole display */
200void LCDFN(clear_display)(void) 235void LCDFN(clear_display)(void)
201{ 236{
202 unsigned bits = (current_vp->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; 237 unsigned bits = (CURRENT_VP->drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0;
203 238
204 memset(LCDFN(framebuffer), bits, FBSIZE); 239 memset(LCDFB(0, 0), bits, FBSIZE);
205 LCDFN(scroll_info).lines = 0; 240 LCDFN(scroll_info).lines = 0;
206} 241}
207 242
@@ -210,37 +245,40 @@ void LCDFN(clear_viewport)(void)
210{ 245{
211 int oldmode; 246 int oldmode;
212 247
213 if (current_vp == &default_vp) 248 if (CURRENT_VP == &default_vp &&
249 default_vp.buffer == &LCDFN(framebuffer_default))
214 { 250 {
215 LCDFN(clear_display)(); 251 LCDFN(clear_display)();
216 } 252 }
217 else 253 else
218 { 254 {
219 oldmode = current_vp->drawmode; 255 oldmode = CURRENT_VP->drawmode;
220 256
221 /* Invert the INVERSEVID bit and set basic mode to SOLID */ 257 /* Invert the INVERSEVID bit and set basic mode to SOLID */
222 current_vp->drawmode = (~current_vp->drawmode & DRMODE_INVERSEVID) | 258 CURRENT_VP->drawmode = (~CURRENT_VP->drawmode & DRMODE_INVERSEVID) |
223 DRMODE_SOLID; 259 DRMODE_SOLID;
224 260
225 LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); 261 LCDFN(fillrect)(0, 0, CURRENT_VP->width, CURRENT_VP->height);
226 262
227 current_vp->drawmode = oldmode; 263 CURRENT_VP->drawmode = oldmode;
228 264
229 LCDFN(scroll_stop_viewport)(current_vp); 265 LCDFN(scroll_stop_viewport)(CURRENT_VP);
230 } 266 }
267
268 CURRENT_VP->flags &= ~(VP_FLAG_VP_SET_CLEAN);
231} 269}
232 270
233/* Set a single pixel */ 271/* Set a single pixel */
234void LCDFN(drawpixel)(int x, int y) 272void LCDFN(drawpixel)(int x, int y)
235{ 273{
236 if ( ((unsigned)x < (unsigned)current_vp->width) 274 if ( ((unsigned)x < (unsigned)CURRENT_VP->width)
237 && ((unsigned)y < (unsigned)current_vp->height) 275 && ((unsigned)y < (unsigned)CURRENT_VP->height)
238#if defined(HAVE_VIEWPORT_CLIP) 276#if defined(HAVE_VIEWPORT_CLIP)
239 && ((unsigned)x < (unsigned)LCDM(WIDTH)) 277 && ((unsigned)x < (unsigned)LCDM(WIDTH))
240 && ((unsigned)y < (unsigned)LCDM(HEIGHT)) 278 && ((unsigned)y < (unsigned)LCDM(HEIGHT))
241#endif 279#endif
242 ) 280 )
243 LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x + x, current_vp->y + y); 281 LCDFN(pixelfuncs)[CURRENT_VP->drawmode](CURRENT_VP->x + x, CURRENT_VP->y + y);
244} 282}
245 283
246/* Draw a line */ 284/* Draw a line */
@@ -252,7 +290,7 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
252 int d, dinc1, dinc2; 290 int d, dinc1, dinc2;
253 int x, xinc1, xinc2; 291 int x, xinc1, xinc2;
254 int y, yinc1, yinc2; 292 int y, yinc1, yinc2;
255 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[current_vp->drawmode]; 293 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode];
256 294
257 deltax = abs(x2 - x1); 295 deltax = abs(x2 - x1);
258 if (deltax == 0) 296 if (deltax == 0)
@@ -308,14 +346,14 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
308 346
309 for (i = 0; i < numpixels; i++) 347 for (i = 0; i < numpixels; i++)
310 { 348 {
311 if ( ((unsigned)x < (unsigned)current_vp->width) 349 if ( ((unsigned)x < (unsigned)CURRENT_VP->width)
312 && ((unsigned)y < (unsigned)current_vp->height) 350 && ((unsigned)y < (unsigned)CURRENT_VP->height)
313#if defined(HAVE_VIEWPORT_CLIP) 351#if defined(HAVE_VIEWPORT_CLIP)
314 && ((unsigned)x < (unsigned)LCDM(WIDTH)) 352 && ((unsigned)x < (unsigned)LCDM(WIDTH))
315 && ((unsigned)y < (unsigned)LCDM(HEIGHT)) 353 && ((unsigned)y < (unsigned)LCDM(HEIGHT))
316#endif 354#endif
317 ) 355 )
318 pfunc(current_vp->x + x, current_vp->y + y); 356 pfunc(CURRENT_VP->x + x, CURRENT_VP->y + y);
319 357
320 if (d < 0) 358 if (d < 0)
321 { 359 {
@@ -350,19 +388,19 @@ void LCDFN(hline)(int x1, int x2, int y)
350 388
351 /******************** In viewport clipping **********************/ 389 /******************** In viewport clipping **********************/
352 /* nothing to draw? */ 390 /* nothing to draw? */
353 if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) 391 if (((unsigned)y >= (unsigned)CURRENT_VP->height) || (x1 >= CURRENT_VP->width)
354 || (x2 < 0)) 392 || (x2 < 0))
355 return; 393 return;
356 394
357 if (x1 < 0) 395 if (x1 < 0)
358 x1 = 0; 396 x1 = 0;
359 if (x2 >= current_vp->width) 397 if (x2 >= CURRENT_VP->width)
360 x2 = current_vp->width-1; 398 x2 = CURRENT_VP->width-1;
361 399
362 /* adjust to viewport */ 400 /* adjust to viewport */
363 x1 += current_vp->x; 401 x1 += CURRENT_VP->x;
364 x2 += current_vp->x; 402 x2 += CURRENT_VP->x;
365 y += current_vp->y; 403 y += CURRENT_VP->y;
366 404
367#if defined(HAVE_VIEWPORT_CLIP) 405#if defined(HAVE_VIEWPORT_CLIP)
368 /********************* Viewport on screen clipping ********************/ 406 /********************* Viewport on screen clipping ********************/
@@ -380,7 +418,7 @@ void LCDFN(hline)(int x1, int x2, int y)
380 418
381 width = x2 - x1 + 1; 419 width = x2 - x1 + 1;
382 420
383 bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; 421 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
384 dst = LCDFB(x1,y>>3); 422 dst = LCDFB(x1,y>>3);
385 mask = BIT_N(y & 7); 423 mask = BIT_N(y & 7);
386 424
@@ -395,6 +433,7 @@ void LCDFN(vline)(int x, int y1, int y2)
395{ 433{
396 int ny; 434 int ny;
397 FBFN(data) *dst; 435 FBFN(data) *dst;
436 int stride_dst;
398 unsigned mask, mask_bottom; 437 unsigned mask, mask_bottom;
399 LCDFN(blockfunc_type) *bfunc; 438 LCDFN(blockfunc_type) *bfunc;
400 439
@@ -408,19 +447,19 @@ void LCDFN(vline)(int x, int y1, int y2)
408 447
409 /******************** In viewport clipping **********************/ 448 /******************** In viewport clipping **********************/
410 /* nothing to draw? */ 449 /* nothing to draw? */
411 if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) 450 if (((unsigned)x >= (unsigned)CURRENT_VP->width) || (y1 >= CURRENT_VP->height)
412 || (y2 < 0)) 451 || (y2 < 0))
413 return; 452 return;
414 453
415 if (y1 < 0) 454 if (y1 < 0)
416 y1 = 0; 455 y1 = 0;
417 if (y2 >= current_vp->height) 456 if (y2 >= CURRENT_VP->height)
418 y2 = current_vp->height-1; 457 y2 = CURRENT_VP->height-1;
419 458
420 /* adjust for viewport */ 459 /* adjust for viewport */
421 y1 += current_vp->y; 460 y1 += CURRENT_VP->y;
422 y2 += current_vp->y; 461 y2 += CURRENT_VP->y;
423 x += current_vp->x; 462 x += CURRENT_VP->x;
424 463
425#if defined(HAVE_VIEWPORT_CLIP) 464#if defined(HAVE_VIEWPORT_CLIP)
426 /********************* Viewport on screen clipping ********************/ 465 /********************* Viewport on screen clipping ********************/
@@ -436,16 +475,17 @@ void LCDFN(vline)(int x, int y1, int y2)
436 y2 = LCDM(HEIGHT)-1; 475 y2 = LCDM(HEIGHT)-1;
437#endif 476#endif
438 477
439 bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; 478 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
440 dst = LCDFB(x,y1>>3); 479 dst = LCDFB(x,y1>>3);
441 ny = y2 - (y1 & ~7); 480 ny = y2 - (y1 & ~7);
442 mask = 0xFFu << (y1 & 7); 481 mask = 0xFFu << (y1 & 7);
443 mask_bottom = 0xFFu >> (~ny & 7); 482 mask_bottom = 0xFFu >> (~ny & 7);
483 stride_dst = CURRENT_VP->buffer->stride;
444 484
445 for (; ny >= 8; ny -= 8) 485 for (; ny >= 8; ny -= 8)
446 { 486 {
447 bfunc(dst, mask, 0xFFu); 487 bfunc(dst, mask, 0xFFu);
448 dst += LCDM(WIDTH); 488 dst += stride_dst;
449 mask = 0xFFu; 489 mask = 0xFFu;
450 } 490 }
451 mask &= mask_bottom; 491 mask &= mask_bottom;
@@ -472,6 +512,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
472{ 512{
473 int ny; 513 int ny;
474 FBFN(data) *dst, *dst_end; 514 FBFN(data) *dst, *dst_end;
515 int stride_dst;
475 unsigned mask, mask_bottom; 516 unsigned mask, mask_bottom;
476 unsigned bits = 0; 517 unsigned bits = 0;
477 LCDFN(blockfunc_type) *bfunc; 518 LCDFN(blockfunc_type) *bfunc;
@@ -479,8 +520,8 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
479 520
480 /******************** In viewport clipping **********************/ 521 /******************** In viewport clipping **********************/
481 /* nothing to draw? */ 522 /* nothing to draw? */
482 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) 523 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width)
483 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 524 || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
484 return; 525 return;
485 526
486 if (x < 0) 527 if (x < 0)
@@ -493,14 +534,14 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
493 height += y; 534 height += y;
494 y = 0; 535 y = 0;
495 } 536 }
496 if (x + width > current_vp->width) 537 if (x + width > CURRENT_VP->width)
497 width = current_vp->width - x; 538 width = CURRENT_VP->width - x;
498 if (y + height > current_vp->height) 539 if (y + height > CURRENT_VP->height)
499 height = current_vp->height - y; 540 height = CURRENT_VP->height - y;
500 541
501 /* adjust for viewport */ 542 /* adjust for viewport */
502 x += current_vp->x; 543 x += CURRENT_VP->x;
503 y += current_vp->y; 544 y += CURRENT_VP->y;
504 545
505#if defined(HAVE_VIEWPORT_CLIP) 546#if defined(HAVE_VIEWPORT_CLIP)
506 /********************* Viewport on screen clipping ********************/ 547 /********************* Viewport on screen clipping ********************/
@@ -526,26 +567,27 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
526 height = LCDM(HEIGHT) - y; 567 height = LCDM(HEIGHT) - y;
527#endif 568#endif
528 569
529 if (current_vp->drawmode & DRMODE_INVERSEVID) 570 if (CURRENT_VP->drawmode & DRMODE_INVERSEVID)
530 { 571 {
531 if (current_vp->drawmode & DRMODE_BG) 572 if (CURRENT_VP->drawmode & DRMODE_BG)
532 { 573 {
533 fillopt = true; 574 fillopt = true;
534 } 575 }
535 } 576 }
536 else 577 else
537 { 578 {
538 if (current_vp->drawmode & DRMODE_FG) 579 if (CURRENT_VP->drawmode & DRMODE_FG)
539 { 580 {
540 fillopt = true; 581 fillopt = true;
541 bits = 0xFFu; 582 bits = 0xFFu;
542 } 583 }
543 } 584 }
544 bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; 585 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
545 dst = LCDFB(x,y>>3); 586 dst = LCDFB(x,y>>3);
546 ny = height - 1 + (y & 7); 587 ny = height - 1 + (y & 7);
547 mask = 0xFFu << (y & 7); 588 mask = 0xFFu << (y & 7);
548 mask_bottom = 0xFFu >> (~ny & 7); 589 mask_bottom = 0xFFu >> (~ny & 7);
590 stride_dst = CURRENT_VP->buffer->stride;
549 591
550 for (; ny >= 8; ny -= 8) 592 for (; ny >= 8; ny -= 8)
551 { 593 {
@@ -561,7 +603,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
561 while (dst_row < dst_end); 603 while (dst_row < dst_end);
562 } 604 }
563 605
564 dst += LCDM(WIDTH); 606 dst += stride_dst;
565 mask = 0xFFu; 607 mask = 0xFFu;
566 } 608 }
567 mask &= mask_bottom; 609 mask &= mask_bottom;
@@ -595,13 +637,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x,
595{ 637{
596 int shift, ny; 638 int shift, ny;
597 FBFN(data) *dst, *dst_end; 639 FBFN(data) *dst, *dst_end;
640 int stride_dst;
598 unsigned mask, mask_bottom; 641 unsigned mask, mask_bottom;
599 LCDFN(blockfunc_type) *bfunc; 642 LCDFN(blockfunc_type) *bfunc;
600 643
601 /******************** Image in viewport clipping **********************/ 644 /******************** Image in viewport clipping **********************/
602 /* nothing to draw? */ 645 /* nothing to draw? */
603 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) 646 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width)
604 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 647 || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
605 return; 648 return;
606 649
607 /* clip image in viewport */ 650 /* clip image in viewport */
@@ -617,14 +660,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x,
617 src_y -= y; 660 src_y -= y;
618 y = 0; 661 y = 0;
619 } 662 }
620 if (x + width > current_vp->width) 663 if (x + width > CURRENT_VP->width)
621 width = current_vp->width - x; 664 width = CURRENT_VP->width - x;
622 if (y + height > current_vp->height) 665 if (y + height > CURRENT_VP->height)
623 height = current_vp->height - y; 666 height = CURRENT_VP->height - y;
624 667
625 /* adjust for viewport */ 668 /* adjust for viewport */
626 x += current_vp->x; 669 x += CURRENT_VP->x;
627 y += current_vp->y; 670 y += CURRENT_VP->y;
628 671
629#if defined(HAVE_VIEWPORT_CLIP) 672#if defined(HAVE_VIEWPORT_CLIP)
630 /********************* Viewport on screen clipping ********************/ 673 /********************* Viewport on screen clipping ********************/
@@ -656,16 +699,17 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x,
656 src_y &= 7; 699 src_y &= 7;
657 y -= src_y; 700 y -= src_y;
658 dst = LCDFB(x,y>>3); 701 dst = LCDFB(x,y>>3);
702 stride_dst = CURRENT_VP->buffer->stride;
659 shift = y & 7; 703 shift = y & 7;
660 ny = height - 1 + shift + src_y; 704 ny = height - 1 + shift + src_y;
661 705
662 bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; 706 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
663 mask = 0xFFu << (shift + src_y); 707 mask = 0xFFu << (shift + src_y);
664 mask_bottom = 0xFFu >> (~ny & 7); 708 mask_bottom = 0xFFu >> (~ny & 7);
665 709
666 if (shift == 0) 710 if (shift == 0)
667 { 711 {
668 bool copyopt = (current_vp->drawmode == DRMODE_SOLID); 712 bool copyopt = (CURRENT_VP->drawmode == DRMODE_SOLID);
669 713
670 for (; ny >= 8; ny -= 8) 714 for (; ny >= 8; ny -= 8)
671 { 715 {
@@ -683,7 +727,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x,
683 } 727 }
684 728
685 src += stride; 729 src += stride;
686 dst += LCDM(WIDTH); 730 dst += stride_dst;
687 mask = 0xFFu; 731 mask = 0xFFu;
688 } 732 }
689 mask &= mask_bottom; 733 mask &= mask_bottom;
@@ -721,7 +765,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const unsigned char *src, int src_x,
721 mask_col >>= 8; 765 mask_col >>= 8;
722 766
723 src_col += stride; 767 src_col += stride;
724 dst_col += LCDM(WIDTH); 768 dst_col += stride_dst;
725 data >>= 8; 769 data >>= 8;
726 } 770 }
727 data |= *src_col << shift; 771 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 @@
39#include "bidi.h" 39#include "bidi.h"
40#include "scroll_engine.h" 40#include "scroll_engine.h"
41 41
42#define ROW_INC LCD_WIDTH 42#define ROW_INC lcd_current_viewport->buffer->stride
43#define COL_INC 1 43#define COL_INC 1
44 44
45extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[]; 45extern lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[];
@@ -62,10 +62,10 @@ void lcd_clear_viewport(void)
62 int x, y, width, height; 62 int x, y, width, height;
63 int len, step; 63 int len, step;
64 64
65 x = current_vp->x; 65 x = lcd_current_viewport->x;
66 y = current_vp->y; 66 y = lcd_current_viewport->y;
67 width = current_vp->width; 67 width = lcd_current_viewport->width;
68 height = current_vp->height; 68 height = lcd_current_viewport->height;
69 69
70#if defined(HAVE_VIEWPORT_CLIP) 70#if defined(HAVE_VIEWPORT_CLIP)
71 /********************* Viewport on screen clipping ********************/ 71 /********************* Viewport on screen clipping ********************/
@@ -97,9 +97,9 @@ void lcd_clear_viewport(void)
97 dst = FBADDR(x, y); 97 dst = FBADDR(x, y);
98 dst_end = FBADDR(x + width - 1 , y + height - 1); 98 dst_end = FBADDR(x + width - 1 , y + height - 1);
99 99
100 if (current_vp->drawmode & DRMODE_INVERSEVID) 100 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
101 { 101 {
102 fb_data px = FB_SCALARPACK(current_vp->fg_pattern); 102 fb_data px = FB_SCALARPACK(lcd_current_viewport->fg_pattern);
103 do 103 do
104 { 104 {
105 fb_data *end = dst + len; 105 fb_data *end = dst + len;
@@ -114,7 +114,7 @@ void lcd_clear_viewport(void)
114 { 114 {
115 if (!lcd_backdrop) 115 if (!lcd_backdrop)
116 { 116 {
117 fb_data px = FB_SCALARPACK(current_vp->bg_pattern); 117 fb_data px = FB_SCALARPACK(lcd_current_viewport->bg_pattern);
118 do 118 do
119 { 119 {
120 fb_data *end = dst + len; 120 fb_data *end = dst + len;
@@ -137,22 +137,24 @@ void lcd_clear_viewport(void)
137 } 137 }
138 } 138 }
139 139
140 if (current_vp == &default_vp) 140 if (lcd_current_viewport == &default_vp)
141 lcd_scroll_stop(); 141 lcd_scroll_stop();
142 else 142 else
143 lcd_scroll_stop_viewport(current_vp); 143 lcd_scroll_stop_viewport(lcd_current_viewport);
144
145 lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN);
144} 146}
145 147
146/*** low-level drawing functions ***/ 148/*** low-level drawing functions ***/
147 149
148static void ICODE_ATTR setpixel(fb_data *address) 150static void ICODE_ATTR setpixel(fb_data *address)
149{ 151{
150 *address = FB_SCALARPACK(current_vp->fg_pattern); 152 *address = FB_SCALARPACK(lcd_current_viewport->fg_pattern);
151} 153}
152 154
153static void ICODE_ATTR clearpixel(fb_data *address) 155static void ICODE_ATTR clearpixel(fb_data *address)
154{ 156{
155 *address = FB_SCALARPACK(current_vp->bg_pattern); 157 *address = FB_SCALARPACK(lcd_current_viewport->bg_pattern);
156} 158}
157 159
158static void ICODE_ATTR clearimgpixel(fb_data *address) 160static void ICODE_ATTR clearimgpixel(fb_data *address)
@@ -194,8 +196,8 @@ void lcd_fillrect(int x, int y, int width, int height)
194 196
195 /******************** In viewport clipping **********************/ 197 /******************** In viewport clipping **********************/
196 /* nothing to draw? */ 198 /* nothing to draw? */
197 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 199 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
198 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 200 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
199 return; 201 return;
200 202
201 if (x < 0) 203 if (x < 0)
@@ -208,14 +210,14 @@ void lcd_fillrect(int x, int y, int width, int height)
208 height += y; 210 height += y;
209 y = 0; 211 y = 0;
210 } 212 }
211 if (x + width > current_vp->width) 213 if (x + width > lcd_current_viewport->width)
212 width = current_vp->width - x; 214 width = lcd_current_viewport->width - x;
213 if (y + height > current_vp->height) 215 if (y + height > lcd_current_viewport->height)
214 height = current_vp->height - y; 216 height = lcd_current_viewport->height - y;
215 217
216 /* adjust for viewport */ 218 /* adjust for viewport */
217 x += current_vp->x; 219 x += lcd_current_viewport->x;
218 y += current_vp->y; 220 y += lcd_current_viewport->y;
219 221
220#if defined(HAVE_VIEWPORT_CLIP) 222#if defined(HAVE_VIEWPORT_CLIP)
221 /********************* Viewport on screen clipping ********************/ 223 /********************* Viewport on screen clipping ********************/
@@ -242,14 +244,14 @@ void lcd_fillrect(int x, int y, int width, int height)
242#endif 244#endif
243 245
244 /* drawmode and optimisation */ 246 /* drawmode and optimisation */
245 if (current_vp->drawmode & DRMODE_INVERSEVID) 247 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
246 { 248 {
247 if (current_vp->drawmode & DRMODE_BG) 249 if (lcd_current_viewport->drawmode & DRMODE_BG)
248 { 250 {
249 if (!lcd_backdrop) 251 if (!lcd_backdrop)
250 { 252 {
251 fillopt = OPT_SET; 253 fillopt = OPT_SET;
252 bits = FB_SCALARPACK(current_vp->bg_pattern); 254 bits = FB_SCALARPACK(lcd_current_viewport->bg_pattern);
253 } 255 }
254 else 256 else
255 fillopt = OPT_COPY; 257 fillopt = OPT_COPY;
@@ -257,13 +259,13 @@ void lcd_fillrect(int x, int y, int width, int height)
257 } 259 }
258 else 260 else
259 { 261 {
260 if (current_vp->drawmode & DRMODE_FG) 262 if (lcd_current_viewport->drawmode & DRMODE_FG)
261 { 263 {
262 fillopt = OPT_SET; 264 fillopt = OPT_SET;
263 bits = FB_SCALARPACK(current_vp->fg_pattern); 265 bits = FB_SCALARPACK(lcd_current_viewport->fg_pattern);
264 } 266 }
265 } 267 }
266 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) 268 if (fillopt == OPT_NONE && lcd_current_viewport->drawmode != DRMODE_COMPLEMENT)
267 return; 269 return;
268 270
269 dst = FBADDR(x, y); 271 dst = FBADDR(x, y);
@@ -327,13 +329,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
327 const unsigned char *src_end; 329 const unsigned char *src_end;
328 fb_data *dst, *dst_col; 330 fb_data *dst, *dst_col;
329 unsigned dmask = 0x100; /* bit 8 == sentinel */ 331 unsigned dmask = 0x100; /* bit 8 == sentinel */
330 int drmode = current_vp->drawmode; 332 int drmode = lcd_current_viewport->drawmode;
331 int row; 333 int row;
332 334
333 /******************** Image in viewport clipping **********************/ 335 /******************** Image in viewport clipping **********************/
334 /* nothing to draw? */ 336 /* nothing to draw? */
335 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 337 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
336 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 338 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
337 return; 339 return;
338 340
339 if (x < 0) 341 if (x < 0)
@@ -348,14 +350,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
348 src_y -= y; 350 src_y -= y;
349 y = 0; 351 y = 0;
350 } 352 }
351 if (x + width > current_vp->width) 353 if (x + width > lcd_current_viewport->width)
352 width = current_vp->width - x; 354 width = lcd_current_viewport->width - x;
353 if (y + height > current_vp->height) 355 if (y + height > lcd_current_viewport->height)
354 height = current_vp->height - y; 356 height = lcd_current_viewport->height - y;
355 357
356 /* adjust for viewport */ 358 /* adjust for viewport */
357 x += current_vp->x; 359 x += lcd_current_viewport->x;
358 y += current_vp->y; 360 y += lcd_current_viewport->y;
359 361
360#if defined(HAVE_VIEWPORT_CLIP) 362#if defined(HAVE_VIEWPORT_CLIP)
361 /********************* Viewport on screen clipping ********************/ 363 /********************* Viewport on screen clipping ********************/
@@ -447,7 +449,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
447 break; 449 break;
448 450
449 case DRMODE_BG: 451 case DRMODE_BG:
450 bg = FB_SCALARPACK(current_vp->bg_pattern); 452 bg = FB_SCALARPACK(lcd_current_viewport->bg_pattern);
451 do 453 do
452 { 454 {
453 if (!(data & 0x01)) 455 if (!(data & 0x01))
@@ -460,7 +462,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
460 break; 462 break;
461 463
462 case DRMODE_FG: 464 case DRMODE_FG:
463 fg = FB_SCALARPACK(current_vp->fg_pattern); 465 fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern);
464 do 466 do
465 { 467 {
466 if (data & 0x01) 468 if (data & 0x01)
@@ -473,7 +475,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
473 break; 475 break;
474 476
475 case DRMODE_SOLID|DRMODE_INT_BD: 477 case DRMODE_SOLID|DRMODE_INT_BD:
476 fg = FB_SCALARPACK(current_vp->fg_pattern); 478 fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern);
477 bo = lcd_backdrop_offset; 479 bo = lcd_backdrop_offset;
478 do 480 do
479 { 481 {
@@ -486,8 +488,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
486 break; 488 break;
487 489
488 case DRMODE_SOLID: 490 case DRMODE_SOLID:
489 fg = FB_SCALARPACK(current_vp->fg_pattern); 491 fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern);
490 bg = FB_SCALARPACK(current_vp->bg_pattern); 492 bg = FB_SCALARPACK(lcd_current_viewport->bg_pattern);
491 do 493 do
492 { 494 {
493 *dst = (data & 0x01) ? fg : bg; 495 *dst = (data & 0x01) ? fg : bg;
@@ -559,10 +561,10 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
559{ 561{
560 fb_data *dst, *dst_row; 562 fb_data *dst, *dst_row;
561 unsigned dmask = 0x00000000; 563 unsigned dmask = 0x00000000;
562 int drmode = current_vp->drawmode; 564 int drmode = lcd_current_viewport->drawmode;
563 /* nothing to draw? */ 565 /* nothing to draw? */
564 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 566 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
565 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 567 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
566 return; 568 return;
567 569
568 /* clipping */ 570 /* clipping */
@@ -578,14 +580,14 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
578 src_y -= y; 580 src_y -= y;
579 y = 0; 581 y = 0;
580 } 582 }
581 if (x + width > current_vp->width) 583 if (x + width > lcd_current_viewport->width)
582 width = current_vp->width - x; 584 width = lcd_current_viewport->width - x;
583 if (y + height > current_vp->height) 585 if (y + height > lcd_current_viewport->height)
584 height = current_vp->height - y; 586 height = lcd_current_viewport->height - y;
585 587
586 /* adjust for viewport */ 588 /* adjust for viewport */
587 x += current_vp->x; 589 x += lcd_current_viewport->x;
588 y += current_vp->y; 590 y += lcd_current_viewport->y;
589 591
590#if defined(HAVE_VIEWPORT_CLIP) 592#if defined(HAVE_VIEWPORT_CLIP)
591 /********************* Viewport on screen clipping ********************/ 593 /********************* Viewport on screen clipping ********************/
@@ -673,7 +675,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
673 /* go through the rows and update each pixel */ 675 /* go through the rows and update each pixel */
674 do 676 do
675 { 677 {
676 /* saving current_vp->fg/bg_pattern and lcd_backdrop_offset into these 678 /* saving lcd_current_viewport->fg/bg_pattern and lcd_backdrop_offset into these
677 * temp vars just before the loop helps gcc to opimize the loop better 679 * temp vars just before the loop helps gcc to opimize the loop better
678 * (testing showed ~15% speedup) */ 680 * (testing showed ~15% speedup) */
679 unsigned fg, bg; 681 unsigned fg, bg;
@@ -734,7 +736,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
734 while (--col); 736 while (--col);
735 break; 737 break;
736 case DRMODE_BG: 738 case DRMODE_BG:
737 bg = current_vp->bg_pattern; 739 bg = lcd_current_viewport->bg_pattern;
738 do 740 do
739 { 741 {
740 unsigned px = FB_UNPACK_SCALAR_LCD(*dst); 742 unsigned px = FB_UNPACK_SCALAR_LCD(*dst);
@@ -757,7 +759,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
757 while (--col); 759 while (--col);
758 break; 760 break;
759 case DRMODE_FG: 761 case DRMODE_FG:
760 fg = current_vp->fg_pattern; 762 fg = lcd_current_viewport->fg_pattern;
761 do 763 do
762 { 764 {
763 unsigned px = FB_UNPACK_SCALAR_LCD(*dst); 765 unsigned px = FB_UNPACK_SCALAR_LCD(*dst);
@@ -769,7 +771,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
769 break; 771 break;
770 case DRMODE_SOLID|DRMODE_INT_BD: 772 case DRMODE_SOLID|DRMODE_INT_BD:
771 bo = lcd_backdrop_offset; 773 bo = lcd_backdrop_offset;
772 fg = current_vp->fg_pattern; 774 fg = lcd_current_viewport->fg_pattern;
773 do 775 do
774 { 776 {
775 unsigned c = FB_UNPACK_SCALAR_LCD(*(fb_data *)((uintptr_t)dst + bo)); 777 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,
780 while (--col); 782 while (--col);
781 break; 783 break;
782 case DRMODE_SOLID|DRMODE_INT_IMG: 784 case DRMODE_SOLID|DRMODE_INT_IMG:
783 bg = current_vp->bg_pattern; 785 bg = lcd_current_viewport->bg_pattern;
784 img_offset = image - dst; 786 img_offset = image - dst;
785 do 787 do
786 { 788 {
@@ -805,8 +807,8 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image,
805 while (--col); 807 while (--col);
806 break; 808 break;
807 case DRMODE_SOLID: 809 case DRMODE_SOLID:
808 bg = current_vp->bg_pattern; 810 bg = lcd_current_viewport->bg_pattern;
809 fg = current_vp->fg_pattern; 811 fg = lcd_current_viewport->fg_pattern;
810 do 812 do
811 { 813 {
812 *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); 814 *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE );
@@ -855,7 +857,7 @@ void lcd_hline(int x1, int x2, int y)
855{ 857{
856 int x, width; 858 int x, width;
857 fb_data *dst, *dst_end; 859 fb_data *dst, *dst_end;
858 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; 860 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
859 861
860 /* direction flip */ 862 /* direction flip */
861 if (x2 < x1) 863 if (x2 < x1)
@@ -867,20 +869,20 @@ void lcd_hline(int x1, int x2, int y)
867 869
868 /******************** In viewport clipping **********************/ 870 /******************** In viewport clipping **********************/
869 /* nothing to draw? */ 871 /* nothing to draw? */
870 if (((unsigned)y >= (unsigned)current_vp->height) || 872 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) ||
871 (x1 >= current_vp->width) || 873 (x1 >= lcd_current_viewport->width) ||
872 (x2 < 0)) 874 (x2 < 0))
873 return; 875 return;
874 876
875 if (x1 < 0) 877 if (x1 < 0)
876 x1 = 0; 878 x1 = 0;
877 if (x2 >= current_vp->width) 879 if (x2 >= lcd_current_viewport->width)
878 x2 = current_vp->width-1; 880 x2 = lcd_current_viewport->width-1;
879 881
880 /* Adjust x1 and y to viewport */ 882 /* Adjust x1 and y to viewport */
881 x1 += current_vp->x; 883 x1 += lcd_current_viewport->x;
882 x2 += current_vp->x; 884 x2 += lcd_current_viewport->x;
883 y += current_vp->y; 885 y += lcd_current_viewport->y;
884 886
885#if defined(HAVE_VIEWPORT_CLIP) 887#if defined(HAVE_VIEWPORT_CLIP)
886 /********************* Viewport on screen clipping ********************/ 888 /********************* Viewport on screen clipping ********************/
@@ -912,7 +914,7 @@ void lcd_vline(int x, int y1, int y2)
912{ 914{
913 int y; 915 int y;
914 fb_data *dst, *dst_end; 916 fb_data *dst, *dst_end;
915 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; 917 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
916 918
917 /* direction flip */ 919 /* direction flip */
918 if (y2 < y1) 920 if (y2 < y1)
@@ -924,20 +926,20 @@ void lcd_vline(int x, int y1, int y2)
924 926
925 /******************** In viewport clipping **********************/ 927 /******************** In viewport clipping **********************/
926 /* nothing to draw? */ 928 /* nothing to draw? */
927 if (((unsigned)x >= (unsigned)current_vp->width) || 929 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) ||
928 (y1 >= current_vp->height) || 930 (y1 >= lcd_current_viewport->height) ||
929 (y2 < 0)) 931 (y2 < 0))
930 return; 932 return;
931 933
932 if (y1 < 0) 934 if (y1 < 0)
933 y1 = 0; 935 y1 = 0;
934 if (y2 >= current_vp->height) 936 if (y2 >= lcd_current_viewport->height)
935 y2 = current_vp->height-1; 937 y2 = lcd_current_viewport->height-1;
936 938
937 /* adjust for viewport */ 939 /* adjust for viewport */
938 x += current_vp->x; 940 x += lcd_current_viewport->x;
939 y1 += current_vp->y; 941 y1 += lcd_current_viewport->y;
940 y2 += current_vp->y; 942 y2 += lcd_current_viewport->y;
941 943
942#if defined(HAVE_VIEWPORT_CLIP) 944#if defined(HAVE_VIEWPORT_CLIP)
943 /********************* Viewport on screen clipping ********************/ 945 /********************* Viewport on screen clipping ********************/
@@ -973,8 +975,8 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
973 975
974 /******************** Image in viewport clipping **********************/ 976 /******************** Image in viewport clipping **********************/
975 /* nothing to draw? */ 977 /* nothing to draw? */
976 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 978 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
977 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 979 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
978 return; 980 return;
979 981
980 if (x < 0) 982 if (x < 0)
@@ -990,14 +992,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
990 y = 0; 992 y = 0;
991 } 993 }
992 994
993 if (x + width > current_vp->width) 995 if (x + width > lcd_current_viewport->width)
994 width = current_vp->width - x; 996 width = lcd_current_viewport->width - x;
995 if (y + height > current_vp->height) 997 if (y + height > lcd_current_viewport->height)
996 height = current_vp->height - y; 998 height = lcd_current_viewport->height - y;
997 999
998 /* adjust for viewport */ 1000 /* adjust for viewport */
999 x += current_vp->x; 1001 x += lcd_current_viewport->x;
1000 y += current_vp->y; 1002 y += lcd_current_viewport->y;
1001 1003
1002#if defined(HAVE_VIEWPORT_CLIP) 1004#if defined(HAVE_VIEWPORT_CLIP)
1003 /********************* Viewport on screen clipping ********************/ 1005 /********************* Viewport on screen clipping ********************/
@@ -1047,8 +1049,8 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
1047 1049
1048 /******************** Image in viewport clipping **********************/ 1050 /******************** Image in viewport clipping **********************/
1049 /* nothing to draw? */ 1051 /* nothing to draw? */
1050 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 1052 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
1051 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 1053 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
1052 return; 1054 return;
1053 1055
1054 if (x < 0) 1056 if (x < 0)
@@ -1064,14 +1066,14 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
1064 y = 0; 1066 y = 0;
1065 } 1067 }
1066 1068
1067 if (x + width > current_vp->width) 1069 if (x + width > lcd_current_viewport->width)
1068 width = current_vp->width - x; 1070 width = lcd_current_viewport->width - x;
1069 if (y + height > current_vp->height) 1071 if (y + height > lcd_current_viewport->height)
1070 height = current_vp->height - y; 1072 height = lcd_current_viewport->height - y;
1071 1073
1072 /* adjust for viewport */ 1074 /* adjust for viewport */
1073 x += current_vp->x; 1075 x += lcd_current_viewport->x;
1074 y += current_vp->y; 1076 y += lcd_current_viewport->y;
1075 1077
1076#if defined(HAVE_VIEWPORT_CLIP) 1078#if defined(HAVE_VIEWPORT_CLIP)
1077 /********************* Viewport on screen clipping ********************/ 1079 /********************* Viewport on screen clipping ********************/
@@ -1104,7 +1106,7 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x,
1104 1106
1105 transparent = FB_SCALARPACK(TRANSPARENT_COLOR); 1107 transparent = FB_SCALARPACK(TRANSPARENT_COLOR);
1106 replacewithfg = FB_SCALARPACK(REPLACEWITHFG_COLOR); 1108 replacewithfg = FB_SCALARPACK(REPLACEWITHFG_COLOR);
1107 fg = FB_SCALARPACK(current_vp->fg_pattern); 1109 fg = FB_SCALARPACK(lcd_current_viewport->fg_pattern);
1108#define CMP(c1, c2) (c1.r == c2.r && c1.g == c2.g && c1.b == c2.b) 1110#define CMP(c1, c2) (c1.r == c2.r && c1.g == c2.g && c1.b == c2.b)
1109 1111
1110 do 1112 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 @@
39 39
40/*** globals ***/ 40/*** globals ***/
41 41
42unsigned char lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; 42static unsigned char lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER;
43unsigned char *lcd_framebuffer = &lcd_static_framebuffer[0][0]; 43static void *lcd_frameaddress_default(int x, int y);
44 44
45static const unsigned char pixmask[4] ICONST_ATTR = { 45static const unsigned char pixmask[4] ICONST_ATTR = {
46 0xC0, 0x30, 0x0C, 0x03 46 0xC0, 0x30, 0x0C, 0x03
@@ -49,6 +49,15 @@ static const unsigned char pixmask[4] ICONST_ATTR = {
49static fb_data* lcd_backdrop = NULL; 49static fb_data* lcd_backdrop = NULL;
50static long lcd_backdrop_offset IDATA_ATTR = 0; 50static long lcd_backdrop_offset IDATA_ATTR = 0;
51 51
52/* shouldn't be changed unless you want system-wide framebuffer changes! */
53struct frame_buffer_t lcd_framebuffer_default =
54{
55 .fb_ptr = &lcd_static_framebuffer[0][0],
56 .get_address_fn = &lcd_frameaddress_default,
57 .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT),
58 .elems = (LCD_FBWIDTH*LCD_FBHEIGHT),
59};
60
52static struct viewport default_vp = 61static struct viewport default_vp =
53{ 62{
54 .x = 0, 63 .x = 0,
@@ -57,18 +66,32 @@ static struct viewport default_vp =
57 .height = LCD_HEIGHT, 66 .height = LCD_HEIGHT,
58 .font = FONT_SYSFIXED, 67 .font = FONT_SYSFIXED,
59 .drawmode = DRMODE_SOLID, 68 .drawmode = DRMODE_SOLID,
69 .buffer = NULL,
60 .fg_pattern = LCD_DEFAULT_FG, 70 .fg_pattern = LCD_DEFAULT_FG,
61 .bg_pattern = LCD_DEFAULT_BG 71 .bg_pattern = LCD_DEFAULT_BG
62}; 72};
63 73
64static struct viewport* current_vp IBSS_ATTR; 74struct viewport* lcd_current_viewport IBSS_ATTR;
65static unsigned fg_pattern IBSS_ATTR; 75static unsigned fg_pattern IBSS_ATTR;
66static unsigned bg_pattern IBSS_ATTR; 76static unsigned bg_pattern IBSS_ATTR;
67 77
78static void *lcd_frameaddress_default(int x, int y)
79{
80 /* the default expects a buffer the same size as the screen */
81 struct frame_buffer_t *fb = lcd_current_viewport->buffer;
82
83#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
84 size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y;
85#else
86 size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x;
87#endif
88 return fb->fb_ptr + element;/*(element % fb->elems);*/
89}
90
68/* LCD init */ 91/* LCD init */
69void lcd_init(void) 92void lcd_init(void)
70{ 93{
71 /* Initialise the viewport */ 94 /* Initialize the viewport */
72 lcd_set_viewport(NULL); 95 lcd_set_viewport(NULL);
73 96
74 lcd_clear_display(); 97 lcd_clear_display();
@@ -81,34 +104,34 @@ void lcd_init(void)
81 104
82void lcd_set_drawmode(int mode) 105void lcd_set_drawmode(int mode)
83{ 106{
84 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 107 lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
85} 108}
86 109
87int lcd_get_drawmode(void) 110int lcd_get_drawmode(void)
88{ 111{
89 return current_vp->drawmode; 112 return lcd_current_viewport->drawmode;
90} 113}
91 114
92void lcd_set_foreground(unsigned brightness) 115void lcd_set_foreground(unsigned brightness)
93{ 116{
94 current_vp->fg_pattern = brightness; 117 lcd_current_viewport->fg_pattern = brightness;
95 fg_pattern = 0x55 * (~brightness & 3); 118 fg_pattern = 0x55 * (~brightness & 3);
96} 119}
97 120
98unsigned lcd_get_foreground(void) 121unsigned lcd_get_foreground(void)
99{ 122{
100 return current_vp->fg_pattern; 123 return lcd_current_viewport->fg_pattern;
101} 124}
102 125
103void lcd_set_background(unsigned brightness) 126void lcd_set_background(unsigned brightness)
104{ 127{
105 current_vp->bg_pattern = brightness; 128 lcd_current_viewport->bg_pattern = brightness;
106 bg_pattern = 0x55 * (~brightness & 3); 129 bg_pattern = 0x55 * (~brightness & 3);
107} 130}
108 131
109unsigned lcd_get_background(void) 132unsigned lcd_get_background(void)
110{ 133{
111 return current_vp->bg_pattern; 134 return lcd_current_viewport->bg_pattern;
112} 135}
113 136
114void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) 137void 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)
120 143
121int lcd_getwidth(void) 144int lcd_getwidth(void)
122{ 145{
123 return current_vp->width; 146 return lcd_current_viewport->width;
124} 147}
125 148
126int lcd_getheight(void) 149int lcd_getheight(void)
127{ 150{
128 return current_vp->height; 151 return lcd_current_viewport->height;
129} 152}
130 153
131void lcd_setfont(int newfont) 154void lcd_setfont(int newfont)
132{ 155{
133 current_vp->font = newfont; 156 lcd_current_viewport->font = newfont;
134} 157}
135 158
136int lcd_getfont(void) 159int lcd_getfont(void)
137{ 160{
138 return current_vp->font; 161 return lcd_current_viewport->font;
139} 162}
140 163
141int lcd_getstringsize(const unsigned char *str, int *w, int *h) 164int lcd_getstringsize(const unsigned char *str, int *w, int *h)
142{ 165{
143 return font_getstringsize(str, w, h, current_vp->font); 166 return font_getstringsize(str, w, h, lcd_current_viewport->font);
144} 167}
145 168
146/*** low-level drawing functions ***/ 169/*** low-level drawing functions ***/
@@ -318,7 +341,7 @@ void lcd_set_backdrop(fb_data* backdrop)
318 lcd_backdrop = backdrop; 341 lcd_backdrop = backdrop;
319 if (backdrop) 342 if (backdrop)
320 { 343 {
321 lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; 344 lcd_backdrop_offset = (long)backdrop - (long)FBADDR(0,0);
322 lcd_pixelfuncs = lcd_pixelfuncs_backdrop; 345 lcd_pixelfuncs = lcd_pixelfuncs_backdrop;
323 lcd_blockfuncs = lcd_blockfuncs_backdrop; 346 lcd_blockfuncs = lcd_blockfuncs_backdrop;
324 } 347 }
@@ -349,16 +372,16 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits)
349/* Clear the whole display */ 372/* Clear the whole display */
350void lcd_clear_display(void) 373void lcd_clear_display(void)
351{ 374{
352 if (current_vp->drawmode & DRMODE_INVERSEVID) 375 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
353 { 376 {
354 memset(lcd_framebuffer, fg_pattern, FRAMEBUFFER_SIZE); 377 memset(FBADDR(0,0), fg_pattern, FRAMEBUFFER_SIZE);
355 } 378 }
356 else 379 else
357 { 380 {
358 if (lcd_backdrop) 381 if (lcd_backdrop)
359 memcpy(lcd_framebuffer, lcd_backdrop, FRAMEBUFFER_SIZE); 382 memcpy(FBADDR(0,0), lcd_backdrop, FRAMEBUFFER_SIZE);
360 else 383 else
361 memset(lcd_framebuffer, bg_pattern, FRAMEBUFFER_SIZE); 384 memset(FBADDR(0,0), bg_pattern, FRAMEBUFFER_SIZE);
362 } 385 }
363 386
364 lcd_scroll_info.lines = 0; 387 lcd_scroll_info.lines = 0;
@@ -369,37 +392,39 @@ void lcd_clear_viewport(void)
369{ 392{
370 int lastmode; 393 int lastmode;
371 394
372 if (current_vp == &default_vp) 395 if (lcd_current_viewport == &default_vp &&
396 default_vp.buffer == &lcd_framebuffer_default)
373 { 397 {
374 lcd_clear_display(); 398 lcd_clear_display();
375 } 399 }
376 else 400 else
377 { 401 {
378 lastmode = current_vp->drawmode; 402 lastmode = lcd_current_viewport->drawmode;
379 403
380 /* Invert the INVERSEVID bit and set basic mode to SOLID */ 404 /* Invert the INVERSEVID bit and set basic mode to SOLID */
381 current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | 405 lcd_current_viewport->drawmode = (~lastmode & DRMODE_INVERSEVID) |
382 DRMODE_SOLID; 406 DRMODE_SOLID;
383 407
384 lcd_fillrect(0, 0, current_vp->width, current_vp->height); 408 lcd_fillrect(0, 0, lcd_current_viewport->width, lcd_current_viewport->height);
385 409
386 current_vp->drawmode = lastmode; 410 lcd_current_viewport->drawmode = lastmode;
387 411
388 lcd_scroll_stop_viewport(current_vp); 412 lcd_scroll_stop_viewport(lcd_current_viewport);
389 } 413 }
414 lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN);
390} 415}
391 416
392/* Set a single pixel */ 417/* Set a single pixel */
393void lcd_drawpixel(int x, int y) 418void lcd_drawpixel(int x, int y)
394{ 419{
395 if ( ((unsigned)x < (unsigned)current_vp->width) 420 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width)
396 && ((unsigned)y < (unsigned)current_vp->height) 421 && ((unsigned)y < (unsigned)lcd_current_viewport->height)
397#if defined(HAVE_VIEWPORT_CLIP) 422#if defined(HAVE_VIEWPORT_CLIP)
398 && ((unsigned)x < (unsigned)LCD_WIDTH) 423 && ((unsigned)x < (unsigned)LCD_WIDTH)
399 && ((unsigned)y < (unsigned)LCD_HEIGHT) 424 && ((unsigned)y < (unsigned)LCD_HEIGHT)
400#endif 425#endif
401 ) 426 )
402 lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); 427 lcd_pixelfuncs[lcd_current_viewport->drawmode](lcd_current_viewport->x + x, lcd_current_viewport->y + y);
403} 428}
404 429
405/* Draw a line */ 430/* Draw a line */
@@ -411,7 +436,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
411 int d, dinc1, dinc2; 436 int d, dinc1, dinc2;
412 int x, xinc1, xinc2; 437 int x, xinc1, xinc2;
413 int y, yinc1, yinc2; 438 int y, yinc1, yinc2;
414 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; 439 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode];
415 440
416 deltay = abs(y2 - y1); 441 deltay = abs(y2 - y1);
417 if (deltay == 0) 442 if (deltay == 0)
@@ -467,14 +492,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
467 492
468 for (i = 0; i < numpixels; i++) 493 for (i = 0; i < numpixels; i++)
469 { 494 {
470 if ( ((unsigned)x < (unsigned)current_vp->width) 495 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width)
471 && ((unsigned)y < (unsigned)current_vp->height) 496 && ((unsigned)y < (unsigned)lcd_current_viewport->height)
472#if defined(HAVE_VIEWPORT_CLIP) 497#if defined(HAVE_VIEWPORT_CLIP)
473 && ((unsigned)x < (unsigned)LCD_WIDTH) 498 && ((unsigned)x < (unsigned)LCD_WIDTH)
474 && ((unsigned)y < (unsigned)LCD_HEIGHT) 499 && ((unsigned)y < (unsigned)LCD_HEIGHT)
475#endif 500#endif
476 ) 501 )
477 pfunc(current_vp->x + x, current_vp->y + y); 502 pfunc(lcd_current_viewport->x + x, lcd_current_viewport->y + y);
478 503
479 if (d < 0) 504 if (d < 0)
480 { 505 {
@@ -509,19 +534,19 @@ void lcd_hline(int x1, int x2, int y)
509 534
510 /******************** In viewport clipping **********************/ 535 /******************** In viewport clipping **********************/
511 /* nothing to draw? */ 536 /* nothing to draw? */
512 if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) 537 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || (x1 >= lcd_current_viewport->width)
513 || (x2 < 0)) 538 || (x2 < 0))
514 return; 539 return;
515 540
516 if (x1 < 0) 541 if (x1 < 0)
517 x1 = 0; 542 x1 = 0;
518 if (x2 >= current_vp->width) 543 if (x2 >= lcd_current_viewport->width)
519 x2 = current_vp->width-1; 544 x2 = lcd_current_viewport->width-1;
520 545
521 /* adjust to viewport */ 546 /* adjust to viewport */
522 x1 += current_vp->x; 547 x1 += lcd_current_viewport->x;
523 x2 += current_vp->x; 548 x2 += lcd_current_viewport->x;
524 y += current_vp->y; 549 y += lcd_current_viewport->y;
525 550
526#if defined(HAVE_VIEWPORT_CLIP) 551#if defined(HAVE_VIEWPORT_CLIP)
527 /********************* Viewport on screen clipping ********************/ 552 /********************* Viewport on screen clipping ********************/
@@ -537,7 +562,7 @@ void lcd_hline(int x1, int x2, int y)
537 x2 = LCD_WIDTH-1; 562 x2 = LCD_WIDTH-1;
538#endif 563#endif
539 564
540 bfunc = lcd_blockfuncs[current_vp->drawmode]; 565 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
541 dst = FBADDR(x1>>2,y); 566 dst = FBADDR(x1>>2,y);
542 nx = x2 - (x1 & ~3); 567 nx = x2 - (x1 & ~3);
543 mask = 0xFFu >> (2 * (x1 & 3)); 568 mask = 0xFFu >> (2 * (x1 & 3));
@@ -557,6 +582,7 @@ void lcd_vline(int x, int y1, int y2)
557{ 582{
558 int y; 583 int y;
559 unsigned char *dst, *dst_end; 584 unsigned char *dst, *dst_end;
585 int stride_dst;
560 unsigned mask; 586 unsigned mask;
561 lcd_blockfunc_type *bfunc; 587 lcd_blockfunc_type *bfunc;
562 588
@@ -570,19 +596,19 @@ void lcd_vline(int x, int y1, int y2)
570 596
571 /******************** In viewport clipping **********************/ 597 /******************** In viewport clipping **********************/
572 /* nothing to draw? */ 598 /* nothing to draw? */
573 if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) 599 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || (y1 >= lcd_current_viewport->height)
574 || (y2 < 0)) 600 || (y2 < 0))
575 return; 601 return;
576 602
577 if (y1 < 0) 603 if (y1 < 0)
578 y1 = 0; 604 y1 = 0;
579 if (y2 >= current_vp->height) 605 if (y2 >= lcd_current_viewport->height)
580 y2 = current_vp->height-1; 606 y2 = lcd_current_viewport->height-1;
581 607
582 /* adjust for viewport */ 608 /* adjust for viewport */
583 y1 += current_vp->y; 609 y1 += lcd_current_viewport->y;
584 y2 += current_vp->y; 610 y2 += lcd_current_viewport->y;
585 x += current_vp->x; 611 x += lcd_current_viewport->x;
586 612
587#if defined(HAVE_VIEWPORT_CLIP) 613#if defined(HAVE_VIEWPORT_CLIP)
588 /********************* Viewport on screen clipping ********************/ 614 /********************* Viewport on screen clipping ********************/
@@ -598,15 +624,16 @@ void lcd_vline(int x, int y1, int y2)
598 y2 = LCD_HEIGHT-1; 624 y2 = LCD_HEIGHT-1;
599#endif 625#endif
600 626
601 bfunc = lcd_blockfuncs[current_vp->drawmode]; 627 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
602 dst = FBADDR(x>>2,y1); 628 dst = FBADDR(x>>2,y1);
629 stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0);
603 mask = pixmask[x & 3]; 630 mask = pixmask[x & 3];
604 631
605 dst_end = dst + (y2 - y1) * LCD_FBWIDTH; 632 dst_end = dst + (y2 - y1) * stride_dst;
606 do 633 do
607 { 634 {
608 bfunc(dst, mask, 0xFFu); 635 bfunc(dst, mask, 0xFFu);
609 dst += LCD_FBWIDTH; 636 dst += stride_dst;
610 } 637 }
611 while (dst <= dst_end); 638 while (dst <= dst_end);
612} 639}
@@ -631,12 +658,13 @@ void lcd_fillrect(int x, int y, int width, int height)
631{ 658{
632 int nx; 659 int nx;
633 unsigned char *dst, *dst_end; 660 unsigned char *dst, *dst_end;
661 int stride_dst;
634 unsigned mask, mask_right; 662 unsigned mask, mask_right;
635 lcd_blockfunc_type *bfunc; 663 lcd_blockfunc_type *bfunc;
636 664
637 /******************** In viewport clipping **********************/ 665 /******************** In viewport clipping **********************/
638 /* nothing to draw? */ 666 /* nothing to draw? */
639 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || (y >= current_vp->height) 667 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) || (y >= lcd_current_viewport->height)
640 || (x + width <= 0) || (y + height <= 0)) 668 || (x + width <= 0) || (y + height <= 0))
641 return; 669 return;
642 670
@@ -650,14 +678,14 @@ void lcd_fillrect(int x, int y, int width, int height)
650 height += y; 678 height += y;
651 y = 0; 679 y = 0;
652 } 680 }
653 if (x + width > current_vp->width) 681 if (x + width > lcd_current_viewport->width)
654 width = current_vp->width - x; 682 width = lcd_current_viewport->width - x;
655 if (y + height > current_vp->height) 683 if (y + height > lcd_current_viewport->height)
656 height = current_vp->height - y; 684 height = lcd_current_viewport->height - y;
657 685
658 /* adjust for viewport */ 686 /* adjust for viewport */
659 x += current_vp->x; 687 x += lcd_current_viewport->x;
660 y += current_vp->y; 688 y += lcd_current_viewport->y;
661 689
662#if defined(HAVE_VIEWPORT_CLIP) 690#if defined(HAVE_VIEWPORT_CLIP)
663 /********************* Viewport on screen clipping ********************/ 691 /********************* Viewport on screen clipping ********************/
@@ -683,21 +711,22 @@ void lcd_fillrect(int x, int y, int width, int height)
683 height = LCD_HEIGHT - y; 711 height = LCD_HEIGHT - y;
684#endif 712#endif
685 713
686 bfunc = lcd_blockfuncs[current_vp->drawmode]; 714 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
687 dst = FBADDR(x>>2,y); 715 dst = FBADDR(x>>2,y);
688 nx = width - 1 + (x & 3); 716 stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0);
689 mask = 0xFFu >> (2 * (x & 3)); 717 nx = width - 1 + (x & 3);
718 mask = 0xFFu >> (2 * (x & 3));
690 mask_right = 0xFFu << (2 * (~nx & 3)); 719 mask_right = 0xFFu << (2 * (~nx & 3));
691 720
692 for (; nx >= 4; nx -= 4) 721 for (; nx >= 4; nx -= 4)
693 { 722 {
694 unsigned char *dst_col = dst; 723 unsigned char *dst_col = dst;
695 724
696 dst_end = dst_col + height * LCD_FBWIDTH; 725 dst_end = dst_col + height * stride_dst;
697 do 726 do
698 { 727 {
699 bfunc(dst_col, mask, 0xFFu); 728 bfunc(dst_col, mask, 0xFFu);
700 dst_col += LCD_FBWIDTH; 729 dst_col += stride_dst;
701 } 730 }
702 while (dst_col < dst_end); 731 while (dst_col < dst_end);
703 732
@@ -706,11 +735,11 @@ void lcd_fillrect(int x, int y, int width, int height)
706 } 735 }
707 mask &= mask_right; 736 mask &= mask_right;
708 737
709 dst_end = dst + height * LCD_FBWIDTH; 738 dst_end = dst + height * stride_dst;
710 do 739 do
711 { 740 {
712 bfunc(dst, mask, 0xFFu); 741 bfunc(dst, mask, 0xFFu);
713 dst += LCD_FBWIDTH; 742 dst += stride_dst;
714 } 743 }
715 while (dst < dst_end); 744 while (dst < dst_end);
716} 745}
@@ -731,14 +760,15 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
731{ 760{
732 const unsigned char *src_end; 761 const unsigned char *src_end;
733 fb_data *dst, *dst_end; 762 fb_data *dst, *dst_end;
763 int stride_dst;
734 unsigned dmask = 0x100; /* bit 8 == sentinel */ 764 unsigned dmask = 0x100; /* bit 8 == sentinel */
735 unsigned dst_mask; 765 unsigned dst_mask;
736 int drmode = current_vp->drawmode; 766 int drmode = lcd_current_viewport->drawmode;
737 767
738 /******************** Image in viewport clipping **********************/ 768 /******************** Image in viewport clipping **********************/
739 /* nothing to draw? */ 769 /* nothing to draw? */
740 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 770 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
741 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 771 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
742 return; 772 return;
743 773
744 if (x < 0) 774 if (x < 0)
@@ -753,13 +783,13 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
753 src_y -= y; 783 src_y -= y;
754 y = 0; 784 y = 0;
755 } 785 }
756 if (x + width > current_vp->width) 786 if (x + width > lcd_current_viewport->width)
757 width = current_vp->width - x; 787 width = lcd_current_viewport->width - x;
758 if (y + height > current_vp->height) 788 if (y + height > lcd_current_viewport->height)
759 height = current_vp->height - y; 789 height = lcd_current_viewport->height - y;
760 790
761 x += current_vp->x; /* adjust for viewport */ 791 x += lcd_current_viewport->x; /* adjust for viewport */
762 y += current_vp->y; /* adjust for viewport */ 792 y += lcd_current_viewport->y; /* adjust for viewport */
763 793
764#if defined(HAVE_VIEWPORT_CLIP) 794#if defined(HAVE_VIEWPORT_CLIP)
765 /********************* Viewport on screen clipping ********************/ 795 /********************* Viewport on screen clipping ********************/
@@ -792,7 +822,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
792 src_end = src + width; 822 src_end = src + width;
793 823
794 dst = FBADDR(x >> 2,y); 824 dst = FBADDR(x >> 2,y);
795 dst_end = dst + height * LCD_FBWIDTH; 825 stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0);
826 dst_end = dst + height * stride_dst;
796 dst_mask = pixmask[x & 3]; 827 dst_mask = pixmask[x & 3];
797 828
798 if (drmode & DRMODE_INVERSEVID) 829 if (drmode & DRMODE_INVERSEVID)
@@ -825,7 +856,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
825 if (data & 0x01) 856 if (data & 0x01)
826 *dst_col ^= dst_mask; 857 *dst_col ^= dst_mask;
827 858
828 dst_col += LCD_FBWIDTH; 859 dst_col += stride_dst;
829 UPDATE_SRC; 860 UPDATE_SRC;
830 } 861 }
831 while (dst_col < dst_end); 862 while (dst_col < dst_end);
@@ -843,7 +874,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
843 *dst_col = block 874 *dst_col = block
844 ^ ((block ^ *(dst_col + bo)) & dst_mask); 875 ^ ((block ^ *(dst_col + bo)) & dst_mask);
845 } 876 }
846 dst_col += LCD_FBWIDTH; 877 dst_col += stride_dst;
847 UPDATE_SRC; 878 UPDATE_SRC;
848 } 879 }
849 while (dst_col < dst_end); 880 while (dst_col < dst_end);
@@ -858,7 +889,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
858 unsigned block = *dst_col; 889 unsigned block = *dst_col;
859 *dst_col = block ^ ((block ^ bg) & dst_mask); 890 *dst_col = block ^ ((block ^ bg) & dst_mask);
860 } 891 }
861 dst_col += LCD_FBWIDTH; 892 dst_col += stride_dst;
862 UPDATE_SRC; 893 UPDATE_SRC;
863 } 894 }
864 while (dst_col < dst_end); 895 while (dst_col < dst_end);
@@ -874,7 +905,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
874 unsigned block = *dst_col; 905 unsigned block = *dst_col;
875 *dst_col = block ^ ((block ^ fg) & dst_mask); 906 *dst_col = block ^ ((block ^ fg) & dst_mask);
876 } 907 }
877 dst_col += LCD_FBWIDTH; 908 dst_col += stride_dst;
878 UPDATE_SRC; 909 UPDATE_SRC;
879 } 910 }
880 while (dst_col < dst_end); 911 while (dst_col < dst_end);
@@ -891,7 +922,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
891 *dst_col = block ^ ((block ^ ((data & 0x01) ? 922 *dst_col = block ^ ((block ^ ((data & 0x01) ?
892 fg : *(dst_col + bo))) & dst_mask); 923 fg : *(dst_col + bo))) & dst_mask);
893 924
894 dst_col += LCD_FBWIDTH; 925 dst_col += stride_dst;
895 UPDATE_SRC; 926 UPDATE_SRC;
896 } 927 }
897 while (dst_col < dst_end); 928 while (dst_col < dst_end);
@@ -905,7 +936,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
905 *dst_col = block ^ ((block ^ ((data & 0x01) ? 936 *dst_col = block ^ ((block ^ ((data & 0x01) ?
906 fg : bg)) & dst_mask); 937 fg : bg)) & dst_mask);
907 938
908 dst_col += LCD_FBWIDTH; 939 dst_col += stride_dst;
909 UPDATE_SRC; 940 UPDATE_SRC;
910 } 941 }
911 while (dst_col < dst_end); 942 while (dst_col < dst_end);
@@ -945,12 +976,13 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x,
945{ 976{
946 int shift, nx; 977 int shift, nx;
947 unsigned char *dst, *dst_end; 978 unsigned char *dst, *dst_end;
979 int stride_dst;
948 unsigned mask, mask_right; 980 unsigned mask, mask_right;
949 981
950 /******************** Image in viewport clipping **********************/ 982 /******************** Image in viewport clipping **********************/
951 /* nothing to draw? */ 983 /* nothing to draw? */
952 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 984 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
953 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 985 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
954 return; 986 return;
955 987
956 if (x < 0) 988 if (x < 0)
@@ -965,14 +997,14 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x,
965 src_y -= y; 997 src_y -= y;
966 y = 0; 998 y = 0;
967 } 999 }
968 if (x + width > current_vp->width) 1000 if (x + width > lcd_current_viewport->width)
969 width = current_vp->width - x; 1001 width = lcd_current_viewport->width - x;
970 if (y + height > current_vp->height) 1002 if (y + height > lcd_current_viewport->height)
971 height = current_vp->height - y; 1003 height = lcd_current_viewport->height - y;
972 1004
973 /* adjust for viewport */ 1005 /* adjust for viewport */
974 x += current_vp->x; 1006 x += lcd_current_viewport->x;
975 y += current_vp->y; 1007 y += lcd_current_viewport->y;
976 1008
977#if defined(HAVE_VIEWPORT_CLIP) 1009#if defined(HAVE_VIEWPORT_CLIP)
978 /********************* Viewport on screen clipping ********************/ 1010 /********************* Viewport on screen clipping ********************/
@@ -1000,12 +1032,13 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x,
1000 height = LCD_HEIGHT - y; 1032 height = LCD_HEIGHT - y;
1001#endif 1033#endif
1002 1034
1003 stride = (stride + 3) >> 2; /* convert to no. of bytes */ 1035 stride = LCD_FBSTRIDE(stride, 0); /* convert to no. of bytes */
1004 1036
1005 src += stride * src_y + (src_x >> 2); /* move starting point */ 1037 src += stride * src_y + (src_x >> 2); /* move starting point */
1006 src_x &= 3; 1038 src_x &= 3;
1007 x -= src_x; 1039 x -= src_x;
1008 dst = FBADDR(x>>2,y); 1040 dst = FBADDR(x>>2,y);
1041 stride_dst = LCD_FBSTRIDE(lcd_current_viewport->buffer->stride, 0);
1009 shift = x & 3; 1042 shift = x & 3;
1010 nx = width - 1 + shift + src_x; 1043 nx = width - 1 + shift + src_x;
1011 1044
@@ -1013,7 +1046,7 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x,
1013 mask_right = 0xFFu << (2 * (~nx & 3)); 1046 mask_right = 0xFFu << (2 * (~nx & 3));
1014 1047
1015 shift *= 2; 1048 shift *= 2;
1016 dst_end = dst + height * LCD_FBWIDTH; 1049 dst_end = dst + height * stride_dst;
1017 do 1050 do
1018 { 1051 {
1019 const unsigned char *src_row = src; 1052 const unsigned char *src_row = src;
@@ -1039,7 +1072,7 @@ void ICODE_ATTR lcd_bitmap_part(const unsigned char *src, int src_x,
1039 setblock(dst_row, mask_row & mask_right, data >> shift); 1072 setblock(dst_row, mask_row & mask_right, data >> shift);
1040 1073
1041 src += stride; 1074 src += stride;
1042 dst += LCD_FBWIDTH; 1075 dst += stride_dst;
1043 } 1076 }
1044 while (dst < dst_end); 1077 while (dst < dst_end);
1045} 1078}
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 @@
36 36
37/*** globals ***/ 37/*** globals ***/
38 38
39fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER; 39static fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] IRAM_LCDFRAMEBUFFER;
40fb_data *lcd_framebuffer = &lcd_static_framebuffer[0][0]; 40static void *lcd_frameaddress_default(int x, int y);
41 41
42const unsigned char lcd_dibits[16] ICONST_ATTR = { 42const unsigned char lcd_dibits[16] ICONST_ATTR = {
43 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, 43 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
@@ -51,6 +51,15 @@ static const unsigned char pixmask[4] ICONST_ATTR = {
51static fb_data* lcd_backdrop = NULL; 51static fb_data* lcd_backdrop = NULL;
52static long lcd_backdrop_offset IDATA_ATTR = 0; 52static long lcd_backdrop_offset IDATA_ATTR = 0;
53 53
54/* shouldn't be changed unless you want system-wide framebuffer changes! */
55struct frame_buffer_t lcd_framebuffer_default =
56{
57 .fb_ptr = &lcd_static_framebuffer[0][0],
58 .get_address_fn = &lcd_frameaddress_default,
59 .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT),
60 .elems = (LCD_FBWIDTH*LCD_FBHEIGHT),
61};
62
54static struct viewport default_vp = 63static struct viewport default_vp =
55{ 64{
56 .x = 0, 65 .x = 0,
@@ -59,18 +68,32 @@ static struct viewport default_vp =
59 .height = LCD_HEIGHT, 68 .height = LCD_HEIGHT,
60 .font = FONT_SYSFIXED, 69 .font = FONT_SYSFIXED,
61 .drawmode = DRMODE_SOLID, 70 .drawmode = DRMODE_SOLID,
71 .buffer = NULL,
62 .fg_pattern = LCD_DEFAULT_FG, 72 .fg_pattern = LCD_DEFAULT_FG,
63 .bg_pattern = LCD_DEFAULT_BG 73 .bg_pattern = LCD_DEFAULT_BG
64}; 74};
65 75
66static struct viewport* current_vp IBSS_ATTR; 76struct viewport* lcd_current_viewport IBSS_ATTR;
67static unsigned fg_pattern IBSS_ATTR; 77static unsigned fg_pattern IBSS_ATTR;
68static unsigned bg_pattern IBSS_ATTR; 78static unsigned bg_pattern IBSS_ATTR;
69 79
80static void *lcd_frameaddress_default(int x, int y)
81{
82 /* the default expects a buffer the same size as the screen */
83 struct frame_buffer_t *fb = lcd_current_viewport->buffer;
84
85#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
86 size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y;
87#else
88 size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x;
89#endif
90 return fb->fb_ptr + element; /*(element % fb->elems);*/
91}
92
70/* LCD init */ 93/* LCD init */
71void lcd_init(void) 94void lcd_init(void)
72{ 95{
73 /* Initialise the viewport */ 96 /* Initialize the viewport */
74 lcd_set_viewport(NULL); 97 lcd_set_viewport(NULL);
75 98
76 lcd_clear_display(); 99 lcd_clear_display();
@@ -83,34 +106,34 @@ void lcd_init(void)
83 106
84void lcd_set_drawmode(int mode) 107void lcd_set_drawmode(int mode)
85{ 108{
86 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 109 lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
87} 110}
88 111
89int lcd_get_drawmode(void) 112int lcd_get_drawmode(void)
90{ 113{
91 return current_vp->drawmode; 114 return lcd_current_viewport->drawmode;
92} 115}
93 116
94void lcd_set_foreground(unsigned brightness) 117void lcd_set_foreground(unsigned brightness)
95{ 118{
96 current_vp->fg_pattern = brightness; 119 lcd_current_viewport->fg_pattern = brightness;
97 fg_pattern = 0x55 * (~brightness & 3); 120 fg_pattern = 0x55 * (~brightness & 3);
98} 121}
99 122
100unsigned lcd_get_foreground(void) 123unsigned lcd_get_foreground(void)
101{ 124{
102 return current_vp->fg_pattern; 125 return lcd_current_viewport->fg_pattern;
103} 126}
104 127
105void lcd_set_background(unsigned brightness) 128void lcd_set_background(unsigned brightness)
106{ 129{
107 current_vp->bg_pattern = brightness; 130 lcd_current_viewport->bg_pattern = brightness;
108 bg_pattern = 0x55 * (~brightness & 3); 131 bg_pattern = 0x55 * (~brightness & 3);
109} 132}
110 133
111unsigned lcd_get_background(void) 134unsigned lcd_get_background(void)
112{ 135{
113 return current_vp->bg_pattern; 136 return lcd_current_viewport->bg_pattern;
114} 137}
115 138
116void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) 139void 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)
122 145
123int lcd_getwidth(void) 146int lcd_getwidth(void)
124{ 147{
125 return current_vp->width; 148 return lcd_current_viewport->width;
126} 149}
127 150
128int lcd_getheight(void) 151int lcd_getheight(void)
129{ 152{
130 return current_vp->height; 153 return lcd_current_viewport->height;
131} 154}
132 155
133void lcd_setfont(int newfont) 156void lcd_setfont(int newfont)
134{ 157{
135 current_vp->font = newfont; 158 lcd_current_viewport->font = newfont;
136} 159}
137 160
138int lcd_getfont(void) 161int lcd_getfont(void)
139{ 162{
140 return current_vp->font; 163 return lcd_current_viewport->font;
141} 164}
142 165
143int lcd_getstringsize(const unsigned char *str, int *w, int *h) 166int lcd_getstringsize(const unsigned char *str, int *w, int *h)
144{ 167{
145 return font_getstringsize(str, w, h, current_vp->font); 168 return font_getstringsize(str, w, h, lcd_current_viewport->font);
146} 169}
147 170
148/*** low-level drawing functions ***/ 171/*** low-level drawing functions ***/
@@ -320,7 +343,7 @@ void lcd_set_backdrop(fb_data* backdrop)
320 lcd_backdrop = backdrop; 343 lcd_backdrop = backdrop;
321 if (backdrop) 344 if (backdrop)
322 { 345 {
323 lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer; 346 lcd_backdrop_offset = (long)backdrop - (long)FBADDR(0,0);
324 lcd_pixelfuncs = lcd_pixelfuncs_backdrop; 347 lcd_pixelfuncs = lcd_pixelfuncs_backdrop;
325 lcd_blockfuncs = lcd_blockfuncs_backdrop; 348 lcd_blockfuncs = lcd_blockfuncs_backdrop;
326 } 349 }
@@ -351,16 +374,16 @@ static inline void setblock(fb_data *address, unsigned mask, unsigned bits)
351/* Clear the whole display */ 374/* Clear the whole display */
352void lcd_clear_display(void) 375void lcd_clear_display(void)
353{ 376{
354 if (current_vp->drawmode & DRMODE_INVERSEVID) 377 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
355 { 378 {
356 memset(lcd_framebuffer, fg_pattern, FRAMEBUFFER_SIZE); 379 memset(FBADDR(0,0), fg_pattern, FRAMEBUFFER_SIZE);
357 } 380 }
358 else 381 else
359 { 382 {
360 if (lcd_backdrop) 383 if (lcd_backdrop)
361 memcpy(lcd_framebuffer, lcd_backdrop, FRAMEBUFFER_SIZE); 384 memcpy(FBADDR(0,0), lcd_backdrop, FRAMEBUFFER_SIZE);
362 else 385 else
363 memset(lcd_framebuffer, bg_pattern, FRAMEBUFFER_SIZE); 386 memset(FBADDR(0,0), bg_pattern, FRAMEBUFFER_SIZE);
364 } 387 }
365 388
366 lcd_scroll_info.lines = 0; 389 lcd_scroll_info.lines = 0;
@@ -371,37 +394,39 @@ void lcd_clear_viewport(void)
371{ 394{
372 int lastmode; 395 int lastmode;
373 396
374 if (current_vp == &default_vp) 397 if (lcd_current_viewport == &default_vp &&
398 default_vp.buffer == &lcd_framebuffer_default)
375 { 399 {
376 lcd_clear_display(); 400 lcd_clear_display();
377 } 401 }
378 else 402 else
379 { 403 {
380 lastmode = current_vp->drawmode; 404 lastmode = lcd_current_viewport->drawmode;
381 405
382 /* Invert the INVERSEVID bit and set basic mode to SOLID */ 406 /* Invert the INVERSEVID bit and set basic mode to SOLID */
383 current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | 407 lcd_current_viewport->drawmode = (~lastmode & DRMODE_INVERSEVID) |
384 DRMODE_SOLID; 408 DRMODE_SOLID;
385 409
386 lcd_fillrect(0, 0, current_vp->width, current_vp->height); 410 lcd_fillrect(0, 0, lcd_current_viewport->width, lcd_current_viewport->height);
387 411
388 current_vp->drawmode = lastmode; 412 lcd_current_viewport->drawmode = lastmode;
389 413
390 lcd_scroll_stop_viewport(current_vp); 414 lcd_scroll_stop_viewport(lcd_current_viewport);
391 } 415 }
416 lcd_current_viewport->flags &= ~(VP_FLAG_VP_SET_CLEAN);
392} 417}
393 418
394/* Set a single pixel */ 419/* Set a single pixel */
395void lcd_drawpixel(int x, int y) 420void lcd_drawpixel(int x, int y)
396{ 421{
397 if ( ((unsigned)x < (unsigned)current_vp->width) 422 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width)
398 && ((unsigned)y < (unsigned)current_vp->height) 423 && ((unsigned)y < (unsigned)lcd_current_viewport->height)
399#if defined(HAVE_VIEWPORT_CLIP) 424#if defined(HAVE_VIEWPORT_CLIP)
400 && ((unsigned)x < (unsigned)LCD_WIDTH) 425 && ((unsigned)x < (unsigned)LCD_WIDTH)
401 && ((unsigned)y < (unsigned)LCD_HEIGHT) 426 && ((unsigned)y < (unsigned)LCD_HEIGHT)
402#endif 427#endif
403 ) 428 )
404 lcd_pixelfuncs[current_vp->drawmode](current_vp->x + x, current_vp->y + y); 429 lcd_pixelfuncs[lcd_current_viewport->drawmode](lcd_current_viewport->x + x, lcd_current_viewport->y + y);
405} 430}
406 431
407/* Draw a line */ 432/* Draw a line */
@@ -413,7 +438,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
413 int d, dinc1, dinc2; 438 int d, dinc1, dinc2;
414 int x, xinc1, xinc2; 439 int x, xinc1, xinc2;
415 int y, yinc1, yinc2; 440 int y, yinc1, yinc2;
416 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[current_vp->drawmode]; 441 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[lcd_current_viewport->drawmode];
417 442
418 deltax = abs(x2 - x1); 443 deltax = abs(x2 - x1);
419 if (deltax == 0) 444 if (deltax == 0)
@@ -469,14 +494,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
469 494
470 for (i = 0; i < numpixels; i++) 495 for (i = 0; i < numpixels; i++)
471 { 496 {
472 if ( ((unsigned)x < (unsigned)current_vp->width) 497 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width)
473 && ((unsigned)y < (unsigned)current_vp->height) 498 && ((unsigned)y < (unsigned)lcd_current_viewport->height)
474#if defined(HAVE_VIEWPORT_CLIP) 499#if defined(HAVE_VIEWPORT_CLIP)
475 && ((unsigned)x < (unsigned)LCD_WIDTH) 500 && ((unsigned)x < (unsigned)LCD_WIDTH)
476 && ((unsigned)y < (unsigned)LCD_HEIGHT) 501 && ((unsigned)y < (unsigned)LCD_HEIGHT)
477#endif 502#endif
478 ) 503 )
479 pfunc(current_vp->x + x, current_vp->y + y); 504 pfunc(lcd_current_viewport->x + x, lcd_current_viewport->y + y);
480 505
481 if (d < 0) 506 if (d < 0)
482 { 507 {
@@ -512,19 +537,19 @@ void lcd_hline(int x1, int x2, int y)
512 537
513 /******************** In viewport clipping **********************/ 538 /******************** In viewport clipping **********************/
514 /* nothing to draw? */ 539 /* nothing to draw? */
515 if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) 540 if (((unsigned)y >= (unsigned)lcd_current_viewport->height) || (x1 >= lcd_current_viewport->width)
516 || (x2 < 0)) 541 || (x2 < 0))
517 return; 542 return;
518 543
519 if (x1 < 0) 544 if (x1 < 0)
520 x1 = 0; 545 x1 = 0;
521 if (x2 >= current_vp->width) 546 if (x2 >= lcd_current_viewport->width)
522 x2 = current_vp->width-1; 547 x2 = lcd_current_viewport->width-1;
523 548
524 /* adjust x1 and y to viewport */ 549 /* adjust x1 and y to viewport */
525 x1 += current_vp->x; 550 x1 += lcd_current_viewport->x;
526 x2 += current_vp->x; 551 x2 += lcd_current_viewport->x;
527 y += current_vp->y; 552 y += lcd_current_viewport->y;
528 553
529#if defined(HAVE_VIEWPORT_CLIP) 554#if defined(HAVE_VIEWPORT_CLIP)
530 /********************* Viewport on screen clipping ********************/ 555 /********************* Viewport on screen clipping ********************/
@@ -542,7 +567,7 @@ void lcd_hline(int x1, int x2, int y)
542 567
543 width = x2 - x1 + 1; 568 width = x2 - x1 + 1;
544 569
545 bfunc = lcd_blockfuncs[current_vp->drawmode]; 570 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
546 dst = FBADDR(x1,y>>2); 571 dst = FBADDR(x1,y>>2);
547 mask = pixmask[y & 3]; 572 mask = pixmask[y & 3];
548 573
@@ -557,6 +582,7 @@ void lcd_vline(int x, int y1, int y2)
557{ 582{
558 int ny; 583 int ny;
559 fb_data *dst; 584 fb_data *dst;
585 int stride_dst;
560 unsigned mask, mask_bottom; 586 unsigned mask, mask_bottom;
561 lcd_blockfunc_type *bfunc; 587 lcd_blockfunc_type *bfunc;
562 588
@@ -570,19 +596,19 @@ void lcd_vline(int x, int y1, int y2)
570 596
571 /******************** In viewport clipping **********************/ 597 /******************** In viewport clipping **********************/
572 /* nothing to draw? */ 598 /* nothing to draw? */
573 if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) 599 if (((unsigned)x >= (unsigned)lcd_current_viewport->width) || (y1 >= lcd_current_viewport->height)
574 || (y2 < 0)) 600 || (y2 < 0))
575 return; 601 return;
576 602
577 if (y1 < 0) 603 if (y1 < 0)
578 y1 = 0; 604 y1 = 0;
579 if (y2 >= current_vp->height) 605 if (y2 >= lcd_current_viewport->height)
580 y2 = current_vp->height-1; 606 y2 = lcd_current_viewport->height-1;
581 607
582 /* adjust for viewport */ 608 /* adjust for viewport */
583 y1 += current_vp->y; 609 y1 += lcd_current_viewport->y;
584 y2 += current_vp->y; 610 y2 += lcd_current_viewport->y;
585 x += current_vp->x; 611 x += lcd_current_viewport->x;
586 612
587#if defined(HAVE_VIEWPORT_CLIP) 613#if defined(HAVE_VIEWPORT_CLIP)
588 /********************* Viewport on screen clipping ********************/ 614 /********************* Viewport on screen clipping ********************/
@@ -598,8 +624,9 @@ void lcd_vline(int x, int y1, int y2)
598 y2 = LCD_HEIGHT-1; 624 y2 = LCD_HEIGHT-1;
599#endif 625#endif
600 626
601 bfunc = lcd_blockfuncs[current_vp->drawmode]; 627 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
602 dst = FBADDR(x,y1>>2); 628 dst = FBADDR(x,y1>>2);
629 stride_dst = lcd_current_viewport->buffer->stride;
603 ny = y2 - (y1 & ~3); 630 ny = y2 - (y1 & ~3);
604 mask = 0xFFu << (2 * (y1 & 3)); 631 mask = 0xFFu << (2 * (y1 & 3));
605 mask_bottom = 0xFFu >> (2 * (~ny & 3)); 632 mask_bottom = 0xFFu >> (2 * (~ny & 3));
@@ -607,7 +634,7 @@ void lcd_vline(int x, int y1, int y2)
607 for (; ny >= 4; ny -= 4) 634 for (; ny >= 4; ny -= 4)
608 { 635 {
609 bfunc(dst, mask, 0xFFu); 636 bfunc(dst, mask, 0xFFu);
610 dst += LCD_WIDTH; 637 dst += stride_dst;
611 mask = 0xFFu; 638 mask = 0xFFu;
612 } 639 }
613 mask &= mask_bottom; 640 mask &= mask_bottom;
@@ -634,6 +661,7 @@ void lcd_fillrect(int x, int y, int width, int height)
634{ 661{
635 int ny; 662 int ny;
636 fb_data *dst, *dst_end; 663 fb_data *dst, *dst_end;
664 int stride_dst;
637 unsigned mask, mask_bottom; 665 unsigned mask, mask_bottom;
638 unsigned bits = 0; 666 unsigned bits = 0;
639 lcd_blockfunc_type *bfunc; 667 lcd_blockfunc_type *bfunc;
@@ -641,8 +669,8 @@ void lcd_fillrect(int x, int y, int width, int height)
641 669
642 /******************** In viewport clipping **********************/ 670 /******************** In viewport clipping **********************/
643 /* nothing to draw? */ 671 /* nothing to draw? */
644 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) 672 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width)
645 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 673 || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
646 return; 674 return;
647 675
648 if (x < 0) 676 if (x < 0)
@@ -655,14 +683,14 @@ void lcd_fillrect(int x, int y, int width, int height)
655 height += y; 683 height += y;
656 y = 0; 684 y = 0;
657 } 685 }
658 if (x + width > current_vp->width) 686 if (x + width > lcd_current_viewport->width)
659 width = current_vp->width - x; 687 width = lcd_current_viewport->width - x;
660 if (y + height > current_vp->height) 688 if (y + height > lcd_current_viewport->height)
661 height = current_vp->height - y; 689 height = lcd_current_viewport->height - y;
662 690
663 /* adjust for viewport */ 691 /* adjust for viewport */
664 x += current_vp->x; 692 x += lcd_current_viewport->x;
665 y += current_vp->y; 693 y += lcd_current_viewport->y;
666 694
667#if defined(HAVE_VIEWPORT_CLIP) 695#if defined(HAVE_VIEWPORT_CLIP)
668 /********************* Viewport on screen clipping ********************/ 696 /********************* Viewport on screen clipping ********************/
@@ -688,9 +716,9 @@ void lcd_fillrect(int x, int y, int width, int height)
688 height = LCD_HEIGHT - y; 716 height = LCD_HEIGHT - y;
689#endif 717#endif
690 718
691 if (current_vp->drawmode & DRMODE_INVERSEVID) 719 if (lcd_current_viewport->drawmode & DRMODE_INVERSEVID)
692 { 720 {
693 if ((current_vp->drawmode & DRMODE_BG) && !lcd_backdrop) 721 if ((lcd_current_viewport->drawmode & DRMODE_BG) && !lcd_backdrop)
694 { 722 {
695 fillopt = true; 723 fillopt = true;
696 bits = bg_pattern; 724 bits = bg_pattern;
@@ -698,14 +726,15 @@ void lcd_fillrect(int x, int y, int width, int height)
698 } 726 }
699 else 727 else
700 { 728 {
701 if (current_vp->drawmode & DRMODE_FG) 729 if (lcd_current_viewport->drawmode & DRMODE_FG)
702 { 730 {
703 fillopt = true; 731 fillopt = true;
704 bits = fg_pattern; 732 bits = fg_pattern;
705 } 733 }
706 } 734 }
707 bfunc = lcd_blockfuncs[current_vp->drawmode]; 735 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
708 dst = FBADDR(x,y>>2); 736 dst = FBADDR(x,y>>2);
737 stride_dst = lcd_current_viewport->buffer->stride;
709 ny = height - 1 + (y & 3); 738 ny = height - 1 + (y & 3);
710 mask = 0xFFu << (2 * (y & 3)); 739 mask = 0xFFu << (2 * (y & 3));
711 mask_bottom = 0xFFu >> (2 * (~ny & 3)); 740 mask_bottom = 0xFFu >> (2 * (~ny & 3));
@@ -724,7 +753,7 @@ void lcd_fillrect(int x, int y, int width, int height)
724 while (dst_row < dst_end); 753 while (dst_row < dst_end);
725 } 754 }
726 755
727 dst += LCD_WIDTH; 756 dst += stride_dst;
728 mask = 0xFFu; 757 mask = 0xFFu;
729 } 758 }
730 mask &= mask_bottom; 759 mask &= mask_bottom;
@@ -758,13 +787,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
758{ 787{
759 int shift, ny; 788 int shift, ny;
760 fb_data *dst, *dst_end; 789 fb_data *dst, *dst_end;
790 int stride_dst;
761 unsigned mask, mask_bottom; 791 unsigned mask, mask_bottom;
762 lcd_blockfunc_type *bfunc; 792 lcd_blockfunc_type *bfunc;
763 793
764 /******************** Image in viewport clipping **********************/ 794 /******************** Image in viewport clipping **********************/
765 /* nothing to draw? */ 795 /* nothing to draw? */
766 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 796 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width) ||
767 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 797 (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
768 return; 798 return;
769 799
770 if (x < 0) 800 if (x < 0)
@@ -779,14 +809,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
779 src_y -= y; 809 src_y -= y;
780 y = 0; 810 y = 0;
781 } 811 }
782 if (x + width > current_vp->width) 812 if (x + width > lcd_current_viewport->width)
783 width = current_vp->width - x; 813 width = lcd_current_viewport->width - x;
784 if (y + height > current_vp->height) 814 if (y + height > lcd_current_viewport->height)
785 height = current_vp->height - y; 815 height = lcd_current_viewport->height - y;
786 816
787 /* adjust for viewport */ 817 /* adjust for viewport */
788 x += current_vp->x; 818 x += lcd_current_viewport->x;
789 y += current_vp->y; 819 y += lcd_current_viewport->y;
790 820
791#if defined(HAVE_VIEWPORT_CLIP) 821#if defined(HAVE_VIEWPORT_CLIP)
792 /********************* Viewport on screen clipping ********************/ 822 /********************* Viewport on screen clipping ********************/
@@ -818,13 +848,14 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
818 src_y &= 7; 848 src_y &= 7;
819 y -= src_y; 849 y -= src_y;
820 dst = FBADDR(x,y>>2); 850 dst = FBADDR(x,y>>2);
851 stride_dst = lcd_current_viewport->buffer->stride;
821 shift = y & 3; 852 shift = y & 3;
822 ny = height - 1 + shift + src_y; 853 ny = height - 1 + shift + src_y;
823 mask = 0xFFFFu << (2 * (shift + src_y)); 854 mask = 0xFFFFu << (2 * (shift + src_y));
824 /* Overflowing bits aren't important. */ 855 /* Overflowing bits aren't important. */
825 mask_bottom = 0xFFFFu >> (2 * (~ny & 7)); 856 mask_bottom = 0xFFFFu >> (2 * (~ny & 7));
826 857
827 bfunc = lcd_blockfuncs[current_vp->drawmode]; 858 bfunc = lcd_blockfuncs[lcd_current_viewport->drawmode];
828 859
829 if (shift == 0) 860 if (shift == 0)
830 { 861 {
@@ -836,7 +867,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
836 for (; ny >= 8; ny -= 8) 867 for (; ny >= 8; ny -= 8)
837 { 868 {
838 const unsigned char *src_row = src; 869 const unsigned char *src_row = src;
839 fb_data *dst_row = dst + LCD_WIDTH; 870 fb_data *dst_row = dst + stride_dst;
840 871
841 dst_end = dst_row + width; 872 dst_end = dst_row + width;
842 873
@@ -845,7 +876,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
845 do 876 do
846 { 877 {
847 data = *src_row++; 878 data = *src_row++;
848 bfunc(dst_row - LCD_WIDTH, dmask1, lcd_dibits[data&0x0F]); 879 bfunc(dst_row - stride_dst, dmask1, lcd_dibits[data&0x0F]);
849 bfunc(dst_row++, dmask2, lcd_dibits[(data>>4)&0x0F]); 880 bfunc(dst_row++, dmask2, lcd_dibits[(data>>4)&0x0F]);
850 } 881 }
851 while (dst_row < dst_end); 882 while (dst_row < dst_end);
@@ -857,7 +888,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
857 while (dst_row < dst_end); 888 while (dst_row < dst_end);
858 } 889 }
859 src += stride; 890 src += stride;
860 dst += 2*LCD_WIDTH; 891 dst += 2*stride_dst;
861 dmask1 = dmask2 = 0xFFu; 892 dmask1 = dmask2 = 0xFFu;
862 } 893 }
863 dmask1 &= mask_bottom; 894 dmask1 &= mask_bottom;
@@ -873,7 +904,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
873 { 904 {
874 data = *src++; 905 data = *src++;
875 bfunc(dst, dmask1, lcd_dibits[data&0x0F]); 906 bfunc(dst, dmask1, lcd_dibits[data&0x0F]);
876 bfunc((dst++) + LCD_WIDTH, dmask2, lcd_dibits[(data>>4)&0x0F]); 907 bfunc((dst++) + stride_dst, dmask2, lcd_dibits[(data>>4)&0x0F]);
877 } 908 }
878 while (dst < dst_end); 909 while (dst < dst_end);
879 } 910 }
@@ -887,7 +918,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
887 else 918 else
888 { 919 {
889 do 920 do
890 bfunc((dst++) + LCD_WIDTH, dmask2, lcd_dibits[((*src++)>>4)&0x0F]); 921 bfunc((dst++) + stride_dst, dmask2, lcd_dibits[((*src++)>>4)&0x0F]);
891 while (dst < dst_end); 922 while (dst < dst_end);
892 } 923 }
893 } 924 }
@@ -909,7 +940,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
909 { 940 {
910 if (mask_col & 0xFFu) 941 if (mask_col & 0xFFu)
911 bfunc(dst_col, mask_col, lcd_dibits[data&0x0F]); 942 bfunc(dst_col, mask_col, lcd_dibits[data&0x0F]);
912 bfunc(dst_col + LCD_WIDTH, mask_col >> 8, 943 bfunc(dst_col + stride_dst, mask_col >> 8,
913 lcd_dibits[(data>>4)&0x0F]); 944 lcd_dibits[(data>>4)&0x0F]);
914 mask_col = 0xFFFFu; 945 mask_col = 0xFFFFu;
915 } 946 }
@@ -917,7 +948,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
917 mask_col >>= 16; 948 mask_col >>= 16;
918 949
919 src_col += stride; 950 src_col += stride;
920 dst_col += 2*LCD_WIDTH; 951 dst_col += 2*stride_dst;
921 data >>= 8; 952 data >>= 8;
922 } 953 }
923 data |= *src_col << shift; 954 data |= *src_col << shift;
@@ -925,7 +956,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
925 if (mask_col & 0xFFu) 956 if (mask_col & 0xFFu)
926 bfunc(dst_col, mask_col, lcd_dibits[data&0x0F]); 957 bfunc(dst_col, mask_col, lcd_dibits[data&0x0F]);
927 if (mask_col & 0xFF00u) 958 if (mask_col & 0xFF00u)
928 bfunc(dst_col + LCD_WIDTH, mask_col >> 8, 959 bfunc(dst_col + stride_dst, mask_col >> 8,
929 lcd_dibits[(data>>4)&0x0F]); 960 lcd_dibits[(data>>4)&0x0F]);
930 } 961 }
931 while (dst < dst_end); 962 while (dst < dst_end);
@@ -956,12 +987,13 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
956{ 987{
957 int shift, ny; 988 int shift, ny;
958 fb_data *dst, *dst_end; 989 fb_data *dst, *dst_end;
990 int stride_dst;
959 unsigned mask, mask_bottom; 991 unsigned mask, mask_bottom;
960 992
961 /******************** Image in viewport clipping **********************/ 993 /******************** Image in viewport clipping **********************/
962 /* nothing to draw? */ 994 /* nothing to draw? */
963 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) 995 if ((width <= 0) || (height <= 0) || (x >= lcd_current_viewport->width)
964 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 996 || (y >= lcd_current_viewport->height) || (x + width <= 0) || (y + height <= 0))
965 return; 997 return;
966 998
967 if (x < 0) 999 if (x < 0)
@@ -976,14 +1008,14 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
976 src_y -= y; 1008 src_y -= y;
977 y = 0; 1009 y = 0;
978 } 1010 }
979 if (x + width > current_vp->width) 1011 if (x + width > lcd_current_viewport->width)
980 width = current_vp->width - x; 1012 width = lcd_current_viewport->width - x;
981 if (y + height > current_vp->height) 1013 if (y + height > lcd_current_viewport->height)
982 height = current_vp->height - y; 1014 height = lcd_current_viewport->height - y;
983 1015
984 /* adjust for viewport */ 1016 /* adjust for viewport */
985 x += current_vp->x; 1017 x += lcd_current_viewport->x;
986 y += current_vp->y; 1018 y += lcd_current_viewport->y;
987 1019
988#if defined(HAVE_VIEWPORT_CLIP) 1020#if defined(HAVE_VIEWPORT_CLIP)
989 /********************* Viewport on screen clipping ********************/ 1021 /********************* Viewport on screen clipping ********************/
@@ -1010,11 +1042,11 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
1010 if (y + height > LCD_HEIGHT) 1042 if (y + height > LCD_HEIGHT)
1011 height = LCD_HEIGHT - y; 1043 height = LCD_HEIGHT - y;
1012#endif 1044#endif
1013
1014 src += stride * (src_y >> 2) + src_x; /* move starting point */ 1045 src += stride * (src_y >> 2) + src_x; /* move starting point */
1015 src_y &= 3; 1046 src_y &= 3;
1016 y -= src_y; 1047 y -= src_y;
1017 dst = FBADDR(x,y>>2); 1048 dst = FBADDR(x,y>>2);
1049 stride_dst = lcd_current_viewport->buffer->stride;
1018 shift = y & 3; 1050 shift = y & 3;
1019 ny = height - 1 + shift + src_y; 1051 ny = height - 1 + shift + src_y;
1020 1052
@@ -1038,7 +1070,7 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
1038 while (dst_row < dst_end); 1070 while (dst_row < dst_end);
1039 } 1071 }
1040 src += stride; 1072 src += stride;
1041 dst += LCD_WIDTH; 1073 dst += stride_dst;
1042 mask = 0xFFu; 1074 mask = 0xFFu;
1043 } 1075 }
1044 mask &= mask_bottom; 1076 mask &= mask_bottom;
@@ -1077,7 +1109,7 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
1077 mask_col >>= 8; 1109 mask_col >>= 8;
1078 1110
1079 src_col += stride; 1111 src_col += stride;
1080 dst_col += LCD_WIDTH; 1112 dst_col += stride_dst;
1081 data >>= 8; 1113 data >>= 8;
1082 } 1114 }
1083 data |= *src_col << shift; 1115 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 @@
46#define MAIN_LCD 46#define MAIN_LCD
47#endif 47#endif
48 48
49/*** globals ***/ 49#ifdef MAIN_LCD
50#define THIS_STRIDE STRIDE_MAIN
51#else
52#define THIS_STRIDE STRIDE_REMOTE
53#endif
50 54
51FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER; 55#define CURRENT_VP LCDFN(current_viewport)
52FBFN(data) *LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; 56/*** globals ***/
53 57
58static FBFN(data) LCDFN(static_framebuffer)[LCDM(FBHEIGHT)][LCDM(FBWIDTH)] IRAM_LCDFRAMEBUFFER;
59static void *LCDFN(frameaddress_default)(int x, int y);
54 60
55static const FBFN(data) patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000}; 61static const FBFN(data) patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
56 62
57static FBFN(data) *backdrop = NULL; 63static FBFN(data) *backdrop = NULL;
58static long backdrop_offset IDATA_ATTR = 0; 64static long backdrop_offset IDATA_ATTR = 0;
59 65
66/* shouldn't be changed unless you want system-wide framebuffer changes! */
67struct frame_buffer_t LCDFN(framebuffer_default) =
68{
69 .FBFN(ptr) = &LCDFN(static_framebuffer)[0][0],
70 .get_address_fn = &LCDFN(frameaddress_default),
71 .stride = THIS_STRIDE(LCDM(WIDTH), LCDM(HEIGHT)),
72 .elems = (LCDM(FBWIDTH)*LCDM(FBHEIGHT)),
73};
74
60static struct viewport default_vp = 75static struct viewport default_vp =
61{ 76{
62 .x = 0, 77 .x = 0,
@@ -65,19 +80,34 @@ static struct viewport default_vp =
65 .height = LCDM(HEIGHT), 80 .height = LCDM(HEIGHT),
66 .font = FONT_SYSFIXED, 81 .font = FONT_SYSFIXED,
67 .drawmode = DRMODE_SOLID, 82 .drawmode = DRMODE_SOLID,
83 .buffer = NULL,
68 .fg_pattern = LCDM(DEFAULT_FG), 84 .fg_pattern = LCDM(DEFAULT_FG),
69 .bg_pattern = LCDM(DEFAULT_BG) 85 .bg_pattern = LCDM(DEFAULT_BG)
70}; 86};
71 87
72static struct viewport * current_vp IBSS_ATTR; 88struct viewport * CURRENT_VP IBSS_ATTR;
73 89
74static unsigned fg_pattern IBSS_ATTR; 90static unsigned fg_pattern IBSS_ATTR;
75static unsigned bg_pattern IBSS_ATTR; 91static unsigned bg_pattern IBSS_ATTR;
76 92
93static void *LCDFN(frameaddress_default)(int x, int y)
94{
95 /* the default expects a buffer the same size as the screen */
96 struct frame_buffer_t *fb = CURRENT_VP->buffer;
97#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
98 size_t element = (x * LCDM(NATIVE_STRIDE)(fb->stride)) + y;
99#else
100 size_t element = (y * LCDM(NATIVE_STRIDE)(fb->stride)) + x;
101#endif
102 return fb->FBFN(ptr) + element;/*(element % fb->elems);*/
103}
104
77/* LCD init */ 105/* LCD init */
78void LCDFN(init)(void) 106void LCDFN(init)(void)
79{ 107{
108 /* Initialize the viewport */
80 LCDFN(set_viewport)(NULL); 109 LCDFN(set_viewport)(NULL);
110
81 LCDFN(clear_display)(); 111 LCDFN(clear_display)();
82 LCDFN(init_device)(); 112 LCDFN(init_device)();
83#ifdef MAIN_LCD 113#ifdef MAIN_LCD
@@ -105,34 +135,34 @@ unsigned lcd_remote_color_to_native(unsigned color)
105 135
106void LCDFN(set_drawmode)(int mode) 136void LCDFN(set_drawmode)(int mode)
107{ 137{
108 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 138 CURRENT_VP->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
109} 139}
110 140
111int LCDFN(get_drawmode)(void) 141int LCDFN(get_drawmode)(void)
112{ 142{
113 return current_vp->drawmode; 143 return CURRENT_VP->drawmode;
114} 144}
115 145
116void LCDFN(set_foreground)(unsigned brightness) 146void LCDFN(set_foreground)(unsigned brightness)
117{ 147{
118 current_vp->fg_pattern = brightness; 148 CURRENT_VP->fg_pattern = brightness;
119 fg_pattern = patterns[brightness & 3]; 149 fg_pattern = patterns[brightness & 3];
120} 150}
121 151
122unsigned LCDFN(get_foreground)(void) 152unsigned LCDFN(get_foreground)(void)
123{ 153{
124 return current_vp->fg_pattern; 154 return CURRENT_VP->fg_pattern;
125} 155}
126 156
127void LCDFN(set_background)(unsigned brightness) 157void LCDFN(set_background)(unsigned brightness)
128{ 158{
129 current_vp->bg_pattern = brightness; 159 CURRENT_VP->bg_pattern = brightness;
130 bg_pattern = patterns[brightness & 3]; 160 bg_pattern = patterns[brightness & 3];
131} 161}
132 162
133unsigned LCDFN(get_background)(void) 163unsigned LCDFN(get_background)(void)
134{ 164{
135 return current_vp->bg_pattern; 165 return CURRENT_VP->bg_pattern;
136} 166}
137 167
138void LCDFN(set_drawinfo)(int mode, unsigned fg_brightness, 168void LCDFN(set_drawinfo)(int mode, unsigned fg_brightness,
@@ -145,26 +175,26 @@ void LCDFN(set_drawinfo)(int mode, unsigned fg_brightness,
145 175
146int LCDFN(getwidth)(void) 176int LCDFN(getwidth)(void)
147{ 177{
148 return current_vp->width; 178 return CURRENT_VP->width;
149} 179}
150 180
151int LCDFN(getheight)(void) 181int LCDFN(getheight)(void)
152{ 182{
153 return current_vp->height; 183 return CURRENT_VP->height;
154} 184}
155void LCDFN(setfont)(int newfont) 185void LCDFN(setfont)(int newfont)
156{ 186{
157 current_vp->font = newfont; 187 CURRENT_VP->font = newfont;
158} 188}
159 189
160int LCDFN(getfont)(void) 190int LCDFN(getfont)(void)
161{ 191{
162 return current_vp->font; 192 return CURRENT_VP->font;
163} 193}
164 194
165int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h) 195int LCDFN(getstringsize)(const unsigned char *str, int *w, int *h)
166{ 196{
167 return font_getstringsize(str, w, h, current_vp->font); 197 return font_getstringsize(str, w, h, CURRENT_VP->font);
168} 198}
169 199
170/*** low-level drawing functions ***/ 200/*** low-level drawing functions ***/
@@ -345,7 +375,7 @@ void LCDFN(set_backdrop)(FBFN(data) *bd)
345 backdrop = bd; 375 backdrop = bd;
346 if (bd) 376 if (bd)
347 { 377 {
348 backdrop_offset = (long)bd - (long)LCDFN(framebuffer); 378 backdrop_offset = (long)bd - (long)LCDFB(0, 0);
349 LCDFN(pixelfuncs) = LCDFN(pixelfuncs_backdrop); 379 LCDFN(pixelfuncs) = LCDFN(pixelfuncs_backdrop);
350 LCDFN(blockfuncs) = LCDFN(blockfuncs_backdrop); 380 LCDFN(blockfuncs) = LCDFN(blockfuncs_backdrop);
351 } 381 }
@@ -377,15 +407,15 @@ void LCDFN(clear_display)(void)
377{ 407{
378 if (default_vp.drawmode & DRMODE_INVERSEVID) 408 if (default_vp.drawmode & DRMODE_INVERSEVID)
379 { 409 {
380 memset(LCDFN(framebuffer), patterns[default_vp.fg_pattern & 3], 410 memset(LCDFB(0, 0), patterns[default_vp.fg_pattern & 3],
381 FBSIZE); 411 FBSIZE);
382 } 412 }
383 else 413 else
384 { 414 {
385 if (backdrop) 415 if (backdrop)
386 memcpy(LCDFN(framebuffer), backdrop, FBSIZE); 416 memcpy(LCDFB(0, 0), backdrop, FBSIZE);
387 else 417 else
388 memset(LCDFN(framebuffer), patterns[default_vp.bg_pattern & 3], 418 memset(LCDFB(0, 0), patterns[default_vp.bg_pattern & 3],
389 FBSIZE); 419 FBSIZE);
390 } 420 }
391 421
@@ -397,37 +427,39 @@ void LCDFN(clear_viewport)(void)
397{ 427{
398 int lastmode; 428 int lastmode;
399 429
400 if (current_vp == &default_vp) 430 if (CURRENT_VP == &default_vp &&
431 default_vp.buffer == &LCDFN(framebuffer_default))
401 { 432 {
402 LCDFN(clear_display)(); 433 LCDFN(clear_display)();
403 } 434 }
404 else 435 else
405 { 436 {
406 lastmode = current_vp->drawmode; 437 lastmode = CURRENT_VP->drawmode;
407 438
408 /* Invert the INVERSEVID bit and set basic mode to SOLID */ 439 /* Invert the INVERSEVID bit and set basic mode to SOLID */
409 current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) | 440 CURRENT_VP->drawmode = (~lastmode & DRMODE_INVERSEVID) |
410 DRMODE_SOLID; 441 DRMODE_SOLID;
411 442
412 LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); 443 LCDFN(fillrect)(0, 0, CURRENT_VP->width, CURRENT_VP->height);
413 444
414 current_vp->drawmode = lastmode; 445 CURRENT_VP->drawmode = lastmode;
415 446
416 LCDFN(scroll_stop_viewport)(current_vp); 447 LCDFN(scroll_stop_viewport)(CURRENT_VP);
417 } 448 }
449 CURRENT_VP->flags &= ~(VP_FLAG_VP_SET_CLEAN);
418} 450}
419 451
420/* Set a single pixel */ 452/* Set a single pixel */
421void LCDFN(drawpixel)(int x, int y) 453void LCDFN(drawpixel)(int x, int y)
422{ 454{
423 if ( ((unsigned)x < (unsigned)current_vp->width) 455 if ( ((unsigned)x < (unsigned)CURRENT_VP->width)
424 && ((unsigned)y < (unsigned)current_vp->height) 456 && ((unsigned)y < (unsigned)CURRENT_VP->height)
425#if defined(HAVE_VIEWPORT_CLIP) 457#if defined(HAVE_VIEWPORT_CLIP)
426 && ((unsigned)x < (unsigned)LCDM(WIDTH)) 458 && ((unsigned)x < (unsigned)LCDM(WIDTH))
427 && ((unsigned)y < (unsigned)LCDM(HEIGHT)) 459 && ((unsigned)y < (unsigned)LCDM(HEIGHT))
428#endif 460#endif
429 ) 461 )
430 LCDFN(pixelfuncs)[current_vp->drawmode](current_vp->x+x, current_vp->y+y); 462 LCDFN(pixelfuncs)[CURRENT_VP->drawmode](CURRENT_VP->x+x, CURRENT_VP->y+y);
431} 463}
432 464
433/* Draw a line */ 465/* Draw a line */
@@ -439,7 +471,7 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
439 int d, dinc1, dinc2; 471 int d, dinc1, dinc2;
440 int x, xinc1, xinc2; 472 int x, xinc1, xinc2;
441 int y, yinc1, yinc2; 473 int y, yinc1, yinc2;
442 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[current_vp->drawmode]; 474 LCDFN(pixelfunc_type) *pfunc = LCDFN(pixelfuncs)[CURRENT_VP->drawmode];
443 475
444 deltax = abs(x2 - x1); 476 deltax = abs(x2 - x1);
445 if (deltax == 0) 477 if (deltax == 0)
@@ -495,14 +527,14 @@ void LCDFN(drawline)(int x1, int y1, int x2, int y2)
495 527
496 for (i = 0; i < numpixels; i++) 528 for (i = 0; i < numpixels; i++)
497 { 529 {
498 if ( ((unsigned)x < (unsigned)current_vp->width) 530 if ( ((unsigned)x < (unsigned)CURRENT_VP->width)
499 && ((unsigned)y < (unsigned)current_vp->height) 531 && ((unsigned)y < (unsigned)CURRENT_VP->height)
500#if defined(HAVE_VIEWPORT_CLIP) 532#if defined(HAVE_VIEWPORT_CLIP)
501 && ((unsigned)x < (unsigned)LCDM(WIDTH)) 533 && ((unsigned)x < (unsigned)LCDM(WIDTH))
502 && ((unsigned)y < (unsigned)LCDM(HEIGHT)) 534 && ((unsigned)y < (unsigned)LCDM(HEIGHT))
503#endif 535#endif
504 ) 536 )
505 pfunc(current_vp->x + x, current_vp->y + y); 537 pfunc(CURRENT_VP->x + x, CURRENT_VP->y + y);
506 538
507 if (d < 0) 539 if (d < 0)
508 { 540 {
@@ -538,19 +570,19 @@ void LCDFN(hline)(int x1, int x2, int y)
538 570
539 /******************** In viewport clipping **********************/ 571 /******************** In viewport clipping **********************/
540 /* nothing to draw? */ 572 /* nothing to draw? */
541 if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width) 573 if (((unsigned)y >= (unsigned)CURRENT_VP->height) || (x1 >= CURRENT_VP->width)
542 || (x2 < 0)) 574 || (x2 < 0))
543 return; 575 return;
544 576
545 if (x1 < 0) 577 if (x1 < 0)
546 x1 = 0; 578 x1 = 0;
547 if (x2 >= current_vp->width) 579 if (x2 >= CURRENT_VP->width)
548 x2 = current_vp->width-1; 580 x2 = CURRENT_VP->width-1;
549 581
550 /* adjust x1 and y to viewport */ 582 /* adjust x1 and y to viewport */
551 x1 += current_vp->x; 583 x1 += CURRENT_VP->x;
552 x2 += current_vp->x; 584 x2 += CURRENT_VP->x;
553 y += current_vp->y; 585 y += CURRENT_VP->y;
554 586
555#if defined(HAVE_VIEWPORT_CLIP) 587#if defined(HAVE_VIEWPORT_CLIP)
556 /********************* Viewport on screen clipping ********************/ 588 /********************* Viewport on screen clipping ********************/
@@ -568,7 +600,7 @@ void LCDFN(hline)(int x1, int x2, int y)
568 600
569 width = x2 - x1 + 1; 601 width = x2 - x1 + 1;
570 602
571 bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; 603 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
572 dst = LCDFB(x1,y>>3); 604 dst = LCDFB(x1,y>>3);
573 mask = 0x0101 << (y & 7); 605 mask = 0x0101 << (y & 7);
574 606
@@ -583,6 +615,7 @@ void LCDFN(vline)(int x, int y1, int y2)
583{ 615{
584 int ny; 616 int ny;
585 FBFN(data) *dst; 617 FBFN(data) *dst;
618 int stride_dst;
586 unsigned mask, mask_bottom; 619 unsigned mask, mask_bottom;
587 LCDFN(blockfunc_type) *bfunc; 620 LCDFN(blockfunc_type) *bfunc;
588 621
@@ -596,19 +629,19 @@ void LCDFN(vline)(int x, int y1, int y2)
596 629
597 /******************** In viewport clipping **********************/ 630 /******************** In viewport clipping **********************/
598 /* nothing to draw? */ 631 /* nothing to draw? */
599 if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height) 632 if (((unsigned)x >= (unsigned)CURRENT_VP->width) || (y1 >= CURRENT_VP->height)
600 || (y2 < 0)) 633 || (y2 < 0))
601 return; 634 return;
602 635
603 if (y1 < 0) 636 if (y1 < 0)
604 y1 = 0; 637 y1 = 0;
605 if (y2 >= current_vp->height) 638 if (y2 >= CURRENT_VP->height)
606 y2 = current_vp->height-1; 639 y2 = CURRENT_VP->height-1;
607 640
608 /* adjust for viewport */ 641 /* adjust for viewport */
609 y1 += current_vp->y; 642 y1 += CURRENT_VP->y;
610 y2 += current_vp->y; 643 y2 += CURRENT_VP->y;
611 x += current_vp->x; 644 x += CURRENT_VP->x;
612 645
613#if defined(HAVE_VIEWPORT_CLIP) 646#if defined(HAVE_VIEWPORT_CLIP)
614 /********************* Viewport on screen clipping ********************/ 647 /********************* Viewport on screen clipping ********************/
@@ -624,8 +657,9 @@ void LCDFN(vline)(int x, int y1, int y2)
624 y2 = LCDM(HEIGHT)-1; 657 y2 = LCDM(HEIGHT)-1;
625#endif 658#endif
626 659
627 bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; 660 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
628 dst = LCDFB(x,y1>>3); 661 dst = LCDFB(x,y1>>3);
662 stride_dst = CURRENT_VP->buffer->stride;
629 ny = y2 - (y1 & ~7); 663 ny = y2 - (y1 & ~7);
630 mask = (0xFFu << (y1 & 7)) & 0xFFu; 664 mask = (0xFFu << (y1 & 7)) & 0xFFu;
631 mask |= mask << 8; 665 mask |= mask << 8;
@@ -635,7 +669,7 @@ void LCDFN(vline)(int x, int y1, int y2)
635 for (; ny >= 8; ny -= 8) 669 for (; ny >= 8; ny -= 8)
636 { 670 {
637 bfunc(dst, mask, 0xFFFFu); 671 bfunc(dst, mask, 0xFFFFu);
638 dst += LCDM(WIDTH); 672 dst += stride_dst;
639 mask = 0xFFFFu; 673 mask = 0xFFFFu;
640 } 674 }
641 mask &= mask_bottom; 675 mask &= mask_bottom;
@@ -662,6 +696,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
662{ 696{
663 int ny; 697 int ny;
664 FBFN(data) *dst, *dst_end; 698 FBFN(data) *dst, *dst_end;
699 int stride_dst;
665 unsigned mask, mask_bottom; 700 unsigned mask, mask_bottom;
666 unsigned bits = 0; 701 unsigned bits = 0;
667 LCDFN(blockfunc_type) *bfunc; 702 LCDFN(blockfunc_type) *bfunc;
@@ -669,8 +704,8 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
669 704
670 /******************** In viewport clipping **********************/ 705 /******************** In viewport clipping **********************/
671 /* nothing to draw? */ 706 /* nothing to draw? */
672 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) 707 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width)
673 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 708 || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
674 return; 709 return;
675 710
676 if (x < 0) 711 if (x < 0)
@@ -683,14 +718,14 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
683 height += y; 718 height += y;
684 y = 0; 719 y = 0;
685 } 720 }
686 if (x + width > current_vp->width) 721 if (x + width > CURRENT_VP->width)
687 width = current_vp->width - x; 722 width = CURRENT_VP->width - x;
688 if (y + height > current_vp->height) 723 if (y + height > CURRENT_VP->height)
689 height = current_vp->height - y; 724 height = CURRENT_VP->height - y;
690 725
691 /* adjust for viewport */ 726 /* adjust for viewport */
692 x += current_vp->x; 727 x += CURRENT_VP->x;
693 y += current_vp->y; 728 y += CURRENT_VP->y;
694 729
695#if defined(HAVE_VIEWPORT_CLIP) 730#if defined(HAVE_VIEWPORT_CLIP)
696 /********************* Viewport on screen clipping ********************/ 731 /********************* Viewport on screen clipping ********************/
@@ -717,9 +752,9 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
717#endif 752#endif
718 753
719 754
720 if (current_vp->drawmode & DRMODE_INVERSEVID) 755 if (CURRENT_VP->drawmode & DRMODE_INVERSEVID)
721 { 756 {
722 if ((current_vp->drawmode & DRMODE_BG) && !backdrop) 757 if ((CURRENT_VP->drawmode & DRMODE_BG) && !backdrop)
723 { 758 {
724 fillopt = true; 759 fillopt = true;
725 bits = bg_pattern; 760 bits = bg_pattern;
@@ -727,14 +762,15 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
727 } 762 }
728 else 763 else
729 { 764 {
730 if (current_vp->drawmode & DRMODE_FG) 765 if (CURRENT_VP->drawmode & DRMODE_FG)
731 { 766 {
732 fillopt = true; 767 fillopt = true;
733 bits = fg_pattern; 768 bits = fg_pattern;
734 } 769 }
735 } 770 }
736 bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; 771 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
737 dst = LCDFB(x,y>>3); 772 dst = LCDFB(x,y>>3);
773 stride_dst = CURRENT_VP->buffer->stride;
738 ny = height - 1 + (y & 7); 774 ny = height - 1 + (y & 7);
739 mask = (0xFFu << (y & 7)) & 0xFFu; 775 mask = (0xFFu << (y & 7)) & 0xFFu;
740 mask |= mask << 8; 776 mask |= mask << 8;
@@ -755,7 +791,7 @@ void LCDFN(fillrect)(int x, int y, int width, int height)
755 while (dst_row < dst_end); 791 while (dst_row < dst_end);
756 } 792 }
757 793
758 dst += LCDM(WIDTH); 794 dst += stride_dst;
759 mask = 0xFFFFu; 795 mask = 0xFFFFu;
760 } 796 }
761 mask &= mask_bottom; 797 mask &= mask_bottom;
@@ -789,13 +825,14 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x,
789{ 825{
790 int shift, ny; 826 int shift, ny;
791 FBFN(data) *dst, *dst_end; 827 FBFN(data) *dst, *dst_end;
828 int stride_dst;
792 unsigned data, mask, mask_bottom; 829 unsigned data, mask, mask_bottom;
793 LCDFN(blockfunc_type) *bfunc; 830 LCDFN(blockfunc_type) *bfunc;
794 831
795 /******************** Image in viewport clipping **********************/ 832 /******************** Image in viewport clipping **********************/
796 /* nothing to draw? */ 833 /* nothing to draw? */
797 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 834 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width) ||
798 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 835 (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
799 return; 836 return;
800 837
801 if (x < 0) 838 if (x < 0)
@@ -810,14 +847,14 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x,
810 src_y -= y; 847 src_y -= y;
811 y = 0; 848 y = 0;
812 } 849 }
813 if (x + width > current_vp->width) 850 if (x + width > CURRENT_VP->width)
814 width = current_vp->width - x; 851 width = CURRENT_VP->width - x;
815 if (y + height > current_vp->height) 852 if (y + height > CURRENT_VP->height)
816 height = current_vp->height - y; 853 height = CURRENT_VP->height - y;
817 854
818 /* adjust for viewport */ 855 /* adjust for viewport */
819 x += current_vp->x; 856 x += CURRENT_VP->x;
820 y += current_vp->y; 857 y += CURRENT_VP->y;
821 858
822#if defined(HAVE_VIEWPORT_CLIP) 859#if defined(HAVE_VIEWPORT_CLIP)
823 /********************* Viewport on screen clipping ********************/ 860 /********************* Viewport on screen clipping ********************/
@@ -849,10 +886,11 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x,
849 src_y &= 7; 886 src_y &= 7;
850 y -= src_y; 887 y -= src_y;
851 dst = LCDFB(x,y>>3); 888 dst = LCDFB(x,y>>3);
889 stride_dst = CURRENT_VP->buffer->stride;
852 shift = y & 7; 890 shift = y & 7;
853 ny = height - 1 + shift + src_y; 891 ny = height - 1 + shift + src_y;
854 892
855 bfunc = LCDFN(blockfuncs)[current_vp->drawmode]; 893 bfunc = LCDFN(blockfuncs)[CURRENT_VP->drawmode];
856 mask = 0xFFu << (shift + src_y); 894 mask = 0xFFu << (shift + src_y);
857 /* not byte-doubled here because shift+src_y can be > 7 */ 895 /* not byte-doubled here because shift+src_y can be > 7 */
858 mask_bottom = 0xFFu >> (~ny & 7); 896 mask_bottom = 0xFFu >> (~ny & 7);
@@ -877,7 +915,7 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x,
877 while (dst_row < dst_end); 915 while (dst_row < dst_end);
878 916
879 src += stride; 917 src += stride;
880 dst += LCDM(WIDTH); 918 dst += stride_dst;
881 mask = 0xFFFFu; 919 mask = 0xFFFFu;
882 } 920 }
883 mask &= mask_bottom; 921 mask &= mask_bottom;
@@ -921,7 +959,7 @@ void ICODE_ATTR LCDFN(mono_bitmap_part)(const unsigned char *src, int src_x,
921 } 959 }
922 960
923 src_col += stride; 961 src_col += stride;
924 dst_col += LCDM(WIDTH); 962 dst_col += stride_dst;
925 data >>= 8; 963 data >>= 8;
926 } 964 }
927 data |= *src_col << shift; 965 data |= *src_col << shift;
@@ -958,12 +996,13 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x,
958{ 996{
959 int shift, ny; 997 int shift, ny;
960 FBFN(data) *dst, *dst_end; 998 FBFN(data) *dst, *dst_end;
999 int stride_dst;
961 unsigned mask, mask_bottom; 1000 unsigned mask, mask_bottom;
962 1001
963 /******************** Image in viewport clipping **********************/ 1002 /******************** Image in viewport clipping **********************/
964 /* nothing to draw? */ 1003 /* nothing to draw? */
965 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) 1004 if ((width <= 0) || (height <= 0) || (x >= CURRENT_VP->width)
966 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 1005 || (y >= CURRENT_VP->height) || (x + width <= 0) || (y + height <= 0))
967 return; 1006 return;
968 1007
969 if (x < 0) 1008 if (x < 0)
@@ -978,14 +1017,14 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x,
978 src_y -= y; 1017 src_y -= y;
979 y = 0; 1018 y = 0;
980 } 1019 }
981 if (x + width > current_vp->width) 1020 if (x + width > CURRENT_VP->width)
982 width = current_vp->width - x; 1021 width = CURRENT_VP->width - x;
983 if (y + height > current_vp->height) 1022 if (y + height > CURRENT_VP->height)
984 height = current_vp->height - y; 1023 height = CURRENT_VP->height - y;
985 1024
986 /* adjust for viewport */ 1025 /* adjust for viewport */
987 x += current_vp->x; 1026 x += CURRENT_VP->x;
988 y += current_vp->y; 1027 y += CURRENT_VP->y;
989 1028
990#if defined(HAVE_VIEWPORT_CLIP) 1029#if defined(HAVE_VIEWPORT_CLIP)
991 /********************* Viewport on screen clipping ********************/ 1030 /********************* Viewport on screen clipping ********************/
@@ -1017,6 +1056,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x,
1017 src_y &= 7; 1056 src_y &= 7;
1018 y -= src_y; 1057 y -= src_y;
1019 dst = LCDFB(x,y>>3); 1058 dst = LCDFB(x,y>>3);
1059 stride_dst = CURRENT_VP->buffer->stride;
1020 shift = y & 7; 1060 shift = y & 7;
1021 ny = height - 1 + shift + src_y; 1061 ny = height - 1 + shift + src_y;
1022 1062
@@ -1045,7 +1085,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x,
1045 while (dst_row < dst_end); 1085 while (dst_row < dst_end);
1046 } 1086 }
1047 src += stride; 1087 src += stride;
1048 dst += LCDM(WIDTH); 1088 dst += stride_dst;
1049 mask = 0xFFFFu; 1089 mask = 0xFFFFu;
1050 } 1090 }
1051 mask &= mask_bottom; 1091 mask &= mask_bottom;
@@ -1092,7 +1132,7 @@ void ICODE_ATTR LCDFN(bitmap_part)(const FBFN(data) *src, int src_x,
1092 mask_col |= mask_col << 8; 1132 mask_col |= mask_col << 8;
1093 } 1133 }
1094 src_col += stride; 1134 src_col += stride;
1095 dst_col += LCDM(WIDTH); 1135 dst_col += stride_dst;
1096 olddata = data >> 8; 1136 olddata = data >> 8;
1097 } 1137 }
1098 data = *src_col << shift; 1138 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 @@
40#define MAIN_LCD 40#define MAIN_LCD
41#endif 41#endif
42 42
43void LCDFN(set_framebuffer)(FBFN(data) *fb) 43#ifdef MAIN_LCD
44{ 44#define THIS_STRIDE STRIDE_MAIN
45 if (fb) 45#else
46 LCDFN(framebuffer) = fb; 46#define THIS_STRIDE STRIDE_REMOTE
47 else 47#endif
48 LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0];
49}
50 48
49extern void viewport_set_buffer(struct viewport *vp,
50 struct frame_buffer_t *buffer,
51 const enum screen_type screen); /* viewport.c */
51/* 52/*
52 * draws the borders of the current viewport 53 * draws the borders of the current viewport
53 **/ 54 **/
54void LCDFN(draw_border_viewport)(void) 55void LCDFN(draw_border_viewport)(void)
55{ 56{
56 LCDFN(drawrect)(0, 0, current_vp->width, current_vp->height); 57 LCDFN(drawrect)(0, 0, LCDFN(current_viewport)->width, LCDFN(current_viewport)->height);
57} 58}
58 59
59/* 60/*
60 * fills the rectangle formed by current_vp 61 * fills the rectangle formed by LCDFN(current_viewport)
61 **/ 62 **/
62void LCDFN(fill_viewport)(void) 63void LCDFN(fill_viewport)(void)
63{ 64{
64 LCDFN(fillrect)(0, 0, current_vp->width, current_vp->height); 65 LCDFN(fillrect)(0, 0, LCDFN(current_viewport)->width, LCDFN(current_viewport)->height);
65} 66}
66 67
67 68
68/*** Viewports ***/ 69/*** Viewports ***/
69 70/* init_viewport Notes: When a viewport is initialized
70void LCDFN(set_viewport)(struct viewport* vp) 71 * if vp->buffer is NULL the default frame_buffer is assigned
72 * likewise the actual buffer, stride, get_address_fn
73 * are all filled with values from the default buffer if they are not set
74 * RETURNS either the viewport you passed or the default viewport if vp == NULL
75 */
76struct viewport* LCDFN(init_viewport)(struct viewport* vp)
71{ 77{
72 if (vp == NULL) 78 struct frame_buffer_t *fb_default = &LCDFN(framebuffer_default);
73 current_vp = &default_vp; 79 if (!vp) /* NULL vp grabs default viewport */
80 vp = &default_vp;
81
82 /* use defaults if no buffer is provided */
83 if (vp->buffer == NULL || vp->buffer->elems == 0)
84 vp->buffer = fb_default;
74 else 85 else
75 current_vp = vp; 86 {
87 if (vp->buffer->stride == 0)
88 vp->buffer->stride = fb_default->stride;
89
90 if (vp->buffer->data == NULL)
91 vp->buffer->data = fb_default->data;
92
93 if (vp->buffer->get_address_fn == NULL)
94 vp->buffer->get_address_fn = fb_default->get_address_fn;
95 }
96 return vp;
97}
98struct viewport* LCDFN(set_viewport_ex)(struct viewport* vp, int flags)
99{
100 vp = LCDFN(init_viewport)(vp);
101 struct viewport* last_vp = LCDFN(current_viewport);
102 LCDFN(current_viewport) = vp;
76 103
77#if LCDM(DEPTH) > 1 104#if LCDM(DEPTH) > 1
78 LCDFN(set_foreground)(current_vp->fg_pattern); 105 LCDFN(set_foreground)(vp->fg_pattern);
79 LCDFN(set_background)(current_vp->bg_pattern); 106 LCDFN(set_background)(vp->bg_pattern);
80#endif 107#endif
81 108
82#if defined(SIMULATOR) 109#if defined(SIMULATOR)
@@ -84,10 +111,11 @@ void LCDFN(set_viewport)(struct viewport* vp)
84 * be considered an error - the viewport will not draw as it might be 111 * be considered an error - the viewport will not draw as it might be
85 * expected. 112 * expected.
86 */ 113 */
87 if((unsigned) current_vp->x > (unsigned) LCDM(WIDTH) 114
88 || (unsigned) current_vp->y > (unsigned) LCDM(HEIGHT) 115 if((unsigned) vp->x > (unsigned) LCDM(WIDTH)
89 || current_vp->x + current_vp->width > LCDM(WIDTH) 116 || (unsigned) vp->y > (unsigned) LCDM(HEIGHT)
90 || current_vp->y + current_vp->height > LCDM(HEIGHT)) 117 || vp->x + vp->width > LCDM(WIDTH)
118 || vp->y + vp->height > LCDM(HEIGHT))
91 { 119 {
92#if !defined(HAVE_VIEWPORT_CLIP) 120#if !defined(HAVE_VIEWPORT_CLIP)
93 DEBUGF("ERROR: " 121 DEBUGF("ERROR: "
@@ -95,27 +123,68 @@ void LCDFN(set_viewport)(struct viewport* vp)
95 DEBUGF("NOTE: " 123 DEBUGF("NOTE: "
96#endif 124#endif
97 "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", 125 "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n",
98 current_vp->x, current_vp->y, 126 vp->x, vp->y, vp->width, vp->height);
99 current_vp->width, current_vp->height);
100 } 127 }
101#endif 128#endif
129 if(last_vp)
130 {
131 if ((flags & VP_FLAG_CLEAR_FLAG) == VP_FLAG_CLEAR_FLAG)
132 last_vp->flags &= ~flags;
133 else
134 last_vp->flags |= flags;
135 }
136
137 return last_vp;
138}
139
140struct viewport* LCDFN(set_viewport)(struct viewport* vp)
141{
142 return LCDFN(set_viewport_ex)(vp, VP_FLAG_VP_DIRTY);
102} 143}
103 144
104struct viewport *LCDFN(get_viewport)(bool *is_default) 145struct viewport *LCDFN(get_viewport)(bool *is_default)
105{ 146{
106 *is_default = (current_vp == &default_vp); 147#if 0
107 return current_vp; 148 *is_default = memcmp(LCDFN(current_viewport),
149 &default_vp, sizeof(struct viewport)) == 0;
150#else
151 *is_default = LCDFN(current_viewport) == &default_vp;
152#endif
153
154 return LCDFN(current_viewport);
108} 155}
109 156
110void LCDFN(update_viewport)(void) 157void LCDFN(update_viewport)(void)
111{ 158{
112 LCDFN(update_rect)(current_vp->x, current_vp->y, 159 struct viewport* vp = LCDFN(current_viewport);
113 current_vp->width, current_vp->height); 160 if (vp->buffer->stride != LCDFN(framebuffer_default.stride))
161 {
162 LCDFN(update_viewport_rect)(0,0, vp->width, vp->height);
163 return;
164 }
165 LCDFN(update_rect)(vp->x, vp->y, vp->width, vp->height);
114} 166}
115 167
116void LCDFN(update_viewport_rect)(int x, int y, int width, int height) 168void LCDFN(update_viewport_rect)(int x, int y, int width, int height)
117{ 169{
118 LCDFN(update_rect)(current_vp->x + x, current_vp->y + y, width, height); 170 struct viewport* vp = LCDFN(current_viewport);
171
172 /* handle the case of viewport with differing stride from main screen */
173 if (vp->buffer->stride != LCDFN(framebuffer_default.stride))
174 {
175 struct frame_buffer_t *fb = vp->buffer;
176 viewport_set_buffer(vp, NULL, 0);
177
178 LCDFN(bitmap_part)
179 (fb->FBFN(ptr), vp->x, vp->y, fb->stride,
180 vp->x + x, vp->y + y, width, height);
181
182 LCDFN(update_rect)(vp->x + x, vp->y + y, width, height);
183 viewport_set_buffer(vp, fb, 0);
184 return;
185 }
186
187 LCDFN(update_rect)(vp->x + x, vp->y + y, width, height);
119} 188}
120 189
121#ifndef BOOTLOADER 190#ifndef BOOTLOADER
@@ -123,9 +192,9 @@ void LCDFN(update_viewport_rect)(int x, int y, int width, int height)
123static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str) 192static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
124{ 193{
125 unsigned short *ucs; 194 unsigned short *ucs;
126 font_lock(current_vp->font, true); 195 font_lock(LCDFN(current_viewport)->font, true);
127 struct font* pf = font_get(current_vp->font); 196 struct font* pf = font_get(LCDFN(current_viewport)->font);
128 int vp_flags = current_vp->flags; 197 int vp_flags = LCDFN(current_viewport)->flags;
129 int rtl_next_non_diac_width, last_non_diacritic_width; 198 int rtl_next_non_diac_width, last_non_diacritic_width;
130 199
131 if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0) 200 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)
136 /* center takes precedence */ 205 /* center takes precedence */
137 if (vp_flags & VP_FLAG_ALIGN_CENTER) 206 if (vp_flags & VP_FLAG_ALIGN_CENTER)
138 { 207 {
139 x = ((current_vp->width - w)/ 2) + x; 208 x = ((LCDFN(current_viewport)->width - w)/ 2) + x;
140 if (x < 0) 209 if (x < 0)
141 x = 0; 210 x = 0;
142 } 211 }
143 else 212 else
144 { 213 {
145 x = current_vp->width - w - x; 214 x = LCDFN(current_viewport)->width - w - x;
146 x += ofs; 215 x += ofs;
147 ofs = 0; 216 ofs = 0;
148 } 217 }
@@ -158,7 +227,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
158 int width, base_width, drawmode = 0, base_ofs = 0; 227 int width, base_width, drawmode = 0, base_ofs = 0;
159 const unsigned short next_ch = ucs[1]; 228 const unsigned short next_ch = ucs[1];
160 229
161 if (x >= current_vp->width) 230 if (x >= LCDFN(current_viewport)->width)
162 break; 231 break;
163 232
164 is_diac = is_diacritic(*ucs, &is_rtl); 233 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)
219 * buffer using OR, and then draw the final bitmap instead of the 288 * buffer using OR, and then draw the final bitmap instead of the
220 * chars, without touching the drawmode 289 * chars, without touching the drawmode
221 **/ 290 **/
222 drawmode = current_vp->drawmode; 291 drawmode = LCDFN(current_viewport)->drawmode;
223 current_vp->drawmode = DRMODE_FG; 292 LCDFN(current_viewport)->drawmode = DRMODE_FG;
224 293
225 base_ofs = (base_width - width) / 2; 294 base_ofs = (base_width - width) / 2;
226 } 295 }
@@ -237,7 +306,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
237 y, width - ofs, pf->height); 306 y, width - ofs, pf->height);
238 if (is_diac) 307 if (is_diac)
239 { 308 {
240 current_vp->drawmode = drawmode; 309 LCDFN(current_viewport)->drawmode = drawmode;
241 } 310 }
242 311
243 if (next_ch) 312 if (next_ch)
@@ -256,7 +325,7 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
256 } 325 }
257 } 326 }
258 } 327 }
259 font_lock(current_vp->font, false); 328 font_lock(LCDFN(current_viewport)->font, false);
260} 329}
261#else /* BOOTLOADER */ 330#else /* BOOTLOADER */
262/* put a string at a given pixel position, skipping first ofs pixel columns */ 331/* 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)
375 for(i=0; i<LCDFN(scroll_info).lines; i++) 444 for(i=0; i<LCDFN(scroll_info).lines; i++)
376 { 445 {
377 s = &LCDFN(scroll_info).scroll[i]; 446 s = &LCDFN(scroll_info).scroll[i];
378 if (s->x == x && s->y == y && s->vp == current_vp) 447 if (s->x == x && s->y == y && s->vp == LCDFN(current_viewport))
379 return s; 448 return s;
380 } 449 }
381 return NULL; 450 return NULL;
@@ -411,13 +480,13 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
411 480
412 /* prepare rectangle for scrolling. x and y must be calculated early 481 /* prepare rectangle for scrolling. x and y must be calculated early
413 * for find_scrolling_line() to work */ 482 * for find_scrolling_line() to work */
414 cwidth = font_get(current_vp->font)->maxwidth; 483 cwidth = font_get(LCDFN(current_viewport)->font)->maxwidth;
415 height = font_get(current_vp->font)->height; 484 height = font_get(LCDFN(current_viewport)->font)->height;
416 y = y * (linebased ? height : 1); 485 y = y * (linebased ? height : 1);
417 x = x * (linebased ? cwidth : 1); 486 x = x * (linebased ? cwidth : 1);
418 width = current_vp->width - x; 487 width = LCDFN(current_viewport)->width - x;
419 488
420 if (y >= current_vp->height) 489 if (y >= LCDFN(current_viewport)->height)
421 return false; 490 return false;
422 491
423 s = find_scrolling_line(x, y); 492 s = find_scrolling_line(x, y);
@@ -430,7 +499,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
430 * the string width is too small to scroll the scrolling line is 499 * the string width is too small to scroll the scrolling line is
431 * cleared as well */ 500 * cleared as well */
432 if (w < width || restart) { 501 if (w < width || restart) {
433 LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height); 502 LCDFN(scroll_stop_viewport_rect)(LCDFN(current_viewport), x, y, width, height);
434 LCDFN(putsxyofs)(x, y, x_offset, string); 503 LCDFN(putsxyofs)(x, y, x_offset, string);
435 /* nothing to scroll, or out of scrolling lines. Either way, get out */ 504 /* nothing to scroll, or out of scrolling lines. Either way, get out */
436 if (w < width || LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES)) 505 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,
443 strlcpy(s->linebuffer, string, sizeof(s->linebuffer)); 512 strlcpy(s->linebuffer, string, sizeof(s->linebuffer));
444 /* scroll bidirectional or forward only depending on the string width */ 513 /* scroll bidirectional or forward only depending on the string width */
445 if ( LCDFN(scroll_info).bidir_limit ) { 514 if ( LCDFN(scroll_info).bidir_limit ) {
446 s->bidir = w < (current_vp->width) * 515 s->bidir = w < (LCDFN(current_viewport)->width) *
447 (100 + LCDFN(scroll_info).bidir_limit) / 100; 516 (100 + LCDFN(scroll_info).bidir_limit) / 100;
448 } 517 }
449 else 518 else
@@ -457,7 +526,7 @@ static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
457 s->y = y; 526 s->y = y;
458 s->width = width; 527 s->width = width;
459 s->height = height; 528 s->height = height;
460 s->vp = current_vp; 529 s->vp = LCDFN(current_viewport);
461 s->start_tick = current_tick + LCDFN(scroll_info).delay; 530 s->start_tick = current_tick + LCDFN(scroll_info).delay;
462 LCDFN(scroll_info).lines++; 531 LCDFN(scroll_info).lines++;
463 } else { 532 } else {
@@ -497,11 +566,6 @@ bool LCDFN(puts_scroll)(int x, int y, const unsigned char *string)
497 566
498#if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD) 567#if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD)
499/* see lcd-16bit-common.c for others */ 568/* see lcd-16bit-common.c for others */
500#ifdef MAIN_LCD
501#define THIS_STRIDE STRIDE_MAIN
502#else
503#define THIS_STRIDE STRIDE_REMOTE
504#endif
505 569
506void LCDFN(bmp_part)(const struct bitmap* bm, int src_x, int src_y, 570void LCDFN(bmp_part)(const struct bitmap* bm, int src_x, int src_y,
507 int x, int y, int width, int height) 571 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 {
36}; 36};
37 37
38/*** globals ***/ 38/*** globals ***/
39fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] 39static fb_data lcd_static_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]
40 IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16); 40 IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16);
41fb_data *lcd_framebuffer = &lcd_static_framebuffer[0][0]; 41
42static void *lcd_frameaddress_default(int x, int y);
42 43
43static fb_data* lcd_backdrop = NULL; 44static fb_data* lcd_backdrop = NULL;
44static long lcd_backdrop_offset IDATA_ATTR = 0; 45static long lcd_backdrop_offset IDATA_ATTR = 0;
45 46
47/* shouldn't be changed unless you want system-wide framebuffer changes! */
48struct frame_buffer_t lcd_framebuffer_default =
49{
50 .fb_ptr = &lcd_static_framebuffer[0][0],
51 .get_address_fn = &lcd_frameaddress_default,
52 .stride = STRIDE_MAIN(LCD_WIDTH, LCD_HEIGHT),
53 .elems = (LCD_FBWIDTH*LCD_FBHEIGHT),
54};
55
46static struct viewport default_vp = 56static struct viewport default_vp =
47{ 57{
48 .x = 0, 58 .x = 0,
@@ -51,15 +61,32 @@ static struct viewport default_vp =
51 .height = LCD_HEIGHT, 61 .height = LCD_HEIGHT,
52 .font = FONT_SYSFIXED, 62 .font = FONT_SYSFIXED,
53 .drawmode = DRMODE_SOLID, 63 .drawmode = DRMODE_SOLID,
54 .fg_pattern = LCD_DEFAULT_FG, 64 .buffer = NULL,
55 .bg_pattern = LCD_DEFAULT_BG, 65 .fg_pattern = LCD_DEFAULT_FG,
66 .bg_pattern = LCD_DEFAULT_BG,
56}; 67};
57 68
58static struct viewport* current_vp IDATA_ATTR = &default_vp; 69struct viewport* lcd_current_viewport IDATA_ATTR;
70
71static void *lcd_frameaddress_default(int x, int y)
72{
73 /* the default expects a buffer the same size as the screen */
74 struct frame_buffer_t *fb = lcd_current_viewport->buffer;
75
76#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
77 size_t element = (x * LCD_NATIVE_STRIDE(fb->stride)) + y;
78#else
79 size_t element = (y * LCD_NATIVE_STRIDE(fb->stride)) + x;
80#endif
81 return fb->fb_ptr + element;/*(element % fb->elems);*/
82}
59 83
60/* LCD init */ 84/* LCD init */
61void lcd_init(void) 85void lcd_init(void)
62{ 86{
87 /* Initialize the viewport */
88 lcd_set_viewport(NULL);
89
63 lcd_clear_display(); 90 lcd_clear_display();
64 91
65 /* Call device specific init */ 92 /* Call device specific init */
@@ -70,77 +97,77 @@ void lcd_init(void)
70/* Clear the whole display */ 97/* Clear the whole display */
71void lcd_clear_display(void) 98void lcd_clear_display(void)
72{ 99{
73 struct viewport* old_vp = current_vp; 100 struct viewport* old_vp = lcd_current_viewport;
74 101
75 current_vp = &default_vp; 102 lcd_current_viewport = &default_vp;
76 103
77 lcd_clear_viewport(); 104 lcd_clear_viewport();
78 105
79 current_vp = old_vp; 106 lcd_current_viewport = old_vp;
80} 107}
81 108
82/*** parameter handling ***/ 109/*** parameter handling ***/
83 110
84void lcd_set_drawmode(int mode) 111void lcd_set_drawmode(int mode)
85{ 112{
86 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 113 lcd_current_viewport->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
87} 114}
88 115
89int lcd_get_drawmode(void) 116int lcd_get_drawmode(void)
90{ 117{
91 return current_vp->drawmode; 118 return lcd_current_viewport->drawmode;
92} 119}
93 120
94void lcd_set_foreground(unsigned color) 121void lcd_set_foreground(unsigned color)
95{ 122{
96 current_vp->fg_pattern = color; 123 lcd_current_viewport->fg_pattern = color;
97} 124}
98 125
99unsigned lcd_get_foreground(void) 126unsigned lcd_get_foreground(void)
100{ 127{
101 return current_vp->fg_pattern; 128 return lcd_current_viewport->fg_pattern;
102} 129}
103 130
104void lcd_set_background(unsigned color) 131void lcd_set_background(unsigned color)
105{ 132{
106 current_vp->bg_pattern = color; 133 lcd_current_viewport->bg_pattern = color;
107} 134}
108 135
109unsigned lcd_get_background(void) 136unsigned lcd_get_background(void)
110{ 137{
111 return current_vp->bg_pattern; 138 return lcd_current_viewport->bg_pattern;
112} 139}
113 140
114void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color) 141void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color)
115{ 142{
116 lcd_set_drawmode(mode); 143 lcd_set_drawmode(mode);
117 current_vp->fg_pattern = fg_color; 144 lcd_current_viewport->fg_pattern = fg_color;
118 current_vp->bg_pattern = bg_color; 145 lcd_current_viewport->bg_pattern = bg_color;
119} 146}
120 147
121int lcd_getwidth(void) 148int lcd_getwidth(void)
122{ 149{
123 return current_vp->width; 150 return lcd_current_viewport->width;
124} 151}
125 152
126int lcd_getheight(void) 153int lcd_getheight(void)
127{ 154{
128 return current_vp->height; 155 return lcd_current_viewport->height;
129} 156}
130 157
131void lcd_setfont(int newfont) 158void lcd_setfont(int newfont)
132{ 159{
133 current_vp->font = newfont; 160 lcd_current_viewport->font = newfont;
134} 161}
135 162
136int lcd_getfont(void) 163int lcd_getfont(void)
137{ 164{
138 return current_vp->font; 165 return lcd_current_viewport->font;
139} 166}
140 167
141int lcd_getstringsize(const unsigned char *str, int *w, int *h) 168int lcd_getstringsize(const unsigned char *str, int *w, int *h)
142{ 169{
143 return font_getstringsize(str, w, h, current_vp->font); 170 return font_getstringsize(str, w, h, lcd_current_viewport->font);
144} 171}
145 172
146void lcd_set_backdrop(fb_data* backdrop) 173void lcd_set_backdrop(fb_data* backdrop)
@@ -148,7 +175,7 @@ void lcd_set_backdrop(fb_data* backdrop)
148 lcd_backdrop = backdrop; 175 lcd_backdrop = backdrop;
149 if (backdrop) 176 if (backdrop)
150 { 177 {
151 lcd_backdrop_offset = (intptr_t)backdrop - (intptr_t)lcd_framebuffer; 178 lcd_backdrop_offset = (intptr_t)backdrop - (intptr_t)FBADDR(0,0);
152 lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop; 179 lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop;
153 } 180 }
154 else 181 else
@@ -166,14 +193,14 @@ fb_data* lcd_get_backdrop(void)
166/* Set a single pixel */ 193/* Set a single pixel */
167void lcd_drawpixel(int x, int y) 194void lcd_drawpixel(int x, int y)
168{ 195{
169 if ( ((unsigned)x < (unsigned)current_vp->width) 196 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width)
170 && ((unsigned)y < (unsigned)current_vp->height) 197 && ((unsigned)y < (unsigned)lcd_current_viewport->height)
171#if defined(HAVE_VIEWPORT_CLIP) 198#if defined(HAVE_VIEWPORT_CLIP)
172 && ((unsigned)x < (unsigned)LCD_WIDTH) 199 && ((unsigned)x < (unsigned)LCD_WIDTH)
173 && ((unsigned)y < (unsigned)LCD_HEIGHT) 200 && ((unsigned)y < (unsigned)LCD_HEIGHT)
174#endif 201#endif
175 ) 202 )
176 lcd_fastpixelfuncs[current_vp->drawmode](FBADDR(current_vp->x+x, current_vp->y+y)); 203 lcd_fastpixelfuncs[lcd_current_viewport->drawmode](FBADDR(lcd_current_viewport->x+x, lcd_current_viewport->y+y));
177} 204}
178 205
179/* Draw a line */ 206/* Draw a line */
@@ -185,7 +212,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
185 int d, dinc1, dinc2; 212 int d, dinc1, dinc2;
186 int x, xinc1, xinc2; 213 int x, xinc1, xinc2;
187 int y, yinc1, yinc2; 214 int y, yinc1, yinc2;
188 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; 215 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[lcd_current_viewport->drawmode];
189 216
190 deltay = abs(y2 - y1); 217 deltay = abs(y2 - y1);
191 if (deltay == 0) 218 if (deltay == 0)
@@ -241,14 +268,14 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
241 268
242 for (i = 0; i < numpixels; i++) 269 for (i = 0; i < numpixels; i++)
243 { 270 {
244 if ( ((unsigned)x < (unsigned)current_vp->width) 271 if ( ((unsigned)x < (unsigned)lcd_current_viewport->width)
245 && ((unsigned)y < (unsigned)current_vp->height) 272 && ((unsigned)y < (unsigned)lcd_current_viewport->height)
246#if defined(HAVE_VIEWPORT_CLIP) 273#if defined(HAVE_VIEWPORT_CLIP)
247 && ((unsigned)x < (unsigned)LCD_WIDTH) 274 && ((unsigned)x < (unsigned)LCD_WIDTH)
248 && ((unsigned)y < (unsigned)LCD_HEIGHT) 275 && ((unsigned)y < (unsigned)LCD_HEIGHT)
249#endif 276#endif
250 ) 277 )
251 pfunc(FBADDR(x + current_vp->x, y + current_vp->y)); 278 pfunc(FBADDR(x + lcd_current_viewport->x, y + lcd_current_viewport->y));
252 279
253 if (d < 0) 280 if (d < 0)
254 { 281 {
@@ -307,9 +334,9 @@ void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x,
307void ICODE_ATTR lcd_bmp_part(const struct bitmap* bm, int src_x, int src_y, 334void ICODE_ATTR lcd_bmp_part(const struct bitmap* bm, int src_x, int src_y,
308 int x, int y, int width, int height) 335 int x, int y, int width, int height)
309{ 336{
310 int bitmap_stride = STRIDE_MAIN(bm->width, bm->height); 337 int bitmap_stride = LCD_FBSTRIDE(bm->width, bm->height);
311 if (bm->format == FORMAT_MONO) 338 if (bm->format == FORMAT_MONO)
312 lcd_mono_bitmap_part(bm->data, src_x, src_y, bitmap_stride, x, y, width, height); 339 lcd_mono_bitmap_part(bm->data, src_x, src_y, bm->width, x, y, width, height);
313 else if (bm->alpha_offset > 0) 340 else if (bm->alpha_offset > 0)
314 lcd_alpha_bitmap_part_mix((fb_data*)bm->data, bm->data+bm->alpha_offset, 341 lcd_alpha_bitmap_part_mix((fb_data*)bm->data, bm->data+bm->alpha_offset,
315 src_x, src_y, x, y, width, height, 342 src_x, src_y, x, y, width, height,
@@ -554,7 +581,7 @@ void lcd_blit_yuv(unsigned char * const src[3],
554void lcd_gradient_fillrect_part(int x, int y, int width, int height, 581void lcd_gradient_fillrect_part(int x, int y, int width, int height,
555 unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip) 582 unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip)
556{ 583{
557 int old_pattern = current_vp->fg_pattern; 584 int old_pattern = lcd_current_viewport->fg_pattern;
558 int step_mul, i; 585 int step_mul, i;
559 int x1, x2; 586 int x1, x2;
560 x1 = x; 587 x1 = x;
@@ -581,14 +608,14 @@ void lcd_gradient_fillrect_part(int x, int y, int width, int height,
581 } 608 }
582 609
583 for(i = y; i < y + height; i++) { 610 for(i = y; i < y + height; i++) {
584 current_vp->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); 611 lcd_current_viewport->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16);
585 lcd_hline(x1, x2, i); 612 lcd_hline(x1, x2, i);
586 h_r -= rstep; 613 h_r -= rstep;
587 h_g -= gstep; 614 h_g -= gstep;
588 h_b -= bstep; 615 h_b -= bstep;
589 } 616 }
590 617
591 current_vp->fg_pattern = old_pattern; 618 lcd_current_viewport->fg_pattern = old_pattern;
592} 619}
593 620
594/* Fill a rectangle with a gradient. The gradient's color will fade from 621/* 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)
156 } 156 }
157 } 157 }
158 158
159 /* Stash and restore these three, so that the scroll_func 159 /* Stash and restore these four, so that the scroll_func
160 * can do whatever it likes without destroying the state */ 160 * can do whatever it likes without destroying the state */
161 struct frame_buffer_t *framebuf = s->vp->buffer;
161 unsigned drawmode; 162 unsigned drawmode;
162#if LCD_DEPTH > 1 163#if LCD_DEPTH > 1
163 unsigned fg_pattern, bg_pattern; 164 unsigned fg_pattern, bg_pattern;
@@ -174,6 +175,7 @@ bool LCDFN(scroll_now)(struct scrollinfo *s)
174 s->vp->bg_pattern = bg_pattern; 175 s->vp->bg_pattern = bg_pattern;
175#endif 176#endif
176 s->vp->drawmode = drawmode; 177 s->vp->drawmode = drawmode;
178 s->vp->buffer = framebuf;
177 179
178 return ended; 180 return ended;
179} 181}
@@ -205,7 +207,7 @@ static void LCDFN(scroll_worker)(void)
205 * be switched early so that lcd_getstringsize() picks the 207 * be switched early so that lcd_getstringsize() picks the
206 * correct font */ 208 * correct font */
207 vp = LCDFN(get_viewport)(&is_default); 209 vp = LCDFN(get_viewport)(&is_default);
208 LCDFN(set_viewport)(s->vp); 210 LCDFN(set_viewport_ex)(s->vp, 0); /* don't mark the last vp as dirty */
209 211
210 makedelay = false; 212 makedelay = false;
211 step = si->step; 213 step = si->step;
@@ -218,7 +220,7 @@ static void LCDFN(scroll_worker)(void)
218 /* put the line onto the display now */ 220 /* put the line onto the display now */
219 makedelay = LCDFN(scroll_now(s)); 221 makedelay = LCDFN(scroll_now(s));
220 222
221 LCDFN(set_viewport)(vp); 223 LCDFN(set_viewport_ex)(vp, 0); /* don't mark the last vp as dirty */
222 224
223 if (makedelay) 225 if (makedelay)
224 s->start_tick += si->delay + si->ticks; 226 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 @@
34#define REMOTETYPE_H100_LCD 1 34#define REMOTETYPE_H100_LCD 1
35#define REMOTETYPE_H300_LCD 2 35#define REMOTETYPE_H300_LCD 2
36#define REMOTETYPE_H300_NONLCD 3 36#define REMOTETYPE_H300_NONLCD 3
37int remote_type(void); 37 int remote_type(void);
38#endif
39
40#if LCD_REMOTE_DEPTH <= 8
41#if (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) \
42 || (LCD_REMOTE_PIXELFORMAT == HORIZONTAL_INTERLEAVED)
43typedef unsigned short fb_remote_data;
44#define FB_RDATA_SZ 2
45#else
46typedef unsigned char fb_remote_data;
47#define FB_RDATA_SZ 1
48#endif
49#elif LCD_DEPTH <= 16
50typedef unsigned short fb_remote_data;
51#define FB_RDATA_SZ 2
52#else
53typedef unsigned long fb_remote_data;
54#define FB_RDATA_SZ 4
55#endif 38#endif
56 39
57#if LCD_REMOTE_DEPTH > 1 /* greyscale - 8 bit max */ 40#if LCD_REMOTE_DEPTH > 1 /* greyscale - 8 bit max */
58#ifdef HAVE_LCD_COLOR 41#ifdef HAVE_LCD_COLOR
59extern unsigned lcd_remote_color_to_native(unsigned color); 42 extern unsigned lcd_remote_color_to_native(unsigned color);
60#endif 43#endif
61 44
62#define LCD_REMOTE_MAX_LEVEL ((1 << LCD_REMOTE_DEPTH) - 1) 45#define LCD_REMOTE_MAX_LEVEL ((1 << LCD_REMOTE_DEPTH) - 1)
@@ -77,12 +60,19 @@ extern unsigned lcd_remote_color_to_native(unsigned color);
77 60
78/* Frame buffer dimensions (format checks only cover existing targets!) */ 61/* Frame buffer dimensions (format checks only cover existing targets!) */
79#if LCD_REMOTE_DEPTH == 1 62#if LCD_REMOTE_DEPTH == 1
80#define LCD_REMOTE_FBHEIGHT ((LCD_REMOTE_HEIGHT+7)/8) 63#define LCD_REMOTE_STRIDE(w, h) (h)
64#define LCD_REMOTE_FBSTRIDE(w, h) ((h+7)/8)
65#define LCD_REMOTE_FBHEIGHT LCD_REMOTE_FBSTRIDE(LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT)
66#define LCD_REMOTE_NBELEMS(w, h) (((w*LCD_REMOTE_FBSTRIDE(w, h)) + h) / sizeof(fb_remote_data))
81#elif LCD_REMOTE_DEPTH == 2 67#elif LCD_REMOTE_DEPTH == 2
82#if LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED 68#if LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED
83#define LCD_REMOTE_FBHEIGHT ((LCD_REMOTE_HEIGHT+7)/8) 69#define LCD_REMOTE_STRIDE(w, h) (h)
70#define LCD_REMOTE_FBSTRIDE(w, h) ((h+7)/8)
71#define LCD_REMOTE_FBHEIGHT LCD_REMOTE_FBSTRIDE(LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT)
72#define LCD_REMOTE_NBELEMS(w, h) (((w*LCD_REMOTE_FBSTRIDE(w, h)) + h) / sizeof(fb_remote_data))
84#endif 73#endif
85#endif /* LCD_REMOTE_DEPTH */ 74#endif /* LCD_REMOTE_DEPTH */
75
86/* Set defaults if not defined different yet. The defaults apply to both 76/* Set defaults if not defined different yet. The defaults apply to both
87 * dimensions for LCD_REMOTE_DEPTH >= 8 */ 77 * dimensions for LCD_REMOTE_DEPTH >= 8 */
88#ifndef LCD_REMOTE_FBWIDTH 78#ifndef LCD_REMOTE_FBWIDTH
@@ -92,11 +82,20 @@ extern unsigned lcd_remote_color_to_native(unsigned color);
92#define LCD_REMOTE_FBHEIGHT LCD_REMOTE_HEIGHT 82#define LCD_REMOTE_FBHEIGHT LCD_REMOTE_HEIGHT
93#endif 83#endif
94 84
95/* The actual framebuffer */ 85#ifndef LCD_REMOTE_NBELEMS
96extern fb_remote_data *lcd_remote_framebuffer; 86/* At this time (2020) known remote screens only have vertical stride */
97extern fb_remote_data lcd_remote_static_framebuffer[LCD_REMOTE_FBHEIGHT][LCD_REMOTE_FBWIDTH]; 87#define LCD_REMOTE_NBELEMS(w, h) ((w*STRIDE_REMOTE(w, h)) + h) / sizeof(fb_remote_data))
98#define FBREMOTEADDR(x, y) (lcd_remote_framebuffer + ((y) * LCD_REMOTE_FBWIDTH) + (x)) 88#define LCD_REMOTE_STRIDE(w, h) STRIDE_REMOTE(w, h)
99#define FRAMEBUFFER_REMOTE_SIZE (sizeof(lcd_remote_static_framebuffer)) 89#define LCD_REMOTE_FBSTRIDE(w, h) STRIDE_REMOTE(w, h)
90#endif
91
92#ifndef LCD_REMOTE_NATIVE_STRIDE
93#define LCD_REMOTE_NATIVE_STRIDE(s) (s)
94#endif
95
96extern struct viewport* lcd_remote_current_viewport;
97#define FBREMOTEADDR(x,y) (fb_remote_data *)(lcd_remote_current_viewport->buffer->get_address_fn(x, y))
98#define FRAMEBUFFER_REMOTE_SIZE (sizeof(fb_remote_data)*LCD_REMOTE_FBWIDTH*LCD_REMOTE_FBHEIGHT)
100 99
101#if LCD_REMOTE_DEPTH > 1 100#if LCD_REMOTE_DEPTH > 1
102extern void lcd_remote_set_foreground(unsigned foreground); 101extern 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,
112 int src_y, int stride, int x, int y, 111 int src_y, int stride, int x, int y,
113 int width, int height); 112 int width, int height);
114extern void lcd_remote_mono_bitmap(const unsigned char *src, int x, int y, 113extern void lcd_remote_mono_bitmap(const unsigned char *src, int x, int y,
115 int width, int height); 114 int width, int height);
116extern void lcd_remote_bitmap_transparent_part(const fb_remote_data *src, 115extern void lcd_remote_bitmap_transparent_part(const fb_remote_data *src,
117 int src_x, int src_y, 116 int src_x, int src_y,
118 int stride, int x, int y, 117 int stride, int x, int y,
119 int width, int height); 118 int width, int height);
120extern void lcd_bitmap_remote_transparent(const fb_remote_data *src, int x, 119extern void lcd_bitmap_remote_transparent(const fb_remote_data *src, int x,
121 int y, int width, int height); 120 int y, int width, int height);
122#else /* LCD_REMOTE_DEPTH == 1 */ 121#else /* LCD_REMOTE_DEPTH == 1 */
123#define lcd_remote_mono_bitmap lcd_remote_bitmap 122#define lcd_remote_mono_bitmap lcd_remote_bitmap
124#define lcd_remote_mono_bitmap_part lcd_remote_bitmap_part 123#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,
137extern void lcd_remote_bitmap(const fb_remote_data *src, int x, int y, 136extern void lcd_remote_bitmap(const fb_remote_data *src, int x, int y,
138 int width, int height); 137 int width, int height);
139extern void lcd_remote_nine_segment_bmp(const struct bitmap* bm, int x, int y, 138extern void lcd_remote_nine_segment_bmp(const struct bitmap* bm, int x, int y,
140 int width, int height); 139 int width, int height);
141 140
142/* Low-level drawing function types */ 141/* Low-level drawing function types */
143typedef void lcd_remote_pixelfunc_type(int x, int y); 142typedef 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,
146 145
147/* low level drawing function pointer arrays */ 146/* low level drawing function pointer arrays */
148#if LCD_REMOTE_DEPTH > 1 147#if LCD_REMOTE_DEPTH > 1
149extern lcd_remote_pixelfunc_type* const *lcd_remote_pixelfuncs; 148 extern lcd_remote_pixelfunc_type* const *lcd_remote_pixelfuncs;
150extern lcd_remote_blockfunc_type* const *lcd_remote_blockfuncs; 149 extern lcd_remote_blockfunc_type* const *lcd_remote_blockfuncs;
151#else 150#else
152extern lcd_remote_pixelfunc_type* const lcd_remote_pixelfuncs[8]; 151 extern lcd_remote_pixelfunc_type* const lcd_remote_pixelfuncs[8];
153extern lcd_remote_blockfunc_type* const lcd_remote_blockfuncs[8]; 152 extern lcd_remote_blockfunc_type* const lcd_remote_blockfuncs[8];
154#endif 153#endif
155 154
156#endif /* HAVE_LCD_REMOTE */ 155#endif /* HAVE_LCD_REMOTE */
157 156
158#ifdef HAVE_REMOTE_LCD_TICKING 157#ifdef HAVE_REMOTE_LCD_TICKING
159void lcd_remote_emireduce(bool state); 158 void lcd_remote_emireduce(bool state);
160#endif 159#endif
161 160
162void lcd_remote_init_device(void); 161void lcd_remote_init_device(void);
@@ -170,7 +169,10 @@ extern void lcd_remote_init(void);
170extern int lcd_remote_default_contrast(void); 169extern int lcd_remote_default_contrast(void);
171extern void lcd_remote_set_contrast(int val); 170extern void lcd_remote_set_contrast(int val);
172 171
173extern void lcd_remote_set_viewport(struct viewport* vp); 172extern struct viewport* lcd_remote_init_viewport(struct viewport* vp);
173extern struct viewport* lcd_remote_set_viewport(struct viewport* vp);
174extern struct viewport* lcd_remote_set_viewport_ex(struct viewport* vp, int flags);
175
174extern void lcd_remote_clear_display(void); 176extern void lcd_remote_clear_display(void);
175extern void lcd_remote_clear_viewport(void); 177extern void lcd_remote_clear_viewport(void);
176extern void lcd_remote_puts(int x, int y, const unsigned char *str); 178extern void lcd_remote_puts(int x, int y, const unsigned char *str);
@@ -212,7 +214,7 @@ extern void lcd_remote_bidir_scroll(int threshold);
212extern void lcd_remote_scroll_step(int pixels); 214extern void lcd_remote_scroll_step(int pixels);
213 215
214extern void lcd_remote_bmp_part(const struct bitmap* bm, int src_x, int src_y, 216extern void lcd_remote_bmp_part(const struct bitmap* bm, int src_x, int src_y,
215 int x, int y, int width, int height); 217 int x, int y, int width, int height);
216extern void lcd_remote_bmp(const struct bitmap* bm, int x, int y); 218extern void lcd_remote_bmp(const struct bitmap* bm, int x, int y);
217 219
218#endif /* __LCD_REMOTE_H__ */ 220#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 @@
23#define __LCD_H__ 23#define __LCD_H__
24 24
25#include <stdbool.h> 25#include <stdbool.h>
26#include <stddef.h>
26#include "cpu.h" 27#include "cpu.h"
27#include "config.h" 28#include "config.h"
28#include "events.h" 29#include "events.h"
29 30
30#define VP_FLAG_ALIGN_RIGHT 0x01
31#define VP_FLAG_ALIGN_CENTER 0x02
32
33#define VP_FLAG_ALIGNMENT_MASK \
34 (VP_FLAG_ALIGN_RIGHT|VP_FLAG_ALIGN_CENTER)
35
36#define VP_IS_RTL(vp) (((vp)->flags & VP_FLAG_ALIGNMENT_MASK) == VP_FLAG_ALIGN_RIGHT)
37
38struct viewport {
39 int x;
40 int y;
41 int width;
42 int height;
43 int flags;
44 int font;
45 int drawmode;
46 /* needed for even for mono displays to support greylib */
47 unsigned fg_pattern;
48 unsigned bg_pattern;
49};
50 31
51/* Frame buffer stride 32/* Frame buffer stride
52 * 33 *
@@ -101,7 +82,7 @@ enum screen_type {
101 82
102struct scrollinfo; 83struct scrollinfo;
103 84
104#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 85#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
105#define STRIDE_MAIN(w, h) (h) 86#define STRIDE_MAIN(w, h) (h)
106#else 87#else
107#define STRIDE_MAIN(w, h) (w) 88#define STRIDE_MAIN(w, h) (w)
@@ -115,46 +96,105 @@ struct scrollinfo;
115#if LCD_DEPTH <=8 96#if LCD_DEPTH <=8
116#if (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) \ 97#if (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) \
117 || (LCD_PIXELFORMAT == HORIZONTAL_INTERLEAVED) 98 || (LCD_PIXELFORMAT == HORIZONTAL_INTERLEAVED)
118typedef unsigned short fb_data; 99 typedef unsigned short fb_data;
119#define FB_DATA_SZ 2 100#define FB_DATA_SZ 2
120#else 101#else
121typedef unsigned char fb_data; 102 typedef unsigned char fb_data;
122#define FB_DATA_SZ 1 103#define FB_DATA_SZ 1
123#endif 104#endif
124#elif LCD_DEPTH <= 16 105#elif LCD_DEPTH <= 16
125typedef unsigned short fb_data; 106 typedef unsigned short fb_data;
126#define FB_DATA_SZ 2 107#define FB_DATA_SZ 2
127#elif LCD_DEPTH <= 24 108#elif LCD_DEPTH <= 24
128struct _fb_pixel { 109 struct _fb_pixel {
129 unsigned char b, g, r; 110 unsigned char b, g, r;
130}; 111 };
131typedef struct _fb_pixel fb_data; 112 typedef struct _fb_pixel fb_data;
132#define FB_DATA_SZ 3 113#define FB_DATA_SZ 3
133#else /* LCD_DEPTH > 24 */ 114#else /* LCD_DEPTH > 24 */
134#if (LCD_PIXELFORMAT == XRGB8888) 115#if (LCD_PIXELFORMAT == XRGB8888)
135struct _fb_pixel { 116 struct _fb_pixel {
136 unsigned char b, g, r, x; 117 unsigned char b, g, r, x;
137}; 118 };
138typedef struct _fb_pixel fb_data; 119 typedef struct _fb_pixel fb_data;
139#else 120#else
140typedef unsigned long fb_data; 121 typedef unsigned long fb_data;
141#endif 122#endif
142#define FB_DATA_SZ 4 123#define FB_DATA_SZ 4
143#endif /* LCD_DEPTH */ 124#endif /* LCD_DEPTH */
144 125
126#ifdef HAVE_REMOTE_LCD
127#if LCD_REMOTE_DEPTH <= 8
128#if (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) \
129 || (LCD_REMOTE_PIXELFORMAT == HORIZONTAL_INTERLEAVED)
130 typedef unsigned short fb_remote_data;
131#define FB_RDATA_SZ 2
132#else
133 typedef unsigned char fb_remote_data;
134#define FB_RDATA_SZ 1
135#endif
136#elif LCD_DEPTH <= 16
137 typedef unsigned short fb_remote_data;
138#define FB_RDATA_SZ 2
139#else
140 typedef unsigned long fb_remote_data;
141#define FB_RDATA_SZ 4
142#endif
143#endif
144
145#if defined(HAVE_LCD_MODES) 145#if defined(HAVE_LCD_MODES)
146void lcd_set_mode(int mode); 146 void lcd_set_mode(int mode);
147#define LCD_MODE_RGB565 0x00000001 147#define LCD_MODE_RGB565 0x00000001
148#define LCD_MODE_YUV 0x00000002 148#define LCD_MODE_YUV 0x00000002
149#define LCD_MODE_PAL256 0x00000004 149#define LCD_MODE_PAL256 0x00000004
150 150
151#if HAVE_LCD_MODES & LCD_MODE_PAL256 151#if HAVE_LCD_MODES & LCD_MODE_PAL256
152 void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y, 152 void lcd_blit_pal256(unsigned char *src, int src_x, int src_y, int x, int y,
153 int width, int height); 153 int width, int height);
154 void lcd_pal256_update_pal(fb_data *palette); 154 void lcd_pal256_update_pal(fb_data *palette);
155#endif 155#endif
156#endif 156#endif
157 157
158struct frame_buffer_t {
159 union
160 {
161 void *data;
162 char *ch_ptr;
163 fb_data *fb_ptr;
164#ifdef HAVE_REMOTE_LCD
165 fb_remote_data *fb_remote_ptr;
166#endif
167 };
168 void *(*get_address_fn)(int x, int y);
169 ptrdiff_t stride;
170 size_t elems;
171};
172
173#define VP_FLAG_ALIGN_RIGHT 0x01
174#define VP_FLAG_ALIGN_CENTER 0x02
175
176#define VP_FLAG_ALIGNMENT_MASK \
177 (VP_FLAG_ALIGN_RIGHT|VP_FLAG_ALIGN_CENTER)
178
179#define VP_IS_RTL(vp) (((vp)->flags & VP_FLAG_ALIGNMENT_MASK) == VP_FLAG_ALIGN_RIGHT)
180
181#define VP_FLAG_VP_DIRTY 0x4000
182#define VP_FLAG_CLEAR_FLAG 0x8000
183#define VP_FLAG_VP_SET_CLEAN (VP_FLAG_CLEAR_FLAG | VP_FLAG_VP_DIRTY)
184
185struct viewport {
186 int x;
187 int y;
188 int width;
189 int height;
190 int flags;
191 int font;
192 int drawmode;
193 struct frame_buffer_t *buffer;
194 /* needed for even for mono displays to support greylib */
195 unsigned fg_pattern;
196 unsigned bg_pattern;
197};
158 198
159/* common functions */ 199/* common functions */
160extern void lcd_write_command(int byte); 200extern void lcd_write_command(int byte);
@@ -171,7 +211,10 @@ extern int lcd_getwidth(void);
171extern int lcd_getheight(void); 211extern int lcd_getheight(void);
172extern int lcd_getstringsize(const unsigned char *str, int *w, int *h); 212extern int lcd_getstringsize(const unsigned char *str, int *w, int *h);
173 213
174extern void lcd_set_viewport(struct viewport* vp); 214extern struct viewport* lcd_init_viewport(struct viewport* vp);
215extern struct viewport* lcd_set_viewport(struct viewport* vp);
216extern struct viewport* lcd_set_viewport_ex(struct viewport* vp, int flags);
217
175extern void lcd_update(void); 218extern void lcd_update(void);
176extern void lcd_update_viewport(void); 219extern void lcd_update_viewport(void);
177extern void lcd_update_viewport_rect(int x, int y, int width, int height); 220extern 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,
193#if defined(HAVE_LCD_COLOR) 236#if defined(HAVE_LCD_COLOR)
194#if MEMORYSIZE > 2 237#if MEMORYSIZE > 2
195#define LCD_YUV_DITHER 0x1 238#define LCD_YUV_DITHER 0x1
196extern void lcd_yuv_set_options(unsigned options); 239 extern void lcd_yuv_set_options(unsigned options);
197extern void lcd_blit_yuv(unsigned char * const src[3], 240 extern void lcd_blit_yuv(unsigned char * const src[3],
198 int src_x, int src_y, int stride, 241 int src_x, int src_y, int stride,
199 int x, int y, int width, int height); 242 int x, int y, int width, int height);
200#endif /* MEMORYSIZE > 2 */ 243#endif /* MEMORYSIZE > 2 */
201#else 244#else
202extern void lcd_blit_mono(const unsigned char *data, int x, int by, int width, 245 extern void lcd_blit_mono(const unsigned char *data, int x, int by, int width,
203 int bheight, int stride); 246 int bheight, int stride);
204extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, 247 extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases,
205 int bx, int by, int bwidth, int bheight, 248 int bx, int by, int bwidth, int bheight,
206 int stride); 249 int stride);
207#endif 250#endif
@@ -211,9 +254,9 @@ extern void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases,
211extern void lcd_update_rect(int x, int y, int width, int height); 254extern void lcd_update_rect(int x, int y, int width, int height);
212 255
213#ifdef HAVE_REMOTE_LCD 256#ifdef HAVE_REMOTE_LCD
214extern void lcd_remote_update(void); 257 extern void lcd_remote_update(void);
215/* update a fraction of the screen */ 258 /* update a fraction of the screen */
216extern void lcd_remote_update_rect(int x, int y, int width, int height); 259 extern void lcd_remote_update_rect(int x, int y, int width, int height);
217#endif /* HAVE_REMOTE_LCD */ 260#endif /* HAVE_REMOTE_LCD */
218 261
219/* Bitmap formats */ 262/* Bitmap formats */
@@ -239,13 +282,13 @@ enum
239typedef void lcd_pixelfunc_type(int x, int y); 282typedef void lcd_pixelfunc_type(int x, int y);
240typedef void lcd_blockfunc_type(fb_data *address, unsigned mask, unsigned bits); 283typedef void lcd_blockfunc_type(fb_data *address, unsigned mask, unsigned bits);
241#if LCD_DEPTH >= 8 284#if LCD_DEPTH >= 8
242typedef void lcd_fastpixelfunc_type(fb_data *address); 285 typedef void lcd_fastpixelfunc_type(fb_data *address);
243#endif 286#endif
244 287
245#if defined(HAVE_LCD_COLOR) && defined(LCD_REMOTE_DEPTH) && \ 288#if defined(HAVE_LCD_COLOR) && defined(LCD_REMOTE_DEPTH) && \
246 LCD_REMOTE_DEPTH > 1 289 LCD_REMOTE_DEPTH > 1
247/* Just return color for screens use */ 290/* Just return color for screens use */
248static inline unsigned lcd_color_to_native(unsigned color) 291 static inline unsigned lcd_color_to_native(unsigned color)
249 { return color; } 292 { return color; }
250#define SCREEN_COLOR_TO_NATIVE(screen, color) (screen)->color_to_native(color) 293#define SCREEN_COLOR_TO_NATIVE(screen, color) (screen)->color_to_native(color)
251#else 294#else
@@ -286,7 +329,7 @@ static inline unsigned lcd_color_to_native(unsigned color)
286 (((b) >> 3) << 8) ) 329 (((b) >> 3) << 8) )
287/* swap color once - not currenly used in static inits */ 330/* swap color once - not currenly used in static inits */
288#define _SWAPUNPACK(x, _unp_) \ 331#define _SWAPUNPACK(x, _unp_) \
289 ({ typeof (x) _x_ = swap16(x); _unp_(_x_); }) 332 ({ typeof (x) _x_ = swap16(x); _unp_(_x_); })
290#define RGB_UNPACK_RED(x) _SWAPUNPACK((x), _RGB_UNPACK_RED) 333#define RGB_UNPACK_RED(x) _SWAPUNPACK((x), _RGB_UNPACK_RED)
291#define RGB_UNPACK_GREEN(x) _SWAPUNPACK((x), _RGB_UNPACK_GREEN) 334#define RGB_UNPACK_GREEN(x) _SWAPUNPACK((x), _RGB_UNPACK_GREEN)
292#define RGB_UNPACK_BLUE(x) _SWAPUNPACK((x), _RGB_UNPACK_BLUE) 335#define RGB_UNPACK_BLUE(x) _SWAPUNPACK((x), _RGB_UNPACK_BLUE)
@@ -374,16 +417,16 @@ static inline unsigned lcd_color_to_native(unsigned color)
374 * format, so it's the reverse of FB_SCALARPACK_LCD 417 * format, so it's the reverse of FB_SCALARPACK_LCD
375 */ 418 */
376#if LCD_DEPTH >= 24 419#if LCD_DEPTH >= 24
377static inline fb_data scalar_to_fb(unsigned p) 420 static inline fb_data scalar_to_fb(unsigned p)
378{ 421 {
379 union { fb_data st; unsigned sc; } convert; 422 union { fb_data st; unsigned sc; } convert;
380 convert.sc = p; return convert.st; 423 convert.sc = p; return convert.st;
381} 424 }
382static inline unsigned fb_to_scalar(fb_data p) 425 static inline unsigned fb_to_scalar(fb_data p)
383{ 426 {
384 union { fb_data st; unsigned sc; } convert; 427 union { fb_data st; unsigned sc; } convert;
385 convert.st = p; return convert.sc; 428 convert.st = p; return convert.sc;
386} 429 }
387#define FB_RGBPACK(r_, g_, b_) ((fb_data){.r = r_, .g = g_, .b = b_}) 430#define FB_RGBPACK(r_, g_, b_) ((fb_data){.r = r_, .g = g_, .b = b_})
388#define FB_RGBPACK_LCD(r_, g_, b_) FB_RGBPACK(r_, g_, b_) 431#define FB_RGBPACK_LCD(r_, g_, b_) FB_RGBPACK(r_, g_, b_)
389#define FB_UNPACK_RED(fb) ((fb).r) 432#define FB_UNPACK_RED(fb) ((fb).r)
@@ -411,17 +454,28 @@ static inline unsigned fb_to_scalar(fb_data p)
411/* Frame buffer dimensions */ 454/* Frame buffer dimensions */
412#if LCD_DEPTH == 1 455#if LCD_DEPTH == 1
413#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 456#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
414#define LCD_FBWIDTH ((LCD_WIDTH+7)/8) 457#define LCD_FBSTRIDE(w, h) ((w+7)/8)
458#define LCD_FBWIDTH LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT)
459#define LCD_NBELEMS(w, h) (((h*LCD_FBSTRIDE(w, h)) + w) / sizeof(fb_data))
415#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */ 460#else /* LCD_PIXELFORMAT == VERTICAL_PACKING */
416#define LCD_FBHEIGHT ((LCD_HEIGHT+7)/8) 461#define LCD_FBSTRIDE(w, h) ((h+7)/8)
462#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT)
463#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data))
417#endif /* LCD_PIXELFORMAT */ 464#endif /* LCD_PIXELFORMAT */
418#elif LCD_DEPTH == 2 465#elif LCD_DEPTH == 2
419#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 466#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
420#define LCD_FBWIDTH ((LCD_WIDTH+3)/4) 467#define LCD_FBSTRIDE(w, h) ((w+3)>>2)
468#define LCD_NATIVE_STRIDE(s) LCD_FBSTRIDE(s, s)
469#define LCD_FBWIDTH LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT)
470#define LCD_NBELEMS(w, h) (((h*LCD_FBSTRIDE(w, h)) + w) / sizeof(fb_data))
421#elif LCD_PIXELFORMAT == VERTICAL_PACKING 471#elif LCD_PIXELFORMAT == VERTICAL_PACKING
422#define LCD_FBHEIGHT ((LCD_HEIGHT+3)/4) 472#define LCD_FBSTRIDE(w, h) ((h+3)/4)
473#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT)
474#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data))
423#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED 475#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
424#define LCD_FBHEIGHT ((LCD_HEIGHT+7)/8) 476#define LCD_FBSTRIDE(w, h) ((h+7)/8)
477#define LCD_FBHEIGHT LCD_FBSTRIDE(LCD_WIDTH, LCD_HEIGHT)
478#define LCD_NBELEMS(w, h) (((w*LCD_FBSTRIDE(w, h)) + h) / sizeof(fb_data))
425#endif /* LCD_PIXELFORMAT */ 479#endif /* LCD_PIXELFORMAT */
426#endif /* LCD_DEPTH */ 480#endif /* LCD_DEPTH */
427/* Set defaults if not defined different yet. The defaults apply to both 481/* 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)
432#ifndef LCD_FBHEIGHT 486#ifndef LCD_FBHEIGHT
433#define LCD_FBHEIGHT LCD_HEIGHT 487#define LCD_FBHEIGHT LCD_HEIGHT
434#endif 488#endif
435/* The actual framebuffer */ 489
436extern fb_data *lcd_framebuffer; 490#ifndef LCD_NATIVE_STRIDE
491/* 2-bit Horz is the only display that actually defines this */
492#define LCD_NATIVE_STRIDE(s) (s)
493#endif
494
495#ifndef LCD_NBELEMS
437#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 496#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
438#define FBADDR(x, y) (lcd_framebuffer + ((x) * LCD_FBHEIGHT) + (y)) 497#define LCD_NBELEMS(w, h) ((w*STRIDE_MAIN(w, h)) + h)
439#else 498#else
440#define FBADDR(x, y) (lcd_framebuffer + ((y) * LCD_FBWIDTH) + (x)) 499#define LCD_NBELEMS(w, h) ((h*STRIDE_MAIN(w, h)) + w)
441#endif 500#endif
501#define LCD_FBSTRIDE(w, h) STRIDE_MAIN(w, h)
502#endif
503
504#ifndef LCD_STRIDE
505 #define LCD_STRIDE(w, h) STRIDE_MAIN(w, h)
506#endif
507
508extern struct viewport* lcd_current_viewport;
509
510#define FBADDR(x,y) ((fb_data*) lcd_current_viewport->buffer->get_address_fn(x, y))
511
442#define FRAMEBUFFER_SIZE (sizeof(fb_data)*LCD_FBWIDTH*LCD_FBHEIGHT) 512#define FRAMEBUFFER_SIZE (sizeof(fb_data)*LCD_FBWIDTH*LCD_FBHEIGHT)
443 513
444/** Port-specific functions. Enable in port config file. **/ 514/** Port-specific functions. Enable in port config file. **/
@@ -499,7 +569,7 @@ struct bitmap {
499 569
500extern void lcd_set_invert_display(bool yesno); 570extern void lcd_set_invert_display(bool yesno);
501#ifdef HAVE_BACKLIGHT_INVERSION 571#ifdef HAVE_BACKLIGHT_INVERSION
502extern void lcd_set_backlight_inversion(bool yesno); 572 extern void lcd_set_backlight_inversion(bool yesno);
503#endif /* HAVE_BACKLIGHT_INVERSION */ 573#endif /* HAVE_BACKLIGHT_INVERSION */
504extern void lcd_set_flip(bool yesno); 574extern void lcd_set_flip(bool yesno);
505 575
@@ -510,13 +580,13 @@ extern int lcd_getfont(void);
510 580
511/* low level drawing function pointer arrays */ 581/* low level drawing function pointer arrays */
512#if LCD_DEPTH >= 8 582#if LCD_DEPTH >= 8
513extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs; 583 extern lcd_fastpixelfunc_type* const *lcd_fastpixelfuncs;
514#elif LCD_DEPTH > 1 584#elif LCD_DEPTH > 1
515extern lcd_pixelfunc_type* const *lcd_pixelfuncs; 585 extern lcd_pixelfunc_type* const *lcd_pixelfuncs;
516extern lcd_blockfunc_type* const *lcd_blockfuncs; 586 extern lcd_blockfunc_type* const *lcd_blockfuncs;
517#else /* LCD_DEPTH == 1*/ 587#else /* LCD_DEPTH == 1*/
518extern lcd_pixelfunc_type* const lcd_pixelfuncs[8]; 588 extern lcd_pixelfunc_type* const lcd_pixelfuncs[8];
519extern lcd_blockfunc_type* const lcd_blockfuncs[8]; 589 extern lcd_blockfunc_type* const lcd_blockfuncs[8];
520#endif /* LCD_DEPTH */ 590#endif /* LCD_DEPTH */
521 591
522extern void lcd_drawpixel(int x, int y); 592extern void lcd_drawpixel(int x, int y);
@@ -526,45 +596,44 @@ extern void lcd_vline(int x, int y1, int y2);
526extern void lcd_drawrect(int x, int y, int width, int height); 596extern void lcd_drawrect(int x, int y, int width, int height);
527extern void lcd_fillrect(int x, int y, int width, int height); 597extern void lcd_fillrect(int x, int y, int width, int height);
528extern void lcd_gradient_fillrect(int x, int y, int width, int height, 598extern void lcd_gradient_fillrect(int x, int y, int width, int height,
529 unsigned start_rgb, unsigned end_rgb); 599 unsigned start_rgb, unsigned end_rgb);
530extern void lcd_gradient_fillrect_part(int x, int y, int width, int height, 600extern void lcd_gradient_fillrect_part(int x, int y, int width, int height,
531 unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip); 601 unsigned start_rgb, unsigned end_rgb, int src_height, int row_skip);
532extern void lcd_draw_border_viewport(void); 602extern void lcd_draw_border_viewport(void);
533extern void lcd_fill_viewport(void); 603extern void lcd_fill_viewport(void);
534extern void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, 604extern void lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
535 int stride, int x, int y, int width, int height); 605 int stride, int x, int y, int width, int height);
536extern void lcd_bitmap(const fb_data *src, int x, int y, int width, 606extern void lcd_bitmap(const fb_data *src, int x, int y, int width,
537 int height); 607 int height);
538extern void lcd_set_framebuffer(fb_data *fb);
539 608
540extern void lcd_scroll_step(int pixels); 609extern void lcd_scroll_step(int pixels);
541 610
542#if LCD_DEPTH > 1 611#if LCD_DEPTH > 1
543extern void lcd_set_foreground(unsigned foreground); 612 extern void lcd_set_foreground(unsigned foreground);
544extern unsigned lcd_get_foreground(void); 613 extern unsigned lcd_get_foreground(void);
545extern void lcd_set_background(unsigned background); 614 extern void lcd_set_background(unsigned background);
546extern unsigned lcd_get_background(void); 615 extern unsigned lcd_get_background(void);
547#ifdef HAVE_LCD_COLOR 616#ifdef HAVE_LCD_COLOR
548extern void lcd_set_selector_start(unsigned selector); 617 extern void lcd_set_selector_start(unsigned selector);
549extern void lcd_set_selector_end(unsigned selector); 618 extern void lcd_set_selector_end(unsigned selector);
550extern void lcd_set_selector_text(unsigned selector_text); 619 extern void lcd_set_selector_text(unsigned selector_text);
551#endif 620#endif
552extern void lcd_set_drawinfo(int mode, unsigned foreground, 621 extern void lcd_set_drawinfo(int mode, unsigned foreground,
553 unsigned background); 622 unsigned background);
554void lcd_set_backdrop(fb_data* backdrop); 623 void lcd_set_backdrop(fb_data* backdrop);
555 624
556fb_data* lcd_get_backdrop(void); 625 fb_data* lcd_get_backdrop(void);
557 626
558extern void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, 627 extern void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
559 int stride, int x, int y, int width, int height); 628 int stride, int x, int y, int width, int height);
560extern void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, 629 extern void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width,
561 int height); 630 int height);
562extern void lcd_bitmap_transparent_part(const fb_data *src, 631 extern void lcd_bitmap_transparent_part(const fb_data *src,
563 int src_x, int src_y, 632 int src_x, int src_y,
564 int stride, int x, int y, int width, 633 int stride, int x, int y, int width,
565 int height); 634 int height);
566extern void lcd_bitmap_transparent(const fb_data *src, int x, int y, 635 extern void lcd_bitmap_transparent(const fb_data *src, int x, int y,
567 int width, int height); 636 int width, int height);
568#else /* LCD_DEPTH == 1 */ 637#else /* LCD_DEPTH == 1 */
569#define lcd_mono_bitmap lcd_bitmap 638#define lcd_mono_bitmap lcd_bitmap
570#define lcd_mono_bitmap_part lcd_bitmap_part 639#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,
577 646
578/* TODO: Impement this for remote displays if ever needed */ 647/* TODO: Impement this for remote displays if ever needed */
579#if defined(LCD_DPI) && (LCD_DPI > 0) 648#if defined(LCD_DPI) && (LCD_DPI > 0)
580/* returns the pixel density of the display */ 649 /* returns the pixel density of the display */
581static inline int lcd_get_dpi(void) { return LCD_DPI; } 650 static inline int lcd_get_dpi(void) { return LCD_DPI; }
582#else 651#else
583extern int lcd_get_dpi(void); 652 extern int lcd_get_dpi(void);
584#endif /* LCD_DPI */ 653#endif /* LCD_DPI */
585 654
586#endif /* __LCD_H__ */ 655#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)
291 291
292 lcd_write_cmd(R_WRITE_DATA_2_GRAM); 292 lcd_write_cmd(R_WRITE_DATA_2_GRAM);
293 293
294 dbop_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); 294 dbop_write_data(FBADDR(0,0), LCD_WIDTH*LCD_HEIGHT);
295} 295}
296 296
297/* Update a fraction of the display. */ 297/* 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)
251 unsigned int addr; 251 unsigned int addr;
252 direct_fb_access = yes; 252 direct_fb_access = yes;
253 if(yes) 253 if(yes)
254 addr = ((unsigned int)&lcd_framebuffer-CONFIG_SDRAM_START) / 32; 254 addr = ((unsigned int)FBADDR(0,0)-CONFIG_SDRAM_START) / 32;
255 else 255 else
256 addr = ((unsigned int)FRAME-CONFIG_SDRAM_START) / 32; 256 addr = ((unsigned int)FRAME-CONFIG_SDRAM_START) / 32;
257 IO_OSD_OSDWINADH = addr >> 16; 257 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)
489#if CONFIG_ORIENTATION == SCREEN_PORTRAIT 489#if CONFIG_ORIENTATION == SCREEN_PORTRAIT
490 490
491#if defined(LCD_USE_DMA) 491#if defined(LCD_USE_DMA)
492 dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_WIDTH, 492 dma_start_transfer16( (char *)FBADDR(0,0), x, y, LCD_WIDTH,
493 x, y, width, height, 2); 493 x, y, width, height, 2);
494#else 494#else
495 register fb_data *dst; 495 register fb_data *dst;
@@ -514,7 +514,7 @@ void lcd_update_rect(int x, int y, int width, int height)
514#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 514#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
515 515
516#if defined(LCD_USE_DMA) 516#if defined(LCD_USE_DMA)
517 dma_start_transfer16( (char *)lcd_framebuffer, x, y, LCD_HEIGHT, 517 dma_start_transfer16( (char *)FBADDR(0,0), x, y, LCD_HEIGHT,
518 x, y, width, height, 2); 518 x, y, width, height, 2);
519#else 519#else
520 fb_data *src; 520 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)
408 lcd_begin_write_gram(); 408 lcd_begin_write_gram();
409 409
410 dma_count = 1; 410 dma_count = 1;
411 SAR3 = (unsigned long)lcd_framebuffer; 411 SAR3 = (unsigned long)FBADDR(0,0);
412 BCR3 = LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data); 412 BCR3 = LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data);
413 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1) 413 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
414 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) 414 | 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)
218 dma_len = LCD_WIDTH*2; 218 dma_len = LCD_WIDTH*2;
219 219
220 /* Initialize DMA transfer */ 220 /* Initialize DMA transfer */
221 SAR3 = (unsigned long)lcd_framebuffer; 221 SAR3 = (unsigned long)FBADDR(0,0);
222 BCR3 = LCD_WIDTH*2; 222 BCR3 = LCD_WIDTH*2;
223 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1) 223 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
224 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) 224 | 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)
83 if (display_on) 83 if (display_on)
84 { 84 {
85 JNIEnv e = *env_ptr; 85 JNIEnv e = *env_ptr;
86 jobject buffer = e->NewDirectByteBuffer(env_ptr, lcd_framebuffer, 86 jobject buffer = e->NewDirectByteBuffer(env_ptr, FBADDR(0,0),
87 (jlong) FRAMEBUFFER_SIZE); 87 (jlong) FRAMEBUFFER_SIZE);
88 88
89 e->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, 89 e->CallVoidMethod(env_ptr, RockboxFramebuffer_instance,
@@ -97,7 +97,7 @@ void lcd_update_rect(int x, int y, int width, int height)
97 if (display_on) 97 if (display_on)
98 { 98 {
99 JNIEnv e = *env_ptr; 99 JNIEnv e = *env_ptr;
100 jobject buffer = e->NewDirectByteBuffer(env_ptr, lcd_framebuffer, 100 jobject buffer = e->NewDirectByteBuffer(env_ptr, FBADDR(0,0),
101 (jlong) FRAMEBUFFER_SIZE); 101 (jlong) FRAMEBUFFER_SIZE);
102 jobject rect = e->NewObject(env_ptr, AndroidRect_class, AndroidRect_constructor, 102 jobject rect = e->NewObject(env_ptr, AndroidRect_class, AndroidRect_constructor,
103 x, y, x + width, y + height); 103 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,
39 (void)max_y; 39 (void)max_y;
40 (void)getpixel; 40 (void)getpixel;
41 /* Update complete screen via one blit operation (fast) */ 41 /* Update complete screen via one blit operation (fast) */
42 SDL_Surface *lcd = SDL_CreateRGBSurfaceFrom(lcd_framebuffer, LCD_FBWIDTH, 42 SDL_Surface *lcd = SDL_CreateRGBSurfaceFrom(FBADDR(0, 0), LCD_FBWIDTH,
43 LCD_FBHEIGHT, LCD_DEPTH, 43 LCD_FBHEIGHT, LCD_DEPTH,
44 LCD_FBWIDTH * LCD_DEPTH/8, 44 LCD_FBWIDTH * LCD_DEPTH/8,
45 0, 0, 0, 0); 45 0, 0, 0, 0);