Parcourir la source

Set the alpha opaque when blending to an RGB format

Fixes the render_testRGBSurfaceNoAlpha automated test in sdl2-compat

(cherry picked from commit 7bb95bde492a0416497a427282beca601de89c57)
Sam Lantinga il y a 2 semaines
Parent
commit
4d966ff546
5 fichiers modifiés avec 83 ajouts et 42 suppressions
  1. 47 5
      src/video/SDL_blit_A.c
  2. 6 36
      src/video/SDL_blit_N.c
  3. 28 0
      src/video/SDL_pixels.c
  4. 1 1
      src/video/SDL_pixels_c.h
  5. 1 0
      src/video/SDL_surface_c.h

+ 47 - 5
src/video/SDL_blit_A.c

@@ -22,6 +22,7 @@
 
 #ifdef SDL_HAVE_BLIT_A
 
+#include "SDL_pixels_c.h"
 #include "SDL_surface_c.h"
 
 // Functions to perform alpha blended blitting
@@ -968,6 +969,10 @@ static void Blit8888to8888PixelAlphaSwizzle(SDL_BlitInfo *info)
     int dstskip = info->dst_skip;
     const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
     const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
+    bool fill_alpha = !dstfmt->Amask;
+    Uint32 dstAmask, dstAshift;
+
+    SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
 
     while (height--) {
         int i = 0;
@@ -976,6 +981,9 @@ static void Blit8888to8888PixelAlphaSwizzle(SDL_BlitInfo *info)
             Uint32 src32 = *(Uint32 *)src;
             Uint32 dst32 = *(Uint32 *)dst;
             ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
+            if (fill_alpha) {
+                dst32 |= dstAmask;
+            }
             *(Uint32 *)dst = dst32;
             src += 4;
             dst += 4;
@@ -998,6 +1006,10 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
     int dstskip = info->dst_skip;
     const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
     const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
+    bool fill_alpha = !dstfmt->Amask;
+    Uint32 dstAmask, dstAshift;
+
+    SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
 
     // The byte offsets for the start of each pixel
     const __m128i mask_offsets = _mm_set_epi8(
@@ -1011,7 +1023,7 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
         mask_offsets);
 
     const __m128i alpha_splat_mask = _mm_add_epi8(_mm_set1_epi8(srcfmt->Ashift >> 3), mask_offsets);
-    const __m128i alpha_fill_mask = _mm_set1_epi32((int)dstfmt->Amask);
+    const __m128i alpha_fill_mask = _mm_set1_epi32((int)dstAmask);
 
     while (height--) {
         int i = 0;
@@ -1057,7 +1069,11 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
             dst_hi = _mm_mulhi_epu16(dst_hi, _mm_set1_epi16(257));
 
             // Blend the pixels together and save the result
-            _mm_storeu_si128((__m128i *)dst, _mm_packus_epi16(dst_lo, dst_hi));
+            dst128 = _mm_packus_epi16(dst_lo, dst_hi);
+            if (fill_alpha) {
+                dst128 = _mm_or_si128(dst128, alpha_fill_mask);
+            }
+            _mm_storeu_si128((__m128i *)dst, dst128);
 
             src += 16;
             dst += 16;
@@ -1067,6 +1083,9 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelAlphaSwizzleSSE41(SDL_Bli
             Uint32 src32 = *(Uint32 *)src;
             Uint32 dst32 = *(Uint32 *)dst;
             ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
+            if (fill_alpha) {
+                dst32 |= dstAmask;
+            }
             *(Uint32 *)dst = dst32;
             src += 4;
             dst += 4;
@@ -1091,6 +1110,10 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
     int dstskip = info->dst_skip;
     const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
     const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
+    bool fill_alpha = !dstfmt->Amask;
+    Uint32 dstAmask, dstAshift;
+
+    SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
 
     // The byte offsets for the start of each pixel
     const __m256i mask_offsets = _mm256_set_epi8(
@@ -1104,7 +1127,7 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
         mask_offsets);
 
     const __m256i alpha_splat_mask = _mm256_add_epi8(_mm256_set1_epi8(srcfmt->Ashift >> 3), mask_offsets);
-    const __m256i alpha_fill_mask = _mm256_set1_epi32((int)dstfmt->Amask);
+    const __m256i alpha_fill_mask = _mm256_set1_epi32((int)dstAmask);
 
     while (height--) {
         int i = 0;
@@ -1150,7 +1173,11 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
             dst_hi = _mm256_mulhi_epu16(dst_hi, _mm256_set1_epi16(257));
 
             // Blend the pixels together and save the result
-            _mm256_storeu_si256((__m256i *)dst, _mm256_packus_epi16(dst_lo, dst_hi));
+            dst256 = _mm256_packus_epi16(dst_lo, dst_hi);
+            if (fill_alpha) {
+                dst256 = _mm256_or_si256(dst256, alpha_fill_mask);
+            }
+            _mm256_storeu_si256((__m256i *)dst, dst256);
 
             src += 32;
             dst += 32;
@@ -1160,6 +1187,9 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelAlphaSwizzleAVX2(SDL_BlitIn
             Uint32 src32 = *(Uint32 *)src;
             Uint32 dst32 = *(Uint32 *)dst;
             ALPHA_BLEND_SWIZZLE_8888(src32, dst32, srcfmt, dstfmt);
+            if (fill_alpha) {
+                dst32 |= dstAmask;
+            }
             *(Uint32 *)dst = dst32;
             src += 4;
             dst += 4;
@@ -1184,6 +1214,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
     int dstskip = info->dst_skip;
     const SDL_PixelFormatDetails *srcfmt = info->src_fmt;
     const SDL_PixelFormatDetails *dstfmt = info->dst_fmt;
+    bool fill_alpha = !dstfmt->Amask;
+    Uint32 dstAmask, dstAshift;
+
+    SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
 
     // The byte offsets for the start of each pixel
     const uint8x16_t mask_offsets = vreinterpretq_u8_u64(vcombine_u64(
@@ -1197,7 +1231,7 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
             ((srcfmt->Bshift >> 3) << dstfmt->Bshift))));
 
     const uint8x16_t alpha_splat_mask = vaddq_u8(vdupq_n_u8(srcfmt->Ashift >> 3), mask_offsets);
-    const uint8x16_t alpha_fill_mask = vreinterpretq_u8_u32(vdupq_n_u32(dstfmt->Amask));
+    const uint8x16_t alpha_fill_mask = vreinterpretq_u8_u32(vdupq_n_u32(dstAmask));
 
     while (height--) {
         int i = 0;
@@ -1242,6 +1276,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
             // temp   = vraddhn_u16(res_lo, vrshrq_n_u16(res_lo, 8));
             // dst128 = vraddhn_high_u16(temp, res_hi, vrshrq_n_u16(res_hi, 8));
 
+            if (fill_alpha) {
+                dst128 = vorrq_u8(dst128, alpha_fill_mask);
+            }
+
             // Save the result
             vst1q_u8(dst, dst128);
 
@@ -1266,6 +1304,10 @@ static void Blit8888to8888PixelAlphaSwizzleNEON(SDL_BlitInfo *info)
 
             dst32 = vaddhn_u16(res, vshrq_n_u16(res, 8));
 
+            if (fill_alpha) {
+                dst32 = vorr_u8(dst32, vget_low_u8(alpha_fill_mask));
+            }
+
             // Save the result, only low 32-bits
             vst1_lane_u32((Uint32*)dst, vreinterpret_u32_u8(dst32), 0);
 

+ 6 - 36
src/video/SDL_blit_N.c

@@ -2568,36 +2568,6 @@ static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info)
               dstAmask;                                                 \
     } while (0)
 
-#if defined(SDL_SSE4_1_INTRINSICS) || defined(SDL_AVX2_INTRINSICS) || (defined(SDL_NEON_INTRINSICS) && (__ARM_ARCH >= 8))
-static void Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift)
-{
-    if (fmt->Amask) {
-        *mask = fmt->Amask;
-        *shift = fmt->Ashift;
-    } else {
-        *mask = ~(fmt->Rmask | fmt->Gmask | fmt->Bmask);
-        switch (*mask) {
-        case 0x000000FF:
-            *shift = 0;
-            break;
-        case 0x0000FF00:
-            *shift = 8;
-            break;
-        case 0x00FF0000:
-            *shift = 16;
-            break;
-        case 0xFF000000:
-            *shift = 24;
-            break;
-        default:
-            // Should never happen
-            *shift = 0;
-            break;
-        }
-    }
-}
-#endif // SSE4.1, AVX2, and NEON implementations of Blit8888to8888PixelSwizzle
-
 #ifdef SDL_SSE4_1_INTRINSICS
 
 static void SDL_TARGETING("sse4.1") Blit8888to8888PixelSwizzleSSE41(SDL_BlitInfo *info)
@@ -2614,8 +2584,8 @@ static void SDL_TARGETING("sse4.1") Blit8888to8888PixelSwizzleSSE41(SDL_BlitInfo
     Uint32 srcAmask, srcAshift;
     Uint32 dstAmask, dstAshift;
 
-    Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
-    Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
+    SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
+    SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
 
     // The byte offsets for the start of each pixel
     const __m128i mask_offsets = _mm_set_epi8(
@@ -2689,8 +2659,8 @@ static void SDL_TARGETING("avx2") Blit8888to8888PixelSwizzleAVX2(SDL_BlitInfo *i
     Uint32 srcAmask, srcAshift;
     Uint32 dstAmask, dstAshift;
 
-    Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
-    Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
+    SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
+    SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
 
     // The byte offsets for the start of each pixel
     const __m256i mask_offsets = _mm256_set_epi8(
@@ -2764,8 +2734,8 @@ static void Blit8888to8888PixelSwizzleNEON(SDL_BlitInfo *info)
     Uint32 srcAmask, srcAshift;
     Uint32 dstAmask, dstAshift;
 
-    Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
-    Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
+    SDL_Get8888AlphaMaskAndShift(srcfmt, &srcAmask, &srcAshift);
+    SDL_Get8888AlphaMaskAndShift(dstfmt, &dstAmask, &dstAshift);
 
     // The byte offsets for the start of each pixel
     const uint8x16_t mask_offsets = vreinterpretq_u8_u64(vcombine_u64(

+ 28 - 0
src/video/SDL_pixels.c

@@ -692,6 +692,34 @@ void SDL_QuitPixelFormatDetails(void)
     }
 }
 
+void SDL_Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift)
+{
+    if (fmt->Amask) {
+        *mask = fmt->Amask;
+        *shift = fmt->Ashift;
+    } else {
+        *mask = ~(fmt->Rmask | fmt->Gmask | fmt->Bmask);
+        switch (*mask) {
+        case 0x000000FF:
+            *shift = 0;
+            break;
+        case 0x0000FF00:
+            *shift = 8;
+            break;
+        case 0x00FF0000:
+            *shift = 16;
+            break;
+        case 0xFF000000:
+            *shift = 24;
+            break;
+        default:
+            // Should never happen
+            *shift = 0;
+            break;
+        }
+    }
+}
+
 SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat format)
 {
     if (SDL_ISPIXELFORMAT_FOURCC(format)) {

+ 1 - 1
src/video/SDL_pixels_c.h

@@ -29,7 +29,7 @@
 
 
 // Pixel format functions
-extern bool SDL_CalculateSurfaceSize(SDL_PixelFormat format, int width, int height, size_t *size, size_t *pitch, bool minimalPitch);
+extern void SDL_Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift);
 extern SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat pixel_format);
 extern void SDL_QuitPixelFormatDetails(void);
 

+ 1 - 0
src/video/SDL_surface_c.h

@@ -83,6 +83,7 @@ struct SDL_Surface
 // Surface functions
 extern bool SDL_SurfaceValid(SDL_Surface *surface);
 extern void SDL_UpdateSurfaceLockFlag(SDL_Surface *surface);
+extern bool SDL_CalculateSurfaceSize(SDL_PixelFormat format, int width, int height, size_t *size, size_t *pitch, bool minimalPitch);
 extern float SDL_GetDefaultSDRWhitePoint(SDL_Colorspace colorspace);
 extern float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace colorspace);
 extern float SDL_GetDefaultHDRHeadroom(SDL_Colorspace colorspace);