Is it possible to toggle fullscreen without recreating the window? - opengl

Do the three major operating systems Linux, Windows and Mac support toggling between fullscreen and windowed mode without recreating the window? Recreating is problematic since it implies to recreate the OpenGL context as well, or at least some OpenGL objects.
What API functions are available on those platforms for performing the task?

Windows: Yes
X11/GLX: Yes
MacOS-X: It's complicated.
First the easy stuff: In Windows and X11 there are no such things as special fullscreen mode OpenGL windows. They're all just regular toplevel windows and you can add or remove the window decorations (title bar, border) anytime you like. If you remove the window decorations and set the window size to maximized you essentially get a fullscreen OpenGL window; in fact the graphics drivers are smart enough to detect this situation and switch to a fast track then.
Now MacOS X. In MacOS X clear distinction is made between Windowed and Fullscreen (which IMHO is quite annoying).
The good news is, that you can get access to the underlying context object which allows to implement some resource sharing so that you don't have to recreate the data containing OpenGL objects.
Big Fat Disclaimer: I never ventured as deep into MacOS X as I did with other OSs so my practical experience with this certain topic on MacOS X is only theoretical.

Related

How to render child window with Direct2D in native desktop Windows application?

I have a desktop application where all windows (HWND) render itself with Direct2D 1.1. My question is how to do it more correctly?
Should each window has its own Direct2D device context derived from one Direct2D device? In this case, I cannot render transparent content on a child window without additional tricks (I have to change target on parent window’s context, render parent window to Direct2D bitmap and then draw this bitmap on child’s target).
May be it is better to have one Direct2D device context where all windows render itself? I believe DirectComposition works in a similar way. Unfortunately, I cannot use it because I target Windows 7.
You're asking a question whose answer will be very application specific. I recommend avoiding the whole problem of trying to get HWNDs to render with transparency amongst each other, especially if you're throwing Direct2D into the mix. There is just too much pain in that direction. Every version of Windows that you support will have different bugs that you'll be constantly bumping into and grasping at workarounds for.
Case in point: For the v4.0 release of Paint.NET, I converted all text rendering to DirectWrite, and almost all UI controls to use Direct2D. The image thumbnail control at the top of the window (the MDI selector) is using Direct2D for rendering but it also has to compose on top of what's behind it. And it has to play nice with glass on Win7 (it looks great though!). The code for this is awful, tricky, barely maintainable, and it seems to bump into a different rendering bug on every release of Windows: 7, 7 SP1, 8, 8.1, and 10 all behave slightly differently! It's really annoying to test, too; it's the only reason I have to set up and maintain VMs for every version of Windows that I support (other than the installer and updater). Windows 7 worked fine, then 7 SP1 added a bug which required some tuning to how I filled the alpha channel. Windows 8 has flickering when you resize the window unless I do a certain hack, but 8.1 works fine. 10 then has its own flickering bug if software rendering is used. Remote Desktop breaks things in its own way. Then you also have to worry about High Contrast, and whether DWM is enabled/disabled if you're supporting Windows 7. They all behave differently and it's really really painful.
Anyway. What you seem to really need is a UI system like WPF or XAML which doesn't use anything other than a top-level HWND container. At that point you're custom rendering everything and doing your own hit-testing and input routing (and accessibility and all sorts of other things), so it's not a small task.
Regarding the "how to do it more correctly" question and cardinality of device and device context: Have you thought about just using ID2D1Factory::CreateHWNDRenderTarget or ID2D1Factory::CreateDCRenderTarget ? They return ID2D1RenderTarget but you can call QueryInterface to cast them to ID2D1DeviceContext (this fact is missing from the docs but is also clearly intentional). This should simplify working with Direct2D and HWNDs quite a bit. This is what I do in Paint.NET: I still use an HWND for each control, but each control is using its own HWND or DC render target. If you're willing to poke around with Reflector or ILSpy, checkout Direct2DControl and Direct2DControlHandler in the Paint.NET DLLs.
Also, be careful about using more than 1 hardware accelerated HWND render target. You don't want to get into a weird area where every Direct2D-based UI control is waiting on VSync. Using D2D1_PRESENT_OPTIONS_IMMEDIATELY when creating the HWND render target should help. DWM already handles VSync, so you should be fine to tell Direct2D to ignore it unless you're doing some rather specific stuff with animations and timers.

