Skip to content

Commit f1d9c36

Browse files
committed
testshape: now uses SDL_WINDOW_TRANSPARENT instead of the shaped window API
1 parent 2cafa52 commit f1d9c36

File tree

1 file changed

+168
-5
lines changed

1 file changed

+168
-5
lines changed

test/testshape.c

Lines changed: 168 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)