Răsfoiți Sursa

Added Win32 DX9 support.

woollybah 10 ani în urmă
părinte
comite
b0bc8b7b61

+ 403 - 0
d3d9sdlgraphics.mod/d3d9sdlgraphics.bmx

@@ -0,0 +1,403 @@
+Strict
+
+Module sdl.d3d9sdlgraphics
+
+?win32
+
+Import Pub.DirectX
+Import SDL.SDLGraphics
+
+Import BRL.LinkedList
+
+Private
+
+'Global _wndClass$="BBDX9Device Window Class"
+
+Global _driver:TD3D9SDLGraphicsDriver
+
+Global _d3d:IDirect3D9
+Global _d3dCaps:D3DCAPS9
+Global _modes:TGraphicsMode[]
+
+Global _d3dDev:IDirect3DDevice9
+Global _d3dDevRefs:Int
+
+Global _presentParams:D3DPRESENT_PARAMETERS
+
+Global _graphics:TD3D9SDLGraphics
+
+Global _autoRelease:TList
+
+Global _d3dOccQuery:IDirect3DQuery9
+
+Type TD3D9AutoRelease
+	Field unk:IUnknown
+End Type
+
+Function OpenD3DDevice:Int( hwnd:Byte Ptr,width:Int,height:Int,depth:Int,hertz:Int,flags:Int)
+	If _d3dDevRefs
+		If Not _presentParams.GetWindowed() Return False
+		If depth<>0 Return False
+		_d3dDevRefs:+1
+		Return True
+	EndIf
+
+	Local windowed:Int=(depth=0)
+	Local fullscreen:Int=(depth<>0)	
+
+	Local pp:D3DPRESENT_PARAMETERS=New D3DPRESENT_PARAMETERS
+	pp.SetBackBufferWidth(width)
+	pp.SetBackBufferHeight(height)
+	pp.SetBackBufferCount(1)
+	pp.SetBackBufferFormat((D3DFMT_X8R8G8B8 * fullscreen) + (D3DFMT_UNKNOWN * windowed))
+	pp.SetMultiSampleType(D3DMULTISAMPLE_NONE)
+	pp.SetSwapEffect((D3DSWAPEFFECT_DISCARD * fullscreen) + (D3DSWAPEFFECT_COPY * windowed))
+	pp.SethDeviceWindow(hwnd)
+	pp.SetWindowed(windowed)
+	pp.SetFlags(D3DPRESENTFLAG_LOCKABLE_BACKBUFFER)
+	pp.SetFullScreen_RefreshRateInHz(hertz * fullscreen)
+	pp.SetPresentationInterval(D3DPRESENT_INTERVAL_ONE)	'IMMEDIATE
+	
+	Local cflags:Int=D3DCREATE_FPU_PRESERVE
+	
+	_d3dDev = New IDirect3DDevice9
+	
+	'OK, try hardware vertex processing...
+	Local tflags:Int=D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|cflags
+	If _d3d.CreateDevice( 0,D3DDEVTYPE_HAL,hwnd,tflags,pp,_d3dDev )<0
+
+		'Failed! Try mixed vertex processing...
+		tflags=D3DCREATE_MIXED_VERTEXPROCESSING|cflags
+		If _d3d.CreateDevice( 0,D3DDEVTYPE_HAL,hwnd,tflags,pp,_d3dDev )<0
+	
+			'Failed! Try software vertex processing...	
+			tflags=D3DCREATE_SOFTWARE_VERTEXPROCESSING|cflags
+			If _d3d.CreateDevice( 0,D3DDEVTYPE_HAL,hwnd,tflags,pp,_d3dDev )<0
+			
+				_d3dDev = Null
+				'Failed! Go home and watch family guy instead...
+				Return False
+			EndIf
+		EndIf
+	EndIf
+
+	_presentParams=pp
+
+	_d3dDevRefs:+1
+	
+	_autoRelease=New TList
+
+	'Occlusion Query
+	If Not _d3dOccQuery
+		_d3dOccQuery = New IDirect3DQuery9
+		If _d3ddev.CreateQuery(9,_d3dOccQuery)<0 '9 hardcoded for D3DQUERYTYPE_OCCLUSION
+			DebugLog "Cannot create Occlussion Query!"
+			_d3dOccQuery = Null
+		EndIf
+	EndIf
+	If _d3dOccQuery _d3dOccQuery.Issue(2) 'D3DISSUE_BEGIN
+	
+	Return True
+End Function
+
+Function CloseD3DDevice()
+	_d3dDevRefs:-1
+	If Not _d3dDevRefs
+
+		For Local t:TD3D9AutoRelease=EachIn _autoRelease
+			t.unk.Release_
+		Next
+		_autoRelease=Null
+
+		If _d3dOccQuery _d3dOccQuery.Release_
+		_d3dOccQuery = Null
+
+		_d3dDev.Release_
+		_d3dDev=Null
+		_presentParams=Null
+	EndIf
+End Function
+
+Function ResetD3DDevice()
+	If _d3dOccQuery
+		_d3dOccQuery.Release_
+	Else
+		_d3dOccQuery = New IDirect3DQuery9
+	End If
+	
+	If _d3dDev.Reset( _presentParams )<0
+		Throw "_d3dDev.Reset failed"
+	EndIf
+
+	If _d3ddev.CreateQuery(9,_d3dOccQuery)<0
+		_d3dOccQuery = Null
+		DebugLog "Cannot create Occlussion Query!"
+	EndIf
+	If _d3dOccQuery _d3dOccQuery.Issue(2) 'D3DISSUE_BEGIN
+		
+End Function
+
+Public
+
+Global UseDX9RenderLagFix:Int = 0
+
+Type TD3D9SDLGraphics Extends TGraphics
+
+	Method Attach:TD3D9SDLGraphics( hwnd:Byte Ptr,flags:Int )
+		Local rect:Int[4]
+		GetClientRect hwnd,rect
+		Local width:Int=rect[2]-rect[0]
+		Local height:Int=rect[3]-rect[1]
+
+		OpenD3DDevice hwnd,width,height,0,0,flags
+		
+		_hwnd=hwnd
+		_width=width
+		_height=height
+		_flags=flags
+		_attached=True
+
+		Return Self
+	End Method
+	
+	Method Create:TD3D9SDLGraphics( width:Int,height:Int,depth:Int,hertz:Int,flags:Int)
+	
+		
+		_g = SDLGraphicsDriver().CreateGraphics( width, height, depth, hertz, flags | GRAPHICS_WIN32_DX )
+		
+		_hwnd = _g.GetHandle()
+		
+		Local rect:Int[4]
+
+		If Not depth
+			GetClientRect _hwnd,rect
+			width=rect[2]-rect[0]
+			height=rect[3]-rect[1]
+		EndIf
+		
+		If Not OpenD3DDevice( _hwnd,width,height,depth,hertz,flags )
+			DestroyWindow _hwnd
+			Return Null
+		EndIf
+		
+		_width=width
+		_height=height
+		_depth=depth
+		_hertz=hertz
+		_flags=flags
+		
+		Return Self
+	End Method
+	
+	Method GetDirect3DDevice:IDirect3DDevice9()
+		Return _d3dDev
+	End Method
+
+	Method ValidateSize()
+		If _attached
+			Local rect:Int[4]
+			GetClientRect _hwnd,rect
+			_width=rect[2]-rect[0]
+			_height=rect[3]-rect[1]
+			If _width>_presentParams.GetBackBufferWidth() Or _height>_presentParams.GetBackBufferHeight()
+				_presentParams.SetBackBufferWidth(Max( _width,_presentParams.GetBackBufferWidth()) )
+				_presentParams.SetBackBufferHeight(Max( _height,_presentParams.GetBackbufferHeight()) )
+				ResetD3DDevice
+			EndIf
+		EndIf
+	End Method
+	
+	'NOTE: Returns 1 if flip was successful, otherwise device lost or reset...
+	Method Flip:Int( sync:Int )
+	
+		Local reset:Int
+
+		If sync sync=D3DPRESENT_INTERVAL_ONE Else sync=D3DPRESENT_INTERVAL_IMMEDIATE
+		If sync<>_presentParams.GetPresentationInterval()
+			_presentParams.SetPresentationInterval(sync)
+			reset=True
+		EndIf
+		
+		Select _d3dDev.TestCooperativeLevel()
+		Case D3DERR_DRIVERINTERNALERROR
+			Throw "D3D Internal Error"
+		Case D3D_OK
+			If reset
+
+				ResetD3DDevice
+
+			Else If _attached
+			
+				Local rect:Int[]=[0,0,_width,_height]
+				Return _d3dDev.Present( rect,rect,_hwnd,Null )>=0
+
+			Else
+
+				Return _d3dDev.Present( Null,Null,_hwnd,Null )>=0
+
+			EndIf
+		Case D3DERR_DEVICENOTRESET
+
+			ResetD3DDevice
+
+		End Select
+		
+		
+	End Method
+
+	Method Driver:TGraphicsDriver()
+		Return _driver
+	End Method
+	
+	Method GetSettings:Int( width:Int Var,height:Int Var,depth:Int Var,hertz:Int Var,flags:Int Var )
+		'
+		ValidateSize
+		'
+		_g.GetSettings(width, height, depth, hertz, flags)
+	End Method
+
+	Method Close:Int()
+		If Not _hwnd Return False
+		CloseD3DDevice
+		If Not _attached Then
+			_g.Close()
+		End If
+		_hwnd=0
+	End Method
+
+	Method AutoRelease( unk:IUnknown )
+		Local t:TD3D9AutoRelease=New TD3D9AutoRelease
+		t.unk=unk
+		_autoRelease.AddLast t
+	End Method
+	
+	Method ReleaseNow( unk:IUnknown )
+		For Local t:TD3D9AutoRelease=EachIn _autoRelease
+			If t.unk=unk
+				unk.Release_
+				_autoRelease.Remove t
+				Return
+			EndIf
+		Next
+	End Method
+
+	
+	Field _hwnd:Byte Ptr
+	
+	Field _width:Int
+	Field _height:Int
+	Field _depth:Int
+	Field _hertz:Int
+	Field _flags:Int
+	Field _attached:Int
+	
+	Field _g:TSDLGraphics
+
+End Type
+
+Type TD3D9SDLGraphicsDriver Extends TGraphicsDriver
+
+	Method Create:TD3D9SDLGraphicsDriver()
+	
+		'create d3d9
+		'If Not d3d9Lib Return Null
+		
+		_d3d=Direct3DCreate9( 32 )
+		If Not _d3d Return Null
+
+		'get caps
+		_d3dCaps=New D3DCAPS9
+		If _d3d.GetDeviceCaps( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,_d3dCaps )<0
+			_d3d.Release_
+			_d3d=Null
+			Return Null
+		EndIf
+
+		'enum graphics modes		
+		Local n:Int=_d3d.GetAdapterModeCount( D3DADAPTER_DEFAULT,D3DFMT_X8R8G8B8 )
+		_modes=New TGraphicsMode[n]
+		Local j:Int
+		Local d3dmode:D3DDISPLAYMODE = New D3DDISPLAYMODE
+		For Local i:Int=0 Until n
+			If _d3d.EnumAdapterModes( D3DADAPTER_DEFAULT,D3DFMT_X8R8G8B8,i,d3dmode )<0
+				Continue
+			EndIf
+			
+			Local Mode:TGraphicsMode=New TGraphicsMode
+			Mode.width=d3dmode.GetWidth()
+			Mode.height=d3dmode.GetHeight()
+			Mode.hertz=d3dmode.GetRefreshRate()
+			Mode.depth=32
+			_modes[j]=Mode
+			j:+1
+		Next
+		_modes=_modes[..j]
+	
+	
+'		Local name:Short Ptr = _wndClass.ToWString()
+'		'register wndclass
+'		Local wndclass:WNDCLASSW=New WNDCLASSW
+'		wndclass.SethInstance(GetModuleHandleW( Null ))
+'		wndclass.SetlpfnWndProc(D3D9WndProc)
+'		wndclass.SethCursor(LoadCursorW( Null,Short Ptr IDC_ARROW ))
+'		wndclass.SetlpszClassName(name)
+'		RegisterClassW wndclass.classPtr
+'		MemFree name
+
+		Return Self
+	End Method
+	
+	Method GraphicsModes:TGraphicsMode[]()
+		Return _modes
+	End Method
+	
+	Method AttachGraphics:TD3D9SDLGraphics( widget:Byte Ptr,flags:Int )
+		Return New TD3D9SDLGraphics.Attach( widget:Byte Ptr,flags:Int )
+	End Method
+	
+	Method CreateGraphics:TD3D9SDLGraphics( width:Int,height:Int,depth:Int,hertz:Int,flags:Int)
+		Return New TD3D9SDLGraphics.Create( width,height,depth,hertz,flags )
+	End Method
+
+	Method Graphics:TD3D9SDLGraphics()
+		Return _graphics
+	End Method
+		
+	Method SetGraphics( g:TGraphics )
+		_graphics=TD3D9SDLGraphics( g )
+	End Method
+	
+	Method Flip( sync:Int )
+		Local present:Int = _graphics.Flip(sync)
+		If UseDX9RenderLagFix Then
+			Local pixelsdrawn:Int
+			If _d3dOccQuery
+				_d3dOccQuery.Issue(1) 'D3DISSUE_END
+				
+				While _d3dOccQuery.GetData( Varptr pixelsdrawn,4,1 )=1 'D3DGETDATA_FLUSH
+					If  _d3dOccQuery.GetData( Varptr pixelsdrawn,4,1 )<0 Exit
+				Wend
+
+				_d3dOccQuery.Issue(2) 'D3DISSUE_BEGIN
+			EndIf
+		End If
+		
+		Return present
+	End Method
+	
+	Method GetDirect3D:IDirect3D9()
+		Return _d3d
+	End Method
+	
+End Type
+
+Function D3D9SDLGraphicsDriver:TD3D9SDLGraphicsDriver()
+	Global _done:Int
+	If Not _done
+		_driver=New TD3D9SDLGraphicsDriver.Create()
+		_done=True
+	EndIf
+	Return _driver
+End Function
+
+?

