summaryrefslogtreecommitdiff
path: root/apps/plugins/lib
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2012-12-07 01:50:52 -0500
committerMichael Sevakis <jethead71@rockbox.org>2012-12-18 19:16:26 -0500
commit371c86bf3f4d1708fc40db2aa7fa572eb429d0b4 (patch)
treebe339c62eac616ac6938c2929349b72377c10ee2 /apps/plugins/lib
parentf668c3624184fedc14d34f87ad7b5f1e43bc87a1 (diff)
downloadrockbox-371c86bf3f4d1708fc40db2aa7fa572eb429d0b4.tar.gz
rockbox-371c86bf3f4d1708fc40db2aa7fa572eb429d0b4.zip
Adapt OSD in plugin lib to be greylib compatible.
Requires addition of viewports and alternate framebuffers to greylib which are essentially similar to the core implementation except that the framebuffer can be any size and relationship to a viewport. Drawing is always fully clipped to the intersecting area. Adapt oscilloscope.c to the API change. FFT will use the new features (later update). Get rid of silly and wrong lcd_bmp_part use in OSD. Remove it from plugin API (must be made incompatible now). Change-Id: Iafa5e2174148fb8ad11db6b9d4add0dcabc5c563
Diffstat (limited to 'apps/plugins/lib')
-rw-r--r--apps/plugins/lib/grey.h28
-rw-r--r--apps/plugins/lib/grey_core.c9
-rw-r--r--apps/plugins/lib/grey_draw.c300
-rw-r--r--apps/plugins/lib/grey_parm.c161
-rw-r--r--apps/plugins/lib/grey_scroll.c50
-rw-r--r--apps/plugins/lib/mylcd.h11
-rw-r--r--apps/plugins/lib/osd.c778
-rw-r--r--apps/plugins/lib/osd.h62
8 files changed, 1048 insertions, 351 deletions
diff --git a/apps/plugins/lib/grey.h b/apps/plugins/lib/grey.h
index 7c990ad792..d63d19ee4a 100644
--- a/apps/plugins/lib/grey.h
+++ b/apps/plugins/lib/grey.h
@@ -60,6 +60,16 @@ void grey_release(void);
60void grey_show(bool enable); 60void grey_show(bool enable);
61void grey_deferred_lcd_update(void); 61void grey_deferred_lcd_update(void);
62 62
63/* Viewports and framebuffers */
64void grey_clear_viewport(void);
65void grey_set_viewport(struct viewport *vp);
66void grey_viewport_set_fullscreen(struct viewport *vp,
67 const enum screen_type screen);
68void grey_viewport_set_pos(struct viewport *vp,
69 int x, int y, int width, int height);
70void grey_set_framebuffer(unsigned char *buffer);
71void grey_framebuffer_set_pos(int x, int y, int width, int height);
72
63/* Update functions */ 73/* Update functions */
64void grey_update(void); 74void grey_update(void);
65void grey_update_rect(int x, int y, int width, int height); 75void grey_update_rect(int x, int y, int width, int height);
@@ -175,13 +185,23 @@ struct _grey_info
175 unsigned char *values; /* start of greyscale pixel values */ 185 unsigned char *values; /* start of greyscale pixel values */
176 unsigned char *phases; /* start of greyscale pixel phases */ 186 unsigned char *phases; /* start of greyscale pixel phases */
177 unsigned char *buffer; /* start of chunky pixel buffer (for buffered mode) */ 187 unsigned char *buffer; /* start of chunky pixel buffer (for buffered mode) */
188 unsigned char *curbuffer; /* start of current framebuffer (for buffered mode) */
189 int cb_x; /* horizontal position of current framebuffer (for buffered mode) */
190 int cb_y; /* vertical position of current framebuffer (for buffered mode) */
191 int cb_width; /* width of current framebuffer (for buffered mode) */
192 int cb_height; /* height of current framebuffer (for buffered mode) */
193 int clip_l;
194 int clip_t;
195 int clip_r;
196 int clip_b;
178 unsigned char gvalue[256]; /* calculated brightness -> greyvalue table */ 197 unsigned char gvalue[256]; /* calculated brightness -> greyvalue table */
179 int fg_brightness; /* current foreground brightness */ 198 struct viewport *vp; /* current viewport in use */
180 int bg_brightness; /* current background brightness */
181 int drawmode; /* current draw mode */
182 int curfont; /* current selected font */
183}; 199};
184 200
201/* Stuff these here for now. LCD depth of 1 has no 'pattern' members. */
202#define _GREY_FG_BRIGHTNESS(vp) ((vp)->flags)
203#define _GREY_BG_BRIGHTNESS(vp) ((vp)->line_height)
204
185/* Global variable, defined in the plugin */ 205/* Global variable, defined in the plugin */
186extern struct _grey_info _grey_info; 206extern struct _grey_info _grey_info;
187 207
diff --git a/apps/plugins/lib/grey_core.c b/apps/plugins/lib/grey_core.c
index c2e0747718..047e4cc160 100644
--- a/apps/plugins/lib/grey_core.c
+++ b/apps/plugins/lib/grey_core.c
@@ -677,10 +677,11 @@ bool grey_init(unsigned char *gbuf, long gbuf_size,
677 _grey_info.bheight = bdim; 677 _grey_info.bheight = bdim;
678#endif 678#endif
679 _grey_info.flags = features & 0xff; 679 _grey_info.flags = features & 0xff;
680 _grey_info.fg_brightness = 0; 680
681 _grey_info.bg_brightness = 255; 681 /* default viewport and settings */
682 _grey_info.drawmode = DRMODE_SOLID; 682 grey_set_viewport(NULL);
683 _grey_info.curfont = FONT_SYSFIXED; 683 grey_viewport_set_fullscreen(NULL, SCREEN_MAIN);
684 grey_set_framebuffer(NULL);
684 685
685 /* precalculate the value -> pattern index conversion table, taking 686 /* precalculate the value -> pattern index conversion table, taking
686 linearisation and gamma correction into account */ 687 linearisation and gamma correction into account */
diff --git a/apps/plugins/lib/grey_draw.c b/apps/plugins/lib/grey_draw.c
index 3b81694426..171d2734cf 100644
--- a/apps/plugins/lib/grey_draw.c
+++ b/apps/plugins/lib/grey_draw.c
@@ -28,16 +28,18 @@
28#include "plugin.h" 28#include "plugin.h"
29#include "grey.h" 29#include "grey.h"
30 30
31extern struct viewport _grey_default_vp;
32
31/*** low-level drawing functions ***/ 33/*** low-level drawing functions ***/
32 34
33static void setpixel(unsigned char *address) 35static void setpixel(unsigned char *address)
34{ 36{
35 *address = _grey_info.fg_brightness; 37 *address = _GREY_FG_BRIGHTNESS(_grey_info.vp);
36} 38}
37 39
38static void clearpixel(unsigned char *address) 40static void clearpixel(unsigned char *address)
39{ 41{
40 *address = _grey_info.bg_brightness; 42 *address = _GREY_BG_BRIGHTNESS(_grey_info.vp);
41} 43}
42 44
43static void flippixel(unsigned char *address) 45static void flippixel(unsigned char *address)
@@ -57,35 +59,56 @@ void (* const _grey_pixelfuncs[8])(unsigned char *address) = {
57 59
58/*** Drawing functions ***/ 60/*** Drawing functions ***/
59 61
62/* Clear the current viewport */
63void grey_clear_viewport(void)
64{
65 struct viewport *vp = _grey_info.vp;
66 int drawmode = vp->drawmode;
67 vp->drawmode = DRMODE_SOLID | DRMODE_INVERSEVID;
68 grey_fillrect(0, 0, vp->width, vp->height);
69 vp->drawmode = drawmode;
70}
71
60/* Clear the whole display */ 72/* Clear the whole display */
61void grey_clear_display(void) 73void grey_clear_display(void)
62{ 74{
63 int value = (_grey_info.drawmode & DRMODE_INVERSEVID) ? 75 struct viewport *vp = &_grey_default_vp;
64 _grey_info.fg_brightness : _grey_info.bg_brightness;
65 76
66 rb->memset(_grey_info.buffer, value, 77 int value = (vp->drawmode & DRMODE_INVERSEVID) ?
67 _GREY_MULUQ(_grey_info.width, _grey_info.height)); 78 _GREY_FG_BRIGHTNESS(vp) : _GREY_BG_BRIGHTNESS(vp);
79
80 rb->memset(_grey_info.curbuffer, value,
81 _GREY_MULUQ(_grey_info.cb_width, _grey_info.cb_height));
68} 82}
69 83
70/* Set a single pixel */ 84/* Set a single pixel */
71void grey_drawpixel(int x, int y) 85void grey_drawpixel(int x, int y)
72{ 86{
73 if (((unsigned)x < (unsigned)_grey_info.width) 87 if (x >= _grey_info.clip_l && x < _grey_info.clip_r &&
74 && ((unsigned)y < (unsigned)_grey_info.height)) 88 y >= _grey_info.clip_t && y < _grey_info.clip_b)
75 _grey_pixelfuncs[_grey_info.drawmode](&_grey_info.buffer[_GREY_MULUQ( 89 {
76 _grey_info.width, y) + x]); 90 int dst_stride = _grey_info.cb_width;
91 struct viewport *vp = _grey_info.vp;
92 _grey_pixelfuncs[vp->drawmode](
93 &_grey_info.curbuffer[
94 _GREY_MULUQ(dst_stride, vp->y - _grey_info.cb_y + y) +
95 vp->x - _grey_info.cb_x + x]);
96 }
77} 97}
78 98
79/* Draw a line */ 99/* Draw a line */
80void grey_drawline(int x1, int y1, int x2, int y2) 100void grey_drawline(int x1, int y1, int x2, int y2)
81{ 101{
102 struct viewport *vp = _grey_info.vp;
82 int numpixels; 103 int numpixels;
83 int i; 104 int i;
84 int deltax, deltay; 105 int deltax, deltay;
85 int d, dinc1, dinc2; 106 int d, dinc1, dinc2;
86 int x, xinc1, xinc2; 107 int x, xinc1, xinc2;
87 int y, yinc1, yinc2; 108 int y, yinc1, yinc2;
88 void (*pfunc)(unsigned char *address) = _grey_pixelfuncs[_grey_info.drawmode]; 109 void (*pfunc)(unsigned char *address) = _grey_pixelfuncs[vp->drawmode];
110 int dwidth;
111 int xoffs, yoffs;
89 112
90 deltax = abs(x2 - x1); 113 deltax = abs(x2 - x1);
91 deltay = abs(y2 - y1); 114 deltay = abs(y2 - y1);
@@ -127,11 +150,18 @@ void grey_drawline(int x1, int y1, int x2, int y2)
127 x = x1; 150 x = x1;
128 y = y1; 151 y = y1;
129 152
153 dwidth = _grey_info.cb_width;
154 xoffs = vp->x - _grey_info.cb_x;
155 yoffs = vp->y - _grey_info.cb_y;
156
130 for (i = 0; i < numpixels; i++) 157 for (i = 0; i < numpixels; i++)
131 { 158 {
132 if (((unsigned)x < (unsigned)_grey_info.width) 159 if (x >= _grey_info.clip_l && x < _grey_info.clip_r &&
133 && ((unsigned)y < (unsigned)_grey_info.height)) 160 y >= _grey_info.clip_t && y < _grey_info.clip_b)
134 pfunc(&_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]); 161 {
162 pfunc(&_grey_info.curbuffer[_GREY_MULUQ(dwidth, yoffs + y) +
163 xoffs + x]);
164 }
135 165
136 if (d < 0) 166 if (d < 0)
137 { 167 {
@@ -151,10 +181,12 @@ void grey_drawline(int x1, int y1, int x2, int y2)
151/* Draw a horizontal line (optimised) */ 181/* Draw a horizontal line (optimised) */
152void grey_hline(int x1, int x2, int y) 182void grey_hline(int x1, int x2, int y)
153{ 183{
184 struct viewport *vp = _grey_info.vp;
154 int x; 185 int x;
155 int value = 0; 186 int value = 0;
156 unsigned char *dst; 187 unsigned char *dst;
157 bool fillopt = false; 188 bool fillopt = false;
189 int dwidth;
158 190
159 /* direction flip */ 191 /* direction flip */
160 if (x2 < x1) 192 if (x2 < x1)
@@ -165,37 +197,40 @@ void grey_hline(int x1, int x2, int y)
165 } 197 }
166 198
167 /* nothing to draw? */ 199 /* nothing to draw? */
168 if (((unsigned)y >= (unsigned)_grey_info.height) 200 if (y < _grey_info.clip_t || y >= _grey_info.clip_b ||
169 || (x1 >= _grey_info.width) || (x2 < 0)) 201 x1 >= _grey_info.clip_r || x2 < _grey_info.clip_l)
170 return; 202 return;
171 203
172 /* drawmode and optimisation */ 204 /* drawmode and optimisation */
173 if (_grey_info.drawmode & DRMODE_INVERSEVID) 205 if (vp->drawmode & DRMODE_INVERSEVID)
174 { 206 {
175 if (_grey_info.drawmode & DRMODE_BG) 207 if (vp->drawmode & DRMODE_BG)
176 { 208 {
177 fillopt = true; 209 fillopt = true;
178 value = _grey_info.bg_brightness; 210 value = _GREY_BG_BRIGHTNESS(vp);
179 } 211 }
180 } 212 }
181 else 213 else
182 { 214 {
183 if (_grey_info.drawmode & DRMODE_FG) 215 if (vp->drawmode & DRMODE_FG)
184 { 216 {
185 fillopt = true; 217 fillopt = true;
186 value = _grey_info.fg_brightness; 218 value = _GREY_FG_BRIGHTNESS(vp);
187 } 219 }
188 } 220 }
189 if (!fillopt && _grey_info.drawmode != DRMODE_COMPLEMENT) 221 if (!fillopt && vp->drawmode != DRMODE_COMPLEMENT)
190 return; 222 return;
191 223
192 /* clipping */ 224 /* clipping */
193 if (x1 < 0) 225 if (x1 < _grey_info.clip_l)
194 x1 = 0; 226 x1 = _grey_info.clip_l;
195 if (x2 >= _grey_info.width) 227 if (x2 >= _grey_info.clip_r)
196 x2 = _grey_info.width - 1; 228 x2 = _grey_info.clip_r - 1;
197 229
198 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x1]; 230 dwidth = _grey_info.cb_width;
231 dst = &_grey_info.curbuffer[
232 _GREY_MULUQ(dwidth, vp->y - _grey_info.cb_y + y) +
233 vp->x - _grey_info.cb_x + x1];
199 234
200 if (fillopt) 235 if (fillopt)
201 rb->memset(dst, value, x2 - x1 + 1); 236 rb->memset(dst, value, x2 - x1 + 1);
@@ -211,9 +246,11 @@ void grey_hline(int x1, int x2, int y)
211/* Draw a vertical line (optimised) */ 246/* Draw a vertical line (optimised) */
212void grey_vline(int x, int y1, int y2) 247void grey_vline(int x, int y1, int y2)
213{ 248{
249 struct viewport *vp = _grey_info.vp;
214 int y; 250 int y;
215 unsigned char *dst, *dst_end; 251 unsigned char *dst, *dst_end;
216 void (*pfunc)(unsigned char *address); 252 void (*pfunc)(unsigned char *address);
253 int dwidth;
217 254
218 /* direction flip */ 255 /* direction flip */
219 if (y2 < y1) 256 if (y2 < y1)
@@ -224,24 +261,27 @@ void grey_vline(int x, int y1, int y2)
224 } 261 }
225 262
226 /* nothing to draw? */ 263 /* nothing to draw? */
227 if (((unsigned)x >= (unsigned)_grey_info.width) 264 if (x < _grey_info.clip_l || x >= _grey_info.clip_r ||
228 || (y1 >= _grey_info.height) || (y2 < 0)) 265 y1 >= _grey_info.clip_b || y2 < _grey_info.clip_t)
229 return; 266 return;
230 267
231 /* clipping */ 268 /* clipping */
232 if (y1 < 0) 269 if (y1 < _grey_info.clip_t)
233 y1 = 0; 270 y1 = _grey_info.clip_t;
234 if (y2 >= _grey_info.height) 271 if (y2 >= _grey_info.clip_b)
235 y2 = _grey_info.height - 1; 272 y2 = _grey_info.clip_b - 1;
236 273
237 pfunc = _grey_pixelfuncs[_grey_info.drawmode]; 274 dwidth = _grey_info.cb_width;
238 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y1) + x]; 275 pfunc = _grey_pixelfuncs[vp->drawmode];
239 276 dst = &_grey_info.curbuffer[
240 dst_end = dst + _GREY_MULUQ(_grey_info.width, y2 - y1); 277 _GREY_MULUQ(dwidth, vp->y - _grey_info.cb_y + y1) +
278 vp->x - _grey_info.cb_x + x];
279
280 dst_end = dst + _GREY_MULUQ(dwidth, y2 - y1);
241 do 281 do
242 { 282 {
243 pfunc(dst); 283 pfunc(dst);
244 dst += _grey_info.width; 284 dst += dwidth;
245 } 285 }
246 while (dst <= dst_end); 286 while (dst <= dst_end);
247} 287}
@@ -334,53 +374,63 @@ void grey_drawrect(int x, int y, int width, int height)
334/* Fill a rectangular area */ 374/* Fill a rectangular area */
335void grey_fillrect(int x, int y, int width, int height) 375void grey_fillrect(int x, int y, int width, int height)
336{ 376{
377 struct viewport *vp = _grey_info.vp;
337 int value = 0; 378 int value = 0;
338 unsigned char *dst, *dst_end; 379 unsigned char *dst, *dst_end;
339 bool fillopt = false; 380 bool fillopt = false;
340 381 int dwidth;
341 /* nothing to draw? */
342 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
343 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
344 return;
345 382
346 /* drawmode and optimisation */ 383 /* drawmode and optimisation */
347 if (_grey_info.drawmode & DRMODE_INVERSEVID) 384 if (vp->drawmode & DRMODE_INVERSEVID)
348 { 385 {
349 if (_grey_info.drawmode & DRMODE_BG) 386 if (vp->drawmode & DRMODE_BG)
350 { 387 {
351 fillopt = true; 388 fillopt = true;
352 value = _grey_info.bg_brightness; 389 value = _GREY_BG_BRIGHTNESS(vp);
353 } 390 }
354 } 391 }
355 else 392 else
356 { 393 {
357 if (_grey_info.drawmode & DRMODE_FG) 394 if (vp->drawmode & DRMODE_FG)
358 { 395 {
359 fillopt = true; 396 fillopt = true;
360 value = _grey_info.fg_brightness; 397 value = _GREY_FG_BRIGHTNESS(vp);
398
361 } 399 }
362 } 400 }
363 if (!fillopt && _grey_info.drawmode != DRMODE_COMPLEMENT) 401 if (!fillopt && vp->drawmode != DRMODE_COMPLEMENT)
364 return; 402 return;
365 403
366 /* clipping */ 404 /* clipping */
367 if (x < 0) 405 if (x < _grey_info.clip_l)
368 { 406 {
369 width += x; 407 width += x - _grey_info.clip_l;
370 x = 0; 408 x = _grey_info.clip_l;
371 } 409 }
372 if (y < 0) 410
411 if (x + width > _grey_info.clip_r)
412 width = _grey_info.clip_r - x;
413
414 if (width <= 0)
415 return;
416
417 if (y < _grey_info.clip_t)
373 { 418 {
374 height += y; 419 height += y - _grey_info.clip_t;
375 y = 0; 420 y = _grey_info.clip_t;
376 } 421 }
377 if (x + width > _grey_info.width) 422
378 width = _grey_info.width - x; 423 if (y + height > _grey_info.clip_b)
379 if (y + height > _grey_info.height) 424 height = _grey_info.clip_b - y;
380 height = _grey_info.height - y; 425
426 if (height <= 0)
427 return;
381 428
382 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; 429 dwidth = _grey_info.cb_width;
383 dst_end = dst + _GREY_MULUQ(_grey_info.width, height); 430 dst = &_grey_info.curbuffer[
431 _GREY_MULUQ(dwidth, _grey_info.vp->y - _grey_info.cb_y + y) +
432 _grey_info.vp->x - _grey_info.cb_x + x];
433 dst_end = dst + _GREY_MULUQ(dwidth, height);
384 434
385 do 435 do
386 { 436 {
@@ -395,7 +445,7 @@ void grey_fillrect(int x, int y, int width, int height)
395 *dst_row = ~(*dst_row); 445 *dst_row = ~(*dst_row);
396 while (++dst_row < row_end); 446 while (++dst_row < row_end);
397 } 447 }
398 dst += _grey_info.width; 448 dst += dwidth;
399 } 449 }
400 while (dst < dst_end); 450 while (dst < dst_end);
401} 451}
@@ -413,40 +463,49 @@ void grey_fillrect(int x, int y, int width, int height)
413void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, 463void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
414 int stride, int x, int y, int width, int height) 464 int stride, int x, int y, int width, int height)
415{ 465{
466 struct viewport *vp = _grey_info.vp;
416 const unsigned char *src_end; 467 const unsigned char *src_end;
417 unsigned char *dst, *dst_end; 468 unsigned char *dst, *dst_end;
418 unsigned dmask = 0x100; /* bit 8 == sentinel */ 469 unsigned dmask = 0x100; /* bit 8 == sentinel */
419 int drmode = _grey_info.drawmode; 470 int drmode = vp->drawmode;
420 int dwidth; 471 int dwidth;
421 472
422 /* nothing to draw? */
423 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
424 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
425 return;
426
427 /* clipping */ 473 /* clipping */
428 if (x < 0) 474 if (x < _grey_info.clip_l)
429 { 475 {
430 width += x; 476 int dx = x - _grey_info.clip_l;
431 src_x -= x; 477 width += dx;
432 x = 0; 478 src_x -= dx;
479 x = _grey_info.clip_l;
433 } 480 }
434 if (y < 0) 481
482 if (x + width > _grey_info.clip_r)
483 width = _grey_info.clip_r - x;
484
485 if (width <= 0)
486 return;
487
488 if (y < _grey_info.clip_t)
435 { 489 {
436 height += y; 490 int dy = y - _grey_info.clip_t;
437 src_y -= y; 491 height += dy;
438 y = 0; 492 src_y += dy;
493 y = _grey_info.clip_t;
439 } 494 }
440 if (x + width > _grey_info.width) 495
441 width = _grey_info.width - x; 496 if (y + height > _grey_info.clip_b)
442 if (y + height > _grey_info.height) 497 height = _grey_info.clip_b - y;
443 height = _grey_info.height - y; 498
499 if (height <= 0)
500 return;
444 501
445 src += _GREY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */ 502 src += _GREY_MULUQ(stride, src_y >> 3) + src_x; /* move starting point */
446 src_y &= 7; 503 src_y &= 7;
447 src_end = src + width; 504 src_end = src + width;
448 dwidth = _grey_info.width; 505 dwidth = _grey_info.cb_width;
449 dst = &_grey_info.buffer[_GREY_MULUQ(dwidth, y) + x]; 506 dst = &_grey_info.curbuffer[
507 _GREY_MULUQ(dwidth, vp->y - _grey_info.cb_y + y) +
508 vp->x - _grey_info.cb_x + x];
450 dst_end = dst + _GREY_MULUQ(dwidth, height); 509 dst_end = dst + _GREY_MULUQ(dwidth, height);
451 510
452 if (drmode & DRMODE_INVERSEVID) 511 if (drmode & DRMODE_INVERSEVID)
@@ -485,7 +544,7 @@ void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
485 break; 544 break;
486 545
487 case DRMODE_BG: 546 case DRMODE_BG:
488 bg = _grey_info.bg_brightness; 547 bg = _GREY_BG_BRIGHTNESS(vp);
489 do 548 do
490 { 549 {
491 if (!(data & 0x01)) 550 if (!(data & 0x01))
@@ -498,7 +557,7 @@ void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
498 break; 557 break;
499 558
500 case DRMODE_FG: 559 case DRMODE_FG:
501 fg = _grey_info.fg_brightness; 560 fg = _GREY_FG_BRIGHTNESS(vp);
502 do 561 do
503 { 562 {
504 if (data & 0x01) 563 if (data & 0x01)
@@ -511,8 +570,8 @@ void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
511 break; 570 break;
512 571
513 case DRMODE_SOLID: 572 case DRMODE_SOLID:
514 fg = _grey_info.fg_brightness; 573 fg = _GREY_FG_BRIGHTNESS(vp);
515 bg = _grey_info.bg_brightness; 574 bg = _GREY_BG_BRIGHTNESS(vp);
516 do 575 do
517 { 576 {
518 *dst_col = (data & 0x01) ? fg : bg; 577 *dst_col = (data & 0x01) ? fg : bg;
@@ -537,38 +596,48 @@ void grey_gray_bitmap_part(const unsigned char *src, int src_x, int src_y,
537 int stride, int x, int y, int width, int height) 596 int stride, int x, int y, int width, int height)
538{ 597{
539 unsigned char *dst, *dst_end; 598 unsigned char *dst, *dst_end;
540 599 int dwidth;
541 /* nothing to draw? */
542 if ((width <= 0) || (height <= 0) || (x >= _grey_info.width)
543 || (y >= _grey_info.height) || (x + width <= 0) || (y + height <= 0))
544 return;
545 600
546 /* clipping */ 601 /* clipping */
547 if (x < 0) 602 if (x < _grey_info.clip_l)
548 { 603 {
549 width += x; 604 int dx = x - _grey_info.clip_l;
550 src_x -= x; 605 width += dx;
551 x = 0; 606 src_x -= dx;
607 x = _grey_info.clip_l;
552 } 608 }
609
610 if (x + width > _grey_info.clip_r)
611 width = _grey_info.clip_r - x;
612
613 if (width <= 0)
614 return;
615
553 if (y < 0) 616 if (y < 0)
554 { 617 {
555 height += y; 618 int dy = y - _grey_info.clip_t;
556 src_y -= y; 619 height += dy;
557 y = 0; 620 src_y -= dy;
621 y = _grey_info.clip_t;
558 } 622 }
559 if (x + width > _grey_info.width)
560 width = _grey_info.width - x;
561 if (y + height > _grey_info.height)
562 height = _grey_info.height - y;
563 623
564 src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */ 624 if (y + height > _grey_info.clip_b)
565 dst = &_grey_info.buffer[_GREY_MULUQ(_grey_info.width, y) + x]; 625 height = _grey_info.clip_b - y;
566 dst_end = dst + _GREY_MULUQ(_grey_info.width, height); 626
627 if (height <= 0)
628 return;
629
630 dwidth = _grey_info.cb_width;
631 src += _GREY_MULUQ(stride, src_y) + src_x; /* move starting point */
632 dst = &_grey_info.curbuffer[
633 _GREY_MULUQ(dwidth, _grey_info.vp->y - _grey_info.cb_y + y) +
634 _grey_info.vp->x - _grey_info.cb_x + x];
635 dst_end = dst + _GREY_MULUQ(dwidth, height);
567 636
568 do 637 do
569 { 638 {
570 rb->memcpy(dst, src, width); 639 rb->memcpy(dst, src, width);
571 dst += _grey_info.width; 640 dst += dwidth;
572 src += stride; 641 src += stride;
573 } 642 }
574 while (dst < dst_end); 643 while (dst < dst_end);
@@ -586,11 +655,15 @@ void grey_putsxyofs(int x, int y, int ofs, const unsigned char *str)
586{ 655{
587 int ch; 656 int ch;
588 unsigned short *ucs; 657 unsigned short *ucs;
589 struct font* pf = rb->font_get(_grey_info.curfont); 658 struct font* pf;
590 659
660 if (_grey_info.clip_b <= _grey_info.clip_t)
661 return;
662
663 pf = rb->font_get(_grey_info.vp->font);
591 ucs = rb->bidi_l2v(str, 1); 664 ucs = rb->bidi_l2v(str, 1);
592 665
593 while ((ch = *ucs++) != 0 && x < _grey_info.width) 666 while ((ch = *ucs++) != 0 && x < _grey_info.clip_r)
594 { 667 {
595 int width; 668 int width;
596 const unsigned char *bits; 669 const unsigned char *bits;
@@ -624,9 +697,10 @@ void grey_putsxy(int x, int y, const unsigned char *str)
624/* Clear the greyscale display (sets all pixels to white) */ 697/* Clear the greyscale display (sets all pixels to white) */
625void grey_ub_clear_display(void) 698void grey_ub_clear_display(void)
626{ 699{
627 int value = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? 700 struct viewport *vp = &_grey_default_vp;
628 _grey_info.fg_brightness : 701 int value = _grey_info.gvalue[(vp->drawmode & DRMODE_INVERSEVID) ?
629 _grey_info.bg_brightness]; 702 _GREY_FG_BRIGHTNESS(vp) :
703 _GREY_BG_BRIGHTNESS(vp)];
630 704
631 rb->memset(_grey_info.values, value, 705 rb->memset(_grey_info.values, value,
632 _GREY_MULUQ(_grey_info.width, _grey_info.height)); 706 _GREY_MULUQ(_grey_info.width, _grey_info.height));
diff --git a/apps/plugins/lib/grey_parm.c b/apps/plugins/lib/grey_parm.c
index 00193e12f2..9b4ba8c5f6 100644
--- a/apps/plugins/lib/grey_parm.c
+++ b/apps/plugins/lib/grey_parm.c
@@ -28,6 +28,9 @@
28#include "plugin.h" 28#include "plugin.h"
29#include "grey.h" 29#include "grey.h"
30 30
31/* Default greylib viewport struct */
32struct viewport _grey_default_vp;
33
31/* Set position of the top left corner of the greyscale overlay 34/* Set position of the top left corner of the greyscale overlay
32 Note that depending on the target LCD, either x or y gets rounded 35 Note that depending on the target LCD, either x or y gets rounded
33 to the nearest multiple of 4 or 8 */ 36 to the nearest multiple of 4 or 8 */
@@ -64,37 +67,37 @@ void grey_set_position(int x, int y)
64/* Set the draw mode for subsequent drawing operations */ 67/* Set the draw mode for subsequent drawing operations */
65void grey_set_drawmode(int mode) 68void grey_set_drawmode(int mode)
66{ 69{
67 _grey_info.drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 70 _grey_info.vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
68} 71}
69 72
70/* Return the current draw mode */ 73/* Return the current draw mode */
71int grey_get_drawmode(void) 74int grey_get_drawmode(void)
72{ 75{
73 return _grey_info.drawmode; 76 return _grey_info.vp->drawmode;
74} 77}
75 78
76/* Set the foreground shade for subsequent drawing operations */ 79/* Set the foreground shade for subsequent drawing operations */
77void grey_set_foreground(unsigned brightness) 80void grey_set_foreground(unsigned brightness)
78{ 81{
79 _grey_info.fg_brightness = brightness; 82 _GREY_FG_BRIGHTNESS(_grey_info.vp) = brightness;
80} 83}
81 84
82/* Return the current foreground shade */ 85/* Return the current foreground shade */
83unsigned grey_get_foreground(void) 86unsigned grey_get_foreground(void)
84{ 87{
85 return _grey_info.fg_brightness; 88 return _GREY_FG_BRIGHTNESS(_grey_info.vp);
86} 89}
87 90
88/* Set the background shade for subsequent drawing operations */ 91/* Set the background shade for subsequent drawing operations */
89void grey_set_background(unsigned brightness) 92void grey_set_background(unsigned brightness)
90{ 93{
91 _grey_info.bg_brightness = brightness; 94 _GREY_BG_BRIGHTNESS(_grey_info.vp) = brightness;
92} 95}
93 96
94/* Return the current background shade */ 97/* Return the current background shade */
95unsigned grey_get_background(void) 98unsigned grey_get_background(void)
96{ 99{
97 return _grey_info.bg_brightness; 100 return _GREY_BG_BRIGHTNESS(_grey_info.vp);
98} 101}
99 102
100/* Set draw mode, foreground and background shades at once */ 103/* Set draw mode, foreground and background shades at once */
@@ -108,11 +111,151 @@ void grey_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness)
108/* Set font for the text output routines */ 111/* Set font for the text output routines */
109void grey_setfont(int newfont) 112void grey_setfont(int newfont)
110{ 113{
111 _grey_info.curfont = newfont; 114 _grey_info.vp->font = newfont;
112} 115}
113 116
114/* Get width and height of a text when printed with the current font */ 117/* Get width and height of a text when printed with the current font */
115int grey_getstringsize(const unsigned char *str, int *w, int *h) 118int grey_getstringsize(const unsigned char *str, int *w, int *h)
119{
120 return rb->font_getstringsize(str, w, h, _grey_info.vp->font);
121}
122
123/* Helper to establish visible area between viewport and framebuffer */
124static void grey_update_clip_rect(void)
125{
126 if (!(_grey_info.flags & GREY_BUFFERED))
127 return; /* no chunky buffer */
128
129 struct viewport *vp = _grey_info.vp;
130
131 if (!vp || !_grey_info.curbuffer)
132 return;
133
134 /* Get overall intersection of framebuffer and viewport in viewport
135 coordinates so that later clipping of drawing is kept as simple as
136 possible. If l <= r and/or b <= t after intersecting, draw routines
137 will see this as an empty area. */
138 _grey_info.clip_l = _grey_info.cb_x - vp->x;
139 _grey_info.clip_t = _grey_info.cb_y - vp->y;
140 _grey_info.clip_r = _grey_info.clip_l + _grey_info.cb_width;
141 _grey_info.clip_b = _grey_info.clip_t + _grey_info.cb_height;
142
143 if (_grey_info.clip_l < 0)
144 _grey_info.clip_l = 0;
145
146 if (_grey_info.clip_t < 0)
147 _grey_info.clip_t = 0;
148
149 if (_grey_info.clip_r > vp->width)
150 _grey_info.clip_r = vp->width;
151
152 if (_grey_info.clip_b > vp->height)
153 _grey_info.clip_b = vp->height;
154}
155
156/* Set current grey viewport for draw routines */
157void grey_set_viewport(struct viewport *vp)
158{
159 if (vp == NULL)
160 vp = &_grey_default_vp;
161
162 if (_grey_info.vp != vp)
163 {
164 _grey_info.vp = vp;
165 grey_update_clip_rect();
166 }
167}
168
169/* Set viewport to default settings */
170void grey_viewport_set_fullscreen(struct viewport *vp,
171 const enum screen_type screen)
172{
173 if (vp == NULL)
174 vp = &_grey_default_vp;
175
176 vp->x = 0;
177 vp->y = 0;
178 vp->width = _grey_info.width;
179 vp->height = _grey_info.height;
180 _GREY_FG_BRIGHTNESS(vp) = 0;
181 _GREY_BG_BRIGHTNESS(vp) = 255;
182 vp->drawmode = DRMODE_SOLID;
183 vp->font = FONT_SYSFIXED;
184
185 if (vp == _grey_info.vp)
186 grey_update_clip_rect(); /* is current one in use */
187
188 (void)screen;
189}
190
191void grey_viewport_set_pos(struct viewport *vp,
192 int x, int y, int width, int height)
193{
194 if (vp == NULL || vp == &_grey_default_vp)
195 return; /* Cannot be moved or resized */
196
197 if (width < 0)
198 width = 0; /* 'tis okay */
199
200 if (height < 0)
201 height = 0;
202
203 vp->x = x;
204 vp->y = y;
205 vp->width = width;
206 vp->height = height;
207
208 if (vp == _grey_info.vp)
209 grey_update_clip_rect(); /* is current one in use */
210}
211
212/* Set current grey chunky buffer for draw routines */
213void grey_set_framebuffer(unsigned char *buffer)
214{
215 if (!(_grey_info.flags & GREY_BUFFERED))
216 return; /* no chunky buffer */
217
218 if (buffer == NULL)
219 buffer = _grey_info.buffer; /* Default */
220
221 if (buffer != _grey_info.curbuffer)
222 {
223 _grey_info.curbuffer = buffer;
224
225 if (buffer == _grey_info.buffer)
226 {
227 /* Setting to default fb resets dimensions */
228 grey_framebuffer_set_pos(0, 0, 0, 0);
229 }
230 }
231}
232
233/* Specify the dimensions of the current framebuffer */
234void grey_framebuffer_set_pos(int x, int y, int width, int height)
116{ 235{
117 return rb->font_getstringsize(str, w, h, _grey_info.curfont); 236 if (!(_grey_info.flags & GREY_BUFFERED))
237 return; /* no chunky buffer */
238
239 if (_grey_info.curbuffer == _grey_info.buffer)
240 {
241 /* This cannot be moved or resized */
242 x = 0;
243 y = 0;
244 width = _grey_info.width;
245 height = _grey_info.height;
246 }
247 else if (width <= 0 || height <= 0)
248 return;
249
250 if (x == _grey_info.cb_x && y == _grey_info.cb_y &&
251 width == _grey_info.cb_width && height == _grey_info.cb_height)
252 return; /* No change */
253
254 _grey_info.cb_x = x;
255 _grey_info.cb_y = y;
256 _grey_info.cb_width = width;
257 _grey_info.cb_height = height;
258
259 grey_update_clip_rect();
118} 260}
261
diff --git a/apps/plugins/lib/grey_scroll.c b/apps/plugins/lib/grey_scroll.c
index 35f73b70c4..78e5725d05 100644
--- a/apps/plugins/lib/grey_scroll.c
+++ b/apps/plugins/lib/grey_scroll.c
@@ -28,11 +28,14 @@
28#include "plugin.h" 28#include "plugin.h"
29#include "grey.h" 29#include "grey.h"
30 30
31extern struct viewport _grey_default_vp;
32
31/*** Scrolling ***/ 33/*** Scrolling ***/
32 34
33/* Scroll left */ 35/* Scroll left */
34void grey_scroll_left(int count) 36void grey_scroll_left(int count)
35{ 37{
38 struct viewport *vp = &_grey_default_vp;
36 unsigned char *data, *data_end; 39 unsigned char *data, *data_end;
37 int length, blank; 40 int length, blank;
38 41
@@ -45,8 +48,8 @@ void grey_scroll_left(int count)
45 data = _grey_info.buffer; 48 data = _grey_info.buffer;
46 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); 49 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
47 length = _grey_info.width - count; 50 length = _grey_info.width - count;
48 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? 51 blank = (vp->drawmode & DRMODE_INVERSEVID) ?
49 _grey_info.fg_brightness : _grey_info.bg_brightness; 52 _GREY_FG_BRIGHTNESS(vp) : _GREY_BG_BRIGHTNESS(vp);
50 53
51 do 54 do
52 { 55 {
@@ -61,6 +64,7 @@ void grey_scroll_left(int count)
61/* Scroll right */ 64/* Scroll right */
62void grey_scroll_right(int count) 65void grey_scroll_right(int count)
63{ 66{
67 struct viewport *vp = &_grey_default_vp;
64 unsigned char *data, *data_end; 68 unsigned char *data, *data_end;
65 int length, blank; 69 int length, blank;
66 70
@@ -73,8 +77,8 @@ void grey_scroll_right(int count)
73 data = _grey_info.buffer; 77 data = _grey_info.buffer;
74 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); 78 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
75 length = _grey_info.width - count; 79 length = _grey_info.width - count;
76 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? 80 blank = (vp->drawmode & DRMODE_INVERSEVID) ?
77 _grey_info.fg_brightness : _grey_info.bg_brightness; 81 _GREY_FG_BRIGHTNESS(vp) : _GREY_BG_BRIGHTNESS(vp);
78 82
79 do 83 do
80 { 84 {
@@ -88,6 +92,7 @@ void grey_scroll_right(int count)
88/* Scroll up */ 92/* Scroll up */
89void grey_scroll_up(int count) 93void grey_scroll_up(int count)
90{ 94{
95 struct viewport *vp = &_grey_default_vp;
91 long shift, length; 96 long shift, length;
92 int blank; 97 int blank;
93 98
@@ -99,8 +104,8 @@ void grey_scroll_up(int count)
99 104
100 shift = _GREY_MULUQ(_grey_info.width, count); 105 shift = _GREY_MULUQ(_grey_info.width, count);
101 length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count); 106 length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count);
102 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? 107 blank = (vp->drawmode & DRMODE_INVERSEVID) ?
103 _grey_info.fg_brightness : _grey_info.bg_brightness; 108 _GREY_FG_BRIGHTNESS(vp) : _GREY_BG_BRIGHTNESS(vp);
104 109
105 rb->memmove(_grey_info.buffer, _grey_info.buffer + shift, 110 rb->memmove(_grey_info.buffer, _grey_info.buffer + shift,
106 length); 111 length);
@@ -110,6 +115,7 @@ void grey_scroll_up(int count)
110/* Scroll down */ 115/* Scroll down */
111void grey_scroll_down(int count) 116void grey_scroll_down(int count)
112{ 117{
118 struct viewport *vp = &_grey_default_vp;
113 long shift, length; 119 long shift, length;
114 int blank; 120 int blank;
115 121
@@ -121,8 +127,8 @@ void grey_scroll_down(int count)
121 127
122 shift = _GREY_MULUQ(_grey_info.width, count); 128 shift = _GREY_MULUQ(_grey_info.width, count);
123 length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count); 129 length = _GREY_MULUQ(_grey_info.width, _grey_info.height - count);
124 blank = (_grey_info.drawmode & DRMODE_INVERSEVID) ? 130 blank = (vp->drawmode & DRMODE_INVERSEVID) ?
125 _grey_info.fg_brightness : _grey_info.bg_brightness; 131 _GREY_FG_BRIGHTNESS(vp) : _GREY_BG_BRIGHTNESS(vp);
126 132
127 rb->memmove(_grey_info.buffer + shift, _grey_info.buffer, 133 rb->memmove(_grey_info.buffer + shift, _grey_info.buffer,
128 length); 134 length);
@@ -134,6 +140,7 @@ void grey_scroll_down(int count)
134/* Scroll left */ 140/* Scroll left */
135void grey_ub_scroll_left(int count) 141void grey_ub_scroll_left(int count)
136{ 142{
143 struct viewport *vp = &_grey_default_vp;
137 unsigned char *data, *data_end; 144 unsigned char *data, *data_end;
138 int blank, length; 145 int blank, length;
139 146
@@ -147,9 +154,9 @@ void grey_ub_scroll_left(int count)
147 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); 154 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
148 length = (_grey_info.width - count) << _GREY_BSHIFT; 155 length = (_grey_info.width - count) << _GREY_BSHIFT;
149 count <<= _GREY_BSHIFT; 156 count <<= _GREY_BSHIFT;
150 blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? 157 blank = _grey_info.gvalue[(vp->drawmode & DRMODE_INVERSEVID) ?
151 _grey_info.fg_brightness : 158 _GREY_FG_BRIGHTNESS(vp) :
152 _grey_info.bg_brightness]; 159 _GREY_BG_BRIGHTNESS(vp)];
153 do 160 do
154 { 161 {
155 rb->memmove(data, data + count, length); 162 rb->memmove(data, data + count, length);
@@ -167,6 +174,7 @@ void grey_ub_scroll_left(int count)
167/* Scroll right */ 174/* Scroll right */
168void grey_ub_scroll_right(int count) 175void grey_ub_scroll_right(int count)
169{ 176{
177 struct viewport *vp = &_grey_default_vp;
170 unsigned char *data, *data_end; 178 unsigned char *data, *data_end;
171 int blank, length; 179 int blank, length;
172 180
@@ -180,9 +188,9 @@ void grey_ub_scroll_right(int count)
180 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height); 188 data_end = data + _GREY_MULUQ(_grey_info.width, _grey_info.height);
181 length = (_grey_info.width - count) << _GREY_BSHIFT; 189 length = (_grey_info.width - count) << _GREY_BSHIFT;
182 count <<= _GREY_BSHIFT; 190 count <<= _GREY_BSHIFT;
183 blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? 191 blank = _grey_info.gvalue[(vp->drawmode & DRMODE_INVERSEVID) ?
184 _grey_info.fg_brightness : 192 _GREY_FG_BRIGHTNESS(vp) :
185 _grey_info.bg_brightness]; 193 _GREY_BG_BRIGHTNESS(vp)];
186 do 194 do
187 { 195 {
188 rb->memmove(data + count, data, length); 196 rb->memmove(data + count, data, length);
@@ -199,6 +207,7 @@ void grey_ub_scroll_right(int count)
199/* Scroll up */ 207/* Scroll up */
200void grey_ub_scroll_up(int count) 208void grey_ub_scroll_up(int count)
201{ 209{
210 struct viewport *vp = &_grey_default_vp;
202 unsigned char *dst, *end, *src; 211 unsigned char *dst, *end, *src;
203 int blank; 212 int blank;
204 213
@@ -210,9 +219,9 @@ void grey_ub_scroll_up(int count)
210 219
211 dst = _grey_info.values; 220 dst = _grey_info.values;
212 end = dst + _GREY_MULUQ(_grey_info.height, _grey_info.width); 221 end = dst + _GREY_MULUQ(_grey_info.height, _grey_info.width);
213 blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? 222 blank = _grey_info.gvalue[(vp->drawmode & DRMODE_INVERSEVID) ?
214 _grey_info.fg_brightness : 223 _GREY_FG_BRIGHTNESS(vp) :
215 _grey_info.bg_brightness]; 224 _GREY_BG_BRIGHTNESS(vp)];
216 225
217#if (LCD_PIXELFORMAT == VERTICAL_PACKING) \ 226#if (LCD_PIXELFORMAT == VERTICAL_PACKING) \
218 || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) 227 || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
@@ -274,6 +283,7 @@ void grey_ub_scroll_up(int count)
274/* Scroll down */ 283/* Scroll down */
275void grey_ub_scroll_down(int count) 284void grey_ub_scroll_down(int count)
276{ 285{
286 struct viewport *vp = &_grey_default_vp;
277 unsigned char *start, *dst; 287 unsigned char *start, *dst;
278 int blank; 288 int blank;
279 289
@@ -285,9 +295,9 @@ void grey_ub_scroll_down(int count)
285 295
286 start = _grey_info.values; 296 start = _grey_info.values;
287 dst = start + _GREY_MULUQ(_grey_info.height, _grey_info.width); 297 dst = start + _GREY_MULUQ(_grey_info.height, _grey_info.width);
288 blank = _grey_info.gvalue[(_grey_info.drawmode & DRMODE_INVERSEVID) ? 298 blank = _grey_info.gvalue[(vp->drawmode & DRMODE_INVERSEVID) ?
289 _grey_info.fg_brightness : 299 _GREY_FG_BRIGHTNESS(vp) :
290 _grey_info.bg_brightness]; 300 _GREY_BG_BRIGHTNESS(vp)];
291 301
292#if (LCD_PIXELFORMAT == VERTICAL_PACKING) \ 302#if (LCD_PIXELFORMAT == VERTICAL_PACKING) \
293 || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) 303 || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
diff --git a/apps/plugins/lib/mylcd.h b/apps/plugins/lib/mylcd.h
index 48e8ca1d47..e363111c71 100644
--- a/apps/plugins/lib/mylcd.h
+++ b/apps/plugins/lib/mylcd.h
@@ -40,12 +40,13 @@
40#define mylcd_(fn) pgfx_##fn 40#define mylcd_(fn) pgfx_##fn
41#define mylcd_ub_(fn) pgfx_##fn 41#define mylcd_ub_(fn) pgfx_##fn
42 42
43#elif defined (HAVE_LCD_BITMAP) && (LCD_DEPTH < 8) && defined(__GREY_H__) 43#elif defined (HAVE_LCD_BITMAP) && (LCD_DEPTH < 4) && defined(__GREY_H__)
44#define MYLCD_CFG_GREYLIB /* using greylib */ 44#define MYLCD_CFG_GREYLIB /* using greylib */
45#define mylcd_(fn) grey_##fn 45#define mylcd_(fn) grey_##fn
46#define myxlcd_(fn) grey_##fn 46#define myxlcd_(fn) grey_##fn
47#define mylcd_ub_(fn) grey_ub_##fn 47#define mylcd_ub_(fn) grey_ub_##fn
48#define myxlcd_ub_(fn) grey_ub_##fn 48#define myxlcd_ub_(fn) grey_ub_##fn
49#define mylcd_viewport_(fn) grey_viewport_##fn
49 50
50/* Common colors */ 51/* Common colors */
51#define MYLCD_BLACK GREY_BLACK 52#define MYLCD_BLACK GREY_BLACK
@@ -61,6 +62,7 @@
61#define myxlcd_(fn) xlcd_##fn 62#define myxlcd_(fn) xlcd_##fn
62#define mylcd_ub_(fn) rb->lcd_##fn 63#define mylcd_ub_(fn) rb->lcd_##fn
63#define myxlcd_ub_(fn) xlcd_##fn 64#define myxlcd_ub_(fn) xlcd_##fn
65#define mylcd_viewport_(fn) rb->viewport_##fn
64 66
65/* Common colors */ 67/* Common colors */
66#define MYLCD_BLACK LCD_BLACK 68#define MYLCD_BLACK LCD_BLACK
@@ -180,4 +182,11 @@ static inline void mylcd_ub_update_rect(int x, int y, int w, int h)
180#define mylcd_ub_scroll_down myxlcd_ub_(scroll_down) 182#define mylcd_ub_scroll_down myxlcd_ub_(scroll_down)
181#endif /* HAVE_LCD_BITMAP */ 183#endif /* HAVE_LCD_BITMAP */
182 184
185/* Viewports */
186#ifdef HAVE_LCD_BITMAP
187#define mylcd_clear_viewport mylcd_(clear_viewport)
188#define mylcd_set_viewport mylcd_(set_viewport)
189#define mylcd_viewport_set_fullscreen mylcd_viewport_(set_fullscreen)
190#endif /* HAVE_LCD_BITMAP */
191
183#endif /* MYLCD_H */ 192#endif /* MYLCD_H */
diff --git a/apps/plugins/lib/osd.c b/apps/plugins/lib/osd.c
index ff0533a898..598a76759c 100644
--- a/apps/plugins/lib/osd.c
+++ b/apps/plugins/lib/osd.c
@@ -21,6 +21,7 @@
21* 21*
22****************************************************************************/ 22****************************************************************************/
23#include "plugin.h" 23#include "plugin.h"
24#include "grey.h"
24#include "osd.h" 25#include "osd.h"
25 26
26#if 1 27#if 1
@@ -28,10 +29,20 @@
28#define DEBUGF(...) 29#define DEBUGF(...)
29#endif 30#endif
30 31
32#if defined(SIMULATOR) && LCD_DEPTH < 4
33/* Sim isn't using --ffunction-sections thus greylib references will happen
34 here even if not using this with greylib on a grayscale display, which
35 demands that a struct _grey_info exist. */
36#ifndef _WIN32
37__attribute__((weak))
38#endif /* _WIN32 */
39 struct _grey_info _grey_info;
40#endif /* defined(SIMULATOR) && LCD_DEPTH < 4 */
41
31/* At this time: assumes use of the default viewport for normal drawing */ 42/* At this time: assumes use of the default viewport for normal drawing */
32 43
33/* If multiple OSD's are wanted, could convert to caller-allocated */ 44/* If multiple OSD's are wanted, could convert to caller-allocated */
34static struct osd 45struct osd
35{ 46{
36 enum osd_status 47 enum osd_status
37 { 48 {
@@ -41,152 +52,314 @@ static struct osd
41 OSD_ERASED, /* Erased in preparation for regular drawing */ 52 OSD_ERASED, /* Erased in preparation for regular drawing */
42 } status; /* View status */ 53 } status; /* View status */
43 struct viewport vp; /* Clipping viewport */ 54 struct viewport vp; /* Clipping viewport */
44 struct bitmap lcd_bitmap; /* The main LCD fb bitmap */ 55 int lcd_bitmap_stride; /* Stride of LCD bitmap */
45 struct bitmap back_bitmap; /* The OSD backbuffer fb bitmap */ 56 void *lcd_bitmap_data; /* Backbuffer framebuffer data */
57 int back_bitmap_stride; /* Stride of backbuffer bitmap */
58 void *back_bitmap_data; /* LCD framebuffer data */
46 int maxwidth; /* How wide may it be at most? */ 59 int maxwidth; /* How wide may it be at most? */
47 int maxheight; /* How high may it be at most? */ 60 int maxheight; /* How high may it be at most? */
48 long timeout; /* Current popup stay duration */ 61 long timeout; /* Current popup stay duration */
49 long hide_tick; /* Tick when it should be hidden */ 62 long hide_tick; /* Tick when it should be hidden */
50 osd_draw_cb_fn_t draw_cb; /* Draw update callback */ 63 osd_draw_cb_fn_t draw_cb; /* Draw update callback */
51} osd; 64 /* Functions to factilitate interface compatibility of OSD types */
65 void * (*init_buffers)(struct osd *osd, unsigned flags, void *buf,
66 size_t *bufsize);
67 void (*set_viewport_pos)(struct viewport *vp, int x, int y, int width,
68 int height);
69 void (*lcd_update)(void);
70 void (*lcd_update_rect)(int x, int y, int width, int height);
71 void (*lcd_set_viewport)(struct viewport *vp);
72 void (*lcd_set_framebuffer)(void *buf);
73 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 int stride, int x, int y, int width, int height);
76};
77
78static struct osd native_osd;
79#if LCD_DEPTH < 4
80static struct osd grey_osd;
81#endif
52 82
53/* Framebuffer allocation macros */ 83/* Framebuffer allocation macros */
54#if LCD_DEPTH == 1 84#if LCD_DEPTH == 1
55# if LCD_PIXELFORMAT == HORIZONTAL_PACKING 85# if LCD_PIXELFORMAT == HORIZONTAL_PACKING
56# define LCD_WIDTH2BYTES(w) (((w)+7)/8) 86# define _OSD_WIDTH2BYTES(w) (((w)+7)/8)
57# define LCD_BYTES2WIDTH(b) ((b)*8) 87# define _OSD_BYTES2WIDTH(b) ((b)*8)
58# elif LCD_PIXELFORMAT == VERTICAL_PACKING 88# elif LCD_PIXELFORMAT == VERTICAL_PACKING
59# define LCD_HEIGHT2BYTES(h) (((h)+7)/8) 89# define _OSD_HEIGHT2BYTES(h) (((h)+7)/8)
60# define LCD_BYTES2HEIGHT(b) ((b)*8) 90# define _OSD_BYTES2HEIGHT(b) ((b)*8)
61# else 91# else
62# error Unknown 1-bit format; please define macros 92# error Unknown 1-bit format; please define macros
63# endif /* LCD_PIXELFORMAT */ 93# endif /* LCD_PIXELFORMAT */
64#elif LCD_DEPTH == 2 94#elif LCD_DEPTH == 2
65# if LCD_PIXELFORMAT == HORIZONTAL_PACKING 95# if LCD_PIXELFORMAT == HORIZONTAL_PACKING
66# define LCD_WIDTH2BYTES(w) (((w)+3)/4) 96# define _OSD_WIDTH2BYTES(w) (((w)+3)/4)
67# define LCD_BYTES2WIDTH(b) ((b)*4) 97# define _OSD_BYTES2WIDTH(b) ((b)*4)
68# elif LCD_PIXELFORMAT == VERTICAL_PACKING 98# elif LCD_PIXELFORMAT == VERTICAL_PACKING
69# define LCD_HEIGHT2BYTES(h) (((h)+3)/4) 99# define _OSD_HEIGHT2BYTES(h) (((h)+3)/4)
70# define LCD_BYTES2HEIGHT(b) ((b)*4) 100# define _OSD_BYTES2HEIGHT(b) ((b)*4)
71# elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED 101# elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
72# define LCD_WIDTH2BYTES(w) ((w)*2) 102# define _OSD_HEIGHT2BYTES(h) (((h)+7)/8*2)
73# define LCD_BYTES2WIDTH(b) ((b)/2) 103# define _OSD_BYTES2HEIGHT(b) ((b)/2*8)
74# define LCD_HEIGHT2BYTES(h) (((h)+7)/8*2)
75# define LCD_BYTES2HEIGHT(b) ((b)/2*8)
76# else 104# else
77# error Unknown 2-bit format; please define macros 105# error Unknown 2-bit format; please define macros
78# endif /* LCD_PIXELFORMAT */ 106# endif /* LCD_PIXELFORMAT */
79#elif LCD_DEPTH == 16 107#elif LCD_DEPTH == 16
80# define LCD_WIDTH2BYTES(w) ((w)*2) 108# if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
81# define LCD_BYTES2WIDTH(b) ((b)/2) 109# define _OSD_HEIGHT2BYTES(h) ((h)*2)
82#else 110# define _OSD_BYTES2HEIGHT(b) ((b)/2)
111# else /* !defined(LCD_STRIDEFORMAT) || LCD_STRIDEFORMAT != VERTICAL_STRIDE */
112# define _OSD_WIDTH2BYTES(w) ((w)*2)
113# define _OSD_BYTES2WIDTH(b) ((b)/2)
114# endif /* end stride type selection */
115#else /* other LCD depth */
83# error Unknown LCD depth; please define macros 116# error Unknown LCD depth; please define macros
84#endif /* LCD_DEPTH */ 117#endif /* LCD_DEPTH */
85/* Set defaults if not defined different yet. */ 118/* Set defaults if not defined differently */
86#ifndef LCD_WIDTH2BYTES 119#ifndef _OSD_WIDTH2BYTES
87# define LCD_WIDTH2BYTES(w) (w) 120# define _OSD_WIDTH2BYTES(w) (w)
88#endif 121#endif
89#ifndef LCD_BYTES2WIDTH 122#ifndef _OSD_BYTES2WIDTH
90# define LCD_BYTES2WIDTH(b) (b) 123# define _OSD_BYTES2WIDTH(b) (b)
91#endif 124#endif
92#ifndef LCD_HEIGHT2BYTES 125#ifndef _OSD_HEIGHT2BYTES
93# define LCD_HEIGHT2BYTES(h) (h) 126# define _OSD_HEIGHT2BYTES(h) (h)
94#endif 127#endif
95#ifndef LCD_BYTES2HEIGHT 128#ifndef _OSD_BYTES2HEIGHT
96# define LCD_BYTES2HEIGHT(b) (b) 129# define _OSD_BYTES2HEIGHT(b) (b)
97#endif 130#endif
131#ifndef _OSD_BUFSIZE
132# define _OSD_BUFSIZE(w, h) (_OSD_WIDTH2BYTES(w)*_OSD_HEIGHT2BYTES(h))
133#endif
134
135static void _osd_destroy(struct osd *osd);
136static bool _osd_show(struct osd *osd, unsigned flags);
137
138
139/** Native LCD routines **/
98 140
99/* Create a bitmap framebuffer from a buffer */ 141/* Create a bitmap framebuffer from a buffer */
100static fb_data * buf_to_fb_bitmap(void *buf, size_t bufsize, 142static void * _osd_lcd_init_buffers(struct osd *osd, unsigned flags,
101 int *width, int *height) 143 void *buf, size_t *bufsize)
102{ 144{
103 /* Used as dest, the LCD functions cannot deal with alternate 145 /* Used as dest, the LCD functions cannot deal with alternate
104 strides as of now - the stride guides the calulations. If 146 strides as of now - the stride guides the calulations. If
105 that is no longer the case, then width or height can be 147 that is no longer the case, then width or height can be
106 used instead (and less memory needed for a small surface!). 148 used instead (and less memory needed for a small surface!).
149 IOW: crappiness means one dimension is non-negotiable.
107 */ 150 */
108 DEBUGF("buf: %p bufsize: %lu\n", buf, (unsigned long)bufsize); 151 DEBUGF("OSD: in(buf=%p bufsize=%lu)\n", buf,
152 (unsigned long)*bufsize);
153
154 rb->viewport_set_fullscreen(&osd->vp, SCREEN_MAIN);
109 155
110#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE 156#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
111 int h = LCD_BYTES2HEIGHT(LCD_HEIGHT2BYTES(LCD_HEIGHT)); 157 int colbytes = _OSD_HEIGHT2BYTES(LCD_HEIGHT);
112 int w = bufsize / LCD_HEIGHT2BYTES(h); 158 int bytecols = *bufsize / colbytes;
159 int w = _OSD_BYTES2WIDTH(bytecols);
160 int h = _OSD_BYTES2HEIGHT(colbytes);
113 161
114 if (w == 0) 162 if (flags & OSD_INIT_MAJOR_HEIGHT)
115 { 163 {
116 DEBUGF("OSD: not enough buffer\n"); 164 if (w == 0 || ((flags & OSD_INIT_MINOR_MIN) && w < osd->maxwidth))
117 return NULL; /* not enough buffer */ 165 {
166 DEBUGF("OSD: not enough buffer\n");
167 return NULL; /* not enough buffer */
168 }
169
170 if ((flags & OSD_INIT_MINOR_MAX) && w > osd->maxwidth)
171 w = osd->maxwidth;
172 }
173 else /* OSD_INIT_MAJOR_WIDTH implied */
174 {
175 if (w == 0 || w < osd->maxwidth)
176 {
177 DEBUGF("OSD: not enough buffer\n");
178 return NULL; /* not enough buffer */
179 }
180 else if (w > osd->maxwidth)
181 {
182 w = osd->maxwidth;
183 }
118 } 184 }
119#else
120 int w = LCD_BYTES2WIDTH(LCD_WIDTH2BYTES(LCD_WIDTH));
121 int h = bufsize / LCD_WIDTH2BYTES(w);
122 185
123 if (h == 0) 186 w = _OSD_BYTES2WIDTH(_OSD_WIDTH2BYTES(w));
187 osd->lcd_bitmap_stride = _OSD_BYTES2HEIGHT(_OSD_HEIGHT2BYTES(LCD_HEIGHT));
188 osd->back_bitmap_stride = h;
189#else /* !defined(LCD_STRIDEFORMAT) || LCD_STRIDEFORMAT != VERTICAL_STRIDE */
190 int rowbytes = _OSD_WIDTH2BYTES(LCD_WIDTH);
191 int byterows = *bufsize / rowbytes;
192 int w = _OSD_BYTES2WIDTH(rowbytes);
193 int h = _OSD_BYTES2HEIGHT(byterows);
194
195 if (flags & OSD_INIT_MAJOR_HEIGHT)
124 { 196 {
125 DEBUGF("OSD: not enough buffer\n"); 197 if (h == 0 || h < osd->maxheight)
126 return NULL; /* not enough buffer */ 198 {
199 DEBUGF("OSD: not enough buffer\n");
200 return NULL;
201 }
202 else if (h > osd->maxheight)
203 {
204 h = osd->maxheight;
205 }
127 } 206 }
128#endif 207 else /* OSD_INIT_MAJOR_WIDTH implied */
208 {
209 if (h == 0 || ((flags & OSD_INIT_MINOR_MIN) && h < osd->maxheight))
210 {
211 DEBUGF("OSD: not enough buffer\n");
212 return NULL;
213 }
129 214
130 DEBUGF("fbw:%d fbh:%d\n", w, h); 215 if ((flags & OSD_INIT_MINOR_MAX) && h > osd->maxheight)
216 h = osd->maxheight;
217 }
131 218
132 *width = w; 219 h = _OSD_BYTES2HEIGHT(_OSD_HEIGHT2BYTES(h));
133 *height = h; 220 osd->lcd_bitmap_stride = _OSD_BYTES2WIDTH(_OSD_WIDTH2BYTES(LCD_WIDTH));
134 221 osd->back_bitmap_stride = w;
135 return (fb_data *)buf; 222#endif /* end stride type selection */
136}
137 223
138static inline void osd_set_vp_pos(int x, int y, int width, int height) 224 osd->lcd_bitmap_data = (void *)rb->lcd_framebuffer;
139{ 225 osd->back_bitmap_data = buf;
140 osd.vp.x = x; 226
141 osd.vp.y = y; 227 osd->maxwidth = w;
142 osd.vp.width = width; 228 osd->maxheight = h;
143 osd.vp.height = height; 229 *bufsize = _OSD_BUFSIZE(w, h);
230
231 DEBUGF("OSD: addr(fb=%p bb=%p)\n", osd->lcd_bitmap_data,
232 osd->back_bitmap_data);
233 DEBUGF("OSD: w=%d h=%d bufsz=%lu\n", w, h, (unsigned long)*bufsize);
234
235 return buf;
144} 236}
145 237
146/* Sync the backbuffer to the on-screen image */ 238/* Set viewport coordinates */
147static void osd_lcd_update_back_buffer(void) 239static void _osd_lcd_viewport_set_pos(
240 struct viewport *vp, int x, int y, int width, int height)
148{ 241{
149 rb->lcd_set_framebuffer((fb_data *)osd.back_bitmap.data); 242 vp->x = x;
150 rb->lcd_bmp_part(&osd.lcd_bitmap, osd.vp.x, osd.vp.y, 243 vp->y = y;
151 0, 0, osd.vp.width, osd.vp.height); 244 vp->width = width;
152 /* Assume it was on default framebuffer for now */ 245 vp->height = height;
153 rb->lcd_set_framebuffer(NULL);
154} 246}
155 247
156/* Erase the OSD to restore the framebuffer */ 248
157static void osd_lcd_erase(void) 249#if LCD_DEPTH < 4
250/** Greylib LCD routines **/
251
252/* Create a greylib bitmap framebuffer from a buffer */
253static void * _osd_grey_init_buffers(struct osd *osd, unsigned flags,
254 void *buf, size_t *bufsize)
158{ 255{
159 rb->lcd_bmp_part(&osd.back_bitmap, 0, 0, osd.vp.x, osd.vp.y, 256 int w, h;
160 osd.vp.width, osd.vp.height); 257
258 DEBUGF("OSD (grey): in(buf=%p bufsize=%lu)\n", buf,
259 (unsigned long)*bufsize);
260
261 grey_viewport_set_fullscreen(&osd->vp, SCREEN_MAIN);
262
263 if (flags & OSD_INIT_MAJOR_HEIGHT)
264 {
265 h = osd->maxheight;
266 w = *bufsize / h;
267
268 if (w == 0 || ((flags & OSD_INIT_MINOR_MIN) && w < osd->maxwidth))
269 {
270 DEBUGF("OSD (grey): Not enough buffer\n");
271 return NULL;
272 }
273
274 if ((flags & OSD_INIT_MINOR_MAX) && w > osd->maxwidth)
275 w = osd->maxwidth;
276 }
277 else /* OSD_INIT_MAJOR_WIDTH implied */
278 {
279 w = osd->maxwidth;
280 h = *bufsize / w;
281
282 if (h == 0 || ((flags & OSD_INIT_MINOR_MIN) && h < osd->maxheight))
283 {
284 DEBUGF("OSD (grey): Not enough buffer\n");
285 return NULL;
286 }
287
288 if ((flags & OSD_INIT_MINOR_MAX) && h > osd->maxheight)
289 h = osd->maxheight;
290 }
291
292 /* Have to peek into _grey_info a bit */
293 osd->lcd_bitmap_stride = _grey_info.width;
294 osd->lcd_bitmap_data = _grey_info.buffer;
295 osd->back_bitmap_stride = w;
296 osd->back_bitmap_data = buf;
297
298 osd->maxwidth = w;
299 osd->maxheight = h;
300 *bufsize = w * h;
301
302 DEBUGF("OSD (grey): addr(fb=%p bb=%p)\n", osd->lcd_bitmap_data,
303 osd->back_bitmap_data);
304 DEBUGF("OSD (grey): w=%d h=%d bufsz=%lu\n", w, h, (unsigned long)*bufsize);
305
306 return buf;
161} 307}
308#endif /* LCD_DEPTH < 4*/
309
310
311/** Common LCD routines **/
162 312
163/* Draw the OSD image portion using the callback */ 313/* Draw the OSD image portion using the callback */
164static void osd_lcd_draw_rect(int x, int y, int width, int height) 314static void _osd_draw_osd_rect(struct osd *osd, int x, int y,
315 int width, int height)
165{ 316{
166 rb->lcd_set_viewport(&osd.vp); 317 osd->lcd_set_viewport(&osd->vp);
167 osd.draw_cb(x, y, width, height); 318 osd->draw_cb(x, y, width, height);
168 rb->lcd_set_viewport(NULL); 319 osd->lcd_set_viewport(NULL);
169} 320}
170 321
171/* Draw the OSD image using the callback */ 322/* Draw the OSD image using the callback */
172static void osd_lcd_draw(void) 323static void _osd_draw_osd(struct osd *osd)
173{ 324{
174 osd_lcd_draw_rect(0, 0, osd.vp.width, osd.vp.height); 325 _osd_draw_osd_rect(osd, 0, 0, osd->vp.width, osd->vp.height);
175} 326}
176 327
328static void _osd_update_viewport(struct osd *osd)
329{
330 osd->lcd_update_rect(osd->vp.x, osd->vp.y, osd->vp.width,
331 osd->vp.height);
332}
177 333
178/** Public APIs **/ 334/* Sync the backbuffer to the framebuffer image */
335static void _osd_update_back_buffer(struct osd *osd)
336{
337 /* Assume it's starting with default viewport for now */
338 osd->lcd_set_framebuffer(osd->back_bitmap_data);
339#if LCD_DEPTH < 4
340 if (osd->lcd_framebuffer_set_pos)
341 osd->lcd_framebuffer_set_pos(0, 0, osd->maxwidth, osd->maxheight);
342#endif /* LCD_DEPTH < 4 */
343 osd->lcd_bitmap_part(osd->lcd_bitmap_data, osd->vp.x, osd->vp.y,
344 osd->lcd_bitmap_stride, 0, 0, osd->vp.width,
345 osd->vp.height);
346 /* Assume it was on default framebuffer for now */
347 osd->lcd_set_framebuffer(NULL);
348}
179 349
180/* Initialized the OSD and set its backbuffer */ 350/* Erase the OSD to restore the framebuffer image */
181bool osd_init(void *backbuf, size_t backbuf_size, 351static void _osd_erase_osd(struct osd *osd)
182 osd_draw_cb_fn_t draw_cb)
183{ 352{
184 osd_show(OSD_HIDE); 353 osd->lcd_bitmap_part(osd->back_bitmap_data, 0, 0, osd->back_bitmap_stride,
354 osd->vp.x, osd->vp.y, osd->vp.width, osd->vp.height);
355}
185 356
186 osd.status = OSD_DISABLED; /* Disabled unless all is okay */ 357/* Initialized the OSD and set its backbuffer */
187 osd_set_vp_pos(0, 0, 0, 0); 358static bool _osd_init(struct osd *osd, unsigned flags, void *backbuf,
188 osd.maxwidth = osd.maxheight = 0; 359 size_t backbuf_size, osd_draw_cb_fn_t draw_cb,
189 osd.timeout = 0; 360 int *width, int *height, size_t *bufused)
361{
362 _osd_destroy(osd);
190 363
191 if (!draw_cb) 364 if (!draw_cb)
192 return false; 365 return false;
@@ -194,95 +367,133 @@ bool osd_init(void *backbuf, size_t backbuf_size,
194 if (!backbuf) 367 if (!backbuf)
195 return false; 368 return false;
196 369
197 ALIGN_BUFFER(backbuf, backbuf_size, FB_DATA_SZ); 370 void *backbuf_orig = backbuf; /* Save in case of ptr advance */
371 ALIGN_BUFFER(backbuf, backbuf_size, MAX(FB_DATA_SZ, 4));
198 372
199 if (!backbuf_size) 373 if (!backbuf_size)
200 return false; 374 return false;
201 375
202 rb->viewport_set_fullscreen(&osd.vp, SCREEN_MAIN); 376 if (flags & OSD_INIT_MAJOR_HEIGHT)
377 {
378 if (!height || *height <= 0)
379 return false;
203 380
204 fb_data *backfb = buf_to_fb_bitmap(backbuf, backbuf_size, 381 if ((flags & (OSD_INIT_MINOR_MIN | OSD_INIT_MINOR_MAX)) &&
205 &osd.maxwidth, &osd.maxheight); 382 (!width || *width <= 0))
383 {
384 return false;
385 }
386 }
387 else
388 {
389 if (!width || *width <= 0)
390 return false;
391
392 if ((flags & (OSD_INIT_MINOR_MIN | OSD_INIT_MINOR_MAX)) &&
393 (!height || *height <= 0))
394 {
395 return false;
396 }
397 }
398
399 /* Store requested sizes in max(width|height) */
400 if (width)
401 osd->maxwidth = *width;
402 else
403 osd->maxwidth = LCD_WIDTH;
206 404
207 if (!backfb) 405 if (height)
406 osd->maxheight = *height;
407 else
408 osd->maxheight = LCD_HEIGHT;
409
410 if (!osd->init_buffers(osd, flags, backbuf, &backbuf_size))
411 {
412 osd->maxwidth = osd->maxheight = 0;
208 return false; 413 return false;
414 }
209 415
210 osd.draw_cb = draw_cb; 416 osd->draw_cb = draw_cb;
211 417
212 /* LCD framebuffer bitmap */ 418 if (bufused)
213 osd.lcd_bitmap.width = LCD_BYTES2WIDTH(LCD_WIDTH2BYTES(LCD_WIDTH)); 419 *bufused = backbuf_size + (backbuf_orig - backbuf);
214 osd.lcd_bitmap.height = LCD_BYTES2HEIGHT(LCD_HEIGHT2BYTES(LCD_HEIGHT));
215#if LCD_DEPTH > 1
216 osd.lcd_bitmap.format = FORMAT_NATIVE;
217 osd.lcd_bitmap.maskdata = NULL;
218#endif
219#ifdef HAVE_LCD_COLOR
220 osd.lcd_bitmap.alpha_offset = 0;
221#endif
222 osd.lcd_bitmap.data = (void *)rb->lcd_framebuffer;
223
224 /* Backbuffer bitmap */
225 osd.back_bitmap.width = osd.maxwidth;
226 osd.back_bitmap.height = osd.maxheight;
227#if LCD_DEPTH > 1
228 osd.back_bitmap.format = FORMAT_NATIVE;
229 osd.back_bitmap.maskdata = NULL;
230#endif
231#ifdef HAVE_LCD_COLOR
232 osd.back_bitmap.alpha_offset = 0;
233#endif
234 osd.back_bitmap.data = (void *)backfb;
235 420
236 DEBUGF("FB:%p BB:%p\n", osd.lcd_bitmap.data, osd.back_bitmap.data); 421 if (width)
422 *width = osd->maxwidth;
423
424 if (height)
425 *height = osd->maxheight;
237 426
238 /* Set the default position to the whole thing */ 427 /* Set the default position to the whole thing */
239 osd_set_vp_pos(0, 0, osd.maxwidth, osd.maxheight); 428 osd->set_viewport_pos(&osd->vp, 0, 0, osd->maxwidth, osd->maxheight);
429
430 osd->status = OSD_HIDDEN; /* Ready when you are */
240 431
241 osd.status = OSD_HIDDEN; /* Ready when you are */ 432 return true;
433}
434
435static void _osd_destroy(struct osd *osd)
436{
437 _osd_show(osd, OSD_HIDE);
438
439 /* Set to essential defaults */
440 osd->status = OSD_DISABLED;
441 osd->set_viewport_pos(&osd->vp, 0, 0, 0, 0);
442 osd->maxwidth = osd->maxheight = 0;
443 osd->timeout = 0;
444}
445
446/* Redraw the entire OSD */
447static bool _osd_update(struct osd *osd)
448{
449 if (osd->status != OSD_VISIBLE)
450 return false;
451
452 _osd_draw_osd(osd);
453 _osd_update_viewport(osd);
242 return true; 454 return true;
243} 455}
244 456
245/* Show/Hide the OSD on screen */ 457/* Show/Hide the OSD on screen */
246bool osd_show(unsigned flags) 458static bool _osd_show(struct osd *osd, unsigned flags)
247{ 459{
248 if (flags & OSD_SHOW) 460 if (flags & OSD_SHOW)
249 { 461 {
250 switch (osd.status) 462 switch (osd->status)
251 { 463 {
252 case OSD_DISABLED: 464 case OSD_DISABLED:
253 break; /* No change */ 465 break; /* No change */
254 466
255 case OSD_HIDDEN: 467 case OSD_HIDDEN:
256 osd_lcd_update_back_buffer(); 468 _osd_update_back_buffer(osd);
257 osd.status = OSD_VISIBLE; 469 osd->status = OSD_VISIBLE;
258 osd_update(); 470 _osd_update(osd);
259 osd.hide_tick = *rb->current_tick + osd.timeout; 471 osd->hide_tick = *rb->current_tick + osd->timeout;
260 break; 472 break;
261 473
262 case OSD_VISIBLE: 474 case OSD_VISIBLE:
263 if (flags & OSD_UPDATENOW) 475 if (flags & OSD_UPDATENOW)
264 osd_update(); 476 _osd_update(osd);
265 /* Fall-through */ 477 /* Fall-through */
266 case OSD_ERASED: 478 case OSD_ERASED:
267 osd.hide_tick = *rb->current_tick + osd.timeout; 479 osd->hide_tick = *rb->current_tick + osd->timeout;
268 return true; 480 return true;
269 } 481 }
270 } 482 }
271 else 483 else
272 { 484 {
273 switch (osd.status) 485 switch (osd->status)
274 { 486 {
275 case OSD_DISABLED: 487 case OSD_DISABLED:
276 case OSD_HIDDEN: 488 case OSD_HIDDEN:
277 break; 489 break;
278 490
279 case OSD_VISIBLE: 491 case OSD_VISIBLE:
280 osd_lcd_erase(); 492 _osd_erase_osd(osd);
281 rb->lcd_update_rect(osd.vp.x, osd.vp.y, osd.vp.width, 493 _osd_update_viewport(osd);
282 osd.vp.height);
283 /* Fall-through */ 494 /* Fall-through */
284 case OSD_ERASED: 495 case OSD_ERASED:
285 osd.status = OSD_HIDDEN; 496 osd->status = OSD_HIDDEN;
286 return true; 497 return true;
287 } 498 }
288 } 499 }
@@ -290,30 +501,20 @@ bool osd_show(unsigned flags)
290 return false; 501 return false;
291} 502}
292 503
293/* Redraw the entire OSD */
294bool osd_update(void)
295{
296 if (osd.status != OSD_VISIBLE)
297 return false;
298
299 osd_lcd_draw();
300
301 rb->lcd_update_rect(osd.vp.x, osd.vp.y, osd.vp.width,
302 osd.vp.height);
303
304 return true;
305}
306
307/* Redraw part of the OSD (viewport-relative coordinates) */ 504/* Redraw part of the OSD (viewport-relative coordinates) */
308bool osd_update_rect(int x, int y, int width, int height) 505static bool _osd_update_rect(struct osd *osd, int x, int y, int width,
506 int height)
309{ 507{
310 if (osd.status != OSD_VISIBLE) 508 if (osd->status != OSD_VISIBLE)
311 return false; 509 return false;
312 510
313 osd_lcd_draw_rect(x, y, width, height); 511 _osd_draw_osd_rect(osd, x, y, width, height);
314 512
315 if (x + width > osd.vp.width) 513 int vp_x = osd->vp.x;
316 width = osd.vp.width - x; 514 int vp_w = osd->vp.width;
515
516 if (x + width > vp_w)
517 width = vp_w - x;
317 518
318 if (x < 0) 519 if (x < 0)
319 { 520 {
@@ -324,8 +525,11 @@ bool osd_update_rect(int x, int y, int width, int height)
324 if (width <= 0) 525 if (width <= 0)
325 return false; 526 return false;
326 527
327 if (y + height > osd.vp.height) 528 int vp_y = osd->vp.y;
328 height = osd.vp.height - y; 529 int vp_h = osd->vp.height;
530
531 if (y + height > vp_h)
532 height = vp_h - y;
329 533
330 if (y < 0) 534 if (y < 0)
331 { 535 {
@@ -336,135 +540,313 @@ bool osd_update_rect(int x, int y, int width, int height)
336 if (height <= 0) 540 if (height <= 0)
337 return false; 541 return false;
338 542
339 rb->lcd_update_rect(osd.vp.x + x, osd.vp.y + y, width, height); 543 osd->lcd_update_rect(vp_x + x, vp_y + y, width, height);
340 544
341 return true; 545 return true;
342} 546}
343 547
344/* Set a new screen location and size (screen coordinates) */ 548/* Set a new screen location and size (screen coordinates) */
345bool osd_update_pos(int x, int y, int width, int height) 549static bool _osd_update_pos(struct osd *osd, int x, int y, int width,
550 int height)
346{ 551{
347 if (osd.status == OSD_DISABLED) 552 if (osd->status == OSD_DISABLED)
348 return false; 553 return false;
349 554
350 if (width < 0) 555 if (width < 0)
351 width = 0; 556 width = 0;
352 else if (width > osd.maxwidth) 557 else if (width > osd->maxwidth)
353 width = osd.maxwidth; 558 width = osd->maxwidth;
354 559
355 if (height < 0) 560 if (height < 0)
356 height = 0; 561 height = 0;
357 else if (height > osd.maxheight) 562 else if (height > osd->maxheight)
358 height = osd.maxheight; 563 height = osd->maxheight;
564
565 int vp_x = osd->vp.x;
566 int vp_y = osd->vp.y;
567 int vp_w = osd->vp.width;
568 int vp_h = osd->vp.height;
359 569
360 if (x == osd.vp.x && y == osd.vp.y && 570 if (x == vp_x && y == vp_y && width == vp_w && height == vp_h)
361 width == osd.vp.width && height == osd.vp.height)
362 return false; /* No change */ 571 return false; /* No change */
363 572
364 if (osd.status != OSD_VISIBLE) 573 if (osd->status != OSD_VISIBLE)
365 { 574 {
366 /* Not visible - just update pos */ 575 /* Not visible - just update pos */
367 osd_set_vp_pos(x, y, width, height); 576 osd->set_viewport_pos(&osd->vp, x, y, width, height);
368 return false; 577 return false;
369 } 578 }
370 579
371 /* Visible area has changed */ 580 /* Visible area has changed */
372 osd_lcd_erase(); 581 _osd_erase_osd(osd);
373 582
374 /* Update the smallest rectangle that encloses both the old and new 583 /* Update the smallest rectangle that encloses both the old and new
375 regions to make the change free of flicker (they may overlap) */ 584 regions to make the change free of flicker (they may overlap) */
376 int xu = MIN(osd.vp.x, x); 585 int xu = MIN(vp_x, x);
377 int yu = MIN(osd.vp.y, y); 586 int yu = MIN(vp_y, y);
378 int wu = MAX(osd.vp.x + osd.vp.width, x + width) - xu; 587 int wu = MAX(vp_x + vp_w, x + width) - xu;
379 int hu = MAX(osd.vp.y + osd.vp.height, y + height) - yu; 588 int hu = MAX(vp_y + vp_h, y + height) - yu;
380 589
381 osd_set_vp_pos(x, y, width, height); 590 osd->set_viewport_pos(&osd->vp, x, y, width, height);
382 osd_lcd_update_back_buffer(); 591 _osd_update_back_buffer(osd);
383 osd_lcd_draw(); 592 _osd_draw_osd(osd);
593 osd->lcd_update_rect(xu, yu, wu, hu);
384 594
385 rb->lcd_update_rect(xu, yu, wu, hu);
386 return true; 595 return true;
387} 596}
388 597
389/* Call periodically to have the OSD timeout and hide itself */ 598/* Call periodically to have the OSD timeout and hide itself */
390void osd_monitor_timeout(void) 599static void _osd_monitor_timeout(struct osd *osd)
391{ 600{
392 if (osd.status <= OSD_HIDDEN) 601 if (osd->status <= OSD_HIDDEN)
393 return; /* Already hidden/disabled */ 602 return; /* Already hidden/disabled */
394 603
395 if (osd.timeout > 0 && TIME_AFTER(*rb->current_tick, osd.hide_tick)) 604 if (osd->timeout > 0 && TIME_AFTER(*rb->current_tick, osd->hide_tick))
396 osd_show(OSD_HIDE); 605 _osd_show(osd, OSD_HIDE);
397} 606}
398 607
399/* Set the OSD timeout value. <= 0 = never timeout */ 608/* Set the OSD timeout value. <= 0 = never timeout */
400void osd_set_timeout(long timeout) 609static void _osd_set_timeout(struct osd *osd, long timeout)
401{ 610{
402 if (osd.status == OSD_DISABLED) 611 if (osd->status == OSD_DISABLED)
403 return; 612 return;
404 613
405 osd.timeout = timeout; 614 osd->timeout = timeout;
406 osd_monitor_timeout(); 615 _osd_monitor_timeout(osd);
407} 616}
408 617
409/* Use the OSD viewport context */ 618/* Use the OSD viewport context */
410struct viewport * osd_get_viewport(void) 619static inline struct viewport * _osd_get_viewport(struct osd *osd)
411{ 620{
412 return &osd.vp; 621 return &osd->vp;
413} 622}
414 623
415/* Get the maximum dimensions calculated by osd_init() */ 624/* Get the maximum dimensions calculated by osd_init() */
416void osd_get_max_dims(int *maxwidth, int *maxheight) 625static void _osd_get_max_dims(struct osd *osd,
626 int *maxwidth, int *maxheight)
417{ 627{
418 if (maxwidth) 628 if (maxwidth)
419 *maxwidth = osd.maxwidth; 629 *maxwidth = osd->maxwidth;
420 630
421 if (maxheight) 631 if (maxheight)
422 *maxheight = osd.maxheight; 632 *maxheight = osd->maxheight;
423} 633}
424 634
425/* Is the OSD enabled? */ 635/* Is the OSD enabled? */
426bool osd_enabled(void) 636static inline bool _osd_enabled(struct osd *osd)
427{ 637{
428 return osd.status != OSD_DISABLED; 638 return osd->status != OSD_DISABLED;
429} 639}
430 640
431 641
432/** LCD update substitutes **/ 642/** LCD update substitutes **/
433 643
434/* Prepare LCD framebuffer for regular drawing */ 644/* Prepare LCD framebuffer for regular drawing */
435void osd_lcd_update_prepare(void) 645static inline void _osd_lcd_update_prepare(struct osd *osd)
436{ 646{
437 if (osd.status == OSD_VISIBLE) 647 if (osd->status == OSD_VISIBLE)
438 { 648 {
439 osd.status = OSD_ERASED; 649 osd->status = OSD_ERASED;
440 osd_lcd_erase(); 650 _osd_erase_osd(osd);
441 } 651 }
442} 652}
443 653
444/* Update the whole screen */ 654/* Update the whole screen */
445void osd_lcd_update(void) 655static inline void _osd_lcd_update(struct osd *osd)
446{ 656{
447 if (osd.status == OSD_ERASED) 657 if (osd->status == OSD_ERASED)
448 { 658 {
449 /* Save the screen image underneath and restore the OSD image */ 659 /* Save the screen image underneath and restore the OSD image */
450 osd.status = OSD_VISIBLE; 660 osd->status = OSD_VISIBLE;
451 osd_lcd_update_back_buffer(); 661 _osd_update_back_buffer(osd);
452 osd_lcd_draw(); 662 _osd_draw_osd(osd);
453 } 663 }
454 664
455 rb->lcd_update(); 665 osd->lcd_update();
456} 666}
457 667
458/* Update a part of the screen */ 668/* Update a part of the screen */
459void osd_lcd_update_rect(int x, int y, int width, int height) 669static void _osd_lcd_update_rect(struct osd *osd,
670 int x, int y, int width, int height)
460{ 671{
461 if (osd.status == OSD_ERASED) 672 if (osd->status == OSD_ERASED)
462 { 673 {
463 /* Save the screen image underneath and restore the OSD image */ 674 /* Save the screen image underneath and restore the OSD image */
464 osd.status = OSD_VISIBLE; 675 osd->status = OSD_VISIBLE;
465 osd_lcd_update_back_buffer(); 676 _osd_update_back_buffer(osd);
466 osd_lcd_draw(); 677 _osd_draw_osd(osd);
467 } 678 }
468 679
469 rb->lcd_update_rect(x, y, width, height); 680 osd->lcd_update_rect(x, y, width, height);
681}
682
683/* Native LCD, public */
684bool osd_init(unsigned flags, void *backbuf, size_t backbuf_size,
685 osd_draw_cb_fn_t draw_cb, int *width, int *height,
686 size_t *bufused)
687{
688 native_osd.init_buffers = _osd_lcd_init_buffers;
689 native_osd.set_viewport_pos = _osd_lcd_viewport_set_pos;
690 native_osd.lcd_update = rb->lcd_update;
691 native_osd.lcd_update_rect = rb->lcd_update_rect;
692 native_osd.lcd_set_viewport = rb->lcd_set_viewport;
693 native_osd.lcd_set_framebuffer = (void *)rb->lcd_set_framebuffer;
694#if LCD_DEPTH < 4
695 native_osd.lcd_framebuffer_set_pos = NULL;
696#endif /* LCD_DEPTH < 4 */
697 native_osd.lcd_bitmap_part = (void *)rb->lcd_bitmap_part;
698
699 return _osd_init(&native_osd, flags, backbuf, backbuf_size, draw_cb,
700 width, height, bufused);
701}
702
703void osd_destroy(void)
704{
705 return _osd_destroy(&native_osd);
706}
707
708bool osd_show(unsigned flags)
709{
710 return _osd_show(&native_osd, flags);
711}
712
713bool osd_update(void)
714{
715 return _osd_update(&native_osd);
716}
717
718bool osd_update_rect(int x, int y, int width, int height)
719{
720 return _osd_update_rect(&native_osd, x, y, width, height);
721}
722
723bool osd_update_pos(int x, int y, int width, int height)
724{
725 return _osd_update_pos(&native_osd, x, y, width, height);
726}
727
728void osd_monitor_timeout(void)
729{
730 _osd_monitor_timeout(&native_osd);
731}
732
733void osd_set_timeout(long timeout)
734{
735 _osd_set_timeout(&native_osd, timeout);
736}
737
738struct viewport * osd_get_viewport(void)
739{
740 return _osd_get_viewport(&native_osd);
741}
742
743void osd_get_max_dims(int *maxwidth, int *maxheight)
744{
745 _osd_get_max_dims(&native_osd, maxwidth, maxheight);
746}
747
748bool osd_enabled(void)
749{
750 return _osd_enabled(&native_osd);
751}
752
753void osd_lcd_update_prepare(void)
754{
755 _osd_lcd_update_prepare(&native_osd);
756}
757
758
759void osd_lcd_update(void)
760{
761 _osd_lcd_update(&native_osd);
762}
763
764void osd_lcd_update_rect(int x, int y, int width, int height)
765{
766 _osd_lcd_update_rect(&native_osd, x, y, width, height);
767}
768
769#if LCD_DEPTH < 4
770/* Greylib LCD, public */
771bool osd_grey_init(unsigned flags, void *backbuf, size_t backbuf_size,
772 osd_draw_cb_fn_t draw_cb, int *width, int *height,
773 size_t *bufused)
774{
775 grey_osd.init_buffers = _osd_grey_init_buffers;
776 grey_osd.set_viewport_pos = grey_viewport_set_pos;
777 grey_osd.lcd_update = grey_update;
778 grey_osd.lcd_update_rect = grey_update_rect;
779 grey_osd.lcd_set_viewport = grey_set_viewport;
780 grey_osd.lcd_set_framebuffer = (void *)grey_set_framebuffer;
781 grey_osd.lcd_framebuffer_set_pos = grey_framebuffer_set_pos;
782 grey_osd.lcd_bitmap_part = (void *)grey_gray_bitmap_part;
783
784 return _osd_init(&grey_osd, flags, backbuf, backbuf_size, draw_cb,
785 width, height, bufused);
786}
787
788void osd_grey_destroy(void)
789{
790 return _osd_destroy(&grey_osd);
791}
792
793bool osd_grey_show(unsigned flags)
794{
795 return _osd_show(&grey_osd, flags);
796}
797
798bool osd_grey_update(void)
799{
800 return _osd_update(&grey_osd);
801}
802
803bool osd_grey_update_rect(int x, int y, int width, int height)
804{
805 return _osd_update_rect(&grey_osd, x, y, width, height);
806}
807
808bool osd_grey_update_pos(int x, int y, int width, int height)
809{
810 return _osd_update_pos(&grey_osd, x, y, width, height);
811}
812
813void osd_grey_monitor_timeout(void)
814{
815 _osd_monitor_timeout(&grey_osd);
816}
817
818void osd_grey_set_timeout(long timeout)
819{
820 _osd_set_timeout(&grey_osd, timeout);
821}
822
823struct viewport * osd_grey_get_viewport(void)
824{
825 return _osd_get_viewport(&grey_osd);
826}
827
828void osd_grey_get_max_dims(int *maxwidth, int *maxheight)
829{
830 _osd_get_max_dims(&grey_osd, maxwidth, maxheight);
831}
832
833bool osd_grey_enabled(void)
834{
835 return _osd_enabled(&grey_osd);
836}
837
838void osd_grey_lcd_update_prepare(void)
839{
840 _osd_lcd_update_prepare(&grey_osd);
841}
842
843void osd_grey_lcd_update(void)
844{
845 _osd_lcd_update(&grey_osd);
846}
847
848void osd_grey_lcd_update_rect(int x, int y, int width, int height)
849{
850 _osd_lcd_update_rect(&grey_osd, x, y, width, height);
470} 851}
852#endif /* LCD_DEPTH < 4 */
diff --git a/apps/plugins/lib/osd.h b/apps/plugins/lib/osd.h
index 89441ae273..b5bf63d9fe 100644
--- a/apps/plugins/lib/osd.h
+++ b/apps/plugins/lib/osd.h
@@ -23,6 +23,10 @@
23#ifndef OSD_H 23#ifndef OSD_H
24#define OSD_H 24#define OSD_H
25 25
26#ifndef HAVE_LCD_BITMAP
27#error OSD requires bitmapped LCD
28#endif
29
26/* At this time: assumes use of the default viewport for normal drawing */ 30/* At this time: assumes use of the default viewport for normal drawing */
27 31
28/* Callback implemented by user. Paramters are OSD vp-relative coordinates */ 32/* Callback implemented by user. Paramters are OSD vp-relative coordinates */
@@ -30,8 +34,20 @@ typedef void (* osd_draw_cb_fn_t)(int x, int y, int width, int height);
30 34
31/* Initialize the OSD, set its backbuffer, update callback and enable it if 35/* Initialize the OSD, set its backbuffer, update callback and enable it if
32 * the call succeeded. */ 36 * the call succeeded. */
33bool osd_init(void *backbuf, size_t backbuf_size, 37enum osd_init_flags
34 osd_draw_cb_fn_t draw_cb); 38{
39 OSD_INIT_MAJOR_WIDTH = 0x0, /* Width guides buffer dims (default) */
40 OSD_INIT_MAJOR_HEIGHT = 0x1, /* Height guides buffer dims */
41 OSD_INIT_MINOR_MIN = 0x2, /* Treat minor axis dim as a minimum */
42 OSD_INIT_MINOR_MAX = 0x4, /* Treat minor axis dim as a maximum */
43 /* To get exact minor size, combine min/max flags */
44};
45bool osd_init(unsigned flags, void *backbuf, size_t backbuf_size,
46 osd_draw_cb_fn_t draw_cb, int *width,
47 int *height, size_t *bufused);
48
49/* Destroy the OSD, rendering it disabled */
50void osd_destroy(void);
35 51
36enum 52enum
37{ 53{
@@ -91,4 +107,46 @@ void osd_lcd_update(void);
91/* Update a part of the screen and restore OSD if it is visible */ 107/* Update a part of the screen and restore OSD if it is visible */
92void osd_lcd_update_rect(int x, int y, int width, int height); 108void osd_lcd_update_rect(int x, int y, int width, int height);
93 109
110#if LCD_DEPTH < 4
111/* Like other functions but for greylib surface (requires GREY_BUFFERED) */
112bool osd_grey_init(unsigned flags, void *backbuf, size_t backbuf_size,
113 osd_draw_cb_fn_t draw_cb, int *width,
114 int *height, size_t *bufused);
115void osd_grey_destroy(void);
116bool osd_grey_show(unsigned flags);
117bool osd_grey_update(void);
118bool osd_grey_update_rect(int x, int y, int width, int height);
119bool osd_grey_update_pos(int x, int y, int width, int height);
120void osd_grey_monitor_timeout(void);
121void osd_grey_set_timeout(long timeout);
122struct viewport * osd_grey_get_viewport(void);
123void osd_grey_get_max_dims(int *maxwidth, int *maxheight);
124bool osd_grey_enabled(void);
125void osd_grey_lcd_update_prepare(void);
126void osd_grey_lcd_update(void);
127void osd_grey_lcd_update_rect(int x, int y, int width, int height);
128#endif /* LCD_DEPTH < 4 */
129
130/* MYLCD-style helper defines to compile with different graphics libs */
131#ifdef __GREY_H__
132#define myosd_(fn) osd_grey_##fn
133#else
134#define myosd_(fn) osd_##fn
135#endif
136
137#define myosd_init myosd_(init)
138#define myosd_destroy myosd_(destroy)
139#define myosd_show myosd_(show)
140#define myosd_update myosd_(update)
141#define myosd_update_rect myosd_(update_rect)
142#define myosd_update_pos myosd_(update_pos)
143#define myosd_monitor_timeout myosd_(monitor_timeout)
144#define myosd_set_timeout myosd_(set_timeout)
145#define myosd_get_viewport myosd_(get_viewport)
146#define myosd_get_max_dims myosd_(get_max_dims)
147#define myosd_enabled myosd_(enabled)
148#define myosd_lcd_update_prepare myosd_(lcd_update_prepare)
149#define myosd_lcd_update myosd_(lcd_update)
150#define myosd_lcd_update_rect myosd_(lcd_update_rect)
151
94#endif /* OSD_H */ 152#endif /* OSD_H */