@@ -24,14 +24,175 @@ typedef struct LoadedPicture
2424 const char * name ;
2525} LoadedPicture ;
2626
27- void render (SDL_Renderer * renderer , SDL_Texture * texture )
27+ static Uint8 * g_bitmap = NULL ;
28+ static int g_bitmap_w = 0 , g_bitmap_h = 0 ;
29+ static SDL_Surface * g_shape_surface = NULL ;
30+ static SDL_Texture * g_shape_texture = NULL ;
31+
32+ /* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
33+ static void SDL_CalculateShapeBitmap (SDL_WindowShapeMode mode , SDL_Surface * shape , Uint8 * bitmap , Uint8 ppb )
34+ {
35+ int x = 0 ;
36+ int y = 0 ;
37+ Uint8 r = 0 , g = 0 , b = 0 , alpha = 0 ;
38+ Uint8 * pixel = NULL ;
39+ Uint32 pixel_value = 0 , mask_value = 0 ;
40+ size_t bytes_per_scanline = (size_t )(shape -> w + (ppb - 1 )) / ppb ;
41+ Uint8 * bitmap_scanline ;
42+ SDL_Color key ;
43+
44+ if (SDL_MUSTLOCK (shape )) {
45+ SDL_LockSurface (shape );
46+ }
47+
48+ SDL_memset (bitmap , 0 , shape -> h * bytes_per_scanline );
49+
50+ for (y = 0 ; y < shape -> h ; y ++ ) {
51+ bitmap_scanline = bitmap + y * bytes_per_scanline ;
52+ for (x = 0 ; x < shape -> w ; x ++ ) {
53+ alpha = 0 ;
54+ pixel_value = 0 ;
55+ pixel = (Uint8 * )(shape -> pixels ) + (y * shape -> pitch ) + (x * shape -> format -> BytesPerPixel );
56+ switch (shape -> format -> BytesPerPixel ) {
57+ case (1 ):
58+ pixel_value = * pixel ;
59+ break ;
60+ case (2 ):
61+ pixel_value = * (Uint16 * )pixel ;
62+ break ;
63+ case (3 ):
64+ pixel_value = * (Uint32 * )pixel & (~shape -> format -> Amask );
65+ break ;
66+ case (4 ):
67+ pixel_value = * (Uint32 * )pixel ;
68+ break ;
69+ }
70+ SDL_GetRGBA (pixel_value , shape -> format , & r , & g , & b , & alpha );
71+ switch (mode .mode ) {
72+ case (ShapeModeDefault ):
73+ mask_value = (alpha >= 1 ? 1 : 0 );
74+ break ;
75+ case (ShapeModeBinarizeAlpha ):
76+ mask_value = (alpha >= mode .parameters .binarizationCutoff ? 1 : 0 );
77+ break ;
78+ case (ShapeModeReverseBinarizeAlpha ):
79+ mask_value = (alpha <= mode .parameters .binarizationCutoff ? 1 : 0 );
80+ break ;
81+ case (ShapeModeColorKey ):
82+ key = mode .parameters .colorKey ;
83+ mask_value = ((key .r != r || key .g != g || key .b != b ) ? 1 : 0 );
84+ break ;
85+ }
86+ bitmap_scanline [x / ppb ] |= mask_value << (x % ppb );
87+ }
88+ }
89+
90+ if (SDL_MUSTLOCK (shape )) {
91+ SDL_UnlockSurface (shape );
92+ }
93+ }
94+
95+ static int SDL3_SetWindowShape (SDL_Window * window , SDL_Surface * shape , SDL_WindowShapeMode * shape_mode )
96+ {
97+ if (g_bitmap ) {
98+ SDL_free (g_bitmap );
99+ g_bitmap = NULL ;
100+ }
101+
102+ if (g_shape_texture ) {
103+ SDL_DestroyTexture (g_shape_texture );
104+ g_shape_texture = NULL ;
105+ }
106+
107+ if (g_shape_surface ) {
108+ SDL_DestroySurface (g_shape_surface );
109+ g_shape_surface = NULL ;
110+ }
111+
112+ if (shape == NULL ) {
113+ return SDL_SetError ("shape" );
114+ }
115+
116+ if (shape_mode == NULL ) {
117+ return SDL_SetError ("shape_mode" );
118+ }
119+
120+ g_bitmap_w = shape -> w ;
121+ g_bitmap_h = shape -> h ;
122+ g_bitmap = (Uint8 * ) SDL_malloc (shape -> w * shape -> h );
123+ if (g_bitmap == NULL ) {
124+ return SDL_OutOfMemory ();
125+ }
126+
127+ SDL_CalculateShapeBitmap (* shape_mode , shape , g_bitmap , 1 );
128+
129+ g_shape_surface = SDL_CreateSurface (g_bitmap_w , g_bitmap_h , SDL_PIXELFORMAT_ABGR8888 );
130+ if (g_shape_surface ) {
131+ int x , y , i = 0 ;
132+ Uint32 * ptr = g_shape_surface -> pixels ;
133+ for (y = 0 ; y < g_bitmap_h ; y ++ ) {
134+ for (x = 0 ; x < g_bitmap_w ; x ++ ) {
135+ Uint8 val = g_bitmap [i ++ ];
136+ if (val == 0 ) {
137+ ptr [x ] = 0 ;
138+ } else {
139+ ptr [x ] = 0xffffffff ;
140+ }
141+ }
142+ ptr = (Uint32 * )((Uint8 * )ptr + g_shape_surface -> pitch );
143+ }
144+ }
145+
146+ return 0 ;
147+ }
148+
149+ static void render (SDL_Renderer * renderer , SDL_Texture * texture )
28150{
29151 /* Clear render-target to blue. */
30152 SDL_SetRenderDrawColor (renderer , 0x00 , 0x00 , 0xff , 0xff );
31153 SDL_RenderClear (renderer );
32154
33155 /* Render the texture. */
34156 SDL_RenderTexture (renderer , texture , NULL , NULL );
157+
158+ /* Apply the shape */
159+ if (g_shape_surface ) {
160+ SDL_RendererInfo info ;
161+ SDL_GetRendererInfo (renderer , & info );
162+
163+ if (info .flags & SDL_RENDERER_SOFTWARE ) {
164+ if (g_bitmap ) {
165+ int x , y , i = 0 ;
166+ Uint8 r , g , b , a ;
167+ SDL_GetRenderDrawColor (renderer , & r , & g , & b , & a );
168+ SDL_SetRenderDrawColor (renderer , 0 , 0 , 0 , 0 );
169+ for (y = 0 ; y < g_bitmap_h ; y ++ ) {
170+ for (x = 0 ; x < g_bitmap_w ; x ++ ) {
171+ Uint8 val = g_bitmap [i ++ ];
172+ if (val == 0 ) {
173+ SDL_RenderPoint (renderer , (float )x , (float )y );
174+ }
175+ }
176+ }
177+ SDL_SetRenderDrawColor (renderer , r , g , b , a );
178+ }
179+ } else {
180+ if (g_shape_texture == NULL ) {
181+ SDL_BlendMode bm ;
182+
183+ g_shape_texture = SDL_CreateTextureFromSurface (renderer , g_shape_surface );
184+
185+ /* if Alpha is 0, set all to 0, else leave unchanged. */
186+ bm = SDL_ComposeCustomBlendMode (
187+ SDL_BLENDFACTOR_ZERO , SDL_BLENDFACTOR_SRC_ALPHA , SDL_BLENDOPERATION_ADD ,
188+ SDL_BLENDFACTOR_ZERO , SDL_BLENDFACTOR_SRC_ALPHA , SDL_BLENDOPERATION_ADD );
189+
190+ SDL_SetTextureBlendMode (g_shape_texture , bm );
191+ }
192+ SDL_RenderTexture (renderer , g_shape_texture , NULL , NULL );
193+ }
194+ }
195+
35196 SDL_RenderPresent (renderer );
36197}
37198
@@ -52,6 +213,9 @@ int main(int argc, char **argv)
52213 Uint32 pixelFormat = 0 ;
53214 int w , h , access = 0 ;
54215
216+ // SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
217+ // SDL_SetHint(SDL_HINT_VIDEO_FORCE_EGL, "0");
218+
55219 /* Enable standard application logging */
56220 SDL_LogSetPriority (SDL_LOG_CATEGORY_APPLICATION , SDL_LOG_PRIORITY_INFO );
57221
@@ -103,8 +267,7 @@ int main(int argc, char **argv)
103267 }
104268 }
105269
106- window = SDL_CreateShapedWindow ("SDL_Shape test" ,
107- SHAPED_WINDOW_DIMENSION , SHAPED_WINDOW_DIMENSION , 0 );
270+ window = SDL_CreateWindow ("SDL_Shape test" , SHAPED_WINDOW_DIMENSION , SHAPED_WINDOW_DIMENSION , SDL_WINDOW_TRANSPARENT );
108271 if (window == NULL ) {
109272 for (i = 0 ; i < num_pictures ; i ++ ) {
110273 SDL_DestroySurface (pictures [i ].surface );
@@ -156,7 +319,7 @@ int main(int argc, char **argv)
156319 SDL_QueryTexture (pictures [current_picture ].texture , & pixelFormat , & access , & w , & h );
157320 /* We want to set the window size in pixels */
158321 SDL_SetWindowSize (window , (int )SDL_ceilf (w / mode -> display_scale ), (int )SDL_ceilf (h / mode -> display_scale ));
159- SDL_SetWindowShape (window , pictures [current_picture ].surface , & pictures [current_picture ].mode );
322+ SDL3_SetWindowShape (window , pictures [current_picture ].surface , & pictures [current_picture ].mode );
160323 while (should_exit == 0 ) {
161324 while (SDL_PollEvent (& event )) {
162325 if (event .type == SDL_EVENT_KEY_DOWN ) {
@@ -175,7 +338,7 @@ int main(int argc, char **argv)
175338 SDL_LogInfo (SDL_LOG_CATEGORY_APPLICATION , "Changing to shaped bmp: %s" , pictures [current_picture ].name );
176339 SDL_QueryTexture (pictures [current_picture ].texture , & pixelFormat , & access , & w , & h );
177340 SDL_SetWindowSize (window , (int )SDL_ceilf (w / mode -> display_scale ), (int )SDL_ceilf (h / mode -> display_scale ));
178- SDL_SetWindowShape (window , pictures [current_picture ].surface , & pictures [current_picture ].mode );
341+ SDL3_SetWindowShape (window , pictures [current_picture ].surface , & pictures [current_picture ].mode );
179342 }
180343 if (event .type == SDL_EVENT_QUIT ) {
181344 should_exit = 1 ;
0 commit comments