graphics.bmx 14 KB

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