@@ -17,9 +17,8 @@ static int16_t map_viewport_to_source_y[RG_SCREEN_HEIGHT + 1];
1717static uint32_t screen_line_checksum [RG_SCREEN_HEIGHT + 1 ];
1818
1919// OSD Surface Management
20- static rg_surface_t * osd_surface = NULL ;
21- static rg_rect_t osd_rect ; // Store the OSD's position and size
2220static bool osd_enabled = false;
21+ static rg_osd_t osd ;
2322
2423#define LINE_IS_REPEATED (Y ) (map_viewport_to_source_y[(Y)] == map_viewport_to_source_y[(Y) - 1])
2524// This is to avoid flooring a number that is approximated to .9999999 and be explicit about it
@@ -42,28 +41,53 @@ static const char *SETTING_CUSTOM_ZOOM = "DispCustomZoom";
4241
4342// TODO : make it more user-friendly -> instead of specifying a rect and a surface
4443// just specify the corner and the dimensions (width and height)
45- void rg_display_set_osd_surface ( rg_surface_t * surface , rg_rect_t rect )
44+ rg_surface_t * rg_display_init_osd ( rg_corner_t corner , int width , int height , bool has_transparency )
4645{
47- // Free the old surface if it exists
48- if (osd_surface != NULL ) {
49- rg_surface_free (osd_surface );
50- }
46+ // clipping if osd > display
47+ width = RG_MIN (width , display .screen .width );
48+ height = RG_MIN (height , display .screen .height );
49+
50+ osd .has_transparency = has_transparency ;
5151
52- osd_surface = surface ;
53- osd_rect = rect ; // Store the position and size
54- if (surface != NULL )
55- { // Only clear if a surface is provided
56- uint16_t * buffer = surface -> data ; // Treat the buffer as 16-bit values
57- for (int i = 0 ; i < surface -> width * surface -> height ; i ++ )
58- buffer [i ] = C_TRANSPARENT ; // Assign the black color directly // C_TRANSPARENT
52+ int left , top ;
53+ switch (corner )
54+ {
55+ case CORNER_TOP_LEFT :
56+ left = 0 ;
57+ top = 0 ;
58+ break ;
59+ case CORNER_TOP_RIGHT :
60+ left = display .screen .width - width ;
61+ top = 0 ;
62+ break ;
63+ case CORNER_BOTTOM_LEFT :
64+ left = 0 ;
65+ top = display .screen .height - height ;
66+ break ;
67+ case CORNER_BOTTOM_RIGHT :
68+ left = display .screen .width - width ;
69+ top = display .screen .height - height ;
70+ break ;
71+ default :
72+ left = 0 ;
73+ top = 0 ;
74+ break ;
5975 }
6076
61- osd_enabled = (surface != NULL ); // Enable OSD if surface is valid
62- }
77+ osd .surface = rg_surface_create (width , height , RG_PIXEL_565_LE , MEM_SLOW );
6378
64- rg_surface_t * rg_display_get_osd_surface ()
65- {
66- return osd_surface ;
79+ osd .left = left ;
80+ osd .top = top ;
81+
82+ if (has_transparency )
83+ { // we fill the background with the "transparent color"
84+ uint16_t * buffer = osd .surface -> data ; // Treat the buffer as 16-bit values
85+ for (int i = 0 ; i < osd .surface -> width * osd .surface -> height ; i ++ )
86+ buffer [i ] = C_TRANSPARENT ; // Assign the C_TRANSPARENT color directly to the background
87+ }
88+
89+ osd_enabled = 1 ; // Enable OSD if surface is valid
90+ return osd .surface ;
6791}
6892
6993void rg_display_set_osd_enabled (bool enabled )
@@ -79,8 +103,7 @@ bool rg_display_is_osd_enabled()
79103
80104void deinit_osd ()
81105{
82- rg_surface_free (osd_surface ); // Free the OSD surface
83- osd_surface = NULL ;
106+ rg_surface_free (osd .surface ); // Free the OSD surface
84107 osd_enabled = false;
85108}
86109
@@ -253,25 +276,22 @@ static inline void write_update(const rg_surface_t *update)
253276 lines_remaining -= lines_to_copy ;
254277 }
255278
256- if (osd_enabled && osd_surface != NULL )
279+ if (osd_enabled )
257280 {
258281 // TODO: Draw on screen display. By default it should be bottom left which is fine
259282 // for both virtual keyboard and info labels. Maybe make it configurable later...
260- int * buffer = osd_surface -> data ;
283+ int * buffer = osd . surface -> data ;
261284 RG_ASSERT_ARG (buffer );
262285
263- // Clipping
264- int width = RG_MIN (osd_rect .width , display .screen .width - osd_rect .left );
265- int height = RG_MIN (osd_rect .height , display .screen .height - osd_rect .top );
286+ int width = osd .surface -> width ;
287+ int height = osd .surface -> height ;
266288
267- // This can happen when left or top is out of bound
268- if (width < 0 || height < 0 )
269- return ;
289+ int top = osd .top ;
290+ int left = osd .left ;
270291
271- lcd_set_window (osd_rect .left + display .screen .margin_left , osd_rect .top + display .screen .margin_top , width , height );
292+ lcd_set_window (osd .left + display .screen .margin_left , osd .top + display .screen .margin_top , width , height );
272293
273294 // TODO : find a way to get the background pixels
274- // TODO : only draw the osd when the "background surface" has changed
275295 for (size_t y = 0 ; y < height ;)
276296 {
277297 uint16_t * lcd_buffer = lcd_get_buffer (LCD_BUFFER_LENGTH );
@@ -280,7 +300,7 @@ static inline void write_update(const rg_surface_t *update)
280300 // Copy line by line because stride may not match width
281301 for (size_t line = 0 ; line < num_lines ; ++ line )
282302 {
283- uint16_t * src = (void * )buffer + ((y + line ) * osd_rect . width * 2 );
303+ uint16_t * src = (void * )buffer + ((y + line ) * osd . surface -> width * 2 );
284304 uint16_t * dst = lcd_buffer + (line * width );
285305 for (size_t i = 0 ; i < width ; ++ i ){
286306 if (src [i ] != C_TRANSPARENT ) // only overwrite pixels that aren't transparent
0 commit comments