Monday, February 23, 2009

Receiving/loosing the focus (WM_ACTIVATE) on Windows Mobile


When DirectX application is running in full screen (DDSCL_FULLSCREEN) it does not receive any focus changed events, namely WM_ACTIVATE message.

As stated in
http://msdn.microsoft.com/en-us/library/ms847103.aspx:
"...The exclusive (full-screen) mode prevents other applications from allocating some surface types and from drawing to the primary display. The exclusive mode also prevents other windows on the system from coming to the foreground, so DirectDraw applications must watch for system events (such as incoming phone calls) so they can relinquish control back to the system when necessary..."


The possible solution for that is discussed here
http://social.msdn.microsoft.com/Forums/en-US/vssmartdevicesnative/thread/33bfb706-fd34-4f6a-9679-c6cec4b8fda1/:
"...My solution is not to use DDSCL_FULLSCREEN cooperative level. Use DDSCL_NORMAL..."


Another related link is
http://blogs.msdn.com/windowsmobile/archive/2007/08/13/have-you-migrated-to-directdraw-yet.aspx. Sludge said here:
"...When opening a full screen application, there is no way to receive focus change events. For example on the HTC Touch, screen elements aren't drawn correctly when a phone call comes in, or the volume buttons are used..."


I
t looks that couple of people has problems with not receiving the WM_ACTIVATE message. In order to receive WM_ACTIVATE message the DirectX cooperative level has to be set to DDSCL_NORMAL, not DDSCL_FULLSCREEN.

This looks fine, but it introduces another problem as written here http://msdn.microsoft.com/en-us/library/ms893935.aspx:

"…Processes in NORMAL mode can access primary surfaces but are restricted with regard to flipping, creating complex primaries, and setting display modes…"


On older devices like HTC Wizard(Qtek 9100) where the
HW flipping is not supported it is fine but on e.g. HTC Kaiser when using the NORMAL mode, the application crashes when the primary surface is initialized with the error DDERR_NOCOOPERATIVELEVELSET. This is because the HTC Kaiser supports HW flipping, which is detected, and I try to use it, but this is unfortunately not possible in the DDSCL_NORMAL mode. So I have to choose - either try to be phone friendly and handle the WM_ACTIVATE or be game friendly and use the HW flipping…

The application can loose focus from many reasons, e.g. receiving the call, message, Bluetooth transfer, alarm event, calendar notification, going to sleep mode. Even if I receive the WM_ACTIVATE message I need to follow the complex handling:
  • I call ShowWindow() with SW_HIDE
  • The game loop is interrupted and application is chilled with the GetMessage()
  • After the situation is handled (e.g. call) and the user starts the application again, new process is created.
  • I use the FindWindow() to detect such situation and when I found existing window I set it to foreground by calling SetForegroundWindow() and I exit the new instance
Is there some easier way how to handle it? I'm really pretty new, do I something badly?

Anyway if some Win CE platform developers want to see how to handle such situations in an elegant way - check the DSA (Direct Screen Access) approach used on Symbian platform http://developer.symbian.com/main/downloads/papers/dsa/direct_screen_access.pdf


Every comment welcomed!!

Friday, February 20, 2009

Keypad messages handling on HTC

I'm facing problems with keypad handling, which I observed on HTC devices (I do not have similar problems with HP iPAQ). The result was either the significant program slow down or in the worse the FPS falls to 0 (so the scene was not updated), depending on how fast I was pressing buttons. I have found that problem happens when user presses buttons quickly in sequence. Then the message processing loop becomes too busy and is never leaved, so the screen redrawing is stopped. Below is the simplified game loop. It consists of two parts, at first messages from the queue are picked and handled and then the scene is rendered. Because the PeekMessage() while loop is too busy with key messages handling, it is not leaved and consequently the Update() function is never called.

while ( isRunning )
{
...
// 1a. Pick up message
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
//1b. Handle message
}

// 2. Renders scene
Update();
...
}

