Mercurial > sdl-ios-xcode
diff src/video/SDL_stretch.c @ 3405:d5f2dd33f4eb
Merged improvements to SDL_SoftStretch() from SDL 1.2
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 18 Oct 2009 17:49:40 +0000 |
parents | 99210400e8b9 |
children | 8ae607392409 |
line wrap: on
line diff
--- a/src/video/SDL_stretch.c Sun Oct 18 16:14:35 2009 +0000 +++ b/src/video/SDL_stretch.c Sun Oct 18 17:49:40 2009 +0000 @@ -42,6 +42,16 @@ #ifdef USE_ASM_STRETCH +#ifdef HAVE_MPROTECT +#include <sys/types.h> +#include <sys/mman.h> +#endif +#ifdef __GNUC__ +#define PAGE_ALIGNED __attribute__((__aligned__(4096))) +#else +#define PAGE_ALIGNED +#endif + #if defined(_M_IX86) || defined(i386) #define PREFIX16 0x66 #define STORE_BYTE 0xAA @@ -53,7 +63,7 @@ #error Need assembly opcodes for this architecture #endif -static unsigned char copy_row[4096]; +static unsigned char copy_row[4096] PAGE_ALIGNED; static int generate_rowbytes(int src_w, int dst_w, int bpp) @@ -63,6 +73,7 @@ int bpp; int src_w; int dst_w; + int status; } last; int i; @@ -72,11 +83,12 @@ /* See if we need to regenerate the copy buffer */ if ((src_w == last.src_w) && (dst_w == last.dst_w) && (bpp == last.bpp)) { - return (0); + return (last.status); } last.bpp = bpp; last.src_w = src_w; last.dst_w = dst_w; + last.status = -1; switch (bpp) { case 1: @@ -92,6 +104,13 @@ SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp); return (-1); } +#ifdef HAVE_MPROTECT + /* Make the code writeable */ + if (mprotect(copy_row, sizeof(copy_row), PROT_READ | PROT_WRITE) < 0) { + SDL_SetError("Couldn't make copy buffer writeable"); + return (-1); + } +#endif pos = 0x10000; inc = (src_w << 16) / dst_w; eip = copy_row; @@ -111,47 +130,55 @@ } *eip++ = RETURN; - /* Verify that we didn't overflow (too late) */ + /* Verify that we didn't overflow (too late!!!) */ if (eip > (copy_row + sizeof(copy_row))) { SDL_SetError("Copy buffer overflow"); return (-1); } +#ifdef HAVE_MPROTECT + /* Make the code executable but not writeable */ + if (mprotect(copy_row, sizeof(copy_row), PROT_READ | PROT_EXEC) < 0) { + SDL_SetError("Couldn't make copy buffer executable"); + return (-1); + } +#endif + last.status = 0; return (0); } -#else +#endif /* USE_ASM_STRETCH */ -#define DEFINE_COPY_ROW(name, type) \ -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) \ +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) DEFINE_COPY_ROW(copy_row2, Uint16) DEFINE_COPY_ROW(copy_row4, Uint32) /* *INDENT-ON* */ -#endif /* USE_ASM_STRETCH */ + /* The ASM code doesn't handle 24-bpp stretch blits */ void copy_row3(Uint8 * src, int src_w, Uint8 * dst, int dst_w) { int i; int pos, inc; - Uint8 pixel[3]; + Uint8 pixel[3] = { 0, 0, 0 }; pos = 0x10000; inc = (src_w << 16) / dst_w; @@ -186,9 +213,12 @@ Uint8 *dstp; SDL_Rect full_src; SDL_Rect full_dst; -#if defined(USE_ASM_STRETCH) && defined(__GNUC__) +#ifdef USE_ASM_STRETCH + SDL_bool use_asm = SDL_TRUE; +#ifdef __GNUC__ int u1, u2; #endif +#endif /* USE_ASM_STRETCH */ const int bpp = dst->format->BytesPerPixel; if (src->format->BitsPerPixel != dst->format->BitsPerPixel) { @@ -257,8 +287,8 @@ #ifdef USE_ASM_STRETCH /* Write the opcodes for this stretch */ - if ((bpp != 3) && (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0)) { - return (-1); + if ((bpp == 3) || (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0)) { + use_asm = SDL_FALSE; } #endif @@ -273,13 +303,11 @@ pos -= 0x10000L; } #ifdef USE_ASM_STRETCH - switch (bpp) { - case 3: - copy_row3(srcp, srcrect->w, dstp, dstrect->w); - break; - default: + if (use_asm) { #ifdef __GNUC__ - __asm__ __volatile__("call *%4": "=&D"(u1), "=&S"(u2): "0"(dstp), "1"(srcp), "r"(copy_row):"memory"); + __asm__ __volatile__("call *%4":"=&D"(u1), "=&S"(u2) + :"0"(dstp), "1"(srcp), "r"(copy_row) + :"memory"); #elif defined(_MSC_VER) || defined(__WATCOMC__) /* *INDENT-OFF* */ { @@ -298,26 +326,24 @@ #else #error Need inline assembly for this compiler #endif - break; - } -#else - switch (bpp) { - case 1: - copy_row1(srcp, srcrect->w, dstp, dstrect->w); - break; - case 2: - copy_row2((Uint16 *) srcp, srcrect->w, - (Uint16 *) dstp, dstrect->w); - break; - case 3: - copy_row3(srcp, srcrect->w, dstp, dstrect->w); - break; - case 4: - copy_row4((Uint32 *) srcp, srcrect->w, - (Uint32 *) dstp, dstrect->w); - break; - } + } else #endif + switch (bpp) { + case 1: + copy_row1(srcp, srcrect->w, dstp, dstrect->w); + break; + case 2: + copy_row2((Uint16 *) srcp, srcrect->w, + (Uint16 *) dstp, dstrect->w); + break; + case 3: + copy_row3(srcp, srcrect->w, dstp, dstrect->w); + break; + case 4: + copy_row4((Uint32 *) srcp, srcrect->w, + (Uint32 *) dstp, dstrect->w); + break; + } pos += inc; }