1313#include <SDL.h>
1414#include "nsi_tracing.h"
1515
16+ static int sdl_create_rounded_display_mask (uint16_t width , uint16_t height , uint32_t mask_color ,
17+ void * * round_disp_mask , void * renderer )
18+ {
19+ * round_disp_mask = SDL_CreateTexture (renderer , SDL_PIXELFORMAT_ARGB8888 ,
20+ SDL_TEXTUREACCESS_STREAMING , width , height );
21+ if (* round_disp_mask == NULL ) {
22+ nsi_print_warning ("Failed to create SDL mask texture: %s" , SDL_GetError ());
23+ return -1 ;
24+ }
25+ SDL_SetTextureBlendMode (* round_disp_mask , SDL_BLENDMODE_BLEND );
26+
27+ void * mask_data ;
28+ int mask_pitch ;
29+ int err ;
30+
31+ err = SDL_LockTexture (* round_disp_mask , NULL , & mask_data , & mask_pitch );
32+ if (err != 0 ) {
33+ nsi_print_warning ("Failed to lock mask texture: %d" , err );
34+ return -1 ;
35+ }
36+
37+ /* Create ellipse mask */
38+ float cx = width / 2.0f ;
39+ float cy = height / 2.0f ;
40+ float rx = width / 2.0f ;
41+ float ry = height / 2.0f ;
42+
43+ for (int py = 0 ; py < height ; py ++ ) {
44+ uint32_t * row = (uint32_t * )((uint8_t * )mask_data + mask_pitch * py );
45+
46+ for (int px = 0 ; px < width ; px ++ ) {
47+ /* Calculate normalized distance from center */
48+ float dx = (px - cx ) / rx ;
49+ float dy = (py - cy ) / ry ;
50+ float distance = dx * dx + dy * dy ;
51+
52+ /* Inside ellipse: transparent, outside: mask color with full opacity */
53+ if (distance <= 1.0f ) {
54+ row [px ] = 0x00000000 ; /* Transparent */
55+ } else {
56+ uint32_t r = (mask_color >> 16 ) & 0xff ;
57+ uint32_t g = (mask_color >> 8 ) & 0xff ;
58+ uint32_t b = mask_color & 0xff ;
59+
60+ row [px ] = (0xFF << 24 ) | (r << 16 ) | (g << 8 ) | b ;
61+ }
62+ }
63+ }
64+ SDL_UnlockTexture (* round_disp_mask );
65+
66+ return 0 ;
67+ }
68+
1669int sdl_display_init_bottom (uint16_t height , uint16_t width , uint16_t zoom_pct ,
1770 bool use_accelerator , void * * window , const void * window_user_data ,
1871 const char * title , void * * renderer , void * * mutex , void * * texture ,
1972 void * * read_texture , void * * background_texture ,
2073 uint32_t transparency_grid_color1 , uint32_t transparency_grid_color2 ,
21- uint16_t transparency_grid_cell_size )
74+ uint16_t transparency_grid_cell_size , void * * round_disp_mask ,
75+ uint32_t mask_color )
2276{
2377 /* clang-format off */
2478 * window = SDL_CreateWindow (title , SDL_WINDOWPOS_UNDEFINED , SDL_WINDOWPOS_UNDEFINED ,
@@ -98,6 +152,16 @@ int sdl_display_init_bottom(uint16_t height, uint16_t width, uint16_t zoom_pct,
98152 }
99153 SDL_UnlockTexture (* background_texture );
100154
155+ /* Create ellipse mask texture if rounded mask is enabled */
156+ if (round_disp_mask != NULL ) {
157+ err = sdl_create_rounded_display_mask (width , height , mask_color , round_disp_mask ,
158+ * renderer );
159+ if (err != 0 ) {
160+ nsi_print_warning ("Failed to create rounded display mask" );
161+ return -1 ;
162+ }
163+ }
164+
101165 SDL_SetRenderDrawColor (* renderer , 0 , 0 , 0 , 0xFF );
102166 SDL_RenderClear (* renderer );
103167 SDL_RenderCopy (* renderer , * background_texture , NULL , NULL );
@@ -109,7 +173,7 @@ int sdl_display_init_bottom(uint16_t height, uint16_t width, uint16_t zoom_pct,
109173void sdl_display_write_bottom (const uint16_t height , const uint16_t width , const uint16_t x ,
110174 const uint16_t y , void * renderer , void * mutex , void * texture ,
111175 void * background_texture , uint8_t * buf , bool display_on ,
112- bool frame_incomplete , uint32_t color_tint )
176+ bool frame_incomplete , uint32_t color_tint , void * round_disp_mask )
113177{
114178 SDL_Rect rect ;
115179 int err ;
@@ -136,6 +200,13 @@ void sdl_display_write_bottom(const uint16_t height, const uint16_t width, const
136200 color_tint & 0xff );
137201 SDL_RenderCopy (renderer , texture , NULL , NULL );
138202 SDL_SetTextureColorMod (texture , 255 , 255 , 255 );
203+
204+ if (round_disp_mask != NULL ) {
205+ SDL_SetRenderDrawBlendMode (renderer , SDL_BLENDMODE_MOD );
206+ SDL_RenderCopy (renderer , round_disp_mask , NULL , NULL );
207+ SDL_SetRenderDrawBlendMode (renderer , SDL_BLENDMODE_BLEND );
208+ }
209+
139210 SDL_RenderPresent (renderer );
140211 }
141212
@@ -177,7 +248,7 @@ int sdl_display_read_bottom(const uint16_t height, const uint16_t width,
177248}
178249
179250void sdl_display_blanking_off_bottom (void * renderer , void * texture , void * background_texture ,
180- uint32_t color_tint )
251+ uint32_t color_tint , void * round_disp_mask )
181252{
182253 SDL_RenderClear (renderer );
183254 SDL_RenderCopy (renderer , background_texture , NULL , NULL );
@@ -187,6 +258,14 @@ void sdl_display_blanking_off_bottom(void *renderer, void *texture, void *backgr
187258 color_tint & 0xff );
188259 SDL_RenderCopy (renderer , texture , NULL , NULL );
189260 SDL_SetTextureColorMod (texture , 255 , 255 , 255 );
261+
262+ /* Apply ellipse mask if enabled */
263+ if (round_disp_mask != NULL ) {
264+ SDL_SetRenderDrawBlendMode (renderer , SDL_BLENDMODE_MOD );
265+ SDL_RenderCopy (renderer , round_disp_mask , NULL , NULL );
266+ SDL_SetRenderDrawBlendMode (renderer , SDL_BLENDMODE_BLEND );
267+ }
268+
190269 SDL_RenderPresent (renderer );
191270}
192271
@@ -197,8 +276,14 @@ void sdl_display_blanking_on_bottom(void *renderer)
197276}
198277
199278void sdl_display_cleanup_bottom (void * * window , void * * renderer , void * * mutex , void * * texture ,
200- void * * read_texture , void * * background_texture )
279+ void * * read_texture , void * * background_texture ,
280+ void * * round_disp_mask )
201281{
282+ if (* round_disp_mask != NULL ) {
283+ SDL_DestroyTexture (* round_disp_mask );
284+ * round_disp_mask = NULL ;
285+ }
286+
202287 if (* background_texture != NULL ) {
203288 SDL_DestroyTexture (* background_texture );
204289 * background_texture = NULL ;
0 commit comments