graphics.bmx 14 KB

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