Here is an example of how to tie in recovery for an invalid render device with changing the display resolution. This is useful for windowed applications that want to reset the device resolution after resizing the window.
This example also demonstrates how to safely handle rendering in a thread and also how to maintain a given aspect ratio when altering the device resolution.
Code: Select all
Structure Glob_Globstruct
RenderThreadID.i
ProgramEnding.l
PauseThread.l
DefaultAspectRatio.f
DefaultFOV.f
MaxFOV.f
EndStructure
Global Glob_Globstruct.Glob_Globstruct
Declare WinCallback(hWnd, uMsg, wParam, lParam)
Declare D3DDeviceLost()
Declare D3DDeviceReset()
Declare GDKRenderThread(Null)
ExamineDesktops()
Procedure WinCallback(hWnd, uMsg, wParam, lParam)
Static OldWidth.l, OldHeight.l, FirstRun
Protected NewWidth.l, NewHeight.l
If Not FirstRun
OldWidth=WindowWidth(1)
OldHeight=WindowHeight(1)
FirstRun=1
EndIf
Select uMsg
Case #WM_ERASEBKGND
;/ Don't erase the background to elminate resize flickering
ProcedureReturn 1
Case #WM_SIZING, #WM_WINDOWPOSCHANGING, #WM_SIZE, #WM_WINDOWPOSCHANGED
dbSetWindowSize(WindowWidth(1),WindowHeight(1))
Case #WM_EXITSIZEMOVE
;/ Handle window resizing
If InterlockedCompareExchange_(@Glob_Globstruct\PauseThread,1,0)=0
NewWidth=WindowWidth(1)
NewHeight=WindowHeight(1)
If ((Not NewWidth=OldWidth) Or (Not OldHeight=NewHeight)) And NewWidth>0 And NewHeight>0
Repeat: Delay(1)
Until Glob_Globstruct\PauseThread=2
dbSetDisplayMode(NewWidth,NewHeight)
D3DDeviceReset()
OldWidth=NewWidth
OldHeight=NewHeight
;/ Reset camera aspect ratio
DefaultAspectRatio=Glob_Globstruct\DefaultAspectRatio
DefaultFOV=Glob_Globstruct\DefaultFOV
MaxFOV=Glob_Globstruct\MaxFOV
AspectRatio.f=(NewWidth*DefaultAspectRatio)/(NewHeight*DefaultAspectRatio)
FOV.f=MaxFOV-(AspectRatio.f*100.0)
If FOV.f<DefaultFOV
FOV.f=DefaultFOV
EndIf
If FOV.f>MaxFOV
FOV.f=MaxFOV
EndIf
dbSetCameraAspect(AspectRatio.f,dbCurrentCamera())
dbSetCameraFOV(FOV.f,dbCurrentCamera())
EndIf
;/ Set PauseThread to 0
InterlockedExchange_(@Glob_Globstruct\PauseThread,0)
EndIf
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure D3DDeviceLost()
;/ Notify the render thread that the render device has been lost
If Not Glob_Globstruct\PauseThread
InterlockedExchange_(@Glob_Globstruct\PauseThread,1)
EndIf
EndProcedure
Procedure D3DDeviceReset()
;/ Wait until the render thread is ready for the device to be reset
Repeat: Delay(1)
Until InterlockedCompareExchange_(@Glob_Globstruct\PauseThread,3,2)=2
;/ Reload project data here
dbMakeObjectCube(1,3)
dbScaleObject(1,88,88,88)
dbColorBackdrop(RGB(Random(255),Random(255),Random(255)))
;/ Set PauseThread to 0
InterlockedExchange_(@Glob_Globstruct\PauseThread,0)
EndProcedure
Procedure GDKRenderThread(Null)
Repeat
Delay(1) ;/ Don't use all of the cpu
dbXRotateObject(1,dbWrapValue(dbObjectAngleX(1)+0.3))
dbYRotateObject(1,dbWrapValue(dbObjectAngleY(1)+0.5))
;/ Render the backbuffer
dbSync()
;/ Check for suspend notificatons
If InterlockedCompareExchange_(@Glob_Globstruct\PauseThread,2,1)=1
Repeat: Delay(1)
dbSync()
Until Not Glob_Globstruct\PauseThread
EndIf
Until Glob_Globstruct\ProgramEnding
EndProcedure
;/ Show the PureGDK render window
OpenWindow(0,0,0,640,480,"DarkBasic Professional - PureGDK",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
MDIGadget(0,0,0,640,480,0,0)
AddGadgetItem(0,1,"Render window",0,#PB_Window_TitleBar|#PB_Window_SizeGadget)
hDBWnd=OpenDBWnd(WindowID(1),0,0,WindowWidth(1),WindowHeight(1))
;/ Set the default aspect ratio and FOV
Glob_Globstruct\DefaultAspectRatio=640.0/480.0
Glob_Globstruct\DefaultFOV=61.9621391296
Glob_Globstruct\MaxFOV=164.0
;/ Set the window callback for window 0
SetWindowCallback(@WinCallback(),1)
;/ Set D3D device callbacks
dbSetD3DDeviceCallback(@D3DDeviceLost(),#GDK_Callback_DeviceLost)
dbSetD3DDeviceCallback(@D3DDeviceReset(),#GDK_Callback_DeviceReset)
;/ Load media
dbMakeObjectCube(1,3)
dbScaleObject(1,88,88,88)
dbColorBackdrop(RGB(0,0,0))
;/ Create render thread
Glob_Globstruct\RenderThreadID=CreateThread(@GDKRenderThread(),0)
;/ Program loop
Repeat
Event=WaitWindowEvent()
Until Event=#PB_Event_CloseWindow ;Or dbKeyState(#VK_ESCAPE)
;/ Cleanup
Glob_Globstruct\ProgramEnding=1
WaitThread(Glob_Globstruct\RenderThreadID)
End