graphics.bmx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. Strict
  2. Rem
  3. bbdoc: Graphics/Graphics
  4. End Rem
  5. Module BRL.Graphics
  6. ModuleInfo "Version: 1.08"
  7. ModuleInfo "Author: Mark Sibly"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "Modserver: BRL"
  11. ModuleInfo "History: 1.08 Release"
  12. ModuleInfo "History: Mouse repositioned only in fullscreen mode"
  13. ModuleInfo "History: 1.07 Release"
  14. ModuleInfo "History: Flip mode for attached graphics changed to 0"
  15. ModuleInfo "History: 1.06 Release"
  16. ModuleInfo "History: Fixed softsync period init bug"
  17. ModuleInfo "History: 1.05 Release"
  18. ModuleInfo "History: Fixed softsync routine to prevent overflow"
  19. ModuleInfo "History: 1.04 Release"
  20. ModuleInfo "History: Graphics exceptions now caught"
  21. ModuleInfo "History: 1.03 Release"
  22. ModuleInfo "History: Added DefaultGraphicsFlags() Function"
  23. ModuleInfo "History: 1.02 Release"
  24. ModuleInfo "History: Restored FlipHook"
  25. ModuleInfo "History: 1.01 Release"
  26. ModuleInfo "History: Added default flags to SetGraphicsDriver"
  27. Import BRL.System
  28. Import BRL.PolledInput
  29. Rem
  30. bbdoc: Flip Hook id
  31. about:
  32. Use this id with #AddHook to register a function that
  33. is called every #Flip.
  34. End Rem
  35. Global FlipHook=AllocHookId()
  36. Const GRAPHICS_BACKBUFFER= $2
  37. Const GRAPHICS_ALPHABUFFER= $4
  38. Const GRAPHICS_DEPTHBUFFER= $8
  39. Const GRAPHICS_STENCILBUFFER= $10
  40. Const GRAPHICS_ACCUMBUFFER= $20
  41. Const GRAPHICS_BORDERLESS=$40
  42. 'Const GRAPHICS_SWAPINTERVAL0= $40
  43. 'Const GRAPHICS_SWAPINTERVAL1= $80
  44. 'Const GRAPHICS_SWAPINTERVALMASK=GRAPHICS_SWAPINTERVAL0|GRAPHICS_SWAPINTERVAL1
  45. Type TGraphics
  46. Method _pad()
  47. End Method
  48. Method Driver:TGraphicsDriver() Abstract
  49. Method GetSettings( width Var,height Var,depth Var,hertz Var,flags Var ) Abstract
  50. Method Close() Abstract
  51. End Type
  52. Type TGraphicsMode
  53. Field width,height,depth,hertz
  54. Method ToString$() Override
  55. Return width+","+height+","+depth+" "+hertz+"Hz"
  56. End Method
  57. End Type
  58. Type TGraphicsDriver
  59. Method GraphicsModes:TGraphicsMode[]() Abstract
  60. Method AttachGraphics:TGraphics( widget:Byte Ptr,flags ) Abstract
  61. Method CreateGraphics:TGraphics( width,height,depth,hertz,flags ) Abstract
  62. Method SetGraphics( g:TGraphics ) Abstract
  63. Method Flip( sync ) Abstract
  64. Method CanResize:Int()
  65. Return False
  66. End Method
  67. End Type
  68. Private
  69. Global _defaultFlags
  70. Global _driver:TGraphicsDriver
  71. Global _graphicsModes:TGraphicsMode[]
  72. Global _graphics:TGraphics,_gWidth,_gHeight,_gDepth,_gHertz,_gFlags
  73. Global _exGraphics:TGraphics
  74. 'Only valid if _exGraphics=_graphics
  75. Global _softSync,_hardSync,_syncRate,_syncPeriod,_syncFrac,_syncAccum,_syncTime
  76. Public
  77. Global GraphicsSeq=1
  78. Function BumpGraphicsSeq()
  79. GraphicsSeq:+1
  80. If Not GraphicsSeq GraphicsSeq=1
  81. End Function
  82. Rem
  83. bbdoc: Set current graphics driver
  84. about:
  85. The current graphics driver determines what kind of graphics are created when you use
  86. the #CreateGraphics or #Graphics functions, as well as the graphics modes available.
  87. The #GLGraphicsDriver, #GLMax2DDriver, #D3D7Max2DDriver and #D3D9Max2DDriver functions can all be
  88. used to obtain a graphics driver.
  89. The @defaultFlags parameter allows you to specify graphics flags that will be applied to any
  90. graphics created with #CreateGraphics or #Graphics.
  91. End Rem
  92. Function SetGraphicsDriver( driver:TGraphicsDriver,defaultFlags=GRAPHICS_BACKBUFFER )
  93. BumpGraphicsSeq
  94. If driver<>_driver
  95. If _driver And _graphics _driver.SetGraphics Null
  96. _graphicsModes=Null
  97. _driver=driver
  98. EndIf
  99. _defaultFlags=defaultFlags
  100. _graphics=Null
  101. _gWidth=0
  102. _gHeight=0
  103. _gDepth=0
  104. _gHertz=0
  105. _gFlags=0
  106. End Function
  107. Rem
  108. bbdoc: Get current graphics driver
  109. about:
  110. Returns the current graphics driver as selected by #SetGraphicsDriver
  111. End Rem
  112. Function GetGraphicsDriver:TGraphicsDriver()
  113. Return _driver
  114. End Function
  115. Rem
  116. bbdoc: Get current default graphics flags
  117. End Rem
  118. Function DefaultGraphicsFlags()
  119. Return _defaultFlags
  120. End Function
  121. Rem
  122. bbdoc: Get graphics modes available under the current graphics driver
  123. returns: An array of TGraphicsMode objects
  124. about:
  125. A TGraphicsMode object contains the following fields: @width, @height, @depth and @hertz
  126. End Rem
  127. Function GraphicsModes:TGraphicsMode[]()
  128. If Not _graphicsModes _graphicsModes=_driver.GraphicsModes()
  129. Return _graphicsModes[..]
  130. End Function
  131. Rem
  132. bbdoc: Get number of graphics modes available under the current graphics driver
  133. returns: Number of available Graphics modes
  134. about:
  135. Use #GetGraphicsMode To obtain information about an individual Graphics mode
  136. End Rem
  137. Function CountGraphicsModes()
  138. Return GraphicsModes().length
  139. End Function
  140. Rem
  141. bbdoc: Get information about a graphics mode
  142. about:
  143. #GetGraphicsMode returns information about a specific graphics mode. @mode should be
  144. in the range 0 (inclusive) to the value returned by #CountGraphicsModes (exclusive).
  145. End Rem
  146. Function GetGraphicsMode( index,width Var,height Var,depth Var,hertz Var )
  147. Local Mode:TGraphicsMode=GraphicsModes()[index]
  148. width=Mode.width
  149. height=Mode.height
  150. depth=Mode.depth
  151. hertz=Mode.hertz
  152. End Function
  153. Rem
  154. bbdoc: Determine if a graphics mode exists
  155. returns: True if a matching graphics mode is found
  156. about:
  157. A value of 0 for any of @width, @height, @depth or @hertz will cause that
  158. parameter to be ignored.
  159. End Rem
  160. Function GraphicsModeExists( width,height,depth=0,hertz=0 )
  161. For Local Mode:TGraphicsMode=EachIn GraphicsModes()
  162. If width And width<>Mode.width Continue
  163. If height And height<>Mode.height Continue
  164. If depth And depth<>Mode.depth Continue
  165. If hertz And hertz<>Mode.hertz Continue
  166. Return True
  167. Next
  168. Return False
  169. End Function
  170. Rem
  171. bbdoc: Create a graphics object
  172. returns: A graphics object
  173. about:
  174. #CreateGraphics creates a graphics object. To use this object for rendering, you will
  175. first have to select it using #SetGraphics.
  176. The kind of graphics object returned depends upon the current graphics driver as set by
  177. #SetGraphicsDriver.
  178. End Rem
  179. Function CreateGraphics:TGraphics( width,height,depth,hertz,flags )
  180. flags:|_defaultFlags
  181. Local g:TGraphics
  182. Try
  183. g=_driver.CreateGraphics( width,height,depth,hertz,flags )
  184. Catch ex:Object
  185. ?Debug
  186. WriteStdout "CreateGraphics failed:"+ex.ToString()
  187. ?
  188. End Try
  189. Return g
  190. End Function
  191. Function AttachGraphics:TGraphics( widget:Byte Ptr,flags )
  192. flags:|_defaultFlags
  193. Local g:TGraphics
  194. Try
  195. g=_driver.AttachGraphics( widget,flags )
  196. Catch ex:Object
  197. ?Debug
  198. WriteStdout "AttachGraphics failed:"+ex.ToString()
  199. ?
  200. End Try
  201. Return g
  202. End Function
  203. Rem
  204. bbdoc: Close a graphics object
  205. about:
  206. Once closed, a graphics object can no longer be used.
  207. End Rem
  208. Function CloseGraphics( g:TGraphics )
  209. If g=_exGraphics _exGraphics=Null
  210. If g=_graphics SetGraphics Null
  211. g.Close
  212. End Function
  213. Rem
  214. bbdoc: Set current graphics object
  215. about:
  216. #SetGraphics will also change the current graphics driver if @g uses a different driver
  217. than the current driver.
  218. End Rem
  219. Function SetGraphics( g:TGraphics )
  220. If Not g
  221. If _driver And _graphics _driver.SetGraphics Null
  222. _graphics=Null
  223. _gWidth=0
  224. _gHeight=0
  225. _gDepth=0
  226. _gHertz=0
  227. _gFlags=0
  228. Return
  229. EndIf
  230. Local d:TGraphicsDriver=g.Driver()
  231. If d<>_driver
  232. If _driver And _graphics _driver.SetGraphics Null
  233. _graphicsModes=Null
  234. _driver=d
  235. EndIf
  236. g.GetSettings _gWidth,_gHeight,_gDepth,_gHertz,_gFlags
  237. d.SetGraphics g
  238. _graphics=g
  239. End Function
  240. Rem
  241. bbdoc: Resize the current graphics object to @width, @height.
  242. End Rem
  243. Function GraphicsResize( width:Int, height:Int )
  244. If _driver And _driver.CanResize() And _graphics Then
  245. _gWidth = width
  246. _gHeight = height
  247. End If
  248. End Function
  249. Rem
  250. bbdoc: Get width of current graphics object
  251. returns: The width, in pixels, of the current graphics object
  252. about:
  253. The current graphics object can be changed using #SetGraphics.
  254. End Rem
  255. Function GraphicsWidth()
  256. Return _gWidth
  257. End Function
  258. Rem
  259. bbdoc: Get height of current graphics object
  260. returns: The height, in pixels, of the current graphics object
  261. about:
  262. The current graphics object can be changed using #SetGraphics.
  263. End Rem
  264. Function GraphicsHeight()
  265. Return _gHeight
  266. End Function
  267. Rem
  268. bbdoc: Get depth of current graphics object
  269. returns: The depth, in bits, of the current graphics object
  270. about:
  271. The current graphics object can be changed using #SetGraphics.
  272. End Rem
  273. Function GraphicsDepth()
  274. Return _gDepth
  275. End Function
  276. Rem
  277. bbdoc: Get refresh rate of current graphics object
  278. returns: The refresh rate, in frames per second, of the current graphics object
  279. about:
  280. The current graphics object can be changed using #SetGraphics.
  281. End Rem
  282. Function GraphicsHertz()
  283. Return _gHertz
  284. End Function
  285. Rem
  286. bbdoc: Get flags of current graphics object
  287. returns: The flags of the current graphics object
  288. about:
  289. The current graphics object can be changed using #SetGraphics.
  290. End Rem
  291. Function GraphicsFlags()
  292. Return _gFlags
  293. End Function
  294. Rem
  295. bbdoc: Flip current graphics object
  296. about:
  297. #Flip swap the front and back buffers of the current graphics objects.
  298. If @sync is 0, then the flip occurs as soon as possible. If @sync is 1, then the flip occurs
  299. on the next vertical blank.
  300. If @sync is -1 and the current graphics object was created with the #Graphics command,
  301. then flips will occur at the graphics object's refresh rate, unless the graphics object was
  302. created with a refresh rate of 0 in which case flip occurs immediately.
  303. If @sync is -1 and the current graphics object was NOT created with the #Graphics command,
  304. then the flip will occur on the next vertical blank.
  305. End Rem
  306. Function Flip( sync=-1 )
  307. RunHooks FlipHook,Null
  308. If sync<>-1
  309. _driver.Flip sync
  310. Return
  311. EndIf
  312. If _graphics<>_exGraphics
  313. _driver.Flip True
  314. Return
  315. EndIf
  316. If _softSync
  317. _syncTime:+_syncPeriod
  318. _syncAccum:+_syncFrac
  319. If _syncAccum>=_syncRate
  320. _syncAccum:-_syncRate
  321. _syncTime:+1
  322. EndIf
  323. Local dt=_syncTime-MilliSecs()
  324. If dt>0
  325. Delay dt
  326. Else
  327. _syncTime:-dt
  328. EndIf
  329. _driver.Flip False
  330. Else If _hardSync
  331. _driver.Flip True
  332. Else
  333. _driver.Flip False
  334. EndIf
  335. End Function
  336. Rem
  337. Function Flip( sync=-1 )
  338. RunHooks FlipHook,Null
  339. If sync<>-1
  340. _driver.Flip sync
  341. Return
  342. EndIf
  343. If _graphics<>_exGraphics Or Not _softSync
  344. Local sync=False
  345. If _gDepth sync=True
  346. _driver.Flip sync
  347. Return
  348. EndIf
  349. _syncTime:+_syncPeriod
  350. _syncAccum:+_syncFrac
  351. If _syncAccum>=_syncRate
  352. _syncAccum:-_syncRate
  353. _syncTime:+1
  354. EndIf
  355. Local dt=_syncTime-MilliSecs()
  356. If dt>0
  357. Delay dt
  358. Else
  359. _syncTime:-dt
  360. EndIf
  361. _driver.Flip False
  362. End Function
  363. End Rem
  364. Rem
  365. bbdoc: Begin graphics
  366. returns: A graphics object
  367. about:
  368. #Graphics is a convenience function that simplifies the process of creating a graphics
  369. object.
  370. Once #Graphics has executed, you can begin rendering immediately without any need for
  371. #SetGraphics.
  372. #Graphics also enables #{polled input} mode, providing a simple way to monitor the keyboard
  373. and mouse.
  374. End Rem
  375. Function Graphics:TGraphics( width,height,depth=0,hertz=60,flags=0 )
  376. EndGraphics
  377. flags:|_defaultFlags
  378. Local g:TGraphics=CreateGraphics( width,height,depth,hertz,flags )
  379. If Not g Return
  380. BumpGraphicsSeq
  381. SetGraphics g
  382. If depth
  383. _softSync=False
  384. _hardSync=(hertz<>0)
  385. MoveMouse width/2,height/2
  386. Else
  387. _hardSync=False
  388. _softSync=(hertz<>0)
  389. EndIf
  390. If _softSync
  391. _syncRate=hertz
  392. If _syncRate _syncPeriod=1000/_syncRate Else _syncPeriod=0
  393. _syncFrac=1000-_syncPeriod*_syncRate
  394. _syncAccum=0
  395. _syncTime=MilliSecs()
  396. EndIf
  397. EnablePolledInput
  398. _exGraphics=g
  399. Global _onEnd
  400. If Not _onEnd
  401. _onEnd=True
  402. OnEnd EndGraphics
  403. EndIf
  404. Return g
  405. End Function
  406. Rem
  407. Function Graphics:TGraphics( width,height,depth=0,hertz=60,flags=0 )
  408. EndGraphics
  409. flags:|_defaultFlags
  410. Local g:TGraphics=CreateGraphics( width,height,depth,hertz,flags )
  411. If Not g Return
  412. GraphicsSeq:+1
  413. If Not GraphicsSeq GraphicsSeq=1
  414. SetGraphics g
  415. _softSync=True
  416. If Not hertz
  417. _softSync=False
  418. Else If depth
  419. Local e=MilliSecs()+1000,n
  420. While e-MilliSecs()>0
  421. Local t=MilliSecs()
  422. _driver.Flip True
  423. t=(MilliSecs()-t)-1000/hertz
  424. If t>=-1 And t<=1
  425. n:+1
  426. If n<3 Continue
  427. _softSync=False
  428. Exit
  429. EndIf
  430. n=0
  431. Wend
  432. EndIf
  433. _syncRate=hertz
  434. If _syncRate _syncPeriod=1000/_syncRate Else _syncPeriod=0
  435. _syncFrac=1000-_syncPeriod*_syncRate
  436. _syncAccum=0
  437. _syncTime=MilliSecs()
  438. _exGraphics=g
  439. If depth
  440. MoveMouse width/2,height/2
  441. EndIf
  442. EnablePolledInput
  443. Global _onEnd
  444. If Not _onEnd
  445. _onEnd=True
  446. OnEnd EndGraphics
  447. EndIf
  448. Return g
  449. End Function
  450. End Rem
  451. Rem
  452. bbdoc: End graphics
  453. about:
  454. #EndGraphics closes the graphics object returned by #Graphics.
  455. End Rem
  456. Function EndGraphics()
  457. If Not _exGraphics Return
  458. GraphicsSeq:+1
  459. If Not GraphicsSeq GraphicsSeq=1
  460. DisablePolledInput
  461. CloseGraphics _exGraphics
  462. End Function