+ Warn("IMG_Load('%s') failed: %s", basename, SDL_GetError());
+
+ return;
+ }
+
+ // set transparent color
+ SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
+ SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
+
+ SDL_SetWindowIcon(sdl_window, surface);
+#endif
+}
+
+static boolean equalSDLPixelFormat(SDL_PixelFormat *format1,
+ SDL_PixelFormat *format2)
+{
+ return (format1->format == format2->format &&
+ format1->BitsPerPixel == format2->BitsPerPixel &&
+ format1->BytesPerPixel == format2->BytesPerPixel &&
+ format1->Rmask == format2->Rmask &&
+ format1->Gmask == format2->Gmask &&
+ format1->Bmask == format2->Bmask);
+}
+
+static void SDLCopyColorKey(SDL_Surface *src_surface, SDL_Surface *dst_surface)
+{
+ Pixel color_key;
+ Uint8 r, g, b;
+
+ // check if source surface has a color key
+ if (SDL_GetColorKey(src_surface, &color_key) == 0)
+ {
+ // get RGB values of color key of source surface
+ SDL_GetRGB(color_key, src_surface->format, &r, &g, &b);
+
+ // get color key from RGB values in destination surface format
+ color_key = SDL_MapRGB(dst_surface->format, r, g, b);
+
+ // set color key in destination surface
+ SDL_SetColorKey(dst_surface, SET_TRANSPARENT_PIXEL, color_key);
+ }
+ else
+ {
+ // unset color key in destination surface
+ SDL_SetColorKey(dst_surface, UNSET_TRANSPARENT_PIXEL, 0);
+ }
+}
+
+static boolean SDLHasColorKey(SDL_Surface *surface)
+{
+ Pixel color_key;
+
+ return (SDL_GetColorKey(surface, &color_key) == 0);
+}
+
+static boolean SDLHasAlpha(SDL_Surface *surface)
+{
+ SDL_BlendMode blend_mode;
+
+ if (SDL_GetSurfaceBlendMode(surface, &blend_mode) != 0)
+ return FALSE;
+
+ return (blend_mode == SDL_BLENDMODE_BLEND);
+}
+
+static void SDLSetSurfaceAlpha(SDL_Surface *surface, boolean set, int alpha)
+{
+ SDL_BlendMode blend_mode = (set ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
+
+ SDL_SetSurfaceBlendMode(surface, blend_mode);
+ SDL_SetSurfaceAlphaMod(surface, alpha);
+}
+
+static void SDLSetTextureAlpha(SDL_Texture *texture, boolean set, int alpha)
+{
+ SDL_BlendMode blend_mode = (set ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
+
+ SDL_SetTextureBlendMode(texture, blend_mode);
+ SDL_SetTextureAlphaMod(texture, alpha);
+}
+
+static void SDLSetBitmapAlpha(Bitmap *bitmap, boolean is_texture,
+ boolean is_masked)
+{
+ int alpha_next_blit = bitmap->alpha_next_blit;
+
+ // alpha value must be requested every time before blitting, if needed
+ bitmap->alpha_next_blit = -1;
+
+ // nothing to do if requested alpha value is already set
+ if (bitmap->alpha[is_texture][is_masked] == alpha_next_blit)
+ return;
+
+ // store requested alpha value for masked/unmasked surface/texture
+ bitmap->alpha[is_texture][is_masked] = alpha_next_blit;
+
+ // set blend mode if bitmap is masked or if alpha value is defined
+ boolean set_blend_mode = (is_masked || alpha_next_blit != -1);
+
+ // if alpha value is undefined, use default (opaque) alpha value
+ if (alpha_next_blit == -1)
+ alpha_next_blit = SDL_ALPHA_OPAQUE;
+
+ if (is_texture)
+ SDLSetTextureAlpha(is_masked ? bitmap->texture_masked : bitmap->texture,
+ set_blend_mode, alpha_next_blit);
+ else
+ SDLSetSurfaceAlpha(is_masked ? bitmap->surface_masked : bitmap->surface,
+ set_blend_mode, alpha_next_blit);
+}
+
+void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
+{
+ SDLSetSurfaceAlpha(surface, set, alpha);
+}
+
+const char *SDLGetRendererName(void)
+{
+ static SDL_RendererInfo renderer_info;
+
+ SDL_GetRendererInfo(sdl_renderer, &renderer_info);
+
+ return renderer_info.name;
+}
+
+SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
+{
+ SDL_PixelFormat format;
+ SDL_Surface *new_surface;
+
+ if (surface == NULL)
+ return NULL;
+
+ if (backbuffer && backbuffer->surface)
+ {
+ format = *backbuffer->surface->format;
+ format.Amask = surface->format->Amask; // keep alpha channel
+ }
+ else
+ {
+ format = *surface->format;
+ }
+
+ new_surface = SDL_ConvertSurface(surface, &format, 0);
+
+ if (new_surface == NULL)
+ Fail("SDL_ConvertSurface() failed: %s", SDL_GetError());
+
+ // workaround for a bug in SDL 2.0.12 (which does not convert the color key)
+ if (SDLHasColorKey(surface) && !SDLHasColorKey(new_surface))
+ SDLCopyColorKey(surface, new_surface);
+
+ return new_surface;
+}
+
+boolean SDLSetNativeSurface(SDL_Surface **surface)
+{
+ SDL_Surface *new_surface;
+
+ if (surface == NULL ||
+ *surface == NULL ||
+ backbuffer == NULL ||
+ backbuffer->surface == NULL)
+ return FALSE;
+
+ // if pixel format already optimized for destination surface, do nothing
+ if (equalSDLPixelFormat((*surface)->format, backbuffer->surface->format))
+ return FALSE;
+
+ new_surface = SDLGetNativeSurface(*surface);
+
+ SDL_FreeSurface(*surface);
+
+ *surface = new_surface;
+
+ return TRUE;
+}
+
+static SDL_Texture *SDLCreateTextureFromSurface(SDL_Surface *surface)
+{
+ if (program.headless)
+ return NULL;
+
+ SDL_Texture *texture = SDL_CreateTextureFromSurface(sdl_renderer, surface);
+
+ if (texture == NULL)
+ Fail("SDL_CreateTextureFromSurface() failed: %s", SDL_GetError());
+
+ return texture;
+}
+
+void SDLCreateBitmapTextures(Bitmap *bitmap)
+{
+ if (bitmap == NULL)
+ return;