Switch swapchain to windowed mode - directx-11

I need to release the swapchain but looks like it needs to be put it back in windowed mode.
DXGI ERROR: IDXGISwapChain::Release: Swapchain Released while fullscreen. Switch it to the windowed state first. [ MISCELLANEOUS ERROR #66: ]
Anyone knows the simplest way to accomplish this?

To release a swap chain, you should do two things. First, release the render target view and depth/stencil view (if there is one) which are attached to the swap chain. Second put the swap chain in windowed mode:
// Releases the swap chain and all resources that are attached to it.
void ReleaseSwapChain()
{
ReleaseDefaultRTVAndDSV();
if ( pSwapChain )
{
pSwapChain->SetFullscreenState( false, nullptr );
pSwapChain->Release();
pSwapChain = nullptr;
}
}

Related

Input.Touch not working on OSX

I'm a total beginner in Unity and created a function that simply sets the text of a text element when a touch is detected like this:
// Update is called once per frame
void Update () {
if (didTap ()) {
print ("did tap!");
tapText.text = "TAP!";
}
}
private bool didTap() {
print ("checking didtap");
if (Input.touchCount > 0) {
Touch initialTouch = Input.GetTouch (0);
return initialTouch.phase == TouchPhase.Began;
}
return false;
}
When I run this on an actual device (Android phone) it works perfectly, but when I 'click' in the unity editor when running the game nothing happens. I'm running OSX 10.12.2. Anything I need to configure to have the mouse mimic touch events?
You can duplicate Unity's play mode window onto your mobile device by using the UnityRemote app. This will allow you to interact with your phone's features, while still running Unity on your computer.
UnityRemote requires some setup in Unity along with downloading the app. Consider watching this video: Unity Remote Setup Tutorial
Alternatively, see the answer from Hellium in this question, in conjunction with getting the mouse clicks, to only compile code based on the device used.
There's an odd difference between "touch" input and "mouse" input in Unity. Input.touchCount will always return 0 while you're running in the Editor but Input.GetMouseButtonDown(0) works for both the Editor and the first touch of one or more touches while on a mobile build.
You have two options to solve this issue via code (your other option is the remote ryemoss mentioned):
If you're only ever using one touch, use Input.GetMouseButtonDown(0) and Input.GetMouseButtonUp(0).
Use #if UNITY_IOS, #if UNITY_ANDROID and #if UNITY_EDITOR tags to write separate input readers for your platforms and then have them all call into the same functionality.

DirectX11 Swapchain and window losing fullscreen status

I just stumbled on this little annoying behavior, while adding full screen support on a sample program.
Creating a full screen window works, but as soon as I move any window (from another application) on the output that contains my fullscreen window, it automatically switches back to windowed.
Is there any way to prevent this behavior (so full screen window do not go back to windowed)?
As a reference, this is a small standalone example (so problem can be replicated easily).
Also if that is useful, I'm running on Windows 8.1.
I already tried to change WindowAssociationFlags and SwapChainFlags, both with no success, same as using FlipSequential instead of Discard
SharpDX.DXGI.Factory2 factory = new SharpDX.DXGI.Factory2();
SharpDX.DXGI.Adapter adapter = factory.GetAdapter(0);
var renderForm1 = new RenderForm("Form 1");
factory.MakeWindowAssociation(renderForm1.Handle, SharpDX.DXGI.WindowAssociationFlags.IgnoreAll);
Device device = new Device(adapter, DeviceCreationFlags.BgraSupport);
SharpDX.DXGI.SwapChainDescription sd = new SharpDX.DXGI.SwapChainDescription()
{
BufferCount = 2,
ModeDescription = new SharpDX.DXGI.ModeDescription(0, 0, new SharpDX.DXGI.Rational(50, 1), SharpDX.DXGI.Format.R8G8B8A8_UNorm),
IsWindowed = true,
OutputHandle = renderForm1.Handle,
SampleDescription = new SharpDX.DXGI.SampleDescription(1,0),
SwapEffect = SharpDX.DXGI.SwapEffect.Discard,
Usage = SharpDX.DXGI.Usage.RenderTargetOutput,
Flags = SharpDX.DXGI.SwapChainFlags.None
};
var swapChain1 = new SharpDX.DXGI.SwapChain(factory, device, sd);
renderForm1.Left = 1922; //Just hardcoded here to move window to second screen
renderForm1.Width = 1920;
renderForm1.Height = 1080;
renderForm1.FormBorderStyle = FormBorderStyle.None;
swapChain1.SetFullscreenState(true, null);
swapChain1.ResizeBuffers(2, 1920, 1080, SharpDX.DXGI.Format.R8G8B8A8_UNorm, SharpDX.DXGI.SwapChainFlags.AllowModeSwitch);
var resource = Texture2D.FromSwapChain<Texture2D>(swapChain1, 0);
var renderView = new RenderTargetView(device, resource);
RenderLoop.Run(renderForm1, () =>
{
device.ImmediateContext.ClearRenderTargetView(renderView, new SharpDX.Color4(1, 0, 0, 1));
swapChain1.Present(1, SharpDX.DXGI.PresentFlags.None);
});
Edit:
I also tried a c++ sample (just taken DirectX11 basic tutorial from Microsoft and added full screen switch), this leads to the same behavior, so this is not a SharpDX specific issue.
I looked at the message loop, and once this occurs, first fullscreen mode is changed back to windowed, and I receive a WM_DISPLAYCHANGE message).
This sounds like expected behavior. If you have a full screen 'exclusive' mode swapchain and the associated window loses focus, the system automatically switches the application out of full screen mode back to windowed mode by design.
With a single monitor, it mostly works as long as you have your applications' window sized to fill the display. Users can't use the mouse to change focus of your window, and it requires something like ALT+TAB to switch focus.
With multiple monitors, it's a real problem. If you click on another window on another display, your app loses focus and the full screen mode is again switched out. There are also limitations that prevent you from setting full screen 'exclusive' mode on more than one monitor.
Furthermore, on Windows Vista or later the notion of 'exclusive' mode is an illusion: the GPU is always shared anyhow. The 'focus' application gets priority whether it is a full screen or a windowed swap chain.
For a Windows desktop apps you have three choices for a full screen style experience:
Use the traditional full screen 'exclusive' mode with a window sized to fill the display, along with setting the display mode which may not be what the user has set for Windows generally. Here you have IsWindowed = false.
You set the window size to fill the full display (i.e. maximized). You can use windows styles to ensure that the window has no frame which results in a full screen style experience (WS_POPUP). Here you have IsWindowed = true, and you should be sure to set DXGI_MWA_NO_ALT_ENTER to avoid allowing DXGI to try to take you to use the 1 case.
You can do the same as 2 with IsWindowed = true and the borderless window sized to match the screen, but you change the display mode to something other than the system default. This is commonly referred to as 'fake full screen'. The display mode gets changed back whenever you exit the application.
1 has all has all the problems with multi-tasking and focus we just described. 2 and 3 allow system notifications and other pop-ups to show up over the game and not force a mode switch. 2 and 3 also work a lot better in multi-monitor setups where you can play your game on one display and use other apps on another display. For multi-tasking most people to prefer a classic window style with a frame border.
Windows Store UWP notions of full screen mode is basically like 2 above. You can't change the display mode with a UWP.
Debugging a full-screen setup is quite challenging. With multiple monitors, 2 and 3 can work with your debugger on the other screen. For true full-screen exclusive mode, really the only option is to use remote debugging from another PC.
Another issue with 1 and 3 is that you can set the display mode to something that won't sync with the display leaving the user with a system with no UI and no way to exit. Ideally with the right driver setup, the DXGI enumeration list does not contain unsupported modes, but it is something to be aware of. For this reason, your UI for selecting a display mode should have a timeout and you should make sure there's a reasonable way to abort the application with the keyboard if the display mode fails to sync at some point in the future. Using the existing display mode as we do in 2 above is always the safest option.
The main reason to use full screen exclusive mode (1) above is to try to get 'flip' rather than 'blit' of the backbuffer/frontbuffer. For most modern systems, this is a negligible performance difference. The other reason to go through the pain of using it is for SLI/Crossfire multi-GPU rendering going to a single display. There are a number of other optimizations required to really make that scenario work, and it's pretty niche. You should seek out the vendor optimization guides for the details.
Most modern games default to using fake full screen rather than full screen 'exclusive' mode. They offer the ability to use a true windowed mode as many users want to be able to multi-task while playing (like looking up hints online, use IM or external voice chat, etc.). AAA Windows desktop games that want to support tuned high-performance gaming for SLI/Crossfire will offer a full screen 'exclusive' mode, but this requires some work to get working fully and entails more work than just some DXGI code.
See DXGI Overview and DirectX Graphics Infrastructure (DXGI): Best Practices
After several attempts and trials, here are the different workarounds I used, none are ideal but all are somehow better than getting a mode change.
1/Force cursor in the middle of the full screen window, with a keyboard shortcut to get control again.
This is not ideal since we can't really do anything while our part is running, but at least prevents accidental "disaster click". It does not prevent keyboard interaction either.
2/Use a DX9 renderer with a shared texture.
DX9 Swapchain can have it's parent window set to desktop, so it does not lose focus when moving to something else.
Having a focused window on top show little borders visible while moving it, but that is a bit more acceptable than losing everything.
Not future proof but guess will stay actual for a while.
3/Stay on Windows 7 and Disable DWM Service:
Doesn't work in Windows 8 anymore, but in my use case since most media companies I work for are still on Windows 7, it stays a valid solution for at least 5 to 10 years.
4/Force the DX11 Window on foreground
Basically continuously call SetForegroundWindow to avoid another window to take focus.
5/Prevent mode switch at presentation level.
Since on my application I got access to when presentation occurs, I use the following routine (before to call Present)
-Get Foreground window handle (using GetForegroundWindow), If Foreground handle is our fullscreen window, just call Present as usual.
If Foreground handle is not our fullscreen window, perform the following. Please note that visibility check is not needed, since even an invisible overlapping window will also cause a full screen loss! (seriously, this is just so bad...)
-Verify if our foreground window overlaps with the monitor:
Call GetWindowRect to get the bounds, and perform intersection with the monitor location.
Alternatively, call Present on the swapchain with the DXGI_PRESENT_TEST flag. If a window is overlapping, the Present call will return DXGI_STATUS_OCCLUDED
If a window overlaps, either Hide it or move it in another monitor (anywhere so it does not overlap):
ShowWindow and SetWindowPos are aperfect fit for this task.
Repeat that Test present call in a loop until it doesn't return the occluded status (this is important, since windows might not have processed the messages immediately); Once occluded flag is gone, call Present as usual.
There is a way to prevent DXGI from automatically leaving fullscreen mode when your process loses focus, though I must warn, it is a bit hackish.
Basically DXGI calls GetForegroundWindow() and checks if the returned window is yours.
If not, it switches off the fullscreen mode.
So if you hook/redirect this function to your own replacement, that always returns your window (regardless of whether it has the focus or not) - that will get the job done.
Here is a simple code that does that. It is for 64-bit mode and assumes that you NEVER need to call the real function, so it simply overwrites its start with a jump instruction to your replacement:
HWND WINAPI get_our_window()
{
return our_window;
}
void disable_automatic_leaving_fullscreen_on_lost_focus()
{
// get the address of GetForegroundWindow
char *p = (char *)GetProcAddress(GetModuleHandleA("user32.dll"), "GetForegroundWindow");
// make the function code writable
DWORD old;
VirtualProtect(p, 12, PAGE_EXECUTE_WRITECOPY, &old);
// overwrite the function start:
// mov rax, <address_of_GetOurWindow>
p[0] = 0x48, p[1] = 0xB8, *(void **)(p + 2) = (void *)get_our_window;
// jmp rax
p[10] = 0xFF, p[11] = 0xE0;
}
This code is only for demonstration.
If you need to retain the ability to call the true function, then you have to hook it in a different, more complicated way, but this is a separate subject

