Fixes from Dmitry Yakimov:
authorSam Lantinga <slouken@libsdl.org>
Sat, 11 Mar 2006 23:46:45 +0000
changeset 1497 420b3f47806d
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
Binary file VisualCE.zip has changed
--- a/include/SDL_config_win32.h	Sat Mar 11 23:44:21 2006 +0000
+++ b/include/SDL_config_win32.h	Sat Mar 11 23:46:45 2006 +0000
@@ -117,10 +117,18 @@
 #define SDL_AUDIO_DRIVER_WAVEOUT	1
 
 /* Enable various cdrom drivers */
-#define SDL_CDROM_WIN32	1
+#ifdef _WIN32_WCE
+#define SDL_CDROM_DISABLED      1
+#else
+#define SDL_CDROM_WIN32		1
+#endif
 
 /* Enable various input drivers */
+#ifdef _WIN32_WCE
+#define SDL_JOYSTICK_DISABLED   1
+#else
 #define SDL_JOYSTICK_WINMM	1
+#endif
 
 /* Enable various shared object loading systems */
 #define SDL_LOADSO_WIN32	1
@@ -136,12 +144,12 @@
 #endif
 
 /* Enable various video drivers */
+#ifdef _WIN32_WCE
+#define SDL_VIDEO_DRIVER_GAPI	1
+#endif
 #ifndef _WIN32_WCE
 #define SDL_VIDEO_DRIVER_DDRAW	1
 #endif
-#ifdef _WIN32_WCE
-#define SDL_VIDEO_DRIVER_GAPI	1
-#endif
 #define SDL_VIDEO_DRIVER_WINDIB	1
 
 /* Enable OpenGL support */
--- a/src/timer/win32/SDL_systimer.c	Sat Mar 11 23:44:21 2006 +0000
+++ b/src/timer/win32/SDL_systimer.c	Sat Mar 11 23:46:45 2006 +0000
@@ -30,10 +30,6 @@
 
 #ifdef _WIN32_WCE
   #error This is WinCE. Please use src/timer/wince/SDL_systimer.c instead.
-
-  /* but if you really want to use this file, use these #defines... */
-  #define USE_GETTICKCOUNT
-  #define USE_SETTIMER
 #endif
 
 #define TIME_WRAP_VALUE	(~(DWORD)0)
@@ -111,62 +107,6 @@
 	Sleep(ms);
 }
 
-#ifdef USE_SETTIMER
-
-static UINT WIN_timer;
-
-int SDL_SYS_TimerInit(void)
-{
-	return(0);
-}
-
-void SDL_SYS_TimerQuit(void)
-{
-	return;
-}
-
-/* Forward declaration because this is called by the timer callback */
-int SDL_SYS_StartTimer(void);
-
-static VOID CALLBACK TimerCallbackProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
-{
-	Uint32 ms;
-
-	ms = SDL_alarm_callback(SDL_alarm_interval);
-	if ( ms != SDL_alarm_interval ) {
-		KillTimer(NULL, idEvent);
-		if ( ms ) {
-			SDL_alarm_interval = ROUND_RESOLUTION(ms);
-			SDL_SYS_StartTimer();
-		} else {
-			SDL_alarm_interval = 0;
-		}
-	}
-}
-
-int SDL_SYS_StartTimer(void)
-{
-	int retval;
-
-	WIN_timer = SetTimer(NULL, 0, SDL_alarm_interval, TimerCallbackProc);
-	if ( WIN_timer ) {
-		retval = 0;
-	} else {
-		retval = -1;
-	}
-	return retval;
-}
-
-void SDL_SYS_StopTimer(void)
-{
-	if ( WIN_timer ) {
-		KillTimer(NULL, WIN_timer);
-		WIN_timer = 0;
-	}
-}
-
-#else /* !USE_SETTIMER */
-
 /* Data to handle a single periodic alarm */
 static UINT timerID = 0;
 
@@ -215,4 +155,3 @@
 	return;
 }
 
-#endif /* USE_SETTIMER */
--- a/src/timer/wince/SDL_systimer.c	Sat Mar 11 23:44:21 2006 +0000
+++ b/src/timer/wince/SDL_systimer.c	Sat Mar 11 23:46:45 2006 +0000
@@ -25,6 +25,7 @@
 #include <windows.h>
 #include <mmsystem.h>
 
+#include "SDL_thread.h"
 #include "SDL_timer.h"
 #include "../SDL_timer_c.h"
 
@@ -91,53 +92,103 @@
 
 static UINT WIN_timer;
 
