1.1 --- a/src/video/SDL_stretch.c Sun Oct 18 16:14:35 2009 +0000
1.2 +++ b/src/video/SDL_stretch.c Sun Oct 18 17:49:40 2009 +0000
1.3 @@ -42,6 +42,16 @@
1.4
1.5 #ifdef USE_ASM_STRETCH
1.6
1.7 +#ifdef HAVE_MPROTECT
1.8 +#include <sys/types.h>
1.9 +#include <sys/mman.h>
1.10 +#endif
1.11 +#ifdef __GNUC__
1.12 +#define PAGE_ALIGNED __attribute__((__aligned__(4096)))
1.13 +#else
1.14 +#define PAGE_ALIGNED
1.15 +#endif
1.16 +
1.17 #if defined(_M_IX86) || defined(i386)
1.18 #define PREFIX16 0x66
1.19 #define STORE_BYTE 0xAA
1.20 @@ -53,7 +63,7 @@
1.21 #error Need assembly opcodes for this architecture
1.22 #endif
1.23
1.24 -static unsigned char copy_row[4096];
1.25 +static unsigned char copy_row[4096] PAGE_ALIGNED;
1.26
1.27 static int
1.28 generate_rowbytes(int src_w, int dst_w, int bpp)
1.29 @@ -63,6 +73,7 @@
1.30 int bpp;
1.31 int src_w;
1.32 int dst_w;
1.33 + int status;
1.34 } last;
1.35
1.36 int i;
1.37 @@ -72,11 +83,12 @@
1.38
1.39 /* See if we need to regenerate the copy buffer */
1.40 if ((src_w == last.src_w) && (dst_w == last.dst_w) && (bpp == last.bpp)) {
1.41 - return (0);
1.42 + return (last.status);
1.43 }
1.44 last.bpp = bpp;
1.45 last.src_w = src_w;
1.46 last.dst_w = dst_w;
1.47 + last.status = -1;
1.48
1.49 switch (bpp) {
1.50 case 1:
1.51 @@ -92,6 +104,13 @@
1.52 SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp);
1.53 return (-1);
1.54 }
1.55 +#ifdef HAVE_MPROTECT
1.56 + /* Make the code writeable */
1.57 + if (mprotect(copy_row, sizeof(copy_row), PROT_READ | PROT_WRITE) < 0) {
1.58 + SDL_SetError("Couldn't make copy buffer writeable");
1.59 + return (-1);
1.60 + }
1.61 +#endif
1.62 pos = 0x10000;
1.63 inc = (src_w << 16) / dst_w;
1.64 eip = copy_row;
1.65 @@ -111,47 +130,55 @@
1.66 }
1.67 *eip++ = RETURN;
1.68
1.69 - /* Verify that we didn't overflow (too late) */
1.70 + /* Verify that we didn't overflow (too late!!!) */
1.71 if (eip > (copy_row + sizeof(copy_row))) {
1.72 SDL_SetError("Copy buffer overflow");
1.73 return (-1);
1.74 }
1.75 +#ifdef HAVE_MPROTECT
1.76 + /* Make the code executable but not writeable */
1.77 + if (mprotect(copy_row, sizeof(copy_row), PROT_READ | PROT_EXEC) < 0) {
1.78 + SDL_SetError("Couldn't make copy buffer executable");
1.79 + return (-1);
1.80 + }
1.81 +#endif
1.82 + last.status = 0;
1.83 return (0);
1.84 }
1.85
1.86 -#else
1.87 +#endif /* USE_ASM_STRETCH */
1.88
1.89 -#define DEFINE_COPY_ROW(name, type) \
1.90 -void name(type *src, int src_w, type *dst, int dst_w) \
1.91 -{ \
1.92 - int i; \
1.93 - int pos, inc; \
1.94 - type pixel = 0; \
1.95 - \
1.96 - pos = 0x10000; \
1.97 - inc = (src_w << 16) / dst_w; \
1.98 - for ( i=dst_w; i>0; --i ) { \
1.99 - while ( pos >= 0x10000L ) { \
1.100 - pixel = *src++; \
1.101 - pos -= 0x10000L; \
1.102 - } \
1.103 - *dst++ = pixel; \
1.104 - pos += inc; \
1.105 - } \
1.106 +#define DEFINE_COPY_ROW(name, type) \
1.107 +void name(type *src, int src_w, type *dst, int dst_w) \
1.108 +{ \
1.109 + int i; \
1.110 + int pos, inc; \
1.111 + type pixel = 0; \
1.112 + \
1.113 + pos = 0x10000; \
1.114 + inc = (src_w << 16) / dst_w; \
1.115 + for ( i=dst_w; i>0; --i ) { \
1.116 + while ( pos >= 0x10000L ) { \
1.117 + pixel = *src++; \
1.118 + pos -= 0x10000L; \
1.119 + } \
1.120 + *dst++ = pixel; \
1.121 + pos += inc; \
1.122 + } \
1.123 }
1.124 /* *INDENT-OFF* */
1.125 DEFINE_COPY_ROW(copy_row1, Uint8)
1.126 DEFINE_COPY_ROW(copy_row2, Uint16)
1.127 DEFINE_COPY_ROW(copy_row4, Uint32)
1.128 /* *INDENT-ON* */
1.129 -#endif /* USE_ASM_STRETCH */
1.130 +
1.131 /* The ASM code doesn't handle 24-bpp stretch blits */
1.132 void
1.133 copy_row3(Uint8 * src, int src_w, Uint8 * dst, int dst_w)
1.134 {
1.135 int i;
1.136 int pos, inc;
1.137 - Uint8 pixel[3];
1.138 + Uint8 pixel[3] = { 0, 0, 0 };
1.139
1.140 pos = 0x10000;
1.141 inc = (src_w << 16) / dst_w;
1.142 @@ -186,9 +213,12 @@
1.143 Uint8 *dstp;
1.144 SDL_Rect full_src;
1.145 SDL_Rect full_dst;
1.146 -#if defined(USE_ASM_STRETCH) && defined(__GNUC__)
1.147 +#ifdef USE_ASM_STRETCH
1.148 + SDL_bool use_asm = SDL_TRUE;
1.149 +#ifdef __GNUC__
1.150 int u1, u2;
1.151 #endif
1.152 +#endif /* USE_ASM_STRETCH */
1.153 const int bpp = dst->format->BytesPerPixel;
1.154
1.155 if (src->format->BitsPerPixel != dst->format->BitsPerPixel) {
1.156 @@ -257,8 +287,8 @@
1.157
1.158 #ifdef USE_ASM_STRETCH
1.159 /* Write the opcodes for this stretch */
1.160 - if ((bpp != 3) && (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0)) {
1.161 - return (-1);
1.162 + if ((bpp == 3) || (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0)) {
1.163 + use_asm = SDL_FALSE;
1.164 }
1.165 #endif
1.166
1.167 @@ -273,13 +303,11 @@
1.168 pos -= 0x10000L;
1.169 }
1.170 #ifdef USE_ASM_STRETCH
1.171 - switch (bpp) {
1.172 - case 3:
1.173 - copy_row3(srcp, srcrect->w, dstp, dstrect->w);
1.174 - break;
1.175 - default:
1.176 + if (use_asm) {
1.177 #ifdef __GNUC__
1.178 - __asm__ __volatile__("call *%4": "=&D"(u1), "=&S"(u2): "0"(dstp), "1"(srcp), "r"(copy_row):"memory");
1.179 + __asm__ __volatile__("call *%4":"=&D"(u1), "=&S"(u2)
1.180 + :"0"(dstp), "1"(srcp), "r"(copy_row)
1.181 + :"memory");
1.182 #elif defined(_MSC_VER) || defined(__WATCOMC__)
1.183 /* *INDENT-OFF* */
1.184 {
1.185 @@ -298,26 +326,24 @@
1.186 #else
1.187 #error Need inline assembly for this compiler
1.188 #endif
1.189 - break;
1.190 - }
1.191 -#else
1.192 - switch (bpp) {
1.193 - case 1:
1.194 - copy_row1(srcp, srcrect->w, dstp, dstrect->w);
1.195 - break;
1.196 - case 2:
1.197 - copy_row2((Uint16 *) srcp, srcrect->w,
1.198 - (Uint16 *) dstp, dstrect->w);
1.199 - break;
1.200 - case 3:
1.201 - copy_row3(srcp, srcrect->w, dstp, dstrect->w);
1.202 - break;
1.203 - case 4:
1.204 - copy_row4((Uint32 *) srcp, srcrect->w,
1.205 - (Uint32 *) dstp, dstrect->w);
1.206 - break;
1.207 - }
1.208 + } else
1.209 #endif
1.210 + switch (bpp) {
1.211 + case 1:
1.212 + copy_row1(srcp, srcrect->w, dstp, dstrect->w);
1.213 + break;
1.214 + case 2:
1.215 + copy_row2((Uint16 *) srcp, srcrect->w,
1.216 + (Uint16 *) dstp, dstrect->w);
1.217 + break;
1.218 + case 3:
1.219 + copy_row3(srcp, srcrect->w, dstp, dstrect->w);
1.220 + break;
1.221 + case 4:
1.222 + copy_row4((Uint32 *) srcp, srcrect->w,
1.223 + (Uint32 *) dstp, dstrect->w);
1.224 + break;
1.225 + }
1.226 pos += inc;
1.227 }
1.228