I just did a test where I discovered that using the DirectX driver, which is the one we're haivng problems with, you can set a fullscreen mode, and then switch to a canvas for graphics and it works fine. But you cannot go from having a canvas to fullscreen. So my guess is that something is wrong in the code which shuts down the canvas graphics.
Unhandled Exception in d3d7graphis.bmx - new info
BlitzMax Forums/BlitzMax Programming/Unhandled Exception in d3d7graphis.bmx - new info This describes an issue I've seen in my code.
I wonder if it's related to this bug?
At some point, the device is lost/dropped and things go splat.
I wonder if it's related to this bug?
At some point, the device is lost/dropped and things go splat.
I just did a test where I discovered that using the DirectX driver, which is the one we're haivng problems with, you can set a fullscreen mode, and then switch to a canvas for graphics and it works fine. But you cannot go from having a canvas to fullscreen. So my guess is that something is wrong in the code which shuts down the canvas graphics.
I have already reported this bug. It works fine in opengl, but not DX.
One Eyed Jack,
I have already reported this bug. It works fine in opengl, but not DX.
Which is exactly the behaviour of the other (multi canvas) bug. Works great in OGL, deadly in DX7.
Neil
I have already reported this bug. It works fine in opengl, but not DX.
Which is exactly the behaviour of the other (multi canvas) bug. Works great in OGL, deadly in DX7.
Neil
Please syncmods for a new version of dxgraphics/d3d7max2d modules, hopefully switching between fullscreen and windowed is now supported, please post code if you can get it to fail.
Skid,
Holy smoke! All those canvas bugs are gone!
Thanks!
Holy smoke! All those canvas bugs are gone!
Thanks!
I'm still getting a failure in my game, but my test program works fine. I may have changed how my game works though, so I'll look into that.
The program doesn't crash any more when you change video modes, but there's a couple new problems.
I have updated this test program. It starts up in fullscreem and from there you can hit F to toggle back and forth from fullscreen to windowed mode.
In DirectX, you can switch back to canvas, and from there back to fullscreen. But when I switch back to canvas again, I have all these black horizontal lines on the canvas, and everything slows to a crawl.
In OpenGL, which used to work fine, you can switch from fullscreen to windowed mode, and back, but when you go into fullscreen mode the second time, it now shows a flashing start bar at the bottom of the screen, as if you forgot to clear both buffers.
I have a Geforce 6800.
'SetGraphicsDriver GLMax2DDriver() Global App:Application = Application.Create("Fruit Sliders", 800, 600, 0, True) Image:TImage = CreateImage(32, 32) DrawImage(Image, 0, 0) Repeat If KeyHit(KEY_F) App.ToggleFullscreen() DebugLog("State : " + App.Windowed) EndIf Flip True Until KeyHit(KEY_ESCAPE) Type Application Field Name$ Field Width% Field Height% Field Depth% Field Window:TGadget Field Canvas:TGadget Field Panel:TGadget Field TG:TGraphics Field Windowed% ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This function creates the game window, and sets up the graphics objects for windowed and fullscreen modes. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Function Create:Application(AppName$, AppWidth%, AppHeight%, AppDepth%=0, Fullscreen%=False) Local X%, Y% Local App:Application ' Create new application. App = New Application ' Store application settings. App.Name$ = AppName$ App.Width = AppWidth App.Height = AppHeight App.Depth = AppDepth ' If Depth is 0, try to find a suitable fullscreen bit depth. If App.Depth = 0 App.Depth = 16 If GraphicsModeExists(App.Width, App.Height, 24) Then App.Depth = 24 If GraphicsModeExists(App.Width, App.Height, 32) Then App.Depth = 32 EndIf ' Create a window in the center of the screen. X = GadgetWidth(Desktop())/2 - App.Width/2 Y = GadgetHeight(Desktop())/2 - App.Height/2 App.Window = CreateWindow(App.Name$, X, Y, App.Width, App.Height, Null, WINDOW_TITLEBAR|WINDOW_RESIZABLE|WINDOW_CLIENTCOORDS|WINDOW_HIDDEN) SetMinWindowSize(App.Window, GadgetWidth(App.Window), GadgetHeight(App.Window)) ' Create a panel in the window, drawn behind the canvas, which fills the empty space around the gameplay area when the window is maximized. App.Panel = CreatePanel(0, 0, App.Width, App.Height, App.Window) SetPanelColor(App.Panel, 0, 0, 0) SetGadgetLayout(App.Panel, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED) ' Create a canvas. App.Canvas = CreateCanvas(ClientWidth(App.Window)/2-App.Width/2, ClientHeight(App.Window)/2-App.Height/2, App.Width, App.Height, App.Panel) ' Set game to windowed or fullscreen as desired. Select Fullscreen Case False App.SetWindowed() Case True App.SetFullscreen() End Select ' Return new application instance. Return App End Function ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method toggles between fullscreen or windowed mode, choosing the opposite of whichever is currently enabled. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method ToggleFullscreen() Select Windowed Case False SetWindowed() Case True SetFullscreen() End Select End Method ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method puts the application in windowed mode. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method SetWindowed() ' Set drawing operations to go to canvas. EndGraphics SetGraphics CanvasGraphics(Canvas) Windowed = True ShowGadget Window ActivateGadget Canvas ' Canvas must be activated for input or else game will make user click on canvas before any polled keyboard input is returned. EnablePolledInput() End Method ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method sets the application to fullscreen mode, unless no fullscreen mode in the desired resolution exists. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method SetFullscreen() Local G:TGraphics ' Set drawing operations to fullscreen. HideGadget Window G = Graphics(Width, Height, Depth) Windowed = False ' If the operation fails, put us back in windowed mode. Otherwise, hide the window, and record that fullscreen is enabled. If G = Null Then SetWindowed() End Method End Type ' ----------------------------------------------------------------------------------------------------------------------------------------------------------- ' This function overrides the standard RuntimeError function which does not work properly. Assert also does not work. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------- Function RuntimeError(Error$) EndGraphics Notify(Error$, True) End End Function
I have updated this test program. It starts up in fullscreem and from there you can hit F to toggle back and forth from fullscreen to windowed mode.
In DirectX, you can switch back to canvas, and from there back to fullscreen. But when I switch back to canvas again, I have all these black horizontal lines on the canvas, and everything slows to a crawl.
In OpenGL, which used to work fine, you can switch from fullscreen to windowed mode, and back, but when you go into fullscreen mode the second time, it now shows a flashing start bar at the bottom of the screen, as if you forgot to clear both buffers.
I have a Geforce 6800.
Here is another test app. It works the same as the above, but it uses a different method to attempt to change between modes.
The first app creates a canvas graphics context, and each time it switches to fullscreen it creates a new fullscreen graphics context.
This app creates a new fullscreen context each time you switch to fullscreen just like the other app, but it also creates a whole new canvas each time you switch to windowed mode, freeing the old one on switch to windowed mode.
This one displays the start menu bar flicker right away in OpenGL, and in DirectX fails to switch back to fullscreen from the canvas.
The first app creates a canvas graphics context, and each time it switches to fullscreen it creates a new fullscreen graphics context.
This app creates a new fullscreen context each time you switch to fullscreen just like the other app, but it also creates a whole new canvas each time you switch to windowed mode, freeing the old one on switch to windowed mode.
This one displays the start menu bar flicker right away in OpenGL, and in DirectX fails to switch back to fullscreen from the canvas.
'SetGraphicsDriver GLMax2DDriver() Global App:Application = Application.Create("Fruit Sliders", 800, 600, 0, True) Image:TImage = CreateImage(32, 32) DrawImage(Image, 0, 0) Repeat If KeyHit(KEY_F) App.ToggleFullscreen() DebugLog("State : " + App.Windowed) EndIf Flip True Until KeyHit(KEY_ESCAPE) Type Application Field Name$ Field Width% Field Height% Field Depth% Field Window:TGadget Field Canvas:TGadget Field Panel:TGadget Field TG_FullScreen:TGraphics Field TG_Canvas:TGraphics Field Windowed% ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This function creates the game window, and sets up the graphics objects for windowed and fullscreen modes. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Function Create:Application(AppName$, AppWidth%, AppHeight%, AppDepth%=0, Fullscreen%=False) Local X%, Y% Local App:Application 'SetGraphicsDriver GLMax2DDriver() ' Create new application. App = New Application ' Store application settings. App.Name$ = AppName$ App.Width = AppWidth App.Height = AppHeight App.Depth = AppDepth ' If Depth is 0, try to find a suitable fullscreen bit depth. If App.Depth = 0 App.Depth = 16 If GraphicsModeExists(App.Width, App.Height, 24) Then App.Depth = 24 If GraphicsModeExists(App.Width, App.Height, 32) Then App.Depth = 32 EndIf ' Create a window in the center of the screen. X = GadgetWidth(Desktop())/2 - App.Width/2 Y = GadgetHeight(Desktop())/2 - App.Height/2 App.Window = CreateWindow(App.Name$, X, Y, App.Width, App.Height, Null, WINDOW_TITLEBAR|WINDOW_RESIZABLE|WINDOW_CLIENTCOORDS|WINDOW_HIDDEN) SetMinWindowSize(App.Window, GadgetWidth(App.Window), GadgetHeight(App.Window)) ' Create a panel in the window, drawn behind the canvas, which fills the empty space around the gameplay area when the window is maximized. App.Panel = CreatePanel(0, 0, App.Width, App.Height, App.Window) SetPanelColor(App.Panel, 0, 0, 0) SetGadgetLayout(App.Panel, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED) ' Create a canvas. ' App.Canvas = CreateCanvas(ClientWidth(App.Window)/2-App.Width/2, ClientHeight(App.Window)/2-App.Height/2, App.Width, App.Height, App.Panel) ' App.TG_Canvas = CanvasGraphics(App.Canvas) ' Set game to windowed or fullscreen as desired. Select Fullscreen Case False App.SetWindowed() Case True App.SetFullscreen() End Select ' Return new application instance. Return App End Function ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method toggles between fullscreen or windowed mode, choosing the opposite of whichever is currently enabled. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method ToggleFullscreen() Select Windowed Case False SetWindowed() Case True SetFullscreen() End Select End Method ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method puts the application in windowed mode. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method SetWindowed() ' End fullscreen mode if enabled. If TG_Fullscreen <> Null CloseGraphics TG_Fullscreen TG_Fullscreen = Null EndIf ' Create a canvas. If Canvas = Null Canvas = CreateCanvas(ClientWidth(Window)/2-Width/2, ClientHeight(Window)/2-Height/2, Width, Height, Panel) TG_Canvas = CanvasGraphics(Canvas) EndIf If Canvas = Null Then RuntimeError("Error in Application.SetWindowed() : Could not create canvas!") If TG_Canvas = Null Then RuntimeError("Error in Application.SetWindowed() : Could not get canvas graphics context!") SetGraphics TG_Canvas Windowed = True ShowGadget Window ActivateGadget Canvas ' Canvas must be activated for input or else game will make user click on canvas before any polled keyboard input is returned. EnablePolledInput() End Method ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method sets the application to fullscreen mode, unless no fullscreen mode in the desired resolution exists. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method SetFullscreen() Local G:TGraphics ' Hide window, free canvas. HideGadget Window If Canvas <> Null CloseGraphics(TG_Canvas) TG_Canvas = Null FreeGadget Canvas Canvas = Null EndIf ' Set drawing operations to fullscreen. If TG_Fullscreen = Null Then TG_Fullscreen = Graphics(Width, Height, Depth) Windowed = False ' If the operation fails, put us back in windowed mode. Otherwise, hide the window, and record that fullscreen is enabled. If TG_Fullscreen = Null RuntimeError("Error in Application.SetFullscreen() : Could not set full screen mode!") 'SetWindowed() EndIf End Method End Type ' ----------------------------------------------------------------------------------------------------------------------------------------------------------- ' This function overrides the standard RuntimeError function which does not work properly. Assert also does not work. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------- Function RuntimeError(Error$) EndGraphics Notify(Error$, True) End End Function
Here is yet another test program:
This version attempts to create a canvas when the window is created, then when switching to fullscreen for the first time, it uses CreateGraphics() to create a fullscreen graphics context. From there on, it attempts to switch between the two contexts with SetGraphics, and never tries to recreate either.
This version fails the worst though. In DirectX, it crashes when attempting to switch back to windowed from fullscreen, giving "createsurface failed" as the error. (If you alter the app to attempt to run in windowed mode first, it will switch from canvas to fullscreen but not back.) In OpenGL, things are even weirder than before. Not only do you have the flashing start menu bar at the bottom of the screen, but after you switch back to windowed mode, if you press F again, nothing happens! You have to actually click the window button on the task bar to get it to go back into fullscreen mode. And once there, the formerly flashing start menu bar in fullscreen now has flashing streaks of black over it, as if Flip True is no longer waiting for the vertical refresh.
'SetGraphicsDriver GLMax2DDriver() Global App:Application = Application.Create("Fruit Sliders", 800, 600, 0, True) Image:TImage = CreateImage(32, 32) DrawImage(Image, 0, 0) Repeat If KeyHit(KEY_F) App.ToggleFullscreen() DebugLog("State : " + App.Windowed) EndIf Flip True Until KeyHit(KEY_ESCAPE) Type Application Field Name$ Field Width% Field Height% Field Depth% Field Window:TGadget Field Canvas:TGadget Field Panel:TGadget Field TG_FullScreen:TGraphics Field TG_Canvas:TGraphics Field Windowed% ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This function creates the game window, and sets up the graphics objects for windowed and fullscreen modes. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Function Create:Application(AppName$, AppWidth%, AppHeight%, AppDepth%=0, Fullscreen%=False) Local X%, Y% Local App:Application 'SetGraphicsDriver GLMax2DDriver() ' Create new application. App = New Application ' Store application settings. App.Name$ = AppName$ App.Width = AppWidth App.Height = AppHeight App.Depth = AppDepth ' If Depth is 0, try to find a suitable fullscreen bit depth. If App.Depth = 0 App.Depth = 16 If GraphicsModeExists(App.Width, App.Height, 24) Then App.Depth = 24 If GraphicsModeExists(App.Width, App.Height, 32) Then App.Depth = 32 EndIf ' Create a window in the center of the screen. X = GadgetWidth(Desktop())/2 - App.Width/2 Y = GadgetHeight(Desktop())/2 - App.Height/2 App.Window = CreateWindow(App.Name$, X, Y, App.Width, App.Height, Null, WINDOW_TITLEBAR|WINDOW_RESIZABLE|WINDOW_CLIENTCOORDS|WINDOW_HIDDEN) SetMinWindowSize(App.Window, GadgetWidth(App.Window), GadgetHeight(App.Window)) ' Create a panel in the window, drawn behind the canvas, which fills the empty space around the gameplay area when the window is maximized. App.Panel = CreatePanel(0, 0, App.Width, App.Height, App.Window) SetPanelColor(App.Panel, 0, 0, 0) SetGadgetLayout(App.Panel, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED) ' Create a canvas. App.Canvas = CreateCanvas(ClientWidth(App.Window)/2-App.Width/2, ClientHeight(App.Window)/2-App.Height/2, App.Width, App.Height, App.Panel) App.TG_Canvas = CanvasGraphics(App.Canvas) ' Set game to windowed or fullscreen as desired. Select Fullscreen Case False App.SetWindowed() Case True App.SetFullscreen() End Select ' Return new application instance. Return App End Function ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method toggles between fullscreen or windowed mode, choosing the opposite of whichever is currently enabled. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method ToggleFullscreen() Select Windowed Case False SetWindowed() Case True SetFullscreen() End Select End Method ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method puts the application in windowed mode. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method SetWindowed() SetGraphics TG_Canvas Windowed = True ShowGadget Window ActivateGadget Canvas ' Canvas must be activated for input or else game will make user click on canvas before any polled keyboard input is returned. EnablePolledInput() End Method ' ------------------------------------------------------------------------------------------------------------------------------------------------------- ' This method sets the application to fullscreen mode, unless no fullscreen mode in the desired resolution exists. ' ------------------------------------------------------------------------------------------------------------------------------------------------------- Method SetFullscreen() Local G:TGraphics If TG_Fullscreen = Null Then TG_Fullscreen = CreateGraphics(Width, Height, Depth, 0, 0) Windowed = False ' If the switch to fullscreen failed, put us back in windowed mode. If TG_Fullscreen = Null RuntimeError("Error in Application.SetFullscreen() : Could not set full screen mode!") 'SetWindowed() Else HideGadget Window SetGraphics TG_Fullscreen EnablePolledInput() EndIf End Method End Type ' ----------------------------------------------------------------------------------------------------------------------------------------------------------- ' This function overrides the standard RuntimeError function which does not work properly. Assert also does not work. ' ----------------------------------------------------------------------------------------------------------------------------------------------------------- Function RuntimeError(Error$) EndGraphics Notify(Error$, True) End End Function
This version attempts to create a canvas when the window is created, then when switching to fullscreen for the first time, it uses CreateGraphics() to create a fullscreen graphics context. From there on, it attempts to switch between the two contexts with SetGraphics, and never tries to recreate either.
This version fails the worst though. In DirectX, it crashes when attempting to switch back to windowed from fullscreen, giving "createsurface failed" as the error. (If you alter the app to attempt to run in windowed mode first, it will switch from canvas to fullscreen but not back.) In OpenGL, things are even weirder than before. Not only do you have the flashing start menu bar at the bottom of the screen, but after you switch back to windowed mode, if you press F again, nothing happens! You have to actually click the window button on the task bar to get it to go back into fullscreen mode. And once there, the formerly flashing start menu bar in fullscreen now has flashing streaks of black over it, as if Flip True is no longer waiting for the vertical refresh.
Hmm, CloseGraphics on a canvas graphics or a FreeGadget Canvas which calls CloseGraphics both seem to cause that failure. Will hopefully have it fixed tomorrow.
OK try another syncmods.
Sswift, thanks heaps for the various examples, each one did need a different tweak and I'm sure you'll find some more ways of crashing it.
I'll hold off posting the recomended method of switching between fullscreen as I'm kindof curious if you can come up with any more exotic methods.
Also while i'm thinking of it you should probably use clientwidth and clientheight of the desktop in your code, the gadgetwidth and gadgetheight desktop() versions on a multimonitor setup return the combined size meaning your window sits between the two displays instead of being centered on the primary display.
Sswift, thanks heaps for the various examples, each one did need a different tweak and I'm sure you'll find some more ways of crashing it.
I'll hold off posting the recomended method of switching between fullscreen as I'm kindof curious if you can come up with any more exotic methods.
Also while i'm thinking of it you should probably use clientwidth and clientheight of the desktop in your code, the gadgetwidth and gadgetheight desktop() versions on a multimonitor setup return the combined size meaning your window sits between the two displays instead of being centered on the primary display.
Heh, well the reason I came up with all those examples was I was trying to find ONE method that worked, not cause I was being clever and coming up with ways to crash it intentionally. :-)
Thanks for the heads up on that desktop thing, I'll make that change in my code.
I'll try the syncmods thing and see if my three examples work. And if I can think of any other ways to switch between fullscreen and windowed, I'll let ya know. :-)
Thanks for the heads up on that desktop thing, I'll make that change in my code.
I'll try the syncmods thing and see if my three examples work. And if I can think of any other ways to switch between fullscreen and windowed, I'll let ya know. :-)
When running the first example in DirectX, switching to fullscreen from canvas works fine, but when you switch back you get garbage in the window... blocks of old buffer interspersed with blackness, and short horizontal lines missing throughout.
When running the first example in OpenGL, every other time you go fullscreen, you get the flashing start bar on the bottom of the screen.
---
When running the second example in DirectX, when you switch to canvas, my system slows to a crawl, but goes back to normal when I manage to switch back to fullscreen.
When running the second example in OpenGL, the flashing start bar appears in fullscreen every time.
---
When running the third example in DirectX, when you switch back to windowed from fullscreen everything slows to a crawl, and it fails to switch back to fullscreen mode.
When running th third example in OpenGL, once more, we have the flashing start menu bar, but this time you also get two window buttons on the start menu bar, and clicking one of them takes you back to fullscreen more.
I suspect the system is slowing to a crawl in those two examples because the Hz is getting messed up or something and Flip True in windowed mode is allowing the program to flip the buffer a thousand times a second rather than how it is normally limited to 60 or so.
All that said, I can confirm that within an actual GAME, the second method works. There's a start bar flash on the bottom of the screen for a moment while the screen is black and it is switching from windowed mode to fullscreen in OpenGL... And you see a large desktop image in the background for a moment when switching back.... But otherwise, it seems to work. It's just not as pretty as it should be. Also in DirectX, the start menu bar takes it's sweet time returning to normal and displaying the window's button on it when you return from fullscreen mode.
I'll have to try some of the other methods and see if one of them works better in the actual game environment.
When running the first example in OpenGL, every other time you go fullscreen, you get the flashing start bar on the bottom of the screen.
---
When running the second example in DirectX, when you switch to canvas, my system slows to a crawl, but goes back to normal when I manage to switch back to fullscreen.
When running the second example in OpenGL, the flashing start bar appears in fullscreen every time.
---
When running the third example in DirectX, when you switch back to windowed from fullscreen everything slows to a crawl, and it fails to switch back to fullscreen mode.
When running th third example in OpenGL, once more, we have the flashing start menu bar, but this time you also get two window buttons on the start menu bar, and clicking one of them takes you back to fullscreen more.
I suspect the system is slowing to a crawl in those two examples because the Hz is getting messed up or something and Flip True in windowed mode is allowing the program to flip the buffer a thousand times a second rather than how it is normally limited to 60 or so.
All that said, I can confirm that within an actual GAME, the second method works. There's a start bar flash on the bottom of the screen for a moment while the screen is black and it is switching from windowed mode to fullscreen in OpenGL... And you see a large desktop image in the background for a moment when switching back.... But otherwise, it seems to work. It's just not as pretty as it should be. Also in DirectX, the start menu bar takes it's sweet time returning to normal and displaying the window's button on it when you return from fullscreen mode.
I'll have to try some of the other methods and see if one of them works better in the actual game environment.
I can confirm some odd slowdowns when using multiple canvases until I've gone fullscreen and back.