+#if ( _WIN32_WCE <= 420 )
+
+static HANDLE timersThread = 0;
+static HANDLE timersQuitEvent = 0;
+
+DWORD TimersThreadProc(void *data)
+{
+	while(WaitForSingleObject(timersQuitEvent, 10) == WAIT_TIMEOUT)
+	{
+		SDL_ThreadedTimerCheck();
+	}
+	return 0;
+}
+
 int SDL_SYS_TimerInit(void)
 {
-	return(0);
+	// create a thread to process a threaded timers
+	// SetTimer does not suit the needs because 
+	// TimerCallbackProc will be called only when WM_TIMER occured
+
+	timersQuitEvent = CreateEvent(0, TRUE, FALSE, 0);
+	if( !timersQuitEvent )
+	{
+		SDL_SetError("Cannot create event for timers thread");
+		return -1;
+	}
+	timersThread = CreateThread(NULL, 0, TimersThreadProc, 0, 0, 0);
+	if( !timersThread )
+	{
+		SDL_SetError("Cannot create timers thread, check amount of RAM available");
+		return -1;
+	}
+	SetThreadPriority(timersThread, THREAD_PRIORITY_HIGHEST);
+
+	return(SDL_SetTimerThreaded(1));
 }
 
 void SDL_SYS_TimerQuit(void)
 {
+	SetEvent(timersQuitEvent);
+	if( WaitForSingleObject(timersThread, 2000) == WAIT_TIMEOUT )
+		TerminateThread(timersThread, 0);
+	CloseHandle(timersThread);
+	CloseHandle(timersQuitEvent);
 	return;
 }
 
-/* Forward declaration because this is called by the timer callback */
-int SDL_SYS_StartTimer(void);
+#else
+
+#pragma comment(lib, "mmtimer.lib")
+
+/* Data to handle a single periodic alarm */
+static UINT timerID = 0;
 
-static VOID CALLBACK TimerCallbackProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
+static void CALLBACK HandleAlarm(UINT uID,  UINT uMsg, DWORD dwUser,
+						DWORD dw1, DWORD dw2)
 {
-	Uint32 ms;
+	SDL_ThreadedTimerCheck();
+}
+
+
+int SDL_SYS_TimerInit(void)
+{
+	MMRESULT result;
 
-	ms = SDL_alarm_callback(SDL_alarm_interval);
-	if ( ms != SDL_alarm_interval ) {
-		KillTimer(NULL, idEvent);
-		if ( ms ) {
-			SDL_alarm_interval = ROUND_RESOLUTION(ms);
-			SDL_SYS_StartTimer();
-		} else {
-			SDL_alarm_interval = 0;
-		}
+	/* Set timer resolution */
+	result = timeBeginPeriod(TIMER_RESOLUTION);
+	if ( result != TIMERR_NOERROR ) {
+		SDL_SetError("Warning: Can't set %d ms timer resolution",
+							TIMER_RESOLUTION);
+	}
+	/* Allow 10 ms of drift so we don't chew on CPU */
+	timerID = timeSetEvent(TIMER_RESOLUTION,1,HandleAlarm,0,TIME_PERIODIC);
+	if ( ! timerID ) {
+		SDL_SetError("timeSetEvent() failed");
+		return(-1);
 	}
+	return(SDL_SetTimerThreaded(1));
 }
 
+void SDL_SYS_TimerQuit(void)
+{
+	if ( timerID ) {
+		timeKillEvent(timerID);
+	}
+	timeEndPeriod(TIMER_RESOLUTION);
+}
+
+#endif
+
 int SDL_SYS_StartTimer(void)
 {
-	int retval;
-
-	WIN_timer = SetTimer(NULL, 0, SDL_alarm_interval, TimerCallbackProc);
-	if ( WIN_timer ) {
-		retval = 0;
-	} else {
-		retval = -1;
-	}
-	return retval;
+	SDL_SetError("Internal logic error: WinCE uses threaded timer");
+	return(-1);
 }
 
 void SDL_SYS_StopTimer(void)
 {
-	if ( WIN_timer ) {
-		KillTimer(NULL, WIN_timer);
-		WIN_timer = 0;
-	}
+	return;
 }
-
--- a/src/video/gapi/SDL_gapivideo.c	Sat Mar 11 23:44:21 2006 +0000
+++ b/src/video/gapi/SDL_gapivideo.c	Sat Mar 11 23:46:45 2006 +0000
@@ -1088,6 +1088,9 @@
 
 static void GAPI_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
 {
+	// we do not want to corrupt video memory
+	if( gapi->suspended ) return;
+
 	if( gapi->needUpdate )
 		gapi->videoMem = gapi->gxFunc.GXBeginDraw(); 
 
@@ -1172,10 +1175,55 @@
 	OutputDebugString(TEXT("GAPI_PaletteChanged NOT IMPLEMENTED !\r\n"));
 }
 
-/* Exported for the windows message loop only */
 static void GAPI_WinPAINT(_THIS, HDC hdc)
 {
-	OutputDebugString(TEXT("GAPI_WinPAINT NOT IMPLEMENTED !\r\n"));
+	// draw current offscreen buffer on hdc
+
+	int bpp = 16; // we always use either 8 or 16 bpp internally
+
+	unsigned short *bitmapData;
+	HBITMAP hb;
+	HDC srcDC;
+
+    // Create a DIB
+    BYTE buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD)] = {0};
+    BITMAPINFO*       pBMI    = (BITMAPINFO*)buffer;
+    BITMAPINFOHEADER* pHeader = &pBMI->bmiHeader;
+    DWORD*            pColors = (DWORD*)&pBMI->bmiColors;   
+
+	// CreateDIBSection does not support 332 pixel format on wce
+	if( gapi->gxProperties.cBPP == 8 ) return;
+
+    // DIB Header
+    pHeader->biSize            = sizeof(BITMAPINFOHEADER);
+    pHeader->biWidth           = this->hidden->w;
+    pHeader->biHeight          = -this->hidden->h;
+    pHeader->biPlanes          = 1;
+    pHeader->biBitCount        = bpp;
+    pHeader->biCompression     = BI_RGB;
+    pHeader->biSizeImage       = (this->hidden->w * this->hidden->h * bpp) / 8;
+	
+    // Color masks
+	if( bpp == 16 )
+	{
+		pColors[0] = REDMASK;
+		pColors[1] = GREENMASK;
+		pColors[2] = BLUEMASK;
+		pHeader->biCompression = BI_BITFIELDS;
+	}
+    // Create the DIB
+    hb =  CreateDIBSection( 0, pBMI, DIB_RGB_COLORS, (void**)&bitmapData, 0, 0 );
+
+	// copy data
+	// FIXME: prevent misalignment, but I've never seen non aligned width of screen
+	memcpy(bitmapData, this->hidden->buffer, pHeader->biSizeImage);
+	srcDC = CreateCompatibleDC(hdc);
+	SelectObject(srcDC, hb);
+
+	BitBlt(hdc, 0, 0, this->hidden->w, this->hidden->h, srcDC, 0, 0, SRCCOPY);
+
+	DeleteObject(hb);
+	DeleteDC(srcDC);
 }
 
 int GAPI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 
