A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 879 lines 24 kB view raw
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 */