Win32 prevent window "snap"

How can I disable the snap feature of Windows 7 for my application (progmatically)? Or is there any way to detect if the application has been snapped, and specifically call an API function to unsnap it?
Calling SetWindowPos() or ShowWindow() does not unsnap it correctly *(SW_MAXIMIZE does). Calling SetWindowPos() actually causes strange behavior in future calls to SetWindowPos() and MoveWindow(). The same inconsistencies do not apply to a window that is maximized.
I figured out a way to unsnap, by calling ShowWindow() with SW_MAXIMIZE. This is odd since no other values unsnap with this call, even though the window can be moved away, it is still anchored to the side of the screen. Maximizing it fixes the problem, whereafter I can move the window where it needs to be.
#define WM_RESTOREORIGINALSTYLE WM_USER+... /* your first free USER message */
case WM_SYSCOMMAND:
{
if(wParam==(SC_MOVE|2)) wParam=SC_SIZE|9;
if((wParam&0xFFE0)==SC_SIZE && (wParam&0x000F)) // handles MOVE and SIZE in one "if"
{
long int oldStyle=GetWindowLongW(hwnd,GWL_STYLE);
PostMessageW(hwnd,WM_RESTOREORIGINALSTYLE,GWL_STYLE,oldStyle);
SetWindowLongW(hwnd,GWL_STYLE,oldStyle &0xFEFEFFFF); // disable WS_MAXIMIZE and WS_MAXIMIZEBOX
DefWindowProcW(hwnd,WM_SYSCOMMAND,wParam,lParam);
return 0;
}
return DefWindowProcW(hwnd,WM_SYSCOMMAND,wParam,lParam);
}
case WM_RESTOREORIGINALSTYLE:
{
if((long int)wParam==GWL_STYLE)
SetWindowLongW(hwnd,GWL_STYLE,lParam);
return 0;
}
The PostMessage will be processed in subsequent message loop - it means ASAP after entering into move-size loop.
If you use own drawing method of frame, please do not forget to redraw your frame correctly on WM_STYLECHANGED message, internally store oldStyle in your class.
Why it works? Windows check snap condition at start of move/size action. If WS_MAXIMIZE and WS_MAXIMIZEBOX are disabled at start, the snap behaviour is disabled.
The SC_SIZE|9 is equivalent of SC_MOVE|2 without blocking redrawing for half a second.
If you don't want to enable dragging maximized windows if they are fully maximized, check state of SC_MOVE item in system menu and if it is enabled, directly return 0 in WM_SYSCOMMAND.
Verified on Windows 8.1.

