diff options
Diffstat (limited to 'apps/plugins/lib')
-rw-r--r-- | apps/plugins/lib/grey.h | 28 | ||||
-rw-r--r-- | apps/plugins/lib/grey_core.c | 9 | ||||
-rw-r--r-- | apps/plugins/lib/grey_draw.c | 300 | ||||
-rw-r--r-- | apps/plugins/lib/grey_parm.c | 161 | ||||
-rw-r--r-- | apps/plugins/lib/grey_scroll.c | 50 | ||||
-rw-r--r-- | apps/plugins/lib/mylcd.h | 11 | ||||
-rw-r--r-- | apps/plugins/lib/osd.c | 778 | ||||
-rw-r--r-- | apps/plugins/lib/osd.h | 62 |
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); | |||
60 | void grey_show(bool enable); | 60 | void grey_show(bool enable); |
61 | void grey_deferred_lcd_update(void); | 61 | void grey_deferred_lcd_update(void); |
62 | 62 | ||
63 | /* Viewports and framebuffers */ | ||
64 | void grey_clear_viewport(void); | ||
65 | void grey_set_viewport(struct viewport *vp); | ||
66 | void grey_viewport_set_fullscreen(struct viewport *vp, | ||
67 | const enum screen_type screen); | ||
68 | void grey_viewport_set_pos(struct viewport *vp, | ||
69 | int x, int y, int width, int height); | ||
70 | void grey_set_framebuffer(unsigned char *buffer); | ||
71 | void grey_framebuffer_set_pos(int x, int y, int width, int height); | ||
72 | |||
63 | /* Update functions */ | 73 | /* Update functions */ |
64 | void grey_update(void); | 74 | void grey_update(void); |
65 | void grey_update_rect(int x, int y, int width, int height); | 75 | void 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 */ |
186 | extern struct _grey_info _grey_info; | 206 | extern 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 | ||
31 | extern struct viewport _grey_default_vp; | ||
32 | |||
31 | /*** low-level drawing functions ***/ | 33 | /*** low-level drawing functions ***/ |
32 | 34 | ||
33 | static void setpixel(unsigned char *address) | 35 | static 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 | ||
38 | static void clearpixel(unsigned char *address) | 40 | static 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 | ||
43 | static void flippixel(unsigned char *address) | 45 | static 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 */ | ||
63 | void 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 */ |
61 | void grey_clear_display(void) | 73 | void 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 */ |
71 | void grey_drawpixel(int x, int y) | 85 | void 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 */ |
80 | void grey_drawline(int x1, int y1, int x2, int y2) | 100 | void 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) */ |
152 | void grey_hline(int x1, int x2, int y) | 182 | void 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) */ |
212 | void grey_vline(int x, int y1, int y2) | 247 | void 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 */ |
335 | void grey_fillrect(int x, int y, int width, int height) | 375 | void 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) | |||
413 | void grey_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | 463 | void 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) */ |
625 | void grey_ub_clear_display(void) | 698 | void 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 */ | ||
32 | struct 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 */ |
65 | void grey_set_drawmode(int mode) | 68 | void 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 */ |
71 | int grey_get_drawmode(void) | 74 | int 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 */ |
77 | void grey_set_foreground(unsigned brightness) | 80 | void 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 */ |
83 | unsigned grey_get_foreground(void) | 86 | unsigned 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 */ |
89 | void grey_set_background(unsigned brightness) | 92 | void 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 */ |
95 | unsigned grey_get_background(void) | 98 | unsigned 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 */ |
109 | void grey_setfont(int newfont) | 112 | void 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 */ |
115 | int grey_getstringsize(const unsigned char *str, int *w, int *h) | 118 | int 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 */ | ||
124 | static 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 */ | ||
157 | void 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 */ | ||
170 | void 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 | |||
191 | void 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 */ | ||
213 | void 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 */ | ||
234 | void 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 | ||
31 | extern struct viewport _grey_default_vp; | ||
32 | |||
31 | /*** Scrolling ***/ | 33 | /*** Scrolling ***/ |
32 | 34 | ||
33 | /* Scroll left */ | 35 | /* Scroll left */ |
34 | void grey_scroll_left(int count) | 36 | void 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 */ |
62 | void grey_scroll_right(int count) | 65 | void 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 */ |
89 | void grey_scroll_up(int count) | 93 | void 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 */ |
111 | void grey_scroll_down(int count) | 116 | void 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 */ |
135 | void grey_ub_scroll_left(int count) | 141 | void 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 */ |
168 | void grey_ub_scroll_right(int count) | 175 | void 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 */ |
200 | void grey_ub_scroll_up(int count) | 208 | void 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 */ |
275 | void grey_ub_scroll_down(int count) | 284 | void 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 */ |
34 | static struct osd | 45 | struct 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 | |||
78 | static struct osd native_osd; | ||
79 | #if LCD_DEPTH < 4 | ||
80 | static 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 | |||
135 | static void _osd_destroy(struct osd *osd); | ||
136 | static 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 */ |
100 | static fb_data * buf_to_fb_bitmap(void *buf, size_t bufsize, | 142 | static 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 | ||
138 | static 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 */ |
147 | static void osd_lcd_update_back_buffer(void) | 239 | static 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 | |
157 | static void osd_lcd_erase(void) | 249 | #if LCD_DEPTH < 4 |
250 | /** Greylib LCD routines **/ | ||
251 | |||
252 | /* Create a greylib bitmap framebuffer from a buffer */ | ||
253 | static 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 */ |
164 | static void osd_lcd_draw_rect(int x, int y, int width, int height) | 314 | static 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 */ |
172 | static void osd_lcd_draw(void) | 323 | static 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 | ||
328 | static 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 */ |
335 | static 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 */ |
181 | bool osd_init(void *backbuf, size_t backbuf_size, | 351 | static 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); | 358 | static 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 | |||
435 | static 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 */ | ||
447 | static 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 */ |
246 | bool osd_show(unsigned flags) | 458 | static 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 */ | ||
294 | bool 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) */ |
308 | bool osd_update_rect(int x, int y, int width, int height) | 505 | static 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) */ |
345 | bool osd_update_pos(int x, int y, int width, int height) | 549 | static 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 */ |
390 | void osd_monitor_timeout(void) | 599 | static 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 */ |
400 | void osd_set_timeout(long timeout) | 609 | static 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 */ |
410 | struct viewport * osd_get_viewport(void) | 619 | static 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() */ |
416 | void osd_get_max_dims(int *maxwidth, int *maxheight) | 625 | static 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? */ |
426 | bool osd_enabled(void) | 636 | static 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 */ |
435 | void osd_lcd_update_prepare(void) | 645 | static 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 */ |
445 | void osd_lcd_update(void) | 655 | static 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 */ |
459 | void osd_lcd_update_rect(int x, int y, int width, int height) | 669 | static 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 */ | ||
684 | bool 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 | |||
703 | void osd_destroy(void) | ||
704 | { | ||
705 | return _osd_destroy(&native_osd); | ||
706 | } | ||
707 | |||
708 | bool osd_show(unsigned flags) | ||
709 | { | ||
710 | return _osd_show(&native_osd, flags); | ||
711 | } | ||
712 | |||
713 | bool osd_update(void) | ||
714 | { | ||
715 | return _osd_update(&native_osd); | ||
716 | } | ||
717 | |||
718 | bool 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 | |||
723 | bool 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 | |||
728 | void osd_monitor_timeout(void) | ||
729 | { | ||
730 | _osd_monitor_timeout(&native_osd); | ||
731 | } | ||
732 | |||
733 | void osd_set_timeout(long timeout) | ||
734 | { | ||
735 | _osd_set_timeout(&native_osd, timeout); | ||
736 | } | ||
737 | |||
738 | struct viewport * osd_get_viewport(void) | ||
739 | { | ||
740 | return _osd_get_viewport(&native_osd); | ||
741 | } | ||
742 | |||
743 | void osd_get_max_dims(int *maxwidth, int *maxheight) | ||
744 | { | ||
745 | _osd_get_max_dims(&native_osd, maxwidth, maxheight); | ||
746 | } | ||
747 | |||
748 | bool osd_enabled(void) | ||
749 | { | ||
750 | return _osd_enabled(&native_osd); | ||
751 | } | ||
752 | |||
753 | void osd_lcd_update_prepare(void) | ||
754 | { | ||
755 | _osd_lcd_update_prepare(&native_osd); | ||
756 | } | ||
757 | |||
758 | |||
759 | void osd_lcd_update(void) | ||
760 | { | ||
761 | _osd_lcd_update(&native_osd); | ||
762 | } | ||
763 | |||
764 | void 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 */ | ||
771 | bool 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 | |||
788 | void osd_grey_destroy(void) | ||
789 | { | ||
790 | return _osd_destroy(&grey_osd); | ||
791 | } | ||
792 | |||
793 | bool osd_grey_show(unsigned flags) | ||
794 | { | ||
795 | return _osd_show(&grey_osd, flags); | ||
796 | } | ||
797 | |||
798 | bool osd_grey_update(void) | ||
799 | { | ||
800 | return _osd_update(&grey_osd); | ||
801 | } | ||
802 | |||
803 | bool 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 | |||
808 | bool 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 | |||
813 | void osd_grey_monitor_timeout(void) | ||
814 | { | ||
815 | _osd_monitor_timeout(&grey_osd); | ||
816 | } | ||
817 | |||
818 | void osd_grey_set_timeout(long timeout) | ||
819 | { | ||
820 | _osd_set_timeout(&grey_osd, timeout); | ||
821 | } | ||
822 | |||
823 | struct viewport * osd_grey_get_viewport(void) | ||
824 | { | ||
825 | return _osd_get_viewport(&grey_osd); | ||
826 | } | ||
827 | |||
828 | void osd_grey_get_max_dims(int *maxwidth, int *maxheight) | ||
829 | { | ||
830 | _osd_get_max_dims(&grey_osd, maxwidth, maxheight); | ||
831 | } | ||
832 | |||
833 | bool osd_grey_enabled(void) | ||
834 | { | ||
835 | return _osd_enabled(&grey_osd); | ||
836 | } | ||
837 | |||
838 | void osd_grey_lcd_update_prepare(void) | ||
839 | { | ||
840 | _osd_lcd_update_prepare(&grey_osd); | ||
841 | } | ||
842 | |||
843 | void osd_grey_lcd_update(void) | ||
844 | { | ||
845 | _osd_lcd_update(&grey_osd); | ||
846 | } | ||
847 | |||
848 | void 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. */ |
33 | bool osd_init(void *backbuf, size_t backbuf_size, | 37 | enum 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 | }; | ||
45 | bool 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 */ | ||
50 | void osd_destroy(void); | ||
35 | 51 | ||
36 | enum | 52 | enum |
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 */ |
92 | void osd_lcd_update_rect(int x, int y, int width, int height); | 108 | void 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) */ | ||
112 | bool 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); | ||
115 | void osd_grey_destroy(void); | ||
116 | bool osd_grey_show(unsigned flags); | ||
117 | bool osd_grey_update(void); | ||
118 | bool osd_grey_update_rect(int x, int y, int width, int height); | ||
119 | bool osd_grey_update_pos(int x, int y, int width, int height); | ||
120 | void osd_grey_monitor_timeout(void); | ||
121 | void osd_grey_set_timeout(long timeout); | ||
122 | struct viewport * osd_grey_get_viewport(void); | ||
123 | void osd_grey_get_max_dims(int *maxwidth, int *maxheight); | ||
124 | bool osd_grey_enabled(void); | ||
125 | void osd_grey_lcd_update_prepare(void); | ||
126 | void osd_grey_lcd_update(void); | ||
127 | void 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 */ |