Fixes from Dmitry Yakimov:
authorSam Lantinga <slouken@libsdl.org>
Sat, 11 Mar 2006 23:46:45 +0000
changeset 1497420b3f47806d
parent 1496 405e20dc004c
child 1498 3968f7cba10c
Fixes from Dmitry Yakimov:

fixed bugs 159 and 160:

+ added threaded timers support
! fixed restoring sdl window focus (AV in windows message handler)
! disabled forgotten cdrom and joystick in config file.
* disabled minimizing sdl window while loosing focus.
PocketPC does not have a task bar, so it is an inconvenient and unusual
behaviour for PPC users.
+ added WIN_Paint handler for GAPI
! fixed loosing focus while using GAPI videi driver

+ added TestTimer project
* removed unnecessary macros (ENABLE_WINDIB ...) from projects
VisualCE.zip
include/SDL_config_win32.h
src/timer/win32/SDL_systimer.c
src/timer/wince/SDL_systimer.c
src/video/gapi/SDL_gapivideo.c
src/video/gapi/SDL_gapivideo.h
src/video/wincommon/SDL_sysevents.c
     1.1 Binary file VisualCE.zip has changed
     2.1 --- a/include/SDL_config_win32.h	Sat Mar 11 23:44:21 2006 +0000
     2.2 +++ b/include/SDL_config_win32.h	Sat Mar 11 23:46:45 2006 +0000
     2.3 @@ -117,10 +117,18 @@
     2.4  #define SDL_AUDIO_DRIVER_WAVEOUT	1
     2.5  
     2.6  /* Enable various cdrom drivers */
     2.7 -#define SDL_CDROM_WIN32	1
     2.8 +#ifdef _WIN32_WCE
     2.9 +#define SDL_CDROM_DISABLED      1
    2.10 +#else
    2.11 +#define SDL_CDROM_WIN32		1
    2.12 +#endif
    2.13  
    2.14  /* Enable various input drivers */
    2.15 +#ifdef _WIN32_WCE
    2.16 +#define SDL_JOYSTICK_DISABLED   1
    2.17 +#else
    2.18  #define SDL_JOYSTICK_WINMM	1
    2.19 +#endif
    2.20  
    2.21  /* Enable various shared object loading systems */
    2.22  #define SDL_LOADSO_WIN32	1
    2.23 @@ -136,12 +144,12 @@
    2.24  #endif
    2.25  
    2.26  /* Enable various video drivers */
    2.27 +#ifdef _WIN32_WCE
    2.28 +#define SDL_VIDEO_DRIVER_GAPI	1
    2.29 +#endif
    2.30  #ifndef _WIN32_WCE
    2.31  #define SDL_VIDEO_DRIVER_DDRAW	1
    2.32  #endif
    2.33 -#ifdef _WIN32_WCE
    2.34 -#define SDL_VIDEO_DRIVER_GAPI	1
    2.35 -#endif
    2.36  #define SDL_VIDEO_DRIVER_WINDIB	1
    2.37  
    2.38  /* Enable OpenGL support */
     3.1 --- a/src/timer/win32/SDL_systimer.c	Sat Mar 11 23:44:21 2006 +0000
     3.2 +++ b/src/timer/win32/SDL_systimer.c	Sat Mar 11 23:46:45 2006 +0000
     3.3 @@ -30,10 +30,6 @@
     3.4  
     3.5  #ifdef _WIN32_WCE
     3.6    #error This is WinCE. Please use src/timer/wince/SDL_systimer.c instead.
     3.7 -
     3.8 -  /* but if you really want to use this file, use these #defines... */
     3.9 -  #define USE_GETTICKCOUNT
    3.10 -  #define USE_SETTIMER
    3.11  #endif
    3.12  
    3.13  #define TIME_WRAP_VALUE	(~(DWORD)0)
    3.14 @@ -111,62 +107,6 @@
    3.15  	Sleep(ms);
    3.16  }
    3.17  
    3.18 -#ifdef USE_SETTIMER
    3.19 -
    3.20 -static UINT WIN_timer;
    3.21 -
    3.22 -int SDL_SYS_TimerInit(void)
    3.23 -{
    3.24 -	return(0);
    3.25 -}
    3.26 -
    3.27 -void SDL_SYS_TimerQuit(void)
    3.28 -{
    3.29 -	return;
    3.30 -}
    3.31 -
    3.32 -/* Forward declaration because this is called by the timer callback */
    3.33 -int SDL_SYS_StartTimer(void);
    3.34 -
    3.35 -static VOID CALLBACK TimerCallbackProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    3.36 -{
    3.37 -	Uint32 ms;
    3.38 -
    3.39 -	ms = SDL_alarm_callback(SDL_alarm_interval);
    3.40 -	if ( ms != SDL_alarm_interval ) {
    3.41 -		KillTimer(NULL, idEvent);
    3.42 -		if ( ms ) {
    3.43 -			SDL_alarm_interval = ROUND_RESOLUTION(ms);
    3.44 -			SDL_SYS_StartTimer();
    3.45 -		} else {
    3.46 -			SDL_alarm_interval = 0;
    3.47 -		}
    3.48 -	}
    3.49 -}
    3.50 -
    3.51 -int SDL_SYS_StartTimer(void)
    3.52 -{
    3.53 -	int retval;
    3.54 -
    3.55 -	WIN_timer = SetTimer(NULL, 0, SDL_alarm_interval, TimerCallbackProc);
    3.56 -	if ( WIN_timer ) {
    3.57 -		retval = 0;
    3.58 -	} else {
    3.59 -		retval = -1;
    3.60 -	}
    3.61 -	return retval;
    3.62 -}
    3.63 -
    3.64 -void SDL_SYS_StopTimer(void)
    3.65 -{
    3.66 -	if ( WIN_timer ) {
    3.67 -		KillTimer(NULL, WIN_timer);
    3.68 -		WIN_timer = 0;
    3.69 -	}
    3.70 -}
    3.71 -
    3.72 -#else /* !USE_SETTIMER */
    3.73 -
    3.74  /* Data to handle a single periodic alarm */
    3.75  static UINT timerID = 0;
    3.76  
    3.77 @@ -215,4 +155,3 @@
    3.78  	return;
    3.79  }
    3.80  
    3.81 -#endif /* USE_SETTIMER */
     4.1 --- a/src/timer/wince/SDL_systimer.c	Sat Mar 11 23:44:21 2006 +0000
     4.2 +++ b/src/timer/wince/SDL_systimer.c	Sat Mar 11 23:46:45 2006 +0000
     4.3 @@ -25,6 +25,7 @@
     4.4  #include <windows.h>
     4.5  #include <mmsystem.h>
     4.6  
     4.7 +#include "SDL_thread.h"
     4.8  #include "SDL_timer.h"
     4.9  #include "../SDL_timer_c.h"
    4.10  
    4.11 @@ -91,53 +92,103 @@
    4.12  
    4.13  static UINT WIN_timer;
    4.14  
    4.15 +#if ( _WIN32_WCE <= 420 )
    4.16 +
    4.17 +static HANDLE timersThread = 0;
    4.18 +static HANDLE timersQuitEvent = 0;
    4.19 +
    4.20 +DWORD TimersThreadProc(void *data)
    4.21 +{
    4.22 +	while(WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT)
    4.23 +	{
    4.24 +		SDL_ThreadedTimerCheck();
    4.25 +	}
    4.26 +	return 0;
    4.27 +}
    4.28 +
    4.29  int SDL_SYS_TimerInit(void)
    4.30  {
    4.31 -	return(0);
    4.32 +	// create a thread to process a threaded timers
    4.33 +	// SetTimer does not suit the needs because 
    4.34 +	// TimerCallbackProc will be called only when WM_TIMER occured
    4.35 +
    4.36 +	timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0);
    4.37 +	if( !timersQuitEvent )
    4.38 +	{
    4.39 +		SDL_SetError("Cannot create event for timers thread");
    4.40 +		return -1;
    4.41 +	}
    4.42 +	timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0);
    4.43 +	if( !timersThread )
    4.44 +	{
    4.45 +		SDL_SetError("Cannot create timers thread, check amount of RAM available");
    4.46 +		return -1;
    4.47 +	}
    4.48 +	SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST);
    4.49 +
    4.50 +	return(SDL_SetTimerThreaded(1));
    4.51  }
    4.52  
    4.53  void SDL_SYS_TimerQuit(void)
    4.54  {
    4.55 +	SetEvent(timersQuitEvent);
    4.56 +	if( WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT )
    4.57 +		TerminateThread(timersThread, 0);
    4.58 +	CloseHandle(timersThread);
    4.59 +	CloseHandle(timersQuitEvent);
    4.60  	return;
    4.61  }
    4.62  
    4.63 -/* Forward declaration because this is called by the timer callback */
    4.64 -int SDL_SYS_StartTimer(void);
    4.65 +#else
    4.66 +
    4.67 +#pragma comment(lib, "mmtimer.lib")
    4.68 +
    4.69 +/* Data to handle a single periodic alarm */
    4.70 +static UINT timerID = 0;
    4.71  
    4.72 -static VOID CALLBACK TimerCallbackProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
    4.73 +static void CALLBACK HandleAlarm(UINT uID,  UINT uMsg, DWORD dwUser,
    4.74 +						DWORD dw1, DWORD dw2)
    4.75  {
    4.76 -	Uint32 ms;
    4.77 +	SDL_ThreadedTimerCheck();
    4.78 +}
    4.79 +
    4.80 +
    4.81 +int SDL_SYS_TimerInit(void)
    4.82 +{
    4.83 +	MMRESULT result;
    4.84  
    4.85 -	ms = SDL_alarm_callback(SDL_alarm_interval);
    4.86 -	if ( ms != SDL_alarm_interval ) {
    4.87 -		KillTimer(NULL, idEvent);
    4.88 -		if ( ms ) {
    4.89 -			SDL_alarm_interval = ROUND_RESOLUTION(ms);
    4.90 -			SDL_SYS_StartTimer();
    4.91 -		} else {
    4.92 -			SDL_alarm_interval = 0;
    4.93 -		}
    4.94 +	/* Set timer resolution */
    4.95 +	result = timeBeginPeriod(TIMER_RESOLUTION);
    4.96 +	if ( result != TIMERR_NOERROR ) {
    4.97 +		SDL_SetError("Warning: Can't set %d ms timer resolution",
    4.98 +							TIMER_RESOLUTION);
    4.99 +	}
   4.100 +	/* Allow 10 ms of drift so we don't chew on CPU */
   4.101 +	timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC);
   4.102 +	if ( ! timerID ) {
   4.103 +		SDL_SetError("timeSetEvent() failed");
   4.104 +		return(-1);
   4.105  	}
   4.106 +	return(SDL_SetTimerThreaded(1));
   4.107  }
   4.108  
   4.109 +void SDL_SYS_TimerQuit(void)
   4.110 +{
   4.111 +	if ( timerID ) {
   4.112 +		timeKillEvent(timerID);
   4.113 +	}
   4.114 +	timeEndPeriod(TIMER_RESOLUTION);
   4.115 +}
   4.116 +
   4.117 +#endif
   4.118 +
   4.119  int SDL_SYS_StartTimer(void)
   4.120  {
   4.121 -	int retval;
   4.122 -
   4.123 -	WIN_timer = SetTimer(NULL, 0, SDL_alarm_interval, TimerCallbackProc);
   4.124 -	if ( WIN_timer ) {
   4.125 -		retval = 0;
   4.126 -	} else {
   4.127 -		retval = -1;
   4.128 -	}
   4.129 -	return retval;
   4.130 +	SDL_SetError("Internal logic error: WinCE uses threaded timer");
   4.131 +	return(-1);
   4.132  }
   4.133  
   4.134  void SDL_SYS_StopTimer(void)
   4.135  {
   4.136 -	if ( WIN_timer ) {
   4.137 -		KillTimer(NULL, WIN_timer);
   4.138 -		WIN_timer = 0;
   4.139 -	}
   4.140 +	return;
   4.141  }
   4.142 -
     5.1 --- a/src/video/gapi/SDL_gapivideo.c	Sat Mar 11 23:44:21 2006 +0000
     5.2 +++ b/src/video/gapi/SDL_gapivideo.c	Sat Mar 11 23:46:45 2006 +0000
     5.3 @@ -1088,6 +1088,9 @@
     5.4  
     5.5  static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
     5.6  {
     5.7 +	// we do not want to corrupt video memory
     5.8 +	if( gapi->suspended ) return;
     5.9 +
    5.10  	if( gapi->needUpdate )
    5.11  		gapi->videoMem = gapi->gxFunc.GXBeginDraw(); 
    5.12  
    5.13 @@ -1172,10 +1175,55 @@
    5.14  	OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
    5.15  }
    5.16  
    5.17 -/* Exported for the windows message loop only */
    5.18  static void GAPI_WinPAINT(_THIS, HDC hdc)
    5.19  {
    5.20 -	OutputDebugString(TEXT("GAPI_WinPAINT NOT IMPLEMENTED !\r\n"));
    5.21 +	// draw current offscreen buffer on hdc
    5.22 +
    5.23 +	int bpp = 16; // we always use either 8 or 16 bpp internally
    5.24 +
    5.25 +	unsigned short *bitmapData;
    5.26 +	HBITMAP hb;
    5.27 +	HDC srcDC;
    5.28 +
    5.29 +    // Create a DIB
    5.30 +    BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0};
    5.31 +    BITMAPINFO*       pBMI    = (BITMAPINFO*)buffer;
    5.32 +    BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader;
    5.33 +    DWORD*            pColors = (DWORD*)&pBMI->bmiColors;   
    5.34 +
    5.35 +	// CreateDIBSection does not support 332 pixel format on wce
    5.36 +	if( gapi->gxProperties.cBPP == 8 ) return;
    5.37 +
    5.38 +    // DIB Header
    5.39 +    pHeader->biSize            = sizeof(BITMAPINFOHEADER);
    5.40 +    pHeader->biWidth           = this->hidden->w;
    5.41 +    pHeader->biHeight          = -this->hidden->h;
    5.42 +    pHeader->biPlanes          = 1;
    5.43 +    pHeader->biBitCount        = bpp;
    5.44 +    pHeader->biCompression     = BI_RGB;
    5.45 +    pHeader->biSizeImage       = (this->hidden->w * this->hidden->h * bpp) / 8;
    5.46 +	
    5.47 +    // Color masks
    5.48 +	if( bpp == 16 )
    5.49 +	{
    5.50 +		pColors[0] = REDMASK;
    5.51 +		pColors[1] = GREENMASK;
    5.52 +		pColors[2] = BLUEMASK;
    5.53 +		pHeader->biCompression = BI_BITFIELDS;
    5.54 +	}
    5.55 +    // Create the DIB
    5.56 +    hb =  CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 );
    5.57 +
    5.58 +	// copy data
    5.59 +	// FIXME: prevent misalignment, but I've never seen non aligned width of screen
    5.60 +	memcpy(bitmapData, this->hidden->buffer, pHeader->biSizeImage);
    5.61 +	srcDC = CreateCompatibleDC(hdc);
    5.62 +	SelectObject(srcDC, hb);
    5.63 +
    5.64 +	BitBlt(hdc, 0, 0, this->hidden->w, this->hidden->h, srcDC, 0, 0, SRCCOPY);
    5.65 +
    5.66 +	DeleteObject(hb);
    5.67 +	DeleteDC(srcDC);
    5.68  }
    5.69  
    5.70  int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 
     6.1 --- a/src/video/gapi/SDL_gapivideo.h	Sat Mar 11 23:44:21 2006 +0000
     6.2 +++ b/src/video/gapi/SDL_gapivideo.h	Sat Mar 11 23:46:45 2006 +0000
     6.3 @@ -152,6 +152,7 @@
     6.4  	int dstPixelStep; // in bytes
     6.5  	int startOffset; // in bytes
     6.6  	int useVga;
     6.7 +	int suspended; // do not pu anything into video memory
     6.8  };
     6.9  
    6.10  
     7.1 --- a/src/video/wincommon/SDL_sysevents.c	Sat Mar 11 23:44:21 2006 +0000
     7.2 +++ b/src/video/wincommon/SDL_sysevents.c	Sat Mar 11 23:46:45 2006 +0000
     7.3 @@ -106,7 +106,7 @@
     7.4  {
     7.5  	if( !aygshell )
     7.6  		 aygshell = SDL_LoadObject("aygshell.dll");
     7.7 -	if( aygshell )
     7.8 +	if( (aygshell != 0) && (SHFullScreen == 0) )
     7.9  	{
    7.10  		SHFullScreen = (int (WINAPI *)(struct HWND__ *,unsigned long)) SDL_LoadFunction(aygshell, "SHFullScreen");
    7.11  	}
    7.12 @@ -171,7 +171,19 @@
    7.13  
    7.14  static void SDL_RestoreGameMode(void)
    7.15  {
    7.16 +#ifdef _WIN32_WCE
    7.17 +	SDL_VideoDevice *this = current_video;
    7.18 +	if(SDL_strcmp(this->name, "gapi") == 0)
    7.19 +	{
    7.20 +		if( this->hidden->suspended )
    7.21 +		{
    7.22 +			this->hidden->suspended = 0;
    7.23 +		}
    7.24 +	}
    7.25 +#else
    7.26  	ShowWindow(SDL_Window, SW_RESTORE);
    7.27 +#endif
    7.28 +
    7.29  #ifndef NO_CHANGEDISPLAYSETTINGS
    7.30  #ifndef _WIN32_WCE
    7.31  	ChangeDisplaySettings(&SDL_fullscreen_mode, CDS_FULLSCREEN);
    7.32 @@ -180,7 +192,21 @@
    7.33  }
    7.34  static void SDL_RestoreDesktopMode(void)
    7.35  {
    7.36 +
    7.37 +#ifdef _WIN32_WCE
    7.38 +	SDL_VideoDevice *this = current_video;
    7.39 +	if(SDL_strcmp(this->name, "gapi") == 0)
    7.40 +	{
    7.41 +		if( !this->hidden->suspended )
    7.42 +		{
    7.43 +			this->hidden->suspended = 1;
    7.44 +		}
    7.45 +	}
    7.46 +#else
    7.47 +	/* WinCE does not have a taskbar, so minimizing is not convenient */
    7.48  	ShowWindow(SDL_Window, SW_MINIMIZE);
    7.49 +#endif
    7.50 +
    7.51  #ifndef NO_CHANGEDISPLAYSETTINGS
    7.52  #ifndef _WIN32_WCE
    7.53  	ChangeDisplaySettings(NULL, 0);
    7.54 @@ -318,7 +344,7 @@
    7.55  			if ( WINDIB_FULLSCREEN() )
    7.56  			{
    7.57  						LoadAygshell();
    7.58 -						if( aygshell ) 
    7.59 +						if( SHFullScreen )
    7.60  							SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON);
    7.61  						else
    7.62  							ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE);
    7.63 @@ -345,7 +371,7 @@
    7.64  						SDL_RestoreDesktopMode();
    7.65  #if defined(_WIN32_WCE)
    7.66  						LoadAygshell();
    7.67 -						if( aygshell ) 
    7.68 +						if( SHFullScreen ) 
    7.69  							SHFullScreen(SDL_Window, SHFS_SHOWSTARTICON|SHFS_SHOWTASKBAR|SHFS_SHOWSIPBUTTON);
    7.70  						else
    7.71  							ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_SHOW);