graphics.bmx 12 KB

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