d3d9graphics.bmx 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. Strict
  2. Import BRL.Graphics
  3. Import Pub.DirectX
  4. Import BRL.LinkedList
  5. Private
  6. Global _wndClass$="BBDX9Device Window Class"
  7. Global _driver:TD3D9graphicsDriver
  8. Global _d3d:IDirect3D9
  9. Global _d3dCaps:D3DCAPS9
  10. Global _modes:TGraphicsMode[]
  11. Global _d3dDev:IDirect3DDevice9
  12. Global _d3dDevRefs
  13. Global _presentParams:D3DPRESENT_PARAMETERS
  14. Global _graphics:TD3D9Graphics
  15. Global _autoRelease:TList
  16. Type TD3D9AutoRelease
  17. Field unk:IUnknown
  18. End Type
  19. Function D3D9WndProc( hwnd,msg,wp,lp ) "win32"
  20. bbSystemEmitOSEvent hwnd,msg,wp,lp,Null
  21. Select msg
  22. Case WM_CLOSE
  23. Return
  24. Case WM_SYSKEYDOWN
  25. If wp<>KEY_F4 Return
  26. End Select
  27. Return DefWindowProcW( hwnd,msg,wp,lp )
  28. End Function
  29. Function OpenD3DDevice( hwnd,width,height,depth,hertz,flags )
  30. If _d3dDevRefs
  31. If Not _presentParams.Windowed Return False
  32. If depth<>0 Return False
  33. _d3dDevRefs:+1
  34. Return True
  35. EndIf
  36. Local windowed=(depth=0)
  37. Local fullscreen=(depth<>0)
  38. Local pp:D3DPRESENT_PARAMETERS=New D3DPRESENT_PARAMETERS
  39. pp.BackBufferWidth=width
  40. pp.BackBufferHeight=height
  41. pp.BackBufferCount=1
  42. pp.BackBufferFormat=(D3DFMT_X8R8G8B8 * fullscreen) + (D3DFMT_UNKNOWN * windowed)
  43. pp.MultiSampleType=D3DMULTISAMPLE_NONE
  44. pp.SwapEffect=(D3DSWAPEFFECT_DISCARD * fullscreen) + (D3DSWAPEFFECT_COPY * windowed)
  45. pp.hDeviceWindow=hwnd
  46. pp.Windowed=windowed
  47. pp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
  48. pp.FullScreen_RefreshRateInHz=(hertz * fullscreen)
  49. pp.PresentationInterval=D3DPRESENT_INTERVAL_ONE 'IMMEDIATE
  50. Function CheckDepthFormat(format)
  51. Return _d3d.CheckDeviceFormat(0,D3DDEVTYPE_HAL,D3DFMT_X8R8G8B8,D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,format)=D3D_OK
  52. End Function
  53. If flags&GRAPHICS_DEPTHBUFFER Or flags&GRAPHICS_STENCILBUFFER
  54. pp.EnableAutoDepthStencil = True
  55. If flags&GRAPHICS_STENCILBUFFER
  56. If Not CheckDepthFormat( D3DFMT_D24S8 )
  57. If Not CheckDepthFormat( D3DFMT_D24FS8 )
  58. If Not CheckDepthFormat( D3DFMT_D24X4S4 )
  59. If Not CheckDepthFormat( D3DFMT_D15S1 )
  60. Return False
  61. Else
  62. pp.AutoDepthStencilFormat = D3DFMT_D15S1
  63. EndIf
  64. Else
  65. pp.AutoDepthStencilFormat = D3DFMT_D24X4S4
  66. EndIf
  67. Else
  68. pp.AutoDepthStencilFormat = D3DFMT_D24FS8
  69. EndIf
  70. Else
  71. pp.AutoDepthStencilFormat = D3DFMT_D24S8
  72. EndIf
  73. Else
  74. If Not CheckDepthFormat( D3DFMT_D32 )
  75. If Not CheckDepthFormat( D3DFMT_D24X8 )
  76. If Not CheckDepthFormat( D3DFMT_D16 )
  77. Return False
  78. Else
  79. pp.AutoDepthStencilFormat = D3DFMT_D16
  80. EndIf
  81. Else
  82. pp.AutoDepthStencilFormat = D3DFMT_D24X8
  83. EndIf
  84. Else
  85. pp.AutoDepthStencilFormat = D3DFMT_D32
  86. EndIf
  87. EndIf
  88. EndIf
  89. Local cflags=D3DCREATE_FPU_PRESERVE
  90. 'OK, try hardware vertex processing...
  91. Local tflags=D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|cflags
  92. If _d3d.CreateDevice( 0,D3DDEVTYPE_HAL,hwnd,tflags,pp,_d3dDev )<0
  93. 'Failed! Try mixed vertex processing...
  94. tflags=D3DCREATE_MIXED_VERTEXPROCESSING|cflags
  95. If _d3d.CreateDevice( 0,D3DDEVTYPE_HAL,hwnd,tflags,pp,_d3dDev )<0
  96. 'Failed! Try software vertex processing...
  97. tflags=D3DCREATE_SOFTWARE_VERTEXPROCESSING|cflags
  98. If _d3d.CreateDevice( 0,D3DDEVTYPE_HAL,hwnd,tflags,pp,_d3dDev )<0
  99. 'Failed! Go home and watch family guy instead...
  100. Return False
  101. EndIf
  102. EndIf
  103. EndIf
  104. _presentParams=pp
  105. _d3dDevRefs:+1
  106. _autoRelease=New TList
  107. Return True
  108. End Function
  109. Function CloseD3DDevice()
  110. _d3dDevRefs:-1
  111. If Not _d3dDevRefs
  112. For Local t:TD3D9AutoRelease=EachIn _autoRelease
  113. t.unk.Release_
  114. Next
  115. _autoRelease=Null
  116. _d3dDev.Release_
  117. _d3dDev=Null
  118. _presentParams=Null
  119. EndIf
  120. End Function
  121. Function ResetD3DDevice()
  122. If _d3dDev.Reset( _presentParams )<0
  123. Throw "_d3dDev.Reset failed"
  124. EndIf
  125. End Function
  126. Public
  127. Type TD3D9Graphics Extends TGraphics
  128. Method Attach:TD3D9Graphics( hwnd,flags )
  129. Local rect[4]
  130. GetClientRect hwnd,rect
  131. Local width=rect[2]-rect[0]
  132. Local height=rect[3]-rect[1]
  133. OpenD3DDevice hwnd,width,height,0,0,flags
  134. _hwnd=hwnd
  135. _width=width
  136. _height=height
  137. _flags=flags
  138. _attached=True
  139. Return Self
  140. End Method
  141. Method Create:TD3D9Graphics( width,height,depth,hertz,flags )
  142. Local wstyle
  143. If depth
  144. wstyle=WS_VISIBLE|WS_POPUP
  145. Else
  146. wstyle=WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX
  147. EndIf
  148. Local rect[4]
  149. If Not depth
  150. Local desktopRect[4]
  151. GetWindowRect GetDesktopWindow(),desktopRect
  152. rect[0]=desktopRect[2]/2-width/2;
  153. rect[1]=desktopRect[3]/2-height/2;
  154. rect[2]=rect[0]+width;
  155. rect[3]=rect[1]+height;
  156. AdjustWindowRect rect,wstyle,0
  157. EndIf
  158. Local hwnd=CreateWindowExW( 0,_wndClass,AppTitle,wstyle,rect[0],rect[1],rect[2]-rect[0],rect[3]-rect[1],0,0,GetModuleHandleA(Null),Null )
  159. If Not hwnd Return Null
  160. If Not depth
  161. GetClientRect hwnd,rect
  162. width=rect[2]-rect[0]
  163. height=rect[3]-rect[1]
  164. EndIf
  165. If Not OpenD3DDevice( hwnd,width,height,depth,hertz,flags )
  166. DestroyWindow hwnd
  167. Return Null
  168. EndIf
  169. _hwnd=hwnd
  170. _width=width
  171. _height=height
  172. _depth=depth
  173. _hertz=hertz
  174. _flags=flags
  175. Return Self
  176. End Method
  177. Method GetDirect3DDevice:IDirect3DDevice9()
  178. Return _d3dDev
  179. End Method
  180. Method ValidateSize()
  181. If _attached
  182. Local rect[4]
  183. GetClientRect _hwnd,rect
  184. _width=rect[2]-rect[0]
  185. _height=rect[3]-rect[1]
  186. If _width>_presentParams.BackBufferWidth Or _height>_presentParams.BackBufferHeight
  187. _presentParams.BackBufferWidth=Max( _width,_presentParams.BackBufferWidth )
  188. _presentParams.BackBufferHeight=Max( _height,_presentParams.BackbufferHeight )
  189. ResetD3DDevice
  190. EndIf
  191. EndIf
  192. End Method
  193. 'NOTE: Returns 1 if flip was successful, otherwise device lost or reset...
  194. Method Flip( sync )
  195. Local reset
  196. If sync sync=D3DPRESENT_INTERVAL_ONE Else sync=D3DPRESENT_INTERVAL_IMMEDIATE
  197. If sync<>_presentParams.PresentationInterval
  198. _presentParams.PresentationInterval=sync
  199. reset=True
  200. EndIf
  201. Select _d3dDev.TestCooperativeLevel()
  202. Case D3D_OK
  203. If reset
  204. ResetD3DDevice
  205. Else If _attached
  206. Local rect[]=[0,0,_width,_height]
  207. Return _d3dDev.Present( rect,rect,_hwnd,Null )>=0
  208. Else
  209. Return _d3dDev.Present( Null,Null,_hwnd,Null )>=0
  210. EndIf
  211. Case D3DERR_DEVICENOTRESET
  212. ResetD3DDevice
  213. End Select
  214. End Method
  215. Method Driver:TGraphicsDriver()
  216. Return _driver
  217. End Method
  218. Method GetSettings( width Var,height Var,depth Var,hertz Var,flags Var )
  219. '
  220. ValidateSize
  221. '
  222. width=_width
  223. height=_height
  224. depth=_depth
  225. hertz=_hertz
  226. flags=_flags
  227. End Method
  228. Method Close()
  229. If Not _hwnd Return
  230. CloseD3DDevice
  231. If Not _attached DestroyWindow( _hwnd )
  232. _hwnd=0
  233. End Method
  234. Method AutoRelease( unk:IUnknown )
  235. Local t:TD3D9AutoRelease=New TD3D9AutoRelease
  236. t.unk=unk
  237. _autoRelease.AddLast t
  238. End Method
  239. Method ReleaseNow( unk:IUnknown )
  240. For Local t:TD3D9AutoRelease=EachIn _autoRelease
  241. If t.unk=unk
  242. unk.Release_
  243. _autoRelease.Remove t
  244. Return
  245. EndIf
  246. Next
  247. End Method
  248. Field _hwnd
  249. Field _width
  250. Field _height
  251. Field _depth
  252. Field _hertz
  253. Field _flags
  254. Field _attached
  255. End Type
  256. Type TD3D9GraphicsDriver Extends TGraphicsDriver
  257. Method Create:TD3D9GraphicsDriver()
  258. 'create d3d9
  259. If Not d3d9Lib Return
  260. _d3d=Direct3DCreate9( 32 )
  261. If Not _d3d Return Null
  262. 'get caps
  263. _d3dCaps=New D3DCAPS9
  264. If _d3d.GetDeviceCaps( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,_d3dCaps )<0
  265. _d3d.Release_
  266. _d3d=Null
  267. Return Null
  268. EndIf
  269. 'enum graphics modes
  270. Local n=_d3d.GetAdapterModeCount( D3DADAPTER_DEFAULT,D3DFMT_X8R8G8B8 )
  271. _modes=New TGraphicsMode[n]
  272. Local j
  273. For Local i=0 Until n
  274. Local d3dmode:D3DDISPLAYMODE=New D3DDISPLAYMODE
  275. If _d3d.EnumAdapterModes( D3DADAPTER_DEFAULT,D3DFMT_X8R8G8B8,i,d3dmode )<0
  276. Continue
  277. EndIf
  278. Local mode:TGraphicsMode=New TGraphicsMode
  279. mode.width=d3dmode.Width
  280. mode.height=d3dmode.Height
  281. mode.hertz=d3dmode.RefreshRate
  282. mode.depth=32
  283. _modes[j]=mode
  284. j:+1
  285. Next
  286. _modes=_modes[..j]
  287. 'register wndclass
  288. Local wndclass:WNDCLASSW=New WNDCLASSW
  289. wndclass.hInstance=GetModuleHandleW( Null )
  290. wndclass.lpfnWndProc=D3D9WndProc
  291. wndclass.hCursor=LoadCursorW( Null,Short Ptr IDC_ARROW )
  292. wndclass.lpszClassName=_wndClass.ToWString()
  293. RegisterClassW wndclass
  294. MemFree wndclass.lpszClassName
  295. Return Self
  296. End Method
  297. Method GraphicsModes:TGraphicsMode[]()
  298. Return _modes
  299. End Method
  300. Method AttachGraphics:TD3D9Graphics( widget,flags )
  301. Return New TD3D9Graphics.Attach( widget,flags )
  302. End Method
  303. Method CreateGraphics:TD3D9Graphics( width,height,depth,hertz,flags )
  304. Return New TD3D9Graphics.Create( width,height,depth,hertz,flags )
  305. End Method
  306. Method SetGraphics( g:TGraphics )
  307. _graphics=TD3D9Graphics( g )
  308. End Method
  309. Method Flip( sync )
  310. Return _graphics.Flip( sync )
  311. End Method
  312. Method GetDirect3D:IDirect3D9()
  313. Return _d3d
  314. End Method
  315. End Type
  316. Function D3D9GraphicsDriver:TD3D9GraphicsDriver()
  317. Global _done
  318. If Not _done
  319. _driver=New TD3D9GraphicsDriver.Create()
  320. _done=True
  321. EndIf
  322. Return _driver
  323. End Function