From 786e80a844486e48fe6454e87e821f922feb51e5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 21 May 2013 22:01:18 -0700 Subject: [PATCH] Fixed bug 1534 - SIGSEGV in SDL_ConvertSurface() for certain formats in SDL2 Don't assume that 8 bit formats are indexed. Thanks to Gabriel Jacobo for research and potential patches. --- src/video/SDL_blit.c | 15 +- src/video/SDL_blit_N.c | 401 ++++++++++++++++++++-------------------- src/video/SDL_stretch.c | 48 ++--- 3 files changed, 235 insertions(+), 229 deletions(-) diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index d7c258d4c..78e449dd0 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -239,9 +239,11 @@ SDL_CalculateBlit(SDL_Surface * surface) /* Choose a standard blit function */ if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) { blit = SDL_BlitCopy; - } else if (surface->format->BitsPerPixel < 8) { + } else if (surface->format->BitsPerPixel < 8 && + SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) { blit = SDL_CalculateBlit0(surface); - } else if (surface->format->BytesPerPixel == 1) { + } else if (surface->format->BytesPerPixel == 1 && + SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) { blit = SDL_CalculateBlit1(surface); } else if (map->info.flags & SDL_COPY_BLEND) { blit = SDL_CalculateBlitA(surface); @@ -260,8 +262,13 @@ SDL_CalculateBlit(SDL_Surface * surface) if (blit == NULL) #endif { - if (surface->format->BytesPerPixel > 1 - && dst->format->BytesPerPixel > 1) { + Uint32 src_format = surface->format->format; + Uint32 dst_format = dst->format->format; + + if (!SDL_ISPIXELFORMAT_INDEXED(src_format) && + !SDL_ISPIXELFORMAT_FOURCC(src_format) && + !SDL_ISPIXELFORMAT_INDEXED(dst_format) && + !SDL_ISPIXELFORMAT_FOURCC(dst_format)) { blit = SDL_Blit_Slow; } } diff --git a/src/video/SDL_blit_N.c b/src/video/SDL_blit_N.c index 4ca365680..cd127c9db 100644 --- a/src/video/SDL_blit_N.c +++ b/src/video/SDL_blit_N.c @@ -275,7 +275,7 @@ Blit_RGB565_32Altivec(SDL_BlitInfo * info) vector unsigned int v16 = vec_add(v8, v8); vector unsigned short v2 = vec_splat_u16(2); vector unsigned short v3 = vec_splat_u16(3); - /* + /* 0x10 - 0x1f is the alpha 0x00 - 0x0e evens are the red 0x01 - 0x0f odds are zero @@ -422,7 +422,7 @@ Blit_RGB555_32Altivec(SDL_BlitInfo * info) vector unsigned int v16 = vec_add(v8, v8); vector unsigned short v1 = vec_splat_u16(1); vector unsigned short v3 = vec_splat_u16(3); - /* + /* 0x10 - 0x1f is the alpha 0x00 - 0x0e evens are the red 0x01 - 0x0f odds are zero @@ -876,18 +876,18 @@ GetBlitFeatures(void) /* This is now endian dependent */ #if SDL_BYTEORDER == SDL_LIL_ENDIAN -#define HI 1 -#define LO 0 +#define HI 1 +#define LO 0 #else /* SDL_BYTEORDER == SDL_BIG_ENDIAN */ -#define HI 0 -#define LO 1 +#define HI 0 +#define LO 1 #endif /* Special optimized blit for RGB 8-8-8 --> RGB 3-3-2 */ #define RGB888_RGB332(dst, src) { \ - dst = (Uint8)((((src)&0x00E00000)>>16)| \ - (((src)&0x0000E000)>>11)| \ - (((src)&0x000000C0)>>6)); \ + dst = (Uint8)((((src)&0x00E00000)>>16)| \ + (((src)&0x0000E000)>>11)| \ + (((src)&0x000000C0)>>6)); \ } static void Blit_RGB888_index8(SDL_BlitInfo * info) @@ -913,11 +913,11 @@ Blit_RGB888_index8(SDL_BlitInfo * info) if (map == NULL) { while (height--) { #ifdef USE_DUFFS_LOOP - /* *INDENT-OFF* */ - DUFFS_LOOP( - RGB888_RGB332(*dst++, *src); - , width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + RGB888_RGB332(*dst++, *src); + , width); + /* *INDENT-ON* */ #else for (c = width / 4; c; --c) { /* Pack RGB into 8bit pixel */ @@ -949,13 +949,13 @@ Blit_RGB888_index8(SDL_BlitInfo * info) while (height--) { #ifdef USE_DUFFS_LOOP - /* *INDENT-OFF* */ - DUFFS_LOOP( - RGB888_RGB332(Pixel, *src); - *dst++ = map[Pixel]; - ++src; - , width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + , width); + /* *INDENT-ON* */ #else for (c = width / 4; c; --c) { /* Pack RGB into 8bit pixel */ @@ -995,17 +995,17 @@ Blit_RGB888_index8(SDL_BlitInfo * info) /* Special optimized blit for RGB 8-8-8 --> RGB 5-5-5 */ #define RGB888_RGB555(dst, src) { \ - *(Uint16 *)(dst) = (Uint16)((((*src)&0x00F80000)>>9)| \ - (((*src)&0x0000F800)>>6)| \ - (((*src)&0x000000F8)>>3)); \ + *(Uint16 *)(dst) = (Uint16)((((*src)&0x00F80000)>>9)| \ + (((*src)&0x0000F800)>>6)| \ + (((*src)&0x000000F8)>>3)); \ } #define RGB888_RGB555_TWO(dst, src) { \ - *(Uint32 *)(dst) = (((((src[HI])&0x00F80000)>>9)| \ - (((src[HI])&0x0000F800)>>6)| \ - (((src[HI])&0x000000F8)>>3))<<16)| \ - (((src[LO])&0x00F80000)>>9)| \ - (((src[LO])&0x0000F800)>>6)| \ - (((src[LO])&0x000000F8)>>3); \ + *(Uint32 *)(dst) = (((((src[HI])&0x00F80000)>>9)| \ + (((src[HI])&0x0000F800)>>6)| \ + (((src[HI])&0x000000F8)>>3))<<16)| \ + (((src[LO])&0x00F80000)>>9)| \ + (((src[LO])&0x0000F800)>>6)| \ + (((src[LO])&0x000000F8)>>3); \ } static void Blit_RGB888_RGB555(SDL_BlitInfo * info) @@ -1028,13 +1028,13 @@ Blit_RGB888_RGB555(SDL_BlitInfo * info) #ifdef USE_DUFFS_LOOP while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - RGB888_RGB555(dst, src); - ++src; - ++dst; - , width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + RGB888_RGB555(dst, src); + ++src; + ++dst; + , width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } @@ -1119,17 +1119,17 @@ Blit_RGB888_RGB555(SDL_BlitInfo * info) /* Special optimized blit for RGB 8-8-8 --> RGB 5-6-5 */ #define RGB888_RGB565(dst, src) { \ - *(Uint16 *)(dst) = (Uint16)((((*src)&0x00F80000)>>8)| \ - (((*src)&0x0000FC00)>>5)| \ - (((*src)&0x000000F8)>>3)); \ + *(Uint16 *)(dst) = (Uint16)((((*src)&0x00F80000)>>8)| \ + (((*src)&0x0000FC00)>>5)| \ + (((*src)&0x000000F8)>>3)); \ } #define RGB888_RGB565_TWO(dst, src) { \ - *(Uint32 *)(dst) = (((((src[HI])&0x00F80000)>>8)| \ - (((src[HI])&0x0000FC00)>>5)| \ - (((src[HI])&0x000000F8)>>3))<<16)| \ - (((src[LO])&0x00F80000)>>8)| \ - (((src[LO])&0x0000FC00)>>5)| \ - (((src[LO])&0x000000F8)>>3); \ + *(Uint32 *)(dst) = (((((src[HI])&0x00F80000)>>8)| \ + (((src[HI])&0x0000FC00)>>5)| \ + (((src[HI])&0x000000F8)>>3))<<16)| \ + (((src[LO])&0x00F80000)>>8)| \ + (((src[LO])&0x0000FC00)>>5)| \ + (((src[LO])&0x000000F8)>>3); \ } static void Blit_RGB888_RGB565(SDL_BlitInfo * info) @@ -1152,13 +1152,13 @@ Blit_RGB888_RGB565(SDL_BlitInfo * info) #ifdef USE_DUFFS_LOOP while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - RGB888_RGB565(dst, src); - ++src; - ++dst; - , width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + RGB888_RGB565(dst, src); + ++src; + ++dst; + , width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } @@ -1265,14 +1265,14 @@ Blit_RGB565_32(SDL_BlitInfo * info, const Uint32 * map) #ifdef USE_DUFFS_LOOP while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { - *dst++ = RGB565_32(dst, src, map); - src += 2; - }, - width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + { + *dst++ = RGB565_32(dst, src, map); + src += 2; + }, + width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } @@ -1863,9 +1863,9 @@ Blit_RGB565_BGRA8888(SDL_BlitInfo * info) /* Special optimized blit for RGB 8-8-8 --> RGB 3-3-2 */ #ifndef RGB888_RGB332 #define RGB888_RGB332(dst, src) { \ - dst = (((src)&0x00E00000)>>16)| \ - (((src)&0x0000E000)>>11)| \ - (((src)&0x000000C0)>>6); \ + dst = (((src)&0x00E00000)>>16)| \ + (((src)&0x0000E000)>>11)| \ + (((src)&0x000000C0)>>6); \ } #endif static void @@ -1892,13 +1892,13 @@ Blit_RGB888_index8_map(SDL_BlitInfo * info) #ifdef USE_DUFFS_LOOP while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - RGB888_RGB332(Pixel, *src); - *dst++ = map[Pixel]; - ++src; - , width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + RGB888_RGB332(Pixel, *src); + *dst++ = map[Pixel]; + ++src; + , width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } @@ -1969,20 +1969,20 @@ BlitNto1(SDL_BlitInfo * info) if (map == NULL) { while (height--) { #ifdef USE_DUFFS_LOOP - /* *INDENT-OFF* */ - DUFFS_LOOP( - DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, - sR, sG, sB); - if ( 1 ) { - /* Pack RGB into 8bit pixel */ - *dst = ((sR>>5)<<(3+2))| - ((sG>>5)<<(2)) | - ((sB>>6)<<(0)) ; - } - dst++; - src += srcbpp; - , width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = ((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ; + } + dst++; + src += srcbpp; + , width); + /* *INDENT-ON* */ #else for (c = width; c; --c) { DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); @@ -2001,20 +2001,20 @@ BlitNto1(SDL_BlitInfo * info) } else { while (height--) { #ifdef USE_DUFFS_LOOP - /* *INDENT-OFF* */ - DUFFS_LOOP( - DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, - sR, sG, sB); - if ( 1 ) { - /* Pack RGB into 8bit pixel */ - *dst = map[((sR>>5)<<(3+2))| - ((sG>>5)<<(2)) | - ((sB>>6)<<(0)) ]; - } - dst++; - src += srcbpp; - , width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( 1 ) { + /* Pack RGB into 8bit pixel */ + *dst = map[((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + , width); + /* *INDENT-ON* */ #else for (c = width; c; --c) { DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); @@ -2051,15 +2051,15 @@ Blit4to4MaskAlpha(SDL_BlitInfo * info) Uint32 mask = (info->a >> dstfmt->Aloss) << dstfmt->Ashift; while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { - *dst = *src | mask; - ++dst; - ++src; - }, - width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + { + *dst = *src | mask; + ++dst; + ++src; + }, + width); + /* *INDENT-ON* */ src = (Uint32 *) ((Uint8 *) src + srcskip); dst = (Uint32 *) ((Uint8 *) dst + dstskip); } @@ -2068,15 +2068,15 @@ Blit4to4MaskAlpha(SDL_BlitInfo * info) Uint32 mask = srcfmt->Rmask | srcfmt->Gmask | srcfmt->Bmask; while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { - *dst = *src & mask; - ++dst; - ++src; - }, - width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + { + *dst = *src & mask; + ++dst; + ++src; + }, + width); + /* *INDENT-ON* */ src = (Uint32 *) ((Uint8 *) src + srcskip); dst = (Uint32 *) ((Uint8 *) dst + dstskip); } @@ -2099,20 +2099,20 @@ BlitNtoN(SDL_BlitInfo * info) unsigned alpha = dstfmt->Amask ? info->a : 0; while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { + /* *INDENT-OFF* */ + DUFFS_LOOP( + { Uint32 Pixel; - unsigned sR; - unsigned sG; - unsigned sB; - DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); - ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, alpha); - dst += dstbpp; - src += srcbpp; - }, - width); - /* *INDENT-ON* */ + unsigned sR; + unsigned sG; + unsigned sB; + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, sR, sG, sB); + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, alpha); + dst += dstbpp; + src += srcbpp; + }, + width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } @@ -2170,43 +2170,43 @@ BlitNto1Key(SDL_BlitInfo * info) if (palmap == NULL) { while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { - DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, - sR, sG, sB); - if ( (Pixel & rgbmask) != ckey ) { - /* Pack RGB into 8bit pixel */ - *dst = (Uint8)(((sR>>5)<<(3+2))| - ((sG>>5)<<(2)) | - ((sB>>6)<<(0))); - } - dst++; - src += srcbpp; - }, - width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( (Pixel & rgbmask) != ckey ) { + /* Pack RGB into 8bit pixel */ + *dst = (Uint8)(((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0))); + } + dst++; + src += srcbpp; + }, + width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } } else { while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { - DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, - sR, sG, sB); - if ( (Pixel & rgbmask) != ckey ) { - /* Pack RGB into 8bit pixel */ - *dst = (Uint8)palmap[((sR>>5)<<(3+2))| - ((sG>>5)<<(2)) | - ((sB>>6)<<(0)) ]; - } - dst++; - src += srcbpp; - }, - width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + { + DISEMBLE_RGB(src, srcbpp, srcfmt, Pixel, + sR, sG, sB); + if ( (Pixel & rgbmask) != ckey ) { + /* Pack RGB into 8bit pixel */ + *dst = (Uint8)palmap[((sR>>5)<<(3+2))| + ((sG>>5)<<(2)) | + ((sB>>6)<<(0)) ]; + } + dst++; + src += srcbpp; + }, + width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } @@ -2231,17 +2231,17 @@ Blit2to2Key(SDL_BlitInfo * info) ckey &= rgbmask; while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { - if ( (*srcp & rgbmask) != ckey ) { - *dstp = *srcp; - } - dstp++; - srcp++; - }, - width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + { + if ( (*srcp & rgbmask) != ckey ) { + *dstp = *srcp; + } + dstp++; + srcp++; + }, + width); + /* *INDENT-ON* */ srcp += srcskip; dstp += dstskip; } @@ -2268,23 +2268,23 @@ BlitNtoNKey(SDL_BlitInfo * info) ckey &= rgbmask; while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { + /* *INDENT-OFF* */ + DUFFS_LOOP( + { Uint32 Pixel; - unsigned sR; - unsigned sG; - unsigned sB; - RETRIEVE_RGB_PIXEL(src, srcbpp, Pixel); - if ( (Pixel & rgbmask) != ckey ) { + unsigned sR; + unsigned sG; + unsigned sB; + RETRIEVE_RGB_PIXEL(src, srcbpp, Pixel); + if ( (Pixel & rgbmask) != ckey ) { RGB_FROM_PIXEL(Pixel, srcfmt, sR, sG, sB); - ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, alpha); - } - dst += dstbpp; - src += srcbpp; - }, - width); - /* *INDENT-ON* */ + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, alpha); + } + dst += dstbpp; + src += srcbpp; + }, + width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } @@ -2315,18 +2315,18 @@ BlitNtoNKeyCopyAlpha(SDL_BlitInfo * info) ckey &= rgbmask; while (height--) { - /* *INDENT-OFF* */ - DUFFS_LOOP( - { - DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, sR, sG, sB, sA); - if ( (Pixel & rgbmask) != ckey ) { - ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, sA); - } - dst += dstbpp; - src += srcbpp; - }, - width); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + DUFFS_LOOP( + { + DISEMBLE_RGBA(src, srcbpp, srcfmt, Pixel, sR, sG, sB, sA); + if ( (Pixel & rgbmask) != ckey ) { + ASSEMBLE_RGBA(dst, dstbpp, dstfmt, sR, sG, sB, sA); + } + dst += dstbpp; + src += srcbpp; + }, + width); + /* *INDENT-ON* */ src += srcskip; dst += dstskip; } @@ -2436,7 +2436,6 @@ SDL_CalculateBlitN(SDL_Surface * surface) case 0: blitfun = NULL; if (dstfmt->BitsPerPixel == 8) { - /* We assume 8-bit destinations are palettized */ if ((srcfmt->BytesPerPixel == 4) && (srcfmt->Rmask == 0x00FF0000) && (srcfmt->Gmask == 0x0000FF00) && diff --git a/src/video/SDL_stretch.c b/src/video/SDL_stretch.c index e976d10f0..660c93707 100644 --- a/src/video/SDL_stretch.c +++ b/src/video/SDL_stretch.c @@ -54,12 +54,12 @@ #endif #if defined(_M_IX86) || defined(i386) -#define PREFIX16 0x66 -#define STORE_BYTE 0xAA -#define STORE_WORD 0xAB -#define LOAD_BYTE 0xAC -#define LOAD_WORD 0xAD -#define RETURN 0xC3 +#define PREFIX16 0x66 +#define STORE_BYTE 0xAA +#define STORE_WORD 0xAB +#define LOAD_BYTE 0xAC +#define LOAD_WORD 0xAD +#define RETURN 0xC3 #else #error Need assembly opcodes for this architecture #endif @@ -148,23 +148,23 @@ generate_rowbytes(int src_w, int dst_w, int bpp) #endif /* USE_ASM_STRETCH */ -#define DEFINE_COPY_ROW(name, type) \ -static void name(type *src, int src_w, type *dst, int dst_w) \ -{ \ - int i; \ - int pos, inc; \ - type pixel = 0; \ - \ - pos = 0x10000; \ - inc = (src_w << 16) / dst_w; \ - for ( i=dst_w; i>0; --i ) { \ - while ( pos >= 0x10000L ) { \ - pixel = *src++; \ - pos -= 0x10000L; \ - } \ - *dst++ = pixel; \ - pos += inc; \ - } \ +#define DEFINE_COPY_ROW(name, type) \ +static void name(type *src, int src_w, type *dst, int dst_w) \ +{ \ + int i; \ + int pos, inc; \ + type pixel = 0; \ + \ + pos = 0x10000; \ + inc = (src_w << 16) / dst_w; \ + for ( i=dst_w; i>0; --i ) { \ + while ( pos >= 0x10000L ) { \ + pixel = *src++; \ + pos -= 0x10000L; \ + } \ + *dst++ = pixel; \ + pos += inc; \ + } \ } /* *INDENT-OFF* */ DEFINE_COPY_ROW(copy_row1, Uint8) @@ -220,7 +220,7 @@ SDL_SoftStretch(SDL_Surface * src, const SDL_Rect * srcrect, #endif /* USE_ASM_STRETCH */ const int bpp = dst->format->BytesPerPixel; - if (src->format->BitsPerPixel != dst->format->BitsPerPixel) { + if (src->format->format != dst->format->format) { return SDL_SetError("Only works with same format surfaces"); }