Date: Tue, 13 Jan 2004 19:25:37 +0300
authorSam Lantinga <slouken@libsdl.org>
Wed, 11 Feb 2004 16:10:16 +0000
changeset 809dba98fb391e7
parent 808 0defd90ef27c
child 810 26a0e2d69d39
Date: Tue, 13 Jan 2004 19:25:37 +0300
From: Dmitry Yakimov
Subject: [SDL] [PATCH] SDL bug patch

Let me introduce 2 fixes to SDL.

1. Preventing great slowdown on fast machines while hardware
flipping (it's obviously bug).
2. Setting up 85 Hz of monitor if supported. The reason is that
Win98 by default sets lowest frequency 60 Hz.
And we can't set up maximum frequency because some users can have
wrong monitor drivers.
This is important for shareware and commercial programs.
src/video/windx5/SDL_dx5video.c
     1.1 --- a/src/video/windx5/SDL_dx5video.c	Wed Feb 11 07:26:29 2004 +0000
     1.2 +++ b/src/video/windx5/SDL_dx5video.c	Wed Feb 11 16:10:16 2004 +0000
     1.3 @@ -71,6 +71,7 @@
     1.4  /* This is the rect EnumModes2 uses */
     1.5  struct DX5EnumRect {
     1.6  	SDL_Rect r;
     1.7 +	int refreshRate;
     1.8  	struct DX5EnumRect* next;
     1.9  };
    1.10  static struct DX5EnumRect *enumlists[NUM_MODELISTS];
    1.11 @@ -650,8 +651,10 @@
    1.12  	struct DX5EnumRect *enumrect;
    1.13  #if defined(NONAMELESSUNION)
    1.14  	int bpp = desc->ddpfPixelFormat.u1.dwRGBBitCount;
    1.15 +	int refreshRate = desc->u2.dwRefreshRate;
    1.16  #else
    1.17  	int bpp = desc->ddpfPixelFormat.dwRGBBitCount;
    1.18 +	int refreshRate = desc->dwRefreshRate;
    1.19  #endif
    1.20  
    1.21  	switch (bpp)  {
    1.22 @@ -660,22 +663,33 @@
    1.23  		case 24:
    1.24  		case 32:
    1.25  			bpp /= 8; --bpp;
    1.26 +			if ( enumlists[bpp] &&
    1.27 +			     enumlists[bpp]->r.w == (Uint16)desc->dwWidth &&
    1.28 +			     enumlists[bpp]->r.h == (Uint16)desc->dwHeight ) {
    1.29 +				if ( refreshRate > enumlists[bpp]->refreshRate &&
    1.30 +				     refreshRate <= 85 /* safe value? */ ) {
    1.31 +					enumlists[bpp]->refreshRate = refreshRate;
    1.32 +printf("New refresh rate for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate);
    1.33 +				}
    1.34 +				break;
    1.35 +			}
    1.36  			++SDL_nummodes[bpp];
    1.37  			enumrect = (struct DX5EnumRect*)malloc(sizeof(struct DX5EnumRect));
    1.38  			if ( !enumrect ) {
    1.39  				SDL_OutOfMemory();
    1.40  				return(DDENUMRET_CANCEL);
    1.41  			}
    1.42 +			enumrect->refreshRate = refreshRate;
    1.43  			enumrect->r.x = 0;
    1.44  			enumrect->r.y = 0;
    1.45  			enumrect->r.w = (Uint16)desc->dwWidth;
    1.46  			enumrect->r.h = (Uint16)desc->dwHeight;
    1.47  			enumrect->next = enumlists[bpp];
    1.48  			enumlists[bpp] = enumrect;
    1.49 +printf("New mode for %d bpp: %dx%d at %d Hz\n", (bpp+1)*8, (int)desc->dwWidth, (int)desc->dwHeight, refreshRate);
    1.50  			break;
    1.51  	}
    1.52  
    1.53 -
    1.54  	return(DDENUMRET_OK);
    1.55  }
    1.56  
    1.57 @@ -912,7 +926,7 @@
    1.58  	for ( i=0; i<NUM_MODELISTS; ++i )
    1.59  		enumlists[i] = NULL;
    1.60  
    1.61 -	result = IDirectDraw2_EnumDisplayModes(ddraw2,0,NULL,this,EnumModes2);
    1.62 +	result = IDirectDraw2_EnumDisplayModes(ddraw2,DDEDM_REFRESHRATES,NULL,this,EnumModes2);
    1.63  	if ( result != DD_OK ) {
    1.64  		SetDDerror("DirectDraw2::EnumDisplayModes", result);
    1.65  		return(-1);
    1.66 @@ -926,7 +940,7 @@
    1.67  			return(-1);
    1.68  		}
    1.69  		for ( j = 0, rect = enumlists[i]; rect; ++j, rect = rect->next ) {
    1.70 -			SDL_modelist[i][j]=(SDL_Rect *)rect;
    1.71 +			SDL_modelist[i][j] = &rect->r;
    1.72  		}
    1.73  		SDL_modelist[i][j] = NULL;
    1.74  	}
    1.75 @@ -1195,6 +1209,9 @@
    1.76  
    1.77  	/* Set the display mode, if we are in fullscreen mode */
    1.78  	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    1.79 +		struct DX5EnumRect *rect;
    1.80 +		int maxRefreshRate;
    1.81 +
    1.82  		/* Cover up desktop during mode change */
    1.83  		SDL_resizing = 1;
    1.84  		SetWindowPos(SDL_Window, NULL, 0, 0, 
    1.85 @@ -1207,12 +1224,25 @@
    1.86  			SetForegroundWindow(SDL_Window);
    1.87  			SDL_Delay(100);
    1.88  		}
    1.89 -		result = IDirectDraw2_SetDisplayMode(ddraw2, width, height,
    1.90 -								bpp, 0, 0);
    1.91 +
    1.92 +		/* find maximum monitor refresh rate for this resolution */
    1.93 +		/* Dmitry Yakimov ftech@tula.net */
    1.94 +		maxRefreshRate = 0; /* system default */
    1.95 +		for ( rect = enumlists[bpp / 8 - 1]; rect; rect = rect->next ) {
    1.96 +			if ( (width == rect->r.w) && (height == rect->r.h) ) {
    1.97 +				maxRefreshRate = rect->refreshRate;
    1.98 +				break;
    1.99 +			}
   1.100 +		}
   1.101 +		printf("refresh rate = %d Hz\n", maxRefreshRate);
   1.102 +
   1.103 +		result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, maxRefreshRate, 0);
   1.104  		if ( result != DD_OK ) {
   1.105 -			/* We couldn't set fullscreen mode, try window */
   1.106 -			return(DX5_SetVideoMode(this, current,
   1.107 -				width, height, bpp, flags & ~SDL_FULLSCREEN)); 
   1.108 +			result = IDirectDraw2_SetDisplayMode(ddraw2, width, height, bpp, 0, 0);
   1.109 +			if ( result != DD_OK ) {
   1.110 +				/* We couldn't set fullscreen mode, try window */
   1.111 +				return(DX5_SetVideoMode(this, current, width, height, bpp, flags & ~SDL_FULLSCREEN)); 
   1.112 +			}
   1.113  		}
   1.114  		DX5_DInputReset(this, 1);
   1.115  	} else {
   1.116 @@ -1953,11 +1983,17 @@
   1.117  	LPDIRECTDRAWSURFACE3 dd_surface;
   1.118  
   1.119  	dd_surface = surface->hwdata->dd_surface;
   1.120 -	result = IDirectDrawSurface3_Flip(dd_surface, NULL, 0);
   1.121 +
   1.122 +	/* to prevent big slowdown on fast computers, wait here instead of driver ring 0 code */
   1.123 +	/* Dmitry Yakimov (ftech@tula.net) */
   1.124 +	while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
   1.125 +
   1.126 +	result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
   1.127  	if ( result == DDERR_SURFACELOST ) {
   1.128  		result = IDirectDrawSurface3_Restore(
   1.129  						surface->hwdata->dd_surface);
   1.130 -		result = IDirectDrawSurface3_Flip(dd_surface, NULL, 0);
   1.131 +		while(IDirectDrawSurface3_GetFlipStatus(dd_surface, DDGBS_ISBLTDONE) == DDERR_WASSTILLDRAWING);
   1.132 +		result = IDirectDrawSurface3_Flip(dd_surface, NULL, DDFLIP_WAIT);
   1.133  	}
   1.134  	if ( result != DD_OK ) {
   1.135  		SetDDerror("DirectDrawSurface3::Flip", result);