# HG changeset patch # User Sam Lantinga # Date 1142120805 0 # Node ID 420b3f47806de71a9d195e8bf811475b8a1bb1b9 # Parent 405e20dc004ce4799ad10144bf5d9dfd139f33ba 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 diff -r 405e20dc004c -r 420b3f47806d VisualCE.zip Binary file VisualCE.zip has changed diff -r 405e20dc004c -r 420b3f47806d include/SDL_config_win32.h --- 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 */ diff -r 405e20dc004c -r 420b3f47806d src/timer/win32/SDL_systimer.c --- 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 */ diff -r 405e20dc004c -r 420b3f47806d src/timer/wince/SDL_systimer.c --- 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 #include +#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; } - diff -r 405e20dc004c -r 420b3f47806d src/video/gapi/SDL_gapivideo.c --- 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) diff -r 405e20dc004c -r 420b3f47806d src/video/gapi/SDL_gapivideo.h --- 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 }; diff -r 405e20dc004c -r 420b3f47806d src/video/wincommon/SDL_sysevents.c --- 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);