flibitijibibo / FNA-MGHistory

FNA - Accuracy-focused XNA4 reimplementation for open platforms
http://fna-xna.github.io/
246 stars 37 forks source link

Set Render Target to Another Window #334

Closed BaronKiko closed 8 years ago

BaronKiko commented 8 years ago

Hi, I was wondering if it was possible to support rendering multiple windows in parallel through the use of Render Targets? I can create windows by using the SDL that is made available through something like: var win = SDL.SDL_CreateWindow("Test", 10, 10, 400, 300, SDL.SDL_WindowFlags.SDL_WINDOW_SHOWN | SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE); but beyond there I am stuck. Equally I would need mouse and user input regardless of focus however your mouse behaves differently to XNA, for example in XNA the position of the mouse is always accurate relative to the top left of the initial window however in FNA as soon as you leave the window the mouse stops updating (is this due to the event based structure of SDL?). Is it possible to implement such a feature or more so does it already exist if used correctly? And finally if the need to be implemented how much is there to do and how long would it take roughly?

Kind Regards, Andy A

flibitijibibo commented 8 years ago

Is this something you're doing in XNA or is this something you're trying to do with a new FNA project?

XNA supported extra windows in a way, but a lot of it dealt with the user allocating their own Win32 HWND and stapling it to functions where it was needed. We can do this as well, but with SDL_Window* pointers.

For the mouse, this will be fixed in SDL 2.0.4 where we'll have access to SDL_GetGlobalMouseState, where the position will then be calculated with the current Mouse.WindowHandle position. For now, the best you'll get is setting the WindowHandle and then using SetPosition to warp the mouse to the window, where I believe it should give proper coordinates. (That, or you can request focus with SDL_RaiseWindow.)

The Graphics subsystem is where compatibility will get interesting due to the nature of GL contexts.

Like D3D, a GraphicsDevice is storing its own rendering context, along with a window pointer to present to. You could attempt to use a single GraphicsDevice on multiple windows by getting ugly with SDL_GL_MakeCurrent, but calls to SDL_GL_MakeCurrent are very very slow (and often unstable) and you probably want to avoid it. This might be possible to do on FNA's end, but again, this would be entirely at your own risk... you'd have to swap out the contexts in these places:

Unset GLDevice window, set overrideWindowHandle, undo when complete (4 MakeCurrents): https://github.com/flibitijibibo/FNA/blob/master/src/Graphics/OpenGLDevice.cs#L873

Unset GLDevice window, assign new window from PresentationParameters, set (2 MakeCurrents): https://github.com/flibitijibibo/FNA/blob/master/src/Graphics/OpenGLDevice.cs#L807

Reset THREADED_GL, where applicable (init is at this location): https://github.com/flibitijibibo/FNA/blob/master/src/Graphics/OpenGLDevice.cs#L4570

A slightly easier way to deal with all of this is to just use a second GraphicsDevice next to the second window, and use that GraphicsDevice independently of the rest of XNA (load your own textures/buffers/etc.), and call GraphicsDevice.Present() when the frame is ready.

flibitijibibo commented 8 years ago

Closing due to old age.