ClipCursor is not working

I am working on a DX11 game, and I want to clip the cursor during fullscreen mode to the fullscreen window. I use this method
void MyClass::_SetupCursor( BOOL bFullscreen ) {
// Clip cursor if requested
if( bFullscreen ) {
if(m_bShowCursorWhenFullscreen) {
ShowCursor(m_bShowCursorWhenFullscreen);
}
if(m_bClipCursorWhenFullscreen) {
// Confine cursor to full screen window
RECT windowRect;
GetWindowRect( m_hWnd, &windowRect );
ClipCursor( &windowRect );
}
}
else {
ShowCursor( TRUE );
ClipCursor( NULL );
}
}
However, when I am in fullscreen mode with 2 monitors, I can still move the mouse over to the other monitor. With resolution set to 2048x1152 in fullscreen mode, I get the window rectangle as 1360x768, and that is what it gets clipped to. I confirm that it is clipped using GetClippedRect.
So I have two questions:
1) Why isn't the mouse getting clipped to the monitor my window is in?
2) Why is the window rectangle measured as 1360x768 when I know for a fact the monitor is 2048x1152, and I have the resolution set to 2048x1152?
It turns out that for ClipCursor to work, you must have all your DX11 buffers and your window size correct. I found this out by running my application in fullscreen first, without toggling into it, and ClipCursor worked just fine, even with multiple monitors. For more information on when ClipCursor will fail, check out my other question on stackoverflow: Why is D3D10SDKLayers.dll loaded during my DX11 game? .
ClipCursor will fail ever time the situations i describe in that question arise. Also, in response to my 2nd question, the window size is incorrect because of the situation I describe in the linked question.
Unfortunately according to a comment on the documentation (by a user) it appears that this does not work for multimonitor setups. You may want to develop a method that will reposition the mouse when it goes off screen, turns off the rendring for it, then turn it back on when you move the cursor back to the window (to detect if the mouse moves off the window or not, there is windows messages for that).

