Jump to content

  • Log In with Google      Sign In   
  • Create Account

Super Llama

Member Since 13 Dec 2007
Offline Last Active Feb 26 2014 07:59 AM

#4799909 [D3D9] Device stays lost after alt+tab

Posted by on 18 April 2011 - 08:45 AM

Hey everyone, I've been working on a game engine for quite some time now, and it's got about 4000 lines of code. I'm finally getting around to the fullscreen stuff, and I've got a very odd problem that I can't seem to find the source of, or even any hints. Basically, when I alt-tab out of the window, it sets the cooperative level to D3DERR_DEVICELOST (as expected)-- but when I go back to the window, it stays lost. Even manually resetting the device fails, because it never returns to D3DERR_DEVICENOTRESET. Am I not releasing everything properly when the device is first lost? Is there something I'm missing? I'd like to add that my device reset code works fine when I resize the program in windowed mode, and it properly resizes the backbuffer and reloads all resources-- my problem is just that once my fullscreen device is lost, I can't seem to get it back again.

EDIT: Apparently I wasn't deleting everything in time-- as soon as I set it up so it deletes the old device the instant that it first notices that it is lost, then it started working again. Now my only problem is figuring out when to reinitialize it, because it's randomly reinitializing before I even select the window again... going to have to play with WM_SETFOCUS or something, even though that requires WS_DISABLED which will stop my input from working... kind of an annoying situation, I wish there was just an IsWindowFocused function (perhaps there is?)

EDIT2: Just tried GetActiveWindow() == hwnd, and it didn't seem to work.

EDIT3: Okay so that wasn't the problem-- now when I delete the device, wait until it's active again, and reinitialize, it gives D3DERR_DEVICELOST again (still), not DEVICENOTRESET like it's supposed to be giving. I guess the previous fix was a false hope, because it's still not giving me the chance to reset.

Figured it out
Found the problem-- apparently I wasn't waiting long enough after receiving focus, and I was testing the wrong function. When I used TestCooperativeLevel to look for a DEVICENOTRESET, it didn't work. However, when I just kept calling Reset and looping again if it returned DEVICELOST, it worked perfectly. I did have to mess with WM_SETFOCUS though. Here's an overview of my solution in case you're a googler with the same problem:
1) Check the return value of Present. If it returns DEVICELOST:
2) use SetWindowLong(hwnd,GWL_STYLE,GetWindowLong(hwnd,GWL_STYLE) | WS_DISABLED); to disable input for the window. This is required (at least on windows 7) because for some reason WM_KILLFOCUS and WM_SETFOCUS don't work in fullscreen unless the window is disabled. Don't ask me why.
3) de-allocate all resources as usual.
4) wait for a WM_SETFOCUS to indicate that the window is active again.
5) when the setfocus is received, call Reset repeatedly every 50 ms or so until it returns something other than D3DERR_DEVICELOST.
6) use SetWindowLong(hwnd,GWL_STYLE,GetWindowLong(hwnd,GWL_STYLE) & !WS_DISABLED); to re-enable the window so input can be recieved again.
7) reinitialize all your resources as usual.