I do not understand, what is wrong with HTC devices, that they handle key press related message so slowly, that it blocks the game loop. I thought this is a common issue, so I tried to search Internet, but the only reference I found was there http://blogs.msdn.com/windowsmobile/archive/2007/08/13/have-you-migrated-to-directdraw-yet.aspx. Guy named Fred Di Sano wrote:

"…Getting input via the message pump is kind of clunky and in some cases (like on various HTC devices) it slows down the app!", but I do not find any other reference..."

I did not found any solution except defining the maximal number of messages that can be processed in the loop iteration:


// Max. messages that are processed in one step
const int KMaxMessagesProcessedInOneStep = 3;

while ( isRunning )
{
...
// Messages processed
int messagesProcessed = 0;
// 1a. Pick up message
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
//1b. Handle message

// Check how many messages were processed
messagesProcessed++;
if ( messagesProcessed > KMaxMessagesProcessedInOneStep )
break;
}

// 2. Renders scene
Update();
...
}


I believe this is not the best solution, so if anyone can suggest something better I will appreciate it.

Thursday, February 19, 2009

Some comments about DirectX on Windows Mobile

Some comments about DirectX on Windows Mobile

I'm a Symbian developer, who is currently porting a game to Windows Mobile 5.0. I’m trying to use the DirectX and I naively thought it will be easy, but soon I found it is quite fuzzy and tricky. This forced me to make up this blog to share what I have found and get some comments and tips from experienced developers.


1. Hardware flipping support


First surprise was for me that how many devices do not support the surface hardware flipping. This results in fact that I was forced to blit the content of the back buffer instead of just flipping it. I do not know why I expect the hardware support here – probably because I always connected the DirectX with desktop PCs…


I found here
http://msdn.microsoft.com/en-us/library/aa454897.aspx:
"…From the above code example, note the check for whether the device is capable of "Flipping" surfaces rather than BLT'ing them to display memory. For the vast majority of emerging Windows Mobile platforms, hardware flipping is not available…"


There is nothing to do with this, just accept it...


2. VRAM


Secondly I thought that the back buffer could be created in the VRAM, but the API call always fails when specifying the DDSCAPS_VIDEOMEMORY flag. When I checked the video memory size it returns me some small values (HTC Wizard 200 (Qtek 9100) – 0 bytes, HTC Kaiser 120 (MDA Vario-III) – 153600 bytes, hp iPAQ hw6915 – 28800 bytes). I was not able to create back buffer in VRAM, so I created it in the system memory, which slows the blitting operation again. I do not have any idea what the VRAM is supposed to be used for or how to use it…


I found here http://www.pocketmatrix.com/forums/viewtopic.php?t=28664:

“…1) From what I've come to understand is that most devices have JUST enough video memory to house the primary surface. Sometimes the device has a bit of extra video ram left which is why the free video memory amount is so small.

2) Creating surfaces in video memory generally doesn't seem to work as there isn't ever enough room there to create a big surface. Maybe small ones that are <= to the free video memory size…”

Any ideas how (if) it can be used?

3. Transparency


I have, without any optimization about 25-30 FPS when the whole scene was rendered (no user interaction). When rendering just one bitmap (size 240x180px) the FPS was about 100. Unfortunately when I started to use the color key to specify the transparent parts of bitmaps the FPS falls to 5.


As written in the discussion here

http://www.codeproject.com/KB/mobile/Caleidoscope.aspx?display=PrintAll&fid=348045&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=51:
“…I'm doing some blitting with alpha-test (I need to draw some sprites) but when I use the normal blitting with the DDBLT_KEYSRC flag, I lose much in performance (e.g. when I blit a 240X320 bitmap I have 220 fps but when I blit it with DDBLT_KEYSRC flag to lose the background, I get a fps of about 17 ?!)... for the moment, I’m doing the alpha-test myself by locking the surface and checking each pixel, which brings me a fps of about 25 for the same case... I've also tried doing it using GAPI, but I couldn't get a fps higher than 20…”


The only possible solution I can see there is to try to decrease the number of rendered sprites and simplify the way they are displayed plus I could possibly try to make my own routine for transparency handling, but I do not believe this will give me some more FPS. I welcome any hints on that…