--- a/src/video/gapi/SDL_gapivideo.h	Sat Mar 11 23:44:21 2006 +0000
+++ b/src/video/gapi/SDL_gapivideo.h	Sat Mar 11 23:46:45 2006 +0000
@@ -152,6 +152,7 @@
 	int dstPixelStep; // in bytes
 	int startOffset; // in bytes
 	int useVga;
+	int suspended; // do not pu anything into video memory
 };
 
 
--- a/src/video/wincommon/SDL_sysevents.c	Sat Mar 11 23:44:21 2006 +0000
+++ b/src/video/wincommon/SDL_sysevents.c	Sat Mar 11 23:46:45 2006 +0000
@@ -106,7 +106,7 @@
 {
 	if( !aygshell )
 		 aygshell = SDL_LoadObject("aygshell.dll");
-	if( aygshell )
+	if( (aygshell != 0) && (SHFullScreen == 0) )
 	{
 		SHFullScreen = (int (WINAPI *)(struct HWND__ *,unsigned long)) SDL_LoadFunction(aygshell, "SHFullScreen");
 	}
@@ -171,7 +171,19 @@
 
 static void SDL_RestoreGameMode(void)
 {
+#ifdef _WIN32_WCE
+	SDL_VideoDevice *this = current_video;
+	if(SDL_strcmp(this->name, "gapi") == 0)
+	{
+		if( this->hidden->suspended )
+		{
+			this->hidden->suspended = 0;
+		}
+	}
+#else
 	ShowWindow(SDL_Window, SW_RESTORE);
+#endif
+
 #ifndef NO_CHANGEDISPLAYSETTINGS
 #ifndef _WIN32_WCE
 	ChangeDisplaySettings(&SDL_fullscreen_mode, CDS_FULLSCREEN);
@@ -180,7 +192,21 @@
 }
 static void SDL_RestoreDesktopMode(void)
 {
+
+#ifdef _WIN32_WCE
+	SDL_VideoDevice *this = current_video;
+	if(SDL_strcmp(this->name, "gapi") == 0)
+	{
+		if( !this->hidden->suspended )
+		{
+			this->hidden->suspended = 1;
+		}
+	}
+#else
+	/* WinCE does not have a taskbar, so minimizing is not convenient */
 	ShowWindow(SDL_Window, SW_MINIMIZE);
+#endif
+
 #ifndef NO_CHANGEDISPLAYSETTINGS
 #ifndef _WIN32_WCE
 	ChangeDisplaySettings(NULL, 0);
@@ -318,7 +344,7 @@
 			if ( WINDIB_FULLSCREEN() )
 			{
 						LoadAygshell();
-						if( aygshell ) 
+						if( SHFullScreen )
 							SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON);
 						else
 							ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE);
@@ -345,7 +371,7 @@
 						SDL_RestoreDesktopMode();
 #if defined(_WIN32_WCE)
 						LoadAygshell();
-						if( aygshell ) 
+						if( SHFullScreen ) 
 							SHFullScreen(SDL_Window, SHFS_SHOWSTARTICON|SHFS_SHOWTASKBAR|SHFS_SHOWSIPBUTTON);
 						else
 							ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_SHOW);