CloseGraphics bug with D3D9Max2DDriver

Archives Forums/BlitzMax Bug Reports/CloseGraphics bug with D3D9Max2DDriver

dan_upright(Posted 2014) [#1]
As far as I'm aware, there should be no functional difference between using Graphics() and CreateGraphics() but I get a crash if I handle graphics contexts myself with the D3D9 driver. I don't get the issue with the D3D7 or GL drivers, though I have had some issues with image corruption under GL unless I use GLShareContexts (even if I reload all the images after the new context is created).

This code crashes:
SuperStrict

Local gfx:TGraphics
Local pix:TPixmap = LoadPixmap("smile.jpg")
Local img:TImage
Local counter:Int = 0

SetGraphicsDriver(D3D9Max2DDriver())
gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER)
SetGraphics(gfx)
img = LoadImage(pix)
EnablePolledInput()

Repeat
	CloseGraphics(gfx)
	
	gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER)
	SetGraphics(gfx)
	img = LoadImage(pix)
	
	Cls
	DrawImage(img, 0, 0)
	DrawText(GCMemAlloced(), 0, 240)
	Flip
	counter = counter + 1
	Print counter
Until counter = 10000

But this code doesn't:
SuperStrict

Local pix:TPixmap = LoadPixmap("smile.jpg")
Local img:TImage
Local counter:Int = 0

SetGraphicsDriver(D3D9Max2DDriver())
Graphics(640, 480)
img = LoadImage(pix)
EnablePolledInput()

Repeat
	EndGraphics()
	
	Graphics(640, 480)
	img = LoadImage(pix)
	
	Cls
	DrawImage(img, 0, 0)
	DrawText(GCMemAlloced(), 0, 240)
	Flip
	counter = counter + 1
	Print counter
Until counter = 10000

And neither does this:
SuperStrict

Local gfx:TGraphics
Local pix:TPixmap = LoadPixmap("smile.jpg")
Local img:TImage
Local counter:Int = 0

SetGraphicsDriver(D3D9Max2DDriver())
gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER)
SetGraphics(gfx)
img = LoadImage(pix)
EnablePolledInput()

Repeat
	CloseGraphics(gfx)
	SetGraphicsDriver(D3D9Max2DDriver())
	
	gfx = CreateGraphics(640, 480, 0, 60, GRAPHICS_BACKBUFFER)
	SetGraphics(gfx)
	img = LoadImage(pix)
	
	Cls
	DrawImage(img, 0, 0)
	DrawText(GCMemAlloced(), 0, 240)
	Flip
	counter = counter + 1
	Print counter
Until counter = 10000

You shouldn't have to re-set the driver for a new context, right?


markcw(Posted 2014) [#2]
I've noticed this happens with OpenGL on Windows too - but not in Linux or Mac.

This was with using the maxgui demo with Openb3d (or Minib3d), where SetGraphicsDriver was required before CreateCanvas or you got a black screen.


col(Posted 2014) [#3]
Hiya,

In Max2d.bmx -> TMax2DGraphics -> Close

try

BumpGraphicsSeq

as the last statement before the EndMethod.

Then rebuild the modules. Would need some good wide spread testing before committing as a permanent fix.

Reason for the D3D9 crash in dan_uprights' examples is that the default_font TImageFrame(s) are holding onto D3D texture pointers that were created before the CloseGraphics. Then when you want to DrawText after a new CreateGraphics, Max2D is using those old textures pointers but with a new underlying hardware IDirect3DDevice9 instance.

@Munch
On Windows Max2D defaults to using a D3D9 driver. On Linux and Mac D3D9 doesnt exist so will default to the OpenGL driver. I believe MiniB3D is OpenGL only hence why you need to set the driver to OpenGL before seeing anything.


markcw(Posted 2014) [#4]
Awesome! Thanks Dave.


dan_upright(Posted 2014) [#5]
Nice one Dave, that seems to do the trick for me. Can I ask why the BumpGraphicsSeq goes in that specific method and not in CloseGraphics itself (in brl.graphics)? EndGraphics performs an inline BumpGraphicsSeq but CloseGraphics doesn't, so it seems like there should be parity there, no?

I'm not trying to nitpick, I'd just like to learn so I can have a stab at fixing stuff myself in future.


col(Posted 2014) [#6]
Hey dan_upright,

The graphics drivers have had a fair few number of bug fixes over the years ( especially the D3D9 one ) and I'd imagine there are possible remnants of fixes
that could do with tidying. BRL seems to be just about holding onto maintenance fixes at the mo so I highly doubt this kind of work would get a look-in.

The Max2D graphics systems isn't too complicated once you learn how its all put together.

If you want to learn it feel free to pull it apart to see how it works :-)


dan_upright(Posted 2014) [#7]
The one feature I want more than anything else is to get a borderless fullscreen window without using MaxGUI and a canvas. I had a stab at it the other day but I just blew everything up and it wouldn't have worked on linux/mac anyway. I really need to get a linux install going again.


col(Posted 2014) [#8]
The actual window is created in TD3D9Graphics->Create for D3D, so I'd imagine it the same for OpenGl but in the bbGLGraphicsCreateGraphics function in glgraphics.linux.c/glgraphics.win32.c/glgraphics.macos.m. EDIT: I had a quick glance and I might be wrong?

I suppose you could utilize the flags parameter to modify the window creation style.

A very quick D3D9 example that would need testing some more...

In graphics.bmx add this with the other similar definitions around lines 43 to 47
Const GRAPHICS_BORDERLESS = $40

In d3d9graphics.bmx :: TD3D9Graphics->Create modify the top couple of lines to

Local wstyle

If depth
	wstyle=WS_VISIBLE|WS_POPUP
Else
	If flags & GRAPHICS_BORDERLESS
		wstyle = WS_VISIBLE|WS_POPUP
	Else
		wstyle=WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX
	EndIf
EndIf

Then you can use
Graphics 800,600,,,GRAPHICS_BORDERLESS

to get a borderless D3D9 window.

This is just a quick hack up for an example for you and the flags parameter doesn't feel the right place for it. I mean if you were to allow changes to the window style then you may as well allow for various types of border/system icons as well. This would then be better with its own flag for window style creation variations, and leave the original flag as it is for a 'hardware graphics' setting flag.


dan_upright(Posted 2014) [#9]
I got borderless windows working for all 3 drivers (under win32 at least), thanks for pointing me in the right direction mate.