src/video/SDL_stretch.c
changeset 3405 d5f2dd33f4eb
parent 2859 99210400e8b9
child 3406 8ae607392409
     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