How to make GLFW fullscreen across multiple monitors?

In GLFW, you can tell a window to go fullscreen on a particular monitor when you create it, but is there any way to make it stretch across multiple monitors?
On most platforms, what you are asking for is not really possible using a framework as portable as GLFW.
Fullscreen modes generally fill one logical display. You need something lower-level to setup multi-monitor topologies (AMD and NV have entire APIs and driver settings for this).
You can stretch a window across multiple monitors though and using the DECORATED flag (specifically turning it off), you may be able to make this window spanning multiple monitors appear to be fullscreen (e.g. no border / title bar). Hiding the taskbar (Windows) / launcher/menu (OS X) is another matter though.

C++ & Allegro 4.2 - I need graphics to stretch in windowed mode

I am using C++ with Allegro 4.2 to build a windows game.
I want stretchable graphics in windowed mode.
I'm am one who likes giving users of my programs lots of options; I always hate when I'm playing a game in windowed mode and I'm either not allowed to stretch the window or the content inside the window doesn't stretch with it (this sucks a lot for 640x480 size games played on high resolution screens that don't even allow for fullscreen; requiring a magnify tool to play it properly). I'm wondering if there is some way in Allegro or perhaps if there is another programming library that allows the graphics to stretch with the shape of the window itself. I already know how to have my Allegro applications switch to fullscreen mode; I'm trying to improve the windowed mode.
A big reason for this is because my artstyle is low-resolution art (I call it "Bitmap Brothers" style); it's very good for games since it's organized and easy to edit. I don't want to have to go higher than 640x480 to increase the size because it's far to high for low-resolution art, but my window remains too small during windowed mode.
I noticed that Allegro 5.0.8 has this line of code:
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE);
At the end it says "ALLEGRO_RESIZABLE", could that be the feature I'm looking for? If so, just how much does Allegro change from 4.2 to 5+?
Allegro 4 doesn't support user-resizable windows.
Allegro 5 does (as you've noted), but it is completely rewritten and is not backward compatible at all. Still, I would highly recommend that you switch to it as development on Allegro 4 is all but dead.

SDL window management with OpenGL and DirectX

I'm porting a small graphics engine from DirectX 9 to OpenGL. The engine uses SDL (now ported to 2.0) to manage input and window creation.
I want to know how to correctly handle window events for both OpenGL and DirectX. I'm interested in these for Desktop platforms (linux, OSX and windows)
Window resolution change
Full screen to windowed / windowed to fullscreen handling
Alt+tab handling -
I've tried to search through the net but information is quite not focused in one place. I imagine many others faced the same problem before.
Are there any resources to read guidelines on that kind of handling for my engine?
Is it possible to handle resolution change without losing transfered resources to the renderer system in both OpenGL and DirectX?
Window resolution change
OpenGL itself requires no special treatment for this. Unfortunately SDL goes through a full window reinitialization, including the OpenGL context on a window size change, which means, that all OpenGL state objects (that is, textures, vertex buffers, shaders and so on) are lost.
This is however a limitation of SDL.
Personally I thus prefer GLFW for creating a OpenGL window and context. You can still use SDL for other things though (like audio, networking, image loading and such).
Full screen to windowed / windowed to fullscreen handling
The is effectively a window size change as well. See above.
Alt+tab handling -
OpenGL requires no special effort for this. Just minimize the window when Alt+Tab-ing out and stop the game loop. When the window gets restored just continue the game loop.

A way to return control to Windows when window is not the focus OpenGL - C++

I was wondering if there was an OpenGL command to return control to Windows when the window the rendering is happening in is no longer the focus. As it stands, the mouse is constantly moved to the center of the screen even when it is not the focus.
Any way around this?
Thanks!
OpenGL is a rendering API; it does not have commands that deal with the underlying windowing system. WGL, GLX, and Apples AGL do that sort of thing. And even those APIs don't deal with mouse movement.
If the mouse is being forced to the center of the screen by your application, then it is probably due to some other code that you are using. Many of the common tools for creating OpenGL windows (FreeGLUT, GLFW, Qt, wxWidgets, etc) have commands for capturing the mouse and affecting its position. You will need to check your code and the documentation of whatever software you're using to interface with your window to see where the problem lies.
For windows, make sure you're setting mouse position if windows is active.
if(getactivewindow() == this->hwnd)
setmousepos()
This is probably the issue.