Minimize/restore windows programmatically skipping the animation effect

I need to perform several operations on a list of windows (minimize some of them, restore others) in order to switch between two or more set of windows at once.
The problem with this are those animations you can see when minimizing and restoring a window. The whole process look terrible with all those animations going in and out, up and down.
I cannot, however, disable those animations because this is for other computers and i dont want to change other people's settings, plus those animations are actually useful when you minimize/restore one window only (i.e. when YOU do it manually) because you can see what is happening, but for doing it programmatically on several windows at a time, it's not nice.
I'm currenlty using the SendMessage function to send the WM_SYSCOMMAND message with params SC_MINIMIZE/SC_RESTORE. I dont know whether there is another way.
So, the question:
How can I minimize/restore a window programatically without the animation effect??
PS: The programming language is not important. I can use any language that's nessesary for accomplishing this.
SetWindowPlacement with SW_SHOWMINIMIZED or SW_RESTORE as appropriate for showCmd in WINDOWPLACEMENT seems to bypass window animation. I'd keep an eye on the functionality for future versions of the OS though since documentation does not mention anything about animation.
How about Hide > Minimize > Show ?
You could temporarily disable the animations and then restore the user's original setting.
class WindowsAnimationSuppressor {
public:
WindowsAnimationSuppressor() : m_suppressed(false) {
m_original_settings.cbSize = sizeof(m_original_settings);
if (::SystemParametersInfo(SPI_GETANIMATION,
sizeof(m_original_settings),
&m_original_settings, 0)) {
ANIMATIONINFO no_animation = { sizeof(no_animation), 0 };
::SystemParametersInfo(SPI_SETANIMATION,
sizeof(no_animation), &no_animation,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
m_suppressed = true;
}
}
~WindowsAnimationSuppressor() {
if (m_suppressed) {
::SystemParametersInfo(SPI_SETANIMATION,
sizeof(m_original_settings),
&m_original_settings,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
}
private:
bool m_suppressed;
ANIMATIONINFO m_original_settings;
};
void RearrangeWindows() {
WindowsAnimationSuppressor suppressor;
// Rearrange the windows here ...
}
When the suppressor is constructed, it remembers the user's original setting and turns off the animation. The destructor restores the original settings. By using a c'tor/d'tor, you ensure that the user's settings are restored if your rearranging code throws an exception.
There is a small window of vulnerability here. In theory, the user could change the setting during the operation, and then you'll slam the original setting back. That's extremely rare and not really that bad.

Resources