From 03f8528315fa46c95991a34f3325d7b33ae5538c Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Sat, 02 May 2020 21:48:36 +0000
Subject: [PATCH] Update source to SDL2 2.0.12
---
source/src/video/SDL_surface.c | 223 +++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 164 insertions(+), 59 deletions(-)
diff --git a/source/src/video/SDL_surface.c b/source/src/video/SDL_surface.c
index 1b2ee6c..3795b94 100644
--- a/source/src/video/SDL_surface.c
+++ b/source/src/video/SDL_surface.c
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
- Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+ Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -42,19 +42,12 @@
{
int pitch;
- /* Surface should be 4-byte aligned for speed */
- pitch = width * SDL_BYTESPERPIXEL(format);
- switch (SDL_BITSPERPIXEL(format)) {
- case 1:
- pitch = (pitch + 7) / 8;
- break;
- case 4:
- pitch = (pitch + 1) / 2;
- break;
- default:
- break;
+ if (SDL_ISPIXELFORMAT_FOURCC(format) || SDL_BITSPERPIXEL(format) >= 8) {
+ pitch = (width * SDL_BYTESPERPIXEL(format));
+ } else {
+ pitch = ((width * SDL_BITSPERPIXEL(format)) + 7) / 8;
}
- pitch = (pitch + 3) & ~3; /* 4-byte aligning */
+ pitch = (pitch + 3) & ~3; /* 4-byte aligning for speed */
return pitch;
}
@@ -119,12 +112,13 @@
return NULL;
}
- surface->pixels = SDL_malloc((size_t)size);
+ surface->pixels = SDL_SIMDAlloc((size_t)size);
if (!surface->pixels) {
SDL_FreeSurface(surface);
SDL_OutOfMemory();
return NULL;
}
+ surface->flags |= SDL_SIMD_ALIGNED;
/* This is important for bitmaps */
SDL_memset(surface->pixels, 0, surface->h * surface->pitch);
}
@@ -268,21 +262,7 @@
if (flag) {
surface->map->info.flags |= SDL_COPY_COLORKEY;
surface->map->info.colorkey = key;
- if (surface->format->palette) {
- surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT;
- ++surface->format->palette->version;
- if (!surface->format->palette->version) {
- surface->format->palette->version = 1;
- }
- }
} else {
- if (surface->format->palette) {
- surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_OPAQUE;
- ++surface->format->palette->version;
- if (!surface->format->palette->version) {
- surface->format->palette->version = 1;
- }
- }
surface->map->info.flags &= ~SDL_COPY_COLORKEY;
}
if (surface->map->info.flags != flags) {
@@ -303,7 +283,7 @@
return SDL_FALSE;
}
- return SDL_TRUE;
+ return SDL_TRUE;
}
int
@@ -325,7 +305,7 @@
/* This is a fairly slow function to switch from colorkey to alpha */
static void
-SDL_ConvertColorkeyToAlpha(SDL_Surface * surface)
+SDL_ConvertColorkeyToAlpha(SDL_Surface * surface, SDL_bool ignore_alpha)
{
int x, y;
@@ -347,18 +327,32 @@
Uint16 ckey = (Uint16) surface->map->info.colorkey;
Uint16 mask = (Uint16) (~surface->format->Amask);
- /* Ignore alpha in colorkey comparison */
- ckey &= mask;
- row = (Uint16 *) surface->pixels;
- for (y = surface->h; y--;) {
- spot = row;
- for (x = surface->w; x--;) {
- if ((*spot & mask) == ckey) {
- *spot &= mask;
+ /* Ignore, or not, alpha in colorkey comparison */
+ if (ignore_alpha) {
+ ckey &= mask;
+ row = (Uint16 *) surface->pixels;
+ for (y = surface->h; y--;) {
+ spot = row;
+ for (x = surface->w; x--;) {
+ if ((*spot & mask) == ckey) {
+ *spot &= mask;
+ }
+ ++spot;
}
- ++spot;
+ row += surface->pitch / 2;
}
- row += surface->pitch / 2;
+ } else {
+ row = (Uint16 *) surface->pixels;
+ for (y = surface->h; y--;) {
+ spot = row;
+ for (x = surface->w; x--;) {
+ if (*spot == ckey) {
+ *spot &= mask;
+ }
+ ++spot;
+ }
+ row += surface->pitch / 2;
+ }
}
}
break;
@@ -371,18 +365,32 @@
Uint32 ckey = surface->map->info.colorkey;
Uint32 mask = ~surface->format->Amask;
- /* Ignore alpha in colorkey comparison */
- ckey &= mask;
- row = (Uint32 *) surface->pixels;
- for (y = surface->h; y--;) {
- spot = row;
- for (x = surface->w; x--;) {
- if ((*spot & mask) == ckey) {
- *spot &= mask;
+ /* Ignore, or not, alpha in colorkey comparison */
+ if (ignore_alpha) {
+ ckey &= mask;
+ row = (Uint32 *) surface->pixels;
+ for (y = surface->h; y--;) {
+ spot = row;
+ for (x = surface->w; x--;) {
+ if ((*spot & mask) == ckey) {
+ *spot &= mask;
+ }
+ ++spot;
}
- ++spot;
+ row += surface->pitch / 4;
}
- row += surface->pitch / 4;
+ } else {
+ row = (Uint32 *) surface->pixels;
+ for (y = surface->h; y--;) {
+ spot = row;
+ for (x = surface->w; x--;) {
+ if (*spot == ckey) {
+ *spot &= mask;
+ }
+ ++spot;
+ }
+ row += surface->pitch / 4;
+ }
}
}
break;
@@ -487,7 +495,7 @@
status = 0;
flags = surface->map->info.flags;
surface->map->info.flags &=
- ~(SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD);
+ ~(SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL);
switch (blendMode) {
case SDL_BLENDMODE_NONE:
break;
@@ -499,6 +507,9 @@
break;
case SDL_BLENDMODE_MOD:
surface->map->info.flags |= SDL_COPY_MOD;
+ break;
+ case SDL_BLENDMODE_MUL:
+ surface->map->info.flags |= SDL_COPY_MUL;
break;
default:
status = SDL_Unsupported();
@@ -524,7 +535,7 @@
}
switch (surface->map->
- info.flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD)) {
+ info.flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) {
case SDL_COPY_BLEND:
*blendMode = SDL_BLENDMODE_BLEND;
break;
@@ -533,6 +544,9 @@
break;
case SDL_COPY_MOD:
*blendMode = SDL_BLENDMODE_MOD;
+ break;
+ case SDL_COPY_MUL:
+ *blendMode = SDL_BLENDMODE_MUL;
break;
default:
*blendMode = SDL_BLENDMODE_NONE;
@@ -866,7 +880,7 @@
{
static const Uint32 complex_copy_flags = (
SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA |
- SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD |
+ SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL |
SDL_COPY_COLORKEY
);
@@ -891,11 +905,13 @@
SDL_LockSurface(SDL_Surface * surface)
{
if (!surface->locked) {
+#if SDL_HAVE_RLE
/* Perform the lock */
if (surface->flags & SDL_RLEACCEL) {
SDL_UnRLESurface(surface, 1);
surface->flags |= SDL_RLEACCEL; /* save accel'd state */
}
+#endif
}
/* Increment the surface lock count, for recursive locks */
@@ -916,11 +932,13 @@
return;
}
+#if SDL_HAVE_RLE
/* Update RLE encoded surface with new data */
if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
surface->flags &= ~SDL_RLEACCEL; /* stop lying */
SDL_RLESurface(surface);
}
+#endif
}
/*
@@ -943,6 +961,11 @@
Uint32 copy_flags;
SDL_Color copy_color;
SDL_Rect bounds;
+ int ret;
+ SDL_bool palette_ck_transform = SDL_FALSE;
+ int palette_ck_value = 0;
+ SDL_bool palette_has_alpha = SDL_FALSE;
+ Uint8 *palette_saved_alpha = NULL;
if (!surface) {
SDL_InvalidParamError("surface");
@@ -1003,7 +1026,66 @@
bounds.y = 0;
bounds.w = surface->w;
bounds.h = surface->h;
- SDL_LowerBlit(surface, &bounds, convert, &bounds);
+
+ /* Source surface has a palette with no real alpha (0 or OPAQUE).
+ * Destination format has alpha.
+ * -> set alpha channel to be opaque */
+ if (surface->format->palette && format->Amask) {
+ SDL_bool set_opaque = SDL_FALSE;
+ {
+ int i;
+ for (i = 0; i < surface->format->palette->ncolors; i++) {
+ Uint8 alpha_value = surface->format->palette->colors[i].a;
+
+ if (alpha_value != 0 && alpha_value != SDL_ALPHA_OPAQUE) {
+ /* Palette has at least one alpha value. Don't do anything */
+ set_opaque = SDL_FALSE;
+ palette_has_alpha = SDL_TRUE;
+ break;
+ }
+
+ if (alpha_value == 0) {
+ set_opaque = SDL_TRUE;
+ }
+ }
+ }
+
+ /* Set opaque and backup palette alpha values */
+ if (set_opaque) {
+ int i;
+ palette_saved_alpha = SDL_stack_alloc(Uint8, surface->format->palette->ncolors);
+ for (i = 0; i < surface->format->palette->ncolors; i++) {
+ palette_saved_alpha[i] = surface->format->palette->colors[i].a;
+ surface->format->palette->colors[i].a = SDL_ALPHA_OPAQUE;
+ }
+ }
+ }
+
+ /* Transform colorkey to alpha. for cases where source palette has duplicate values, and colorkey is one of them */
+ if (copy_flags & SDL_COPY_COLORKEY) {
+ if (surface->format->palette && !format->palette) {
+ palette_ck_transform = SDL_TRUE;
+ palette_has_alpha = SDL_TRUE;
+ palette_ck_value = surface->format->palette->colors[surface->map->info.colorkey].a;
+ surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT;
+ }
+ }
+
+ ret = SDL_LowerBlit(surface, &bounds, convert, &bounds);
+
+ /* Restore colorkey alpha value */
+ if (palette_ck_transform) {
+ surface->format->palette->colors[surface->map->info.colorkey].a = palette_ck_value;
+ }
+
+ /* Restore palette alpha values */
+ if (palette_saved_alpha) {
+ int i;
+ for (i = 0; i < surface->format->palette->ncolors; i++) {
+ surface->format->palette->colors[i].a = palette_saved_alpha[i];
+ }
+ SDL_stack_free(palette_saved_alpha);
+ }
/* Clean up the original surface, and update converted surface */
convert->map->info.r = copy_color.r;
@@ -1021,6 +1103,13 @@
surface->map->info.a = copy_color.a;
surface->map->info.flags = copy_flags;
SDL_InvalidateMap(surface->map);
+
+ /* SDL_LowerBlit failed, and so the conversion */
+ if (ret < 0) {
+ SDL_FreeSurface(convert);
+ return NULL;
+ }
+
if (copy_flags & SDL_COPY_COLORKEY) {
SDL_bool set_colorkey_by_color = SDL_FALSE;
@@ -1031,8 +1120,8 @@
surface->format->palette->ncolors * sizeof(SDL_Color)) == 0)) {
/* The palette is identical, just set the same colorkey */
SDL_SetColorKey(convert, 1, surface->map->info.colorkey);
- } else if (format->Amask) {
- /* The alpha was set in the destination from the palette */
+ } else if (!format->palette) {
+ /* Was done by 'palette_ck_transform' */
} else {
set_colorkey_by_color = SDL_TRUE;
}
@@ -1055,7 +1144,7 @@
if (surface->format->palette) {
SDL_SetSurfacePalette(tmp, surface->format->palette);
}
-
+
SDL_FillRect(tmp, NULL, surface->map->info.colorkey);
tmp->map->info.flags &= ~SDL_COPY_COLORKEY;
@@ -1073,7 +1162,7 @@
SDL_SetColorKey(convert, 1, converted_colorkey);
/* This is needed when converting for 3D texture upload */
- SDL_ConvertColorkeyToAlpha(convert);
+ SDL_ConvertColorkeyToAlpha(convert, SDL_TRUE);
}
}
SDL_SetClipRect(convert, &surface->clip_rect);
@@ -1081,6 +1170,7 @@
/* Enable alpha blending by default if the new surface has an
* alpha channel or alpha modulation */
if ((surface->format->Amask && format->Amask) ||
+ (palette_has_alpha && format->Amask) ||
(copy_flags & SDL_COPY_MODULATE_ALPHA)) {
SDL_SetSurfaceBlendMode(convert, SDL_BLENDMODE_BLEND);
}
@@ -1167,6 +1257,7 @@
return SDL_InvalidParamError("dst_pitch");
}
+#if SDL_HAVE_YUV
if (SDL_ISPIXELFORMAT_FOURCC(src_format) && SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
return SDL_ConvertPixels_YUV_to_YUV(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch);
} else if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
@@ -1174,6 +1265,12 @@
} else if (SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
return SDL_ConvertPixels_RGB_to_YUV(width, height, src_format, src, src_pitch, dst_format, dst, dst_pitch);
}
+#else
+ if (SDL_ISPIXELFORMAT_FOURCC(src_format) || SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
+ SDL_SetError("SDL not built with YUV support");
+ return -1;
+ }
+#endif
/* Fast path for same format copy */
if (src_format == dst_format) {
@@ -1226,15 +1323,23 @@
while (surface->locked > 0) {
SDL_UnlockSurface(surface);
}
+#if SDL_HAVE_RLE
if (surface->flags & SDL_RLEACCEL) {
SDL_UnRLESurface(surface, 0);
}
+#endif
if (surface->format) {
SDL_SetSurfacePalette(surface, NULL);
SDL_FreeFormat(surface->format);
surface->format = NULL;
}
- if (!(surface->flags & SDL_PREALLOC)) {
+ if (surface->flags & SDL_PREALLOC) {
+ /* Don't free */
+ } else if (surface->flags & SDL_SIMD_ALIGNED) {
+ /* Free aligned */
+ SDL_SIMDFree(surface->pixels);
+ } else {
+ /* Normal */
SDL_free(surface->pixels);
}
if (surface->map) {
--
Gitblit v1.9.3