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
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);