A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Floating on-screen display
11*
12* Copyright (C) 2012 Michael Sevakis
13*
14* This program is free software; you can redistribute it and/or
15* modify it under the terms of the GNU General Public License
16* as published by the Free Software Foundation; either version 2
17* of the License, or (at your option) any later version.
18*
19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20* KIND, either express or implied.
21*
22****************************************************************************/
23#include "plugin.h"
24#include "grey.h"
25#include "osd.h"
26
27#if 1
28#undef DEBUGF
29#define DEBUGF(...)
30#endif
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
42/* At this time: assumes use of the default viewport for normal drawing */
43
44/* If multiple OSD's are wanted, could convert to caller-allocated */
45struct osd
46{
47 enum osd_status
48 {
49 OSD_DISABLED = 0, /* Disabled entirely */
50 OSD_HIDDEN, /* Hidden from view */
51 OSD_VISIBLE, /* Visible on screen */
52 OSD_ERASED, /* Erased in preparation for regular drawing */
53 } status; /* View status */
54 struct viewport vp; /* Clipping viewport */
55 struct frame_buffer_t framebuf; /* Holds framebuffer reference */
56 int lcd_bitmap_stride; /* Stride of LCD bitmap */
57 void *lcd_bitmap_data; /* Backbuffer framebuffer data */
58 int back_bitmap_stride; /* Stride of backbuffer bitmap */
59 void *back_bitmap_data; /* LCD framebuffer data */
60 int maxwidth; /* How wide may it be at most? */
61 int maxheight; /* How high may it be at most? */
62 long timeout; /* Current popup stay duration */
63 long hide_tick; /* Tick when it should be hidden */
64 osd_draw_cb_fn_t draw_cb; /* Draw update callback */
65 /* Functions to factilitate interface compatibility of OSD types */
66 void * (*init_buffers)(struct osd *osd, unsigned flags, void *buf,
67 size_t *bufsize);
68 void (*set_viewport_pos)(struct viewport *vp, int x, int y, int width,
69 int height);
70 void (*lcd_update)(void);
71 void (*lcd_update_rect)(int x, int y, int width, int height);
72 struct viewport *(*lcd_set_viewport)(struct viewport *vp);
73 void (*lcd_set_framebuffer)(void *buf);
74 void (*lcd_framebuffer_set_pos)(int x, int y, int width, int height);
75 void (*lcd_bitmap_part)(const void *src, int src_x, int src_y,
76 int stride, int x, int y, int width, int height);
77};
78
79static struct osd native_osd;
80#if LCD_DEPTH < 4
81static struct osd grey_osd;
82#endif
83
84/* Framebuffer allocation macros */
85#if LCD_DEPTH == 1
86# if LCD_PIXELFORMAT == HORIZONTAL_PACKING
87# define _OSD_WIDTH2BYTES(w) (((w)+7)/8)
88# define _OSD_BYTES2WIDTH(b) ((b)*8)
89# elif LCD_PIXELFORMAT == VERTICAL_PACKING
90# define _OSD_HEIGHT2BYTES(h) (((h)+7)/8)
91# define _OSD_BYTES2HEIGHT(b) ((b)*8)
92# else
93# error Unknown 1-bit format; please define macros
94# endif /* LCD_PIXELFORMAT */
95#elif LCD_DEPTH == 2
96# if LCD_PIXELFORMAT == HORIZONTAL_PACKING
97# define _OSD_WIDTH2BYTES(w) (((w)+3)/4)
98# define _OSD_BYTES2WIDTH(b) ((b)*4)
99# elif LCD_PIXELFORMAT == VERTICAL_PACKING
100# define _OSD_HEIGHT2BYTES(h) (((h)+3)/4)
101# define _OSD_BYTES2HEIGHT(b) ((b)*4)
102# elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
103# define _OSD_HEIGHT2BYTES(h) (((h)+7)/8*2)
104# define _OSD_BYTES2HEIGHT(b) ((b)/2*8)
105# else
106# error Unknown 2-bit format; please define macros
107# endif /* LCD_PIXELFORMAT */
108#elif LCD_DEPTH == 16
109# if LCD_STRIDEFORMAT == VERTICAL_STRIDE
110# define _OSD_HEIGHT2BYTES(h) ((h)*2)
111# define _OSD_BYTES2HEIGHT(b) ((b)/2)
112# else /* LCD_STRIDEFORMAT != VERTICAL_STRIDE */
113# define _OSD_WIDTH2BYTES(w) ((w)*2)
114# define _OSD_BYTES2WIDTH(b) ((b)/2)
115# endif /* end stride type selection */
116#elif LCD_DEPTH == 24
117# define _OSD_WIDTH2BYTES(w) ((w)*3)
118# define _OSD_BYTES2WIDTH(b) ((b)/3)
119#elif LCD_DEPTH == 32
120# define _OSD_WIDTH2BYTES(w) ((w)*4)
121# define _OSD_BYTES2WIDTH(b) ((b)/4)
122#else /* other LCD depth */
123# error Unknown LCD depth; please define macros
124#endif /* LCD_DEPTH */
125/* Set defaults if not defined differently */
126#ifndef _OSD_WIDTH2BYTES
127# define _OSD_WIDTH2BYTES(w) (w)
128#endif
129#ifndef _OSD_BYTES2WIDTH
130# define _OSD_BYTES2WIDTH(b) (b)
131#endif
132#ifndef _OSD_HEIGHT2BYTES
133# define _OSD_HEIGHT2BYTES(h) (h)
134#endif
135#ifndef _OSD_BYTES2HEIGHT
136# define _OSD_BYTES2HEIGHT(b) (b)
137#endif
138#ifndef _OSD_BUFSIZE
139# define _OSD_BUFSIZE(w, h) (_OSD_WIDTH2BYTES(w)*_OSD_HEIGHT2BYTES(h))
140#endif
141
142static void _osd_destroy(struct osd *osd);
143static bool _osd_show(struct osd *osd, unsigned flags);
144
145
146/** Native LCD routines **/
147
148/* Create a bitmap framebuffer from a buffer */
149static void * _osd_lcd_init_buffers(struct osd *osd, unsigned flags,
150 void *buf, size_t *bufsize)
151{
152 /* Used as dest, the LCD functions cannot deal with alternate
153 strides as of now - the stride guides the calulations. If
154 that is no longer the case, then width or height can be
155 used instead (and less memory needed for a small surface!).
156 IOW: crappiness means one dimension is non-negotiable.
157 */
158 DEBUGF("OSD: in(buf=%p bufsize=%lu)\n", buf,
159 (unsigned long)*bufsize);
160
161 rb->viewport_set_fullscreen(&osd->vp, SCREEN_MAIN);
162
163#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
164 int colbytes = _OSD_HEIGHT2BYTES(LCD_HEIGHT);
165 int bytecols = *bufsize / colbytes;
166 int w = _OSD_BYTES2WIDTH(bytecols);
167 int h = _OSD_BYTES2HEIGHT(colbytes);
168
169 if (flags & OSD_INIT_MAJOR_HEIGHT)
170 {
171 if (w == 0 || ((flags & OSD_INIT_MINOR_MIN) && w < osd->maxwidth))
172 {
173 DEBUGF("OSD: not enough buffer\n");
174 return NULL; /* not enough buffer */
175 }
176
177 if ((flags & OSD_INIT_MINOR_MAX) && w > osd->maxwidth)
178 w = osd->maxwidth;
179 }
180 else /* OSD_INIT_MAJOR_WIDTH implied */
181 {
182 if (w == 0 || w < osd->maxwidth)
183 {
184 DEBUGF("OSD: not enough buffer\n");
185 return NULL; /* not enough buffer */
186 }
187 else if (w > osd->maxwidth)
188 {
189 w = osd->maxwidth;
190 }
191 }
192
193 w = _OSD_BYTES2WIDTH(_OSD_WIDTH2BYTES(w));
194 osd->lcd_bitmap_stride = _OSD_BYTES2HEIGHT(_OSD_HEIGHT2BYTES(LCD_HEIGHT));
195 osd->back_bitmap_stride = h;
196#else /* LCD_STRIDEFORMAT != VERTICAL_STRIDE */
197 int rowbytes = _OSD_WIDTH2BYTES(LCD_WIDTH);
198 int byterows = *bufsize / rowbytes;
199 int w = _OSD_BYTES2WIDTH(rowbytes);
200 int h = _OSD_BYTES2HEIGHT(byterows);
201
202 if (flags & OSD_INIT_MAJOR_HEIGHT)
203 {
204 if (h == 0 || h < osd->maxheight)
205 {
206 DEBUGF("OSD: not enough buffer\n");
207 return NULL;
208 }
209 else if (h > osd->maxheight)
210 {
211 h = osd->maxheight;
212 }
213 }
214 else /* OSD_INIT_MAJOR_WIDTH implied */
215 {
216 if (h == 0 || ((flags & OSD_INIT_MINOR_MIN) && h < osd->maxheight))
217 {
218 DEBUGF("OSD: not enough buffer\n");
219 return NULL;
220 }
221
222 if ((flags & OSD_INIT_MINOR_MAX) && h > osd->maxheight)
223 h = osd->maxheight;
224 }
225
226 h = _OSD_BYTES2HEIGHT(_OSD_HEIGHT2BYTES(h));
227 osd->lcd_bitmap_stride = _OSD_BYTES2WIDTH(_OSD_WIDTH2BYTES(LCD_WIDTH));
228 osd->back_bitmap_stride = w;
229#endif /* end stride type selection */
230
231 /* vp is currently initialized to the default framebuffer */
232 osd->lcd_bitmap_data = osd->vp.buffer->data;
233 osd->back_bitmap_data = buf;
234
235 osd->maxwidth = w;
236 osd->maxheight = h;
237 *bufsize = _OSD_BUFSIZE(w, h);
238
239 DEBUGF("OSD: addr(fb=%p bb=%p)\n", osd->lcd_bitmap_data,
240 osd->back_bitmap_data);
241 DEBUGF("OSD: w=%d h=%d bufsz=%lu\n", w, h, (unsigned long)*bufsize);
242
243 return buf;
244}
245
246/* Set viewport coordinates */
247static void _osd_lcd_viewport_set_pos(
248 struct viewport *vp, int x, int y, int width, int height)
249{
250 vp->x = x;
251 vp->y = y;
252 vp->width = width;
253 vp->height = height;
254}
255
256
257#if LCD_DEPTH < 4
258/** Greylib LCD routines **/
259
260/* Create a greylib bitmap framebuffer from a buffer */
261static void * _osd_grey_init_buffers(struct osd *osd, unsigned flags,
262 void *buf, size_t *bufsize)
263{
264 int w, h;
265
266 DEBUGF("OSD (grey): in(buf=%p bufsize=%lu)\n", buf,
267 (unsigned long)*bufsize);
268
269 grey_viewport_set_fullscreen(&osd->vp, SCREEN_MAIN);
270
271 if (flags & OSD_INIT_MAJOR_HEIGHT)
272 {
273 h = osd->maxheight;
274 w = *bufsize / h;
275
276 if (w == 0 || ((flags & OSD_INIT_MINOR_MIN) && w < osd->maxwidth))
277 {
278 DEBUGF("OSD (grey): Not enough buffer\n");
279 return NULL;
280 }
281
282 if ((flags & OSD_INIT_MINOR_MAX) && w > osd->maxwidth)
283 w = osd->maxwidth;
284 }
285 else /* OSD_INIT_MAJOR_WIDTH implied */
286 {
287 w = osd->maxwidth;
288 h = *bufsize / w;
289
290 if (h == 0 || ((flags & OSD_INIT_MINOR_MIN) && h < osd->maxheight))
291 {
292 DEBUGF("OSD (grey): Not enough buffer\n");
293 return NULL;
294 }
295
296 if ((flags & OSD_INIT_MINOR_MAX) && h > osd->maxheight)
297 h = osd->maxheight;
298 }
299
300 /* Have to peek into _grey_info a bit */
301 osd->lcd_bitmap_stride = _grey_info.width;
302 osd->lcd_bitmap_data = _grey_info.buffer;
303 osd->back_bitmap_stride = w;
304 osd->back_bitmap_data = buf;
305
306 osd->maxwidth = w;
307 osd->maxheight = h;
308 *bufsize = w * h;
309
310 DEBUGF("OSD (grey): addr(fb=%p bb=%p)\n", osd->lcd_bitmap_data,
311 osd->back_bitmap_data);
312 DEBUGF("OSD (grey): w=%d h=%d bufsz=%lu\n", w, h, (unsigned long)*bufsize);
313
314 return buf;
315}
316#endif /* LCD_DEPTH < 4*/
317
318
319/** Common LCD routines **/
320
321/* Draw the OSD image portion using the callback */
322static void _osd_draw_osd_rect(struct osd *osd, int x, int y,
323 int width, int height)
324{
325 osd->lcd_set_viewport(&osd->vp);
326 osd->draw_cb(x, y, width, height);
327 osd->lcd_set_viewport(NULL);
328}
329
330/* Draw the OSD image using the callback */
331static void _osd_draw_osd(struct osd *osd)
332{
333 _osd_draw_osd_rect(osd, 0, 0, osd->vp.width, osd->vp.height);
334}
335
336static void _osd_update_viewport(struct osd *osd)
337{
338 osd->lcd_update_rect(osd->vp.x, osd->vp.y, osd->vp.width,
339 osd->vp.height);
340}
341
342/* Sync the backbuffer to the framebuffer image */
343static void _osd_update_back_buffer(struct osd *osd)
344{
345 /* Assume it's starting with default viewport for now */
346 osd->lcd_set_framebuffer(osd->back_bitmap_data);
347#if LCD_DEPTH < 4
348 if (osd->lcd_framebuffer_set_pos)
349 osd->lcd_framebuffer_set_pos(0, 0, osd->maxwidth, osd->maxheight);
350#endif /* LCD_DEPTH < 4 */
351 osd->lcd_bitmap_part(osd->lcd_bitmap_data, osd->vp.x, osd->vp.y,
352 osd->lcd_bitmap_stride, 0, 0, osd->vp.width,
353 osd->vp.height);
354 /* Assume it was on default framebuffer for now */
355 osd->lcd_set_framebuffer(NULL);
356}
357
358/* Erase the OSD to restore the framebuffer image */
359static void _osd_erase_osd(struct osd *osd)
360{
361 osd->lcd_bitmap_part(osd->back_bitmap_data, 0, 0, osd->back_bitmap_stride,
362 osd->vp.x, osd->vp.y, osd->vp.width, osd->vp.height);
363}
364
365/* Initialized the OSD and set its backbuffer */
366static bool _osd_init(struct osd *osd, unsigned flags, void *backbuf,
367 size_t backbuf_size, osd_draw_cb_fn_t draw_cb,
368 int *width, int *height, size_t *bufused)
369{
370 _osd_destroy(osd);
371
372 if (!draw_cb)
373 return false;
374
375 if (!backbuf)
376 return false;
377
378 void *backbuf_orig = backbuf; /* Save in case of ptr advance */
379 ALIGN_BUFFER(backbuf, backbuf_size, MAX(FB_DATA_SZ, 4));
380
381 if (!backbuf_size)
382 return false;
383
384 if (flags & OSD_INIT_MAJOR_HEIGHT)
385 {
386 if (!height || *height <= 0)
387 return false;
388
389 if ((flags & (OSD_INIT_MINOR_MIN | OSD_INIT_MINOR_MAX)) &&
390 (!width || *width <= 0))
391 {
392 return false;
393 }
394 }
395 else
396 {
397 if (!width || *width <= 0)
398 return false;
399
400 if ((flags & (OSD_INIT_MINOR_MIN | OSD_INIT_MINOR_MAX)) &&
401 (!height || *height <= 0))
402 {
403 return false;
404 }
405 }
406
407 /* Store requested sizes in max(width|height) */
408 if (width)
409 osd->maxwidth = *width;
410 else
411 osd->maxwidth = LCD_WIDTH;
412
413 if (height)
414 osd->maxheight = *height;
415 else
416 osd->maxheight = LCD_HEIGHT;
417
418 if (!osd->init_buffers(osd, flags, backbuf, &backbuf_size))
419 {
420 osd->maxwidth = osd->maxheight = 0;
421 return false;
422 }
423
424 osd->draw_cb = draw_cb;
425
426 if (bufused)
427 *bufused = backbuf_size + (backbuf_orig - backbuf);
428
429 if (width)
430 *width = osd->maxwidth;
431
432 if (height)
433 *height = osd->maxheight;
434
435 /* Set the default position to the whole thing */
436 osd->set_viewport_pos(&osd->vp, 0, 0, osd->maxwidth, osd->maxheight);
437
438 osd->status = OSD_HIDDEN; /* Ready when you are */
439
440 return true;
441}
442
443static void _osd_destroy(struct osd *osd)
444{
445 _osd_show(osd, OSD_HIDE);
446
447 /* Set to essential defaults */
448 osd->status = OSD_DISABLED;
449 osd->set_viewport_pos(&osd->vp, 0, 0, 0, 0);
450 osd->maxwidth = osd->maxheight = 0;
451 osd->timeout = 0;
452}
453
454/* Redraw the entire OSD */
455static bool _osd_update(struct osd *osd)
456{
457 if (osd->status != OSD_VISIBLE)
458 return false;
459
460 _osd_draw_osd(osd);
461 _osd_update_viewport(osd);
462 return true;
463}
464
465/* Show/Hide the OSD on screen */
466static bool _osd_show(struct osd *osd, unsigned flags)
467{
468 if (flags & OSD_SHOW)
469 {
470 switch (osd->status)
471 {
472 case OSD_DISABLED:
473 break; /* No change */
474
475 case OSD_HIDDEN:
476 _osd_update_back_buffer(osd);
477 osd->status = OSD_VISIBLE;
478 _osd_update(osd);
479 osd->hide_tick = *rb->current_tick + osd->timeout;
480 break;
481
482 case OSD_VISIBLE:
483 if (flags & OSD_UPDATENOW)
484 _osd_update(osd);
485 /* Fall-through */
486 case OSD_ERASED:
487 osd->hide_tick = *rb->current_tick + osd->timeout;
488 return true;
489 }
490 }
491 else
492 {
493 switch (osd->status)
494 {
495 case OSD_DISABLED:
496 case OSD_HIDDEN:
497 break;
498
499 case OSD_VISIBLE:
500 _osd_erase_osd(osd);
501 _osd_update_viewport(osd);
502 /* Fall-through */
503 case OSD_ERASED:
504 osd->status = OSD_HIDDEN;
505 return true;
506 }
507 }
508
509 return false;
510}
511
512/* Redraw part of the OSD (viewport-relative coordinates) */
513static bool _osd_update_rect(struct osd *osd, int x, int y, int width,
514 int height)
515{
516 if (osd->status != OSD_VISIBLE)
517 return false;
518
519 _osd_draw_osd_rect(osd, x, y, width, height);
520
521 int vp_x = osd->vp.x;
522 int vp_w = osd->vp.width;
523
524 if (x + width > vp_w)
525 width = vp_w - x;
526
527 if (x < 0)
528 {
529 width += x;
530 x = 0;
531 }
532
533 if (width <= 0)
534 return false;
535
536 int vp_y = osd->vp.y;
537 int vp_h = osd->vp.height;
538
539 if (y + height > vp_h)
540 height = vp_h - y;
541
542 if (y < 0)
543 {
544 height += y;
545 y = 0;
546 }
547
548 if (height <= 0)
549 return false;
550
551 osd->lcd_update_rect(vp_x + x, vp_y + y, width, height);
552
553 return true;
554}
555
556/* Set a new screen location and size (screen coordinates) */
557static bool _osd_update_pos(struct osd *osd, int x, int y, int width,
558 int height)
559{
560 if (osd->status == OSD_DISABLED)
561 return false;
562
563 if (width < 0)
564 width = 0;
565 else if (width > osd->maxwidth)
566 width = osd->maxwidth;
567
568 if (height < 0)
569 height = 0;
570 else if (height > osd->maxheight)
571 height = osd->maxheight;
572
573 int vp_x = osd->vp.x;
574 int vp_y = osd->vp.y;
575 int vp_w = osd->vp.width;
576 int vp_h = osd->vp.height;
577
578 if (x == vp_x && y == vp_y && width == vp_w && height == vp_h)
579 return false; /* No change */
580
581 if (osd->status != OSD_VISIBLE)
582 {
583 /* Not visible - just update pos */
584 osd->set_viewport_pos(&osd->vp, x, y, width, height);
585 return false;
586 }
587
588 /* Visible area has changed */
589 _osd_erase_osd(osd);
590
591 /* Update the smallest rectangle that encloses both the old and new
592 regions to make the change free of flicker (they may overlap) */
593 int xu = MIN(vp_x, x);
594 int yu = MIN(vp_y, y);
595 int wu = MAX(vp_x + vp_w, x + width) - xu;
596 int hu = MAX(vp_y + vp_h, y + height) - yu;
597
598 osd->set_viewport_pos(&osd->vp, x, y, width, height);
599 _osd_update_back_buffer(osd);
600 _osd_draw_osd(osd);
601 osd->lcd_update_rect(xu, yu, wu, hu);
602
603 return true;
604}
605
606/* Call periodically to have the OSD timeout and hide itself */
607static void _osd_monitor_timeout(struct osd *osd)
608{
609 if (osd->status <= OSD_HIDDEN)
610 return; /* Already hidden/disabled */
611
612 if (osd->timeout > 0 && TIME_AFTER(*rb->current_tick, osd->hide_tick))
613 _osd_show(osd, OSD_HIDE);
614}
615
616/* Set the OSD timeout value. <= 0 = never timeout */
617static void _osd_set_timeout(struct osd *osd, long timeout)
618{
619 if (osd->status == OSD_DISABLED)
620 return;
621
622 osd->timeout = timeout;
623 _osd_monitor_timeout(osd);
624}
625
626/* Use the OSD viewport context */
627static inline struct viewport * _osd_get_viewport(struct osd *osd)
628{
629 return &osd->vp;
630}
631
632/* Get the maximum dimensions calculated by osd_init() */
633static void _osd_get_max_dims(struct osd *osd,
634 int *maxwidth, int *maxheight)
635{
636 if (maxwidth)
637 *maxwidth = osd->maxwidth;
638
639 if (maxheight)
640 *maxheight = osd->maxheight;
641}
642
643/* Is the OSD enabled? */
644static inline bool _osd_enabled(struct osd *osd)
645{
646 return osd->status != OSD_DISABLED;
647}
648
649
650/** LCD update substitutes **/
651
652/* Prepare LCD framebuffer for regular drawing */
653static inline void _osd_lcd_update_prepare(struct osd *osd)
654{
655 if (osd->status == OSD_VISIBLE)
656 {
657 osd->status = OSD_ERASED;
658 _osd_erase_osd(osd);
659 }
660}
661
662/* Update the whole screen */
663static inline void _osd_lcd_update(struct osd *osd)
664{
665 if (osd->status == OSD_ERASED)
666 {
667 /* Save the screen image underneath and restore the OSD image */
668 osd->status = OSD_VISIBLE;
669 _osd_update_back_buffer(osd);
670 _osd_draw_osd(osd);
671 }
672
673 osd->lcd_update();
674}
675
676/* Update a part of the screen */
677static void _osd_lcd_update_rect(struct osd *osd,
678 int x, int y, int width, int height)
679{
680 if (osd->status == OSD_ERASED)
681 {
682 /* Save the screen image underneath and restore the OSD image */
683 osd->status = OSD_VISIBLE;
684 _osd_update_back_buffer(osd);
685 _osd_draw_osd(osd);
686 }
687
688 osd->lcd_update_rect(x, y, width, height);
689}
690
691static void _osd_lcd_viewport_set_buffer(void *buffer)
692{
693 if (buffer)
694 {
695 native_osd.framebuf.data = buffer;
696 native_osd.framebuf.elems = native_osd.maxheight * native_osd.maxwidth;
697 native_osd.framebuf.get_address_fn = NULL; /*Default iterator*/
698
699 if (buffer == native_osd.back_bitmap_data)
700 native_osd.framebuf.stride = (native_osd.back_bitmap_stride);
701 else
702 native_osd.framebuf.stride = (native_osd.lcd_bitmap_stride);
703
704 rb->viewport_set_buffer(NULL, &native_osd.framebuf, SCREEN_MAIN);
705 }
706 else
707 rb->viewport_set_buffer(NULL, NULL, SCREEN_MAIN);
708}
709
710/* Native LCD, public */
711bool osd_init(unsigned flags, void *backbuf, size_t backbuf_size,
712 osd_draw_cb_fn_t draw_cb, int *width, int *height,
713 size_t *bufused)
714{
715 native_osd.init_buffers = _osd_lcd_init_buffers;
716 native_osd.set_viewport_pos = _osd_lcd_viewport_set_pos;
717 native_osd.lcd_update = rb->lcd_update;
718 native_osd.lcd_update_rect = rb->lcd_update_rect;
719 native_osd.lcd_set_viewport = rb->lcd_set_viewport;
720 native_osd.lcd_set_framebuffer = (void *)_osd_lcd_viewport_set_buffer;
721#if LCD_DEPTH < 4
722 native_osd.lcd_framebuffer_set_pos = NULL;
723#endif /* LCD_DEPTH < 4 */
724 native_osd.lcd_bitmap_part = (void *)rb->lcd_bitmap_part;
725
726 return _osd_init(&native_osd, flags, backbuf, backbuf_size, draw_cb,
727 width, height, bufused);
728}
729
730void osd_destroy(void)
731{
732 return _osd_destroy(&native_osd);
733}
734
735bool osd_show(unsigned flags)
736{
737 return _osd_show(&native_osd, flags);
738}
739
740bool osd_update(void)
741{
742 return _osd_update(&native_osd);
743}
744
745bool osd_update_rect(int x, int y, int width, int height)
746{
747 return _osd_update_rect(&native_osd, x, y, width, height);
748}
749
750bool osd_update_pos(int x, int y, int width, int height)
751{
752 return _osd_update_pos(&native_osd, x, y, width, height);
753}
754
755void osd_monitor_timeout(void)
756{
757 _osd_monitor_timeout(&native_osd);
758}
759
760void osd_set_timeout(long timeout)
761{
762 _osd_set_timeout(&native_osd, timeout);
763}
764
765struct viewport * osd_get_viewport(void)
766{
767 return _osd_get_viewport(&native_osd);
768}
769
770void osd_get_max_dims(int *maxwidth, int *maxheight)
771{
772 _osd_get_max_dims(&native_osd, maxwidth, maxheight);
773}
774
775bool osd_enabled(void)
776{
777 return _osd_enabled(&native_osd);
778}
779
780void osd_lcd_update_prepare(void)
781{
782 _osd_lcd_update_prepare(&native_osd);
783}
784
785
786void osd_lcd_update(void)
787{
788 _osd_lcd_update(&native_osd);
789}
790
791void osd_lcd_update_rect(int x, int y, int width, int height)
792{
793 _osd_lcd_update_rect(&native_osd, x, y, width, height);
794}
795
796#if LCD_DEPTH < 4
797/* Greylib LCD, public */
798bool osd_grey_init(unsigned flags, void *backbuf, size_t backbuf_size,
799 osd_draw_cb_fn_t draw_cb, int *width, int *height,
800 size_t *bufused)
801{
802 grey_osd.init_buffers = _osd_grey_init_buffers;
803 grey_osd.set_viewport_pos = grey_viewport_set_pos;
804 grey_osd.lcd_update = grey_update;
805 grey_osd.lcd_update_rect = grey_update_rect;
806 grey_osd.lcd_set_viewport = grey_set_viewport;
807 grey_osd.lcd_set_framebuffer = (void *)grey_set_framebuffer;
808 grey_osd.lcd_framebuffer_set_pos = grey_framebuffer_set_pos;
809 grey_osd.lcd_bitmap_part = (void *)grey_gray_bitmap_part;
810
811 return _osd_init(&grey_osd, flags, backbuf, backbuf_size, draw_cb,
812 width, height, bufused);
813}
814
815void osd_grey_destroy(void)
816{
817 return _osd_destroy(&grey_osd);
818}
819
820bool osd_grey_show(unsigned flags)
821{
822 return _osd_show(&grey_osd, flags);
823}
824
825bool osd_grey_update(void)
826{
827 return _osd_update(&grey_osd);
828}
829
830bool osd_grey_update_rect(int x, int y, int width, int height)
831{
832 return _osd_update_rect(&grey_osd, x, y, width, height);
833}
834
835bool osd_grey_update_pos(int x, int y, int width, int height)
836{
837 return _osd_update_pos(&grey_osd, x, y, width, height);
838}
839
840void osd_grey_monitor_timeout(void)
841{
842 _osd_monitor_timeout(&grey_osd);
843}
844
845void osd_grey_set_timeout(long timeout)
846{
847 _osd_set_timeout(&grey_osd, timeout);
848}
849
850struct viewport * osd_grey_get_viewport(void)
851{
852 return _osd_get_viewport(&grey_osd);
853}
854
855void osd_grey_get_max_dims(int *maxwidth, int *maxheight)
856{
857 _osd_get_max_dims(&grey_osd, maxwidth, maxheight);
858}
859
860bool osd_grey_enabled(void)
861{
862 return _osd_enabled(&grey_osd);
863}
864
865void osd_grey_lcd_update_prepare(void)
866{
867 _osd_lcd_update_prepare(&grey_osd);
868}
869
870void osd_grey_lcd_update(void)
871{
872 _osd_lcd_update(&grey_osd);
873}
874
875void osd_grey_lcd_update_rect(int x, int y, int width, int height)
876{
877 _osd_lcd_update_rect(&grey_osd, x, y, width, height);
878}
879#endif /* LCD_DEPTH < 4 */