src/video/SDL_stretch.c
branchSDL-1.2
changeset 4109 cd2ab40f1219
parent 4108 3feb94233f90
child 4159 a1b03ba2fcd0
     1.1 --- a/src/video/SDL_stretch.c	Sat Dec 29 03:50:29 2007 +0000
     1.2 +++ b/src/video/SDL_stretch.c	Sat Dec 29 05:18:33 2007 +0000
     1.3 @@ -42,14 +42,15 @@
     1.4  
     1.5  #ifdef USE_ASM_STRETCH
     1.6  
     1.7 -/* OpenBSD has non-executable memory by default, so use mprotect() */
     1.8 -#ifdef __OpenBSD__
     1.9 -#define USE_MPROTECT
    1.10 -#endif
    1.11 -#ifdef USE_MPROTECT
    1.12 +#ifdef HAVE_MPROTECT
    1.13  #include <sys/types.h>
    1.14  #include <sys/mman.h>
    1.15  #endif
    1.16 +#ifdef __GNUC__
    1.17 +#define PAGE_ALIGNED __attribute__((__aligned__(4096)))
    1.18 +#else
    1.19 +#define PAGE_ALIGNED
    1.20 +#endif
    1.21  
    1.22  #if defined(_M_IX86) || defined(i386)
    1.23  #define PREFIX16	0x66
    1.24 @@ -62,7 +63,7 @@
    1.25  #error Need assembly opcodes for this architecture
    1.26  #endif
    1.27  
    1.28 -static unsigned char copy_row[4096];
    1.29 +static unsigned char copy_row[4096] PAGE_ALIGNED;
    1.30  
    1.31  static int generate_rowbytes(int src_w, int dst_w, int bpp)
    1.32  {
    1.33 @@ -70,6 +71,7 @@
    1.34  		int bpp;
    1.35  		int src_w;
    1.36  		int dst_w;
    1.37 +		int status;
    1.38  	} last;
    1.39  
    1.40  	int i;
    1.41 @@ -80,11 +82,12 @@
    1.42  	/* See if we need to regenerate the copy buffer */
    1.43  	if ( (src_w == last.src_w) &&
    1.44  	     (dst_w == last.dst_w) && (bpp == last.bpp) ) {
    1.45 -		return(0);
    1.46 +		return(last.status);
    1.47  	}
    1.48  	last.bpp = bpp;
    1.49  	last.src_w = src_w;
    1.50  	last.dst_w = dst_w;
    1.51 +	last.status = -1;
    1.52  
    1.53  	switch (bpp) {
    1.54  	    case 1:
    1.55 @@ -100,9 +103,6 @@
    1.56  		SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp);
    1.57  		return(-1);
    1.58  	}
    1.59 -#ifdef USE_MPROTECT
    1.60 -	mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_WRITE|PROT_EXEC);
    1.61 -#endif
    1.62  	pos = 0x10000;
    1.63  	inc = (src_w << 16) / dst_w;
    1.64  	eip = copy_row;
    1.65 @@ -122,15 +122,23 @@
    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 */
    1.77 +	if ( mprotect(copy_row, sizeof(copy_row), PROT_READ|PROT_WRITE|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 @@ -154,8 +162,6 @@
    1.92  DEFINE_COPY_ROW(copy_row2, Uint16)
    1.93  DEFINE_COPY_ROW(copy_row4, Uint32)
    1.94  
    1.95 -#endif /* USE_ASM_STRETCH */
    1.96 -
    1.97  /* The ASM code doesn't handle 24-bpp stretch blits */
    1.98  void copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w)
    1.99  {
   1.100 @@ -195,9 +201,12 @@
   1.101  	Uint8 *dstp;
   1.102  	SDL_Rect full_src;
   1.103  	SDL_Rect full_dst;
   1.104 -#if defined(USE_ASM_STRETCH) && defined(__GNUC__)
   1.105 +#ifdef USE_ASM_STRETCH
   1.106 +	SDL_bool use_asm = SDL_TRUE;
   1.107 +#ifdef __GNUC__
   1.108  	int u1, u2;
   1.109  #endif
   1.110 +#endif /* USE_ASM_STRETCH */
   1.111  	const int bpp = dst->format->BytesPerPixel;
   1.112  
   1.113  	if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) {
   1.114 @@ -266,9 +275,9 @@
   1.115  
   1.116  #ifdef USE_ASM_STRETCH
   1.117  	/* Write the opcodes for this stretch */
   1.118 -	if ( (bpp != 3) &&
   1.119 +	if ( (bpp == 3) ||
   1.120  	     (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0) ) {
   1.121 -		return(-1);
   1.122 +		use_asm = SDL_FALSE;
   1.123  	}
   1.124  #endif
   1.125  
   1.126 @@ -283,11 +292,7 @@
   1.127  			pos -= 0x10000L;
   1.128  		}
   1.129  #ifdef USE_ASM_STRETCH
   1.130 -		switch (bpp) {
   1.131 -		    case 3:
   1.132 -			copy_row3(srcp, srcrect->w, dstp, dstrect->w);
   1.133 -			break;
   1.134 -		    default:
   1.135 +		if (use_asm) {
   1.136  #ifdef __GNUC__
   1.137  			__asm__ __volatile__ (
   1.138  			"call *%4"
   1.139 @@ -311,9 +316,8 @@
   1.140  #else
   1.141  #error Need inline assembly for this compiler
   1.142  #endif
   1.143 -			break;
   1.144 -		}
   1.145 -#else
   1.146 +		} else
   1.147 +#endif
   1.148  		switch (bpp) {
   1.149  		    case 1:
   1.150  			copy_row1(srcp, srcrect->w, dstp, dstrect->w);
   1.151 @@ -330,7 +334,6 @@
   1.152  			          (Uint32 *)dstp, dstrect->w);
   1.153  			break;
   1.154  		}
   1.155 -#endif
   1.156  		pos += inc;
   1.157  	}
   1.158