From f1d9c36136b9d880cc9865c9e989c7310b4ad243 Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Sat, 11 Mar 2023 13:53:54 +0100
Subject: [PATCH] testshape: now uses SDL_WINDOW_TRANSPARENT instead of the
shaped window API
---
test/testshape.c | 173 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 168 insertions(+), 5 deletions(-)
diff --git a/test/testshape.c b/test/testshape.c
index 802648e08fc3..0187956d48cd 100644
--- a/test/testshape.c
+++ b/test/testshape.c
@@ -24,7 +24,129 @@ typedef struct LoadedPicture
const char *name;
} LoadedPicture;
-void render(SDL_Renderer *renderer, SDL_Texture *texture)
+static Uint8 *g_bitmap = NULL;
+static int g_bitmap_w = 0, g_bitmap_h = 0;
+static SDL_Surface *g_shape_surface = NULL;
+static SDL_Texture *g_shape_texture = NULL;
+
+/* REQUIRES that bitmap point to a w-by-h bitmap with ppb pixels-per-byte. */
+static void SDL_CalculateShapeBitmap(SDL_WindowShapeMode mode, SDL_Surface *shape, Uint8 *bitmap, Uint8 ppb)
+{
+ int x = 0;
+ int y = 0;
+ Uint8 r = 0, g = 0, b = 0, alpha = 0;
+ Uint8 *pixel = NULL;
+ Uint32 pixel_value = 0, mask_value = 0;
+ size_t bytes_per_scanline = (size_t)(shape->w + (ppb - 1)) / ppb;
+ Uint8 *bitmap_scanline;
+ SDL_Color key;
+
+ if (SDL_MUSTLOCK(shape)) {
+ SDL_LockSurface(shape);
+ }
+
+ SDL_memset(bitmap, 0, shape->h * bytes_per_scanline);
+
+ for (y = 0; y < shape->h; y++) {
+ bitmap_scanline = bitmap + y * bytes_per_scanline;
+ for (x = 0; x < shape->w; x++) {
+ alpha = 0;
+ pixel_value = 0;
+ pixel = (Uint8 *)(shape->pixels) + (y * shape->pitch) + (x * shape->format->BytesPerPixel);
+ switch (shape->format->BytesPerPixel) {
+ case (1):
+ pixel_value = *pixel;
+ break;
+ case (2):
+ pixel_value = *(Uint16 *)pixel;
+ break;
+ case (3):
+ pixel_value = *(Uint32 *)pixel & (~shape->format->Amask);
+ break;
+ case (4):
+ pixel_value = *(Uint32 *)pixel;
+ break;
+ }
+ SDL_GetRGBA(pixel_value, shape->format, &r, &g, &b, &alpha);
+ switch (mode.mode) {
+ case (ShapeModeDefault):
+ mask_value = (alpha >= 1 ? 1 : 0);
+ break;
+ case (ShapeModeBinarizeAlpha):
+ mask_value = (alpha >= mode.parameters.binarizationCutoff ? 1 : 0);
+ break;
+ case (ShapeModeReverseBinarizeAlpha):
+ mask_value = (alpha <= mode.parameters.binarizationCutoff ? 1 : 0);
+ break;
+ case (ShapeModeColorKey):
+ key = mode.parameters.colorKey;
+ mask_value = ((key.r != r || key.g != g || key.b != b) ? 1 : 0);
+ break;
+ }
+ bitmap_scanline[x / ppb] |= mask_value << (x % ppb);
+ }
+ }
+
+ if (SDL_MUSTLOCK(shape)) {
+ SDL_UnlockSurface(shape);
+ }
+}
+
+static int SDL3_SetWindowShape(SDL_Window *window, SDL_Surface *shape, SDL_WindowShapeMode *shape_mode)
+{
+ if (g_bitmap) {
+ SDL_free(g_bitmap);
+ g_bitmap = NULL;
+ }
+
+ if (g_shape_texture) {
+ SDL_DestroyTexture(g_shape_texture);
+ g_shape_texture = NULL;
+ }
+
+ if (g_shape_surface) {
+ SDL_DestroySurface(g_shape_surface);
+ g_shape_surface = NULL;
+ }
+
+ if (shape == NULL) {
+ return SDL_SetError("shape");
+ }
+
+ if (shape_mode == NULL) {
+ return SDL_SetError("shape_mode");
+ }
+
+ g_bitmap_w = shape->w;
+ g_bitmap_h = shape->h;
+ g_bitmap = (Uint8*) SDL_malloc(shape->w * shape->h);
+ if (g_bitmap == NULL) {
+ return SDL_OutOfMemory();
+ }
+
+ SDL_CalculateShapeBitmap(*shape_mode, shape, g_bitmap, 1);
+
+ g_shape_surface = SDL_CreateSurface(g_bitmap_w, g_bitmap_h, SDL_PIXELFORMAT_ABGR8888);
+ if (g_shape_surface) {
+ int x, y, i = 0;
+ Uint32 *ptr = g_shape_surface->pixels;
+ for (y = 0; y < g_bitmap_h; y++) {
+ for (x = 0; x < g_bitmap_w; x++) {
+ Uint8 val = g_bitmap[i++];
+ if (val == 0) {
+ ptr[x] = 0;
+ } else {
+ ptr[x] = 0xffffffff;
+ }
+ }
+ ptr = (Uint32 *)((Uint8 *)ptr + g_shape_surface->pitch);
+ }
+ }
+
+ return 0;
+}
+
+static void render(SDL_Renderer *renderer, SDL_Texture *texture)
{
/* Clear render-target to blue. */
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0xff, 0xff);
@@ -32,6 +154,45 @@ void render(SDL_Renderer *renderer, SDL_Texture *texture)
/* Render the texture. */
SDL_RenderTexture(renderer, texture, NULL, NULL);
+
+ /* Apply the shape */
+ if (g_shape_surface) {
+ SDL_RendererInfo info;
+ SDL_GetRendererInfo(renderer, &info);
+
+ if (info.flags & SDL_RENDERER_SOFTWARE) {
+ if (g_bitmap) {
+ int x, y, i = 0;
+ Uint8 r, g, b, a;
+ SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
+ for (y = 0; y < g_bitmap_h; y++) {
+ for (x = 0; x < g_bitmap_w; x++) {
+ Uint8 val = g_bitmap[i++];
+ if (val == 0) {
+ SDL_RenderPoint(renderer, (float)x, (float)y);
+ }
+ }
+ }
+ SDL_SetRenderDrawColor(renderer, r, g, b, a);
+ }
+ } else {
+ if (g_shape_texture == NULL) {
+ SDL_BlendMode bm;
+
+ g_shape_texture = SDL_CreateTextureFromSurface(renderer, g_shape_surface);
+
+ /* if Alpha is 0, set all to 0, else leave unchanged. */
+ bm = SDL_ComposeCustomBlendMode(
+ SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD,
+ SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDOPERATION_ADD);
+
+ SDL_SetTextureBlendMode(g_shape_texture, bm);
+ }
+ SDL_RenderTexture(renderer, g_shape_texture, NULL, NULL);
+ }
+ }
+
SDL_RenderPresent(renderer);
}
@@ -52,6 +213,9 @@ int main(int argc, char **argv)
Uint32 pixelFormat = 0;
int w, h, access = 0;
+// SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
+// SDL_SetHint(SDL_HINT_VIDEO_FORCE_EGL, "0");
+
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
@@ -103,8 +267,7 @@ int main(int argc, char **argv)
}
}
- window = SDL_CreateShapedWindow("SDL_Shape test",
- SHAPED_WINDOW_DIMENSION, SHAPED_WINDOW_DIMENSION, 0);
+ window = SDL_CreateWindow("SDL_Shape test", SHAPED_WINDOW_DIMENSION, SHAPED_WINDOW_DIMENSION, SDL_WINDOW_TRANSPARENT);
if (window == NULL) {
for (i = 0; i < num_pictures; i++) {
SDL_DestroySurface(pictures[i].surface);
@@ -156,7 +319,7 @@ int main(int argc, char **argv)
SDL_QueryTexture(pictures[current_picture].texture, &pixelFormat, &access, &w, &h);
/* We want to set the window size in pixels */
SDL_SetWindowSize(window, (int)SDL_ceilf(w / mode->display_scale), (int)SDL_ceilf(h / mode->display_scale));
- SDL_SetWindowShape(window, pictures[current_picture].surface, &pictures[current_picture].mode);
+ SDL3_SetWindowShape(window, pictures[current_picture].surface, &pictures[current_picture].mode);
while (should_exit == 0) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_KEY_DOWN) {
@@ -175,7 +338,7 @@ int main(int argc, char **argv)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Changing to shaped bmp: %s", pictures[current_picture].name);
SDL_QueryTexture(pictures[current_picture].texture, &pixelFormat, &access, &w, &h);
SDL_SetWindowSize(window, (int)SDL_ceilf(w / mode->display_scale), (int)SDL_ceilf(h / mode->display_scale));
- SDL_SetWindowShape(window, pictures[current_picture].surface, &pictures[current_picture].mode);
+ SDL3_SetWindowShape(window, pictures[current_picture].surface, &pictures[current_picture].mode);
}
if (event.type == SDL_EVENT_QUIT) {
should_exit = 1;