+ 655 - 0
d3d9sdlmax2d.mod/d3d9sdlmax2d.bmx

@@ -0,0 +1,655 @@
+
+Strict
+
+Rem
+bbdoc: Direct3D9 Max2D with SDL backend
+about:
+The Direct3D9 Max2D module provides a Direct3D9 driver for #Max2D.
+End Rem
+Module SDL.D3D9SDLMax2D
+
+ModuleInfo "Version: 1.00"
+ModuleInfo "License: zlib/libpng"
+ModuleInfo "Copyright: Blitz Research Ltd, Bruce A Henderson"
+
+ModuleInfo "History: 1.0"
+ModuleInfo "History: Port to bmx-ng."
+
+?win32
+
+Import BRL.Max2D
+Import SDL.D3D9SDLGraphics
+
+Const LOG_ERRS=True'False
+
+Private
+
+Global _gw,_gh,_gd,_gr,_gf
+Global _color
+Global _clscolor
+Global _ix#,_iy#,_jx#,_jy#
+Global _fverts#[24]
+Global _iverts:Int Ptr=Int Ptr( Varptr _fverts[0] )
+Global _lineWidth#
+
+Global _bound_texture:IDirect3DTexture9
+Global _texture_enabled
+
+Global _active_blend
+
+Global _driver:TD3D9SDLMax2DDriver
+Global _d3dDev:IDirect3DDevice9
+Global _d3d9Graphics:TD3D9SDLGraphics
+Global _max2dGraphics:TMax2dGraphics
+
+Function Pow2Size( n )
+	Local t=1
+	While t<n
+		t:*2
+	Wend
+	Return t
+End Function
+
+Function DisableTex()
+	If Not _texture_enabled Return
+	_d3dDev.SetTextureStageState 0,D3DTSS_COLOROP,D3DTOP_SELECTARG2
+	_d3dDev.SetTextureStageState 0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2
+	_texture_enabled=False
+End Function
+
+Function d3derr( str$ )
+	If LOG_ERRS WriteStdout "D3DERR: "+str+"~n"
+End Function
+
+Public
+
+Type TD3D9ImageFrame Extends TImageFrame
+
+	Method Delete()
+		If _texture
+			If _seq=GraphicsSeq
+				If _texture=_bound_texture
+					_d3dDev.SetTexture 0,Null
+					_bound_texture=Null
+				EndIf
+				_d3d9Graphics.ReleaseNow _texture
+			EndIf
+			_texture=Null
+		EndIf
+	End Method
+
+	Method Create:TD3D9ImageFrame( pixmap:TPixmap,flags )
+
+		Local width=pixmap.width,pow2width=Pow2Size( width )
+		Local height=pixmap.height,pow2height=Pow2Size( height )
+		
+		If width<pow2width Or height<pow2height
+			Local src:TPixmap=pixmap
+			pixmap=TPixmap.Create( pow2width,pow2height,PF_BGRA8888 )
+			pixmap.Paste src,0,0
+			If width<pow2width
+				pixmap.Paste pixmap.Window( width-1,0,1,height ),width,0
+			EndIf
+			If height<pow2height
+				pixmap.Paste pixmap.Window( 0,height-1,width,1 ),0,height
+				If width<pow2width 
+					pixmap.Paste pixmap.Window( width-1,height-1,1,1 ),width,height
+				EndIf
+			EndIf
+		Else
+			If pixmap.Format<>PF_BGRA8888 pixmap=pixmap.Convert( PF_BGRA8888 )
+		EndIf
+
+		Local levels=(flags & MIPMAPPEDIMAGE)=0
+		Local format=D3DFMT_A8R8G8B8
+		Local usage=0
+		Local pool=D3DPOOL_MANAGED
+		
+		_texture = New IDirect3DTexture9
+		If _d3dDev.CreateTexture( pow2width,pow2height,levels,usage,format,pool,_texture,Null )<0
+			d3derr "Unable to create texture~n"
+			_texture = Null
+			Return
+		EndIf
+		
+		_d3d9Graphics.AutoRelease _texture
+
+		Local level
+		Local dstsurf:IDirect3DSurface9 = New IDirect3DSurface9
+		Repeat
+			If _texture.GetSurfaceLevel( level,dstsurf )<0
+				If level=0
+					d3derr "_texture.GetSurfaceLevel failed~n"
+				EndIf
+				Exit
+			EndIf
+
+			Local lockedrect:D3DLOCKED_RECT=New D3DLOCKED_RECT
+			If dstsurf.LockRect( lockedrect,Null,0 )<0
+				d3derr "dstsurf.LockRect failed~n"
+			EndIf
+		
+			For Local y=0 Until pixmap.height
+				Local src:Byte Ptr=pixmap.pixels+y*pixmap.pitch
+				Local dst:Byte Ptr=lockedrect.pBits+y*lockedrect.Pitch
+				MemCopy dst,src,pixmap.width*4
+			Next
+		
+			dstsurf.UnlockRect
+			dstsurf.Release_
+			
+			If (flags & MIPMAPPEDIMAGE)=0 Exit
+
+			level:+1
+
+			If pixmap.width>1 And pixmap.height>1
+				pixmap=ResizePixmap( pixmap,pixmap.width/2,pixmap.height/2 )
+			Else If pixmap.width>1
+				pixmap=ResizePixmap( pixmap,pixmap.width/2,pixmap.height )
+			Else If pixmap.height>1
+				pixmap=ResizePixmap( pixmap,pixmap.width,pixmap.height/2 )
+			EndIf
+		Forever
+		
+		_uscale=1.0/pow2width
+		_vscale=1.0/pow2height
+
+		Local u0#,u1#=width * _uscale
+		Local v0#,v1#=height * _vscale
+
+		_fverts[4]=u0
+		_fverts[5]=v0
+		_fverts[10]=u1
+		_fverts[11]=v0
+		_fverts[16]=u1
+		_fverts[17]=v1
+		_fverts[22]=u0
+		_fverts[23]=v1
+		
+		If flags & FILTEREDIMAGE
+			_magfilter=D3DTFG_LINEAR
+			_minfilter=D3DTFG_LINEAR
+			_mipfilter=D3DTFG_LINEAR
+		Else
+			_magfilter=D3DTFG_POINT
+			_minfilter=D3DTFG_POINT
+			_mipfilter=D3DTFG_POINT
+		EndIf
+		
+		_seq=GraphicsSeq
+		
+		Return Self
+	End Method
+	
+	Method Draw( x0#,y0#,x1#,y1#,tx#,ty#,sx#,sy#,sw#,sh# )
+		Local u0#=sx * _uscale
+		Local v0#=sy * _vscale
+		Local u1#=(sx+sw) * _uscale
+		Local v1#=(sy+sh) * _vscale
+	
+		_fverts[0]=x0*_ix+y0*_iy+tx
+		_fverts[1]=x0*_jx+y0*_jy+ty
+		_iverts[3]=_color
+		_fverts[4]=u0
+		_fverts[5]=v0
+		
+		_fverts[6]=x1*_ix+y0*_iy+tx
+		_fverts[7]=x1*_jx+y0*_jy+ty
+		_iverts[9]=_color
+		_fverts[10]=u1
+		_fverts[11]=v0
+		
+		_fverts[12]=x1*_ix+y1*_iy+tx
+		_fverts[13]=x1*_jx+y1*_jy+ty
+		_iverts[15]=_color
+		_fverts[16]=u1
+		_fverts[17]=v1
+		
+		_fverts[18]=x0*_ix+y1*_iy+tx
+		_fverts[19]=x0*_jx+y1*_jy+ty
+		_iverts[21]=_color
+		_fverts[22]=u0
+		_fverts[23]=v1
+		
+		If _texture<>_bound_texture
+			_d3dDev.SetTexture 0,_texture
+			_d3dDev.SetTextureStageState 0,D3DTSS_MAGFILTER,_magfilter
+			_d3dDev.SetTextureStageState 0,D3DTSS_MINFILTER,_minfilter
+			_d3dDev.SetTextureStageState 0,D3DTSS_MIPFILTER,_mipfilter
+			_bound_texture=_texture
+		EndIf
+		
+		If Not _texture_enabled
+			_d3dDev.SetTextureStageState 0,D3DTSS_COLOROP,D3DTOP_MODULATE
+			_d3dDev.SetTextureStageState 0,D3DTSS_ALPHAOP,D3DTOP_MODULATE
+			_texture_enabled=True
+		EndIf
+		
+		_d3dDev.DrawPrimitiveUP D3DPT_TRIANGLEFAN,2,_fverts,24
+	End Method
+	
+	Field _texture:IDirect3DTexture9,_seq
+	
+	Field _magfilter,_minfilter,_mipfilter,_uscale#,_vscale#
+	
+	Field _fverts#[24],_iverts:Int Ptr=Int Ptr( Varptr _fverts[0] )
+
+End Type
+
+Type TD3D9SDLMax2DDriver Extends TMax2dDriver
+
+	Method ToString$()
+		Return "DirectX9"
+	End Method
+
+	Method Create:TD3D9SDLMax2DDriver()
+
+		If Not D3D9SDLGraphicsDriver() Return Null
+
+		Local d3d:IDirect3D9=D3D9SDLGraphicsDriver().GetDirect3D()
+
+		If d3d.CheckDeviceFormat( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,D3DFMT_X8R8G8B8,0,D3DRTYPE_TEXTURE,D3DFMT_A8R8G8B8 )<0
+			Return Null
+		EndIf
+
+		Return Self
+	End Method
+
+	'***** TGraphicsDriver *****
+	Method GraphicsModes:TGraphicsMode[]()
+		Return D3D9SDLGraphicsDriver().GraphicsModes()
+	End Method
+	
+	Method AttachGraphics:TGraphics( widget:Byte Ptr,flags )
+		Local g:TD3D9SDLGraphics=D3D9SDLGraphicsDriver().AttachGraphics( widget,flags )
+		If g Return TMax2DGraphics.Create( g,Self )
+	End Method
+	
+	Method CreateGraphics:TGraphics( width,height,depth,hertz,flags )
+		Local g:TD3D9SDLGraphics=D3D9SDLGraphicsDriver().CreateGraphics( width,height,depth,hertz,flags )
+		If Not g Return Null
+		Return TMax2DGraphics.Create( g,Self )
+	End Method
+	
+	Method SetGraphics( g:TGraphics )
+
+		If Not g
+			If _d3dDev
+				_d3dDev.EndScene
+				_d3dDev=Null
+			EndIf
+			_d3d9graphics=Null
+			_max2dGraphics=Null
+			TMax2DGraphics.ClearCurrent
+			D3D9SDLGraphicsDriver().SetGraphics Null
+			Return
+		EndIf
+
+		_max2dGraphics=TMax2dGraphics( g )
+
+		_d3d9graphics=TD3D9SDLGraphics( _max2dGraphics._graphics )
+
+		If Not _max2dGraphics Or Not _d3d9graphics Then
+			Throw "SetGraphics failed for D3D9"
+		End If
+
+		_d3dDev=_d3d9Graphics.GetDirect3DDevice()
+		
+		D3D9SDLGraphicsDriver().SetGraphics _d3d9Graphics
+
+		If _d3dDev.TestCooperativeLevel()<>D3D_OK Return
+		
+		ResetDevice
+
+		_max2dGraphics.MakeCurrent
+		
+	End Method
+	
+	Method Flip( sync )
+		_d3dDev.EndScene
+		If D3D9SDLGraphicsDriver().Flip( sync )
+			_d3dDev.BeginScene
+		Else If _d3dDev.TestCooperativeLevel()=D3D_OK
+			ResetDevice
+			_max2dGraphics.MakeCurrent
+		EndIf
+
+	End Method
+	
+	Method ResetDevice()
+		_d3d9graphics.ValidateSize
+		_d3d9graphics.GetSettings _gw,_gh,_gd,_gr,_gf
+	
+		Local viewport:D3DVIEWPORT9=New D3DVIEWPORT9
+		viewport.SetX(0)
+		viewport.SetY(0)
+		viewport.SetWidth(_gw)
+		viewport.SetHeight(_gh)
+		viewport.SetMinZ(0.0)
+		viewport.SetMaxZ(1.0)
+		_d3dDev.SetViewport viewport
+
+		_d3dDev.SetRenderState D3DRS_ALPHAREF,$80
+		_d3dDev.SetRenderState D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL
+
+		_d3dDev.SetRenderState D3DRS_ALPHATESTENABLE,False
+		_d3dDev.SetRenderState D3DRS_ALPHABLENDENABLE,False
+		_active_blend=SOLIDBLEND
+		
+		_d3dDev.SetRenderState D3DRS_LIGHTING,False
+		_d3dDev.SetRenderState D3DRS_CULLMODE,D3DCULL_NONE	
+		
+		_d3dDev.SetTexture 0,Null
+		_bound_texture=Null
+
+		_d3dDev.SetFVF D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1
+		
+		_d3dDev.SetTextureStageState 0,D3DTSS_COLORARG1,D3DTA_TEXTURE		
+		_d3dDev.SetTextureStageState 0,D3DTSS_COLORARG2,D3DTA_DIFFUSE		
+		_d3dDev.SetTextureStageState 0,D3DTSS_COLOROP,D3DTOP_SELECTARG2
+		_d3dDev.SetTextureStageState 0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE
+		_d3dDev.SetTextureStageState 0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE
+		_d3dDev.SetTextureStageState 0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2
+		_texture_enabled=False
+		
+		_d3dDev.SetTextureStageState 0,D3DTSS_ADDRESS,D3DTADDRESS_CLAMP
+	
+		_d3dDev.SetTextureStageState 0,D3DTSS_MAGFILTER,D3DTFG_POINT
+		_d3dDev.SetTextureStageState 0,D3DTSS_MINFILTER,D3DTFN_POINT
+		_d3dDev.SetTextureStageState 0,D3DTSS_MIPFILTER,D3DTFP_POINT
+		
+		_d3dDev.BeginScene
+
+	End Method
+
+	'***** TMax2DDriver *****
+	Method CreateFrameFromPixmap:TImageFrame( pixmap:TPixmap,flags )
+		Return New TD3D9ImageFrame.Create( pixmap,flags )
+	End Method
+	
+	Method SetBlend( blend )
+		If blend=_active_blend Return
+		Select blend
+		Case SOLIDBLEND
+			_d3dDev.SetRenderState D3DRS_ALPHATESTENABLE,False
+			_d3dDev.SetRenderState D3DRS_ALPHABLENDENABLE,False
+		Case MASKBLEND
+			_d3dDev.SetRenderState D3DRS_ALPHATESTENABLE,True
+			_d3dDev.SetRenderState D3DRS_ALPHABLENDENABLE,False
+		Case ALPHABLEND
+			_d3dDev.SetRenderState D3DRS_ALPHATESTENABLE,False
+			_d3dDev.SetRenderState D3DRS_ALPHABLENDENABLE,True
+			_d3dDev.SetRenderState D3DRS_SRCBLEND,D3DBLEND_SRCALPHA
+			_d3dDev.SetRenderState D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA
+		Case LIGHTBLEND
+			_d3dDev.SetRenderState D3DRS_ALPHATESTENABLE,False
+			_d3dDev.SetRenderState D3DRS_ALPHABLENDENABLE,True
+			_d3dDev.SetRenderState D3DRS_SRCBLEND,D3DBLEND_SRCALPHA
+			_d3dDev.SetRenderState D3DRS_DESTBLEND,D3DBLEND_ONE
+		Case SHADEBLEND		
+			_d3dDev.SetRenderState D3DRS_ALPHATESTENABLE,False
+			_d3dDev.SetRenderState D3DRS_ALPHABLENDENABLE,True
+			_d3dDev.SetRenderState D3DRS_SRCBLEND,D3DBLEND_ZERO
+			_d3dDev.SetRenderState D3DRS_DESTBLEND,D3DBLEND_SRCCOLOR
+		End Select
+		_active_blend=blend
+	End Method
+	
+	Method SetAlpha( alpha# )
+		alpha=Max(Min(alpha,1),0)
+		_color=(Int(255*alpha) Shl 24)|(_color&$ffffff)
+		_iverts[3]=_color
+		_iverts[9]=_color
+		_iverts[15]=_color
+		_iverts[21]=_color
+	End Method
+	
+	Method SetColor( red,green,blue )
+		red=Max(Min(red,255),0)
+		green=Max(Min(green,255),0)
+		blue=Max(Min(blue,255),0)
+		_color=(_color&$ff000000)|(red Shl 16)|(green Shl 8)|blue		
+		_iverts[3]=_color
+		_iverts[9]=_color
+		_iverts[15]=_color
+		_iverts[21]=_color
+	End Method
+	
+	Method SetClsColor( red,green,blue )
+		red=Max(Min(red,255),0)
+		green=Max(Min(green,255),0)
+		blue=Max(Min(blue,255),0)
+		_clscolor=$ff000000|(red Shl 16)|(green Shl 8)|blue
+	End Method
+	
+	Method SetViewport( x,y,width,height )
+		If x=0 And y=0 And width=_gw And height=_gh 'GraphicsWidth() And height=GraphicsHeight()
+			_d3dDev.SetRenderState D3DRS_SCISSORTESTENABLE,False
+		Else
+			_d3dDev.SetRenderState D3DRS_SCISSORTESTENABLE,True
+			Local rect[]=[x,y,x+width,y+height]
+			_d3dDev.SetScissorRect rect
+		EndIf
+	End Method
+	
+	Method SetTransform( xx#,xy#,yx#,yy# )
+		_ix=xx
+		_iy=xy
+		_jx=yx
+		_jy=yy		
+	End Method
+	
+	Method SetLineWidth( width# )
+		_lineWidth=width
+	End Method
+	
+	Method Cls()
+		_d3dDev.Clear 0,Null,D3DCLEAR_TARGET,_clscolor,0,0
+	End Method
+	
+	Method Plot( x#,y# )
+		_fverts[0]=x+.5
+		_fverts[1]=y+.5
+		DisableTex
+		_d3dDev.DrawPrimitiveUP D3DPT_POINTLIST,1,_fverts,24
+	End Method
+	
+	Method DrawLine( x0#,y0#,x1#,y1#,tx#,ty# )
+		Local lx0# = x0*_ix + y0*_iy + tx
+		Local ly0# = x0*_jx + y0*_jy + ty
+		Local lx1# = x1*_ix + y1*_iy + tx
+		Local ly1# = x1*_jx + y1*_jy + ty
+		If _lineWidth<=1
+			_fverts[0]=lx0+.5
+			_fverts[1]=ly0+.5
+			_fverts[6]=lx1+.5
+			_fverts[7]=ly1+.5
+			DisableTex
+			_d3dDev.DrawPrimitiveUP D3DPT_LINELIST,1,_fverts,24
+			Return
+		EndIf
+		Local lw#=_lineWidth*.5
+		If Abs(ly1-ly0)>Abs(lx1-lx0)
+			_fverts[0]=lx0-lw
+			_fverts[1]=ly0
+			_fverts[6]=lx0+lw
+			_fverts[7]=ly0
+			_fverts[12]=lx1-lw
+			_fverts[13]=ly1
+			_fverts[18]=lx1+lw
+			_fverts[19]=ly1
+		Else
+			_fverts[0]=lx0
+			_fverts[1]=ly0-lw
+			_fverts[6]=lx0
+			_fverts[7]=ly0+lw
+			_fverts[12]=lx1
+			_fverts[13]=ly1-lw
+			_fverts[18]=lx1
+			_fverts[19]=ly1+lw
+		EndIf
+		DisableTex
+		_d3dDev.DrawPrimitiveUP D3DPT_TRIANGLESTRIP,2,_fverts,24
+	End Method
+	
+	Method DrawRect( x0#,y0#,x1#,y1#,tx#,ty# )
+		_fverts[0]  = x0*_ix + y0*_iy + tx
+		_fverts[1]  = x0*_jx + y0*_jy + ty
+		_fverts[6]  = x1*_ix + y0*_iy + tx
+		_fverts[7]  = x1*_jx + y0*_jy + ty
+		_fverts[12] = x0*_ix + y1*_iy + tx
+		_fverts[13] = x0*_jx + y1*_jy + ty
+		_fverts[18] = x1*_ix + y1*_iy + tx
+		_fverts[19] = x1*_jx + y1*_jy + ty
+		DisableTex
+		_d3dDev.DrawPrimitiveUP D3DPT_TRIANGLESTRIP,2,_fverts,24
+	End Method
+	
+	Method DrawOval( x0#,y0#,x1#,y1#,tx#,ty# )
+		Local xr#=(x1-x0)*.5
+		Local yr#=(y1-y0)*.5
+		Local segs=Abs(xr)+Abs(yr)
+		segs=Max(segs,12)&~3
+		x0:+xr
+		y0:+yr
+		Local fverts#[segs*6]
+		Local iverts:Int Ptr=Int Ptr( Varptr fverts[0] )
+		For Local i=0 Until segs
+			Local th#=-i*360#/segs
+			Local x#=x0+Cos(th)*xr
+			Local y#=y0-Sin(th)*yr
+			fverts[i*6+0]=x*_ix+y*_iy+tx
+			fverts[i*6+1]=x*_jx+y*_jy+ty			
+			iverts[i*6+3]=_color
+		Next
+		DisableTex
+		_d3dDev.DrawPrimitiveUP D3DPT_TRIANGLEFAN,segs-2,fverts,24
+	End Method
+	
+	Method DrawPoly( verts#[],handlex#,handley#,tx#,ty# )
+		If verts.length<6 Or (verts.length&1) Return
+		Local segs=verts.length/2
+		Local fverts#[segs*6]
+		Local iverts:Int Ptr=Int Ptr( Varptr fverts[0] )
+		For Local i=0 Until segs
+			Local x#=verts[i*2+0]+handlex
+			Local y#=verts[i*2+1]+handley
+			fverts[i*6+0]= x*_ix + y*_iy + tx
+			fverts[i*6+1]= x*_jx + y*_jy + ty
+			iverts[i*6+3]=_color
+		Next
+		DisableTex
+		_d3dDev.DrawPrimitiveUP D3DPT_TRIANGLEFAN,segs-2,fverts,24
+	End Method
+		
+	'GetDC/BitBlt MUCH faster than locking backbuffer!	
+	Method DrawPixmap( pixmap:TPixmap,x,y )
+		Local width=pixmap.width,height=pixmap.height
+	
+		Local dstsurf:IDirect3DSurface9 = New IDirect3DSurface9
+		If _d3dDev.GetRenderTarget( 0,dstsurf )<0
+			d3derr "GetRenderTarget failed~n"
+			Return
+		EndIf
+		
+		Local desc:D3DSURFACE_DESC=New D3DSURFACE_DESC
+		If dstsurf.GetDesc( desc )<0
+			d3derr "GetDesc failed~n"
+		EndIf
+		
+		Local rect[]=[x,y,x+width,y+height]
+		Local lockedrect:D3DLOCKED_RECT=New D3DLOCKED_RECT
+		If dstsurf.LockRect( lockedrect,rect,0 )<0
+			d3derr "Unable to lock render target surface~n"
+			dstsurf.Release_
+			Return
+		EndIf
+		
+		Local dstpixmap:TPixmap=CreateStaticPixmap( lockedrect.pBits,width,height,lockedrect.Pitch,PF_BGRA8888 );
+		
+		dstpixmap.Paste pixmap,0,0
+		
+		dstsurf.UnlockRect
+		dstsurf.Release_
+	End Method
+
+	'GetDC/BitBlt MUCH faster than locking backbuffer!	
+	Method GrabPixmap:TPixmap( x,y,width,height )
+	
+		Local srcsurf:IDirect3DSurface9
+		If _d3dDev.GetRenderTarget( 0,srcsurf )<0
+			d3derr "GetRenderTarget failed~n"
+		EndIf
+
+		Local dstsurf:IDirect3DSurface9
+		If _d3dDev.CreateOffscreenPlainSurface( width,height,D3DFMT_X8R8G8B8,D3DPOOL_SYSTEMMEM,dstsurf,Null )<0
+			d3derr "CreateOffscreenPlainSurface failed~n"
+		EndIf
+		
+		Local srcdc:Byte Ptr
+		If srcsurf.GetDC( srcdc )<0
+			d3derr "srcsurf.GetDC failed~n"
+		EndIf
+		
+		Local dstdc:Byte Ptr
+		If dstsurf.GetDC( dstdc )<0
+			d3derr "dstsurf.GetDC failed~n"
+		EndIf
+		
+		BitBlt dstdc,0,0,width,height,srcdc,x,y,ROP_SRCCOPY
+		
+		srcsurf.ReleaseDC srcdc
+		dstsurf.ReleaseDC dstdc
+		
+		Local lockedrect:D3DLOCKED_RECT=New D3DLOCKED_RECT
+		If dstsurf.LockRect( lockedrect,Null,D3DLOCK_READONLY )<0
+			d3derr "dstsurf.LockRect failed~n"
+		EndIf
+		
+		Local pixmap:TPixmap=CreatePixmap( width,height,PF_BGRA8888 )
+		
+		'Copy and set alpha in the process...
+		For Local y=0 Until height
+			Local src:Int Ptr=Int Ptr( lockedrect.pBits+y*lockedrect.Pitch )
+			Local dst:Int Ptr=Int Ptr( pixmap.PixelPtr( 0,y ) )
+			For Local x=0 Until width
+				dst[x]=src[x] | $ff000000
+			Next
+		Next
+		
+		srcsurf.Release_
+		dstsurf.Release_
+		
+		Return pixmap
+	End Method
+	
+	Method SetResolution( width#,height# )
+		Local matrix#[]=[..
+		2.0/width,0.0,0.0,0.0,..
+		 0.0,-2.0/height,0.0,0.0,..
+		 0.0,0.0,1.0,0.0,..
+		 -1-(1.0/width),1+(1.0/height),1.0,1.0]
+
+		_d3dDev.SetTransform D3DTS_PROJECTION,matrix
+	End Method
+	
+End Type
+
+Rem
+bbdoc: Get Direct3D9 SDL Max2D Driver
+about:
+The returned driver can be used with #SetGraphicsDriver to enable Direct3D9 Max2D rendering.
+End Rem
+Function D3D9SDLMax2DDriver:TD3D9SDLMax2DDriver()
+	Global _done
+	If Not _done
+		_driver=New TD3D9SDLMax2DDriver.Create()
+		_done=True
+	EndIf
+	Return _driver
+End Function
+
+Local driver:TD3D9SDLMax2DDriver=D3D9SDLMax2DDriver()
+If driver SetGraphicsDriver driver
+
+?

+ 3 - 1
sdlgraphics.mod/common.bmx

@@ -69,6 +69,7 @@ Extern
 	Function bbSDLGraphicsSetGraphics( context:Byte Ptr )
 	Function bbSDLGraphicsFlip( sync:Int )
 	Function bbSDLExit()
+	Function bbSDLGraphicsGetHandle:Byte Ptr(context:Byte Ptr)
 	
 	Function SDL_GetNumVideoDisplays:Int()
 	
@@ -108,4 +109,5 @@ Const SDL_WINDOW_FULLSCREEN_DESKTOP:Int = SDL_WINDOW_FULLSCREEN | $00001000
 Const SDL_WINDOW_FOREIGN:Int = $00000800            ' window Not created by SDL
 Const SDL_WINDOW_ALLOW_HIGHDPI:Int = $00002000       ' window should be created in high-DPI Mode If supported
 
-Const GRAPHICS_RPI_TV_FULLSCREEN:Int = $1000
+Const GRAPHICS_RPI_TV_FULLSCREEN:Int = $1000
+Const GRAPHICS_WIN32_DX:Int = $1000000

+ 28 - 7
sdlgraphics.mod/glue.c

@@ -23,6 +23,7 @@
 
 #include "SDL_video.h"
 #include "SDL_mouse.h"
+#include "SDL_syswm.h"
 
 #include <brl.mod/blitz.mod/blitz.h>
 
@@ -41,6 +42,7 @@ enum{
 	FLAGS_ACCUMBUFFER   = 0x20,
 	FLAGS_BORDERLESS    = 0x40,
 	FLAGS_RPI_TV_FULLSCREEN = 0x1000,
+	FLAGS_DX            = 0x1000000,
 	FLAGS_FULLSCREEN    = 0x80000000
 };
 
@@ -50,6 +52,7 @@ struct BBSDLContext{
 	int mode,width,height,depth,hertz,flags,sync;
 	SDL_Window * window;
 	SDL_GLContext context;
+	SDL_SysWMinfo info;
 };
 
 
@@ -60,6 +63,7 @@ void bbSDLGraphicsGetSettings( BBSDLContext *context, int * width,int * height,i
 void bbSDLGraphicsClose( BBSDLContext *context );
 void bmx_SDL_Poll();
 void bmx_SDL_WaitEvent();
+void * bbSDLGraphicsGetHandle(BBSDLContext *context);
 
 #ifdef __RASPBERRYPI__
 void bmx_tvservice_get_closest_mode(int width, int height, int framerate, int * mode, int * group);
@@ -90,7 +94,11 @@ BBSDLContext *bbSDLGraphicsCreateGraphics( int width,int height,int depth,int hz
 	int mode;
 	char * appTitle = bbStringToUTF8String( bbAppTitle );
 	
-	int windowFlags = SDL_WINDOW_OPENGL;
+	int windowFlags = 0;
+
+	if ((flags & FLAGS_DX) == 0) {
+		windowFlags = SDL_WINDOW_OPENGL;
+	}
 	
 	if (flags & FLAGS_BORDERLESS) windowFlags |= SDL_WINDOW_BORDERLESS;
 	
@@ -104,10 +112,12 @@ BBSDLContext *bbSDLGraphicsCreateGraphics( int width,int height,int depth,int hz
 		mode=MODE_WINDOW;
 	}
 
-	if (flags & FLAGS_BACKBUFFER) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-	if (flags & FLAGS_ALPHABUFFER) SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1);
-	if (flags & FLAGS_DEPTHBUFFER) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
-	if (flags & FLAGS_STENCILBUFFER) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
+	if ((flags & FLAGS_DX) == 0) {
+		if (flags & FLAGS_BACKBUFFER) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+		if (flags & FLAGS_ALPHABUFFER) SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1);
+		if (flags & FLAGS_DEPTHBUFFER) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+		if (flags & FLAGS_STENCILBUFFER) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
+	}
 
 #ifdef __RASPBERRYPI__
 	int rpi_mode;
@@ -127,9 +137,13 @@ printf("error... %s\n", SDL_GetError());fflush(stdout);
 		return NULL;
 	}
 
-	SDL_GL_SetSwapInterval(-1);
+	SDL_GLContext context = 0;
+	
+	if ((flags & FLAGS_DX) == 0) {
+		SDL_GL_SetSwapInterval(-1);
 	
-	SDL_GLContext context = SDL_GL_CreateContext(window);
+		context = SDL_GL_CreateContext(window);
+	}
 
 	BBSDLContext *bbcontext=(BBSDLContext*)malloc( sizeof(BBSDLContext) );
 	memset( bbcontext,0,sizeof(BBSDLContext) );
@@ -146,6 +160,7 @@ printf("error... %s\n", SDL_GetError());fflush(stdout);
 	bbcontext->sync=-1;	
 	bbcontext->window=window;
 	bbcontext->context=context;
+	SDL_GetWindowWMInfo(window, &bbcontext->info);
 	return bbcontext;
 
 }
@@ -214,3 +229,9 @@ void bbSDLExit(){
 #endif
 }
 
+void * bbSDLGraphicsGetHandle(BBSDLContext *context) {
+#ifdef _WIN32
+	return context->info.info.win.window;
+#endif
+	return 0;
+}

+ 6 - 0
sdlgraphics.mod/sdlgraphics.bmx

@@ -62,6 +62,12 @@ Type TSDLGraphics Extends TGraphics
 		bbSDLGraphicsClose( _context )
 		_context=0
 	End Method
+
+	Method GetHandle:Byte Ptr()
+		If _context Then
+			Return bbSDLGraphicsGetHandle(_context)
+		End If
+	End Method
 	
 	Field _context:Byte Ptr