glmax2d.bmx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. SuperStrict
  2. Rem
  3. bbdoc: Graphics/OpenGL Max2D
  4. about:
  5. The OpenGL Max2D module provides an OpenGL driver for #Max2D.
  6. End Rem
  7. Module BRL.GLMax2D
  8. ModuleInfo "Version: 1.15"
  9. ModuleInfo "Author: Mark Sibly"
  10. ModuleInfo "License: zlib/libpng"
  11. ModuleInfo "Copyright: Blitz Research Ltd"
  12. ModuleInfo "Modserver: BRL"
  13. ModuleInfo "History: 1.15"
  14. ModuleInfo "History: Added RenderImages / render2texture"
  15. ModuleInfo "History: 1.14"
  16. ModuleInfo "History: Changed to SuperStrict"
  17. ModuleInfo "History: Extended flags to Long"
  18. ModuleInfo "History: 1.13 Release"
  19. ModuleInfo "History: Cleaned up SetGraphics"
  20. ModuleInfo "History: 1.12 Release"
  21. ModuleInfo "History: Fixed filtered image min filters"
  22. ModuleInfo "History: 1.11 Release"
  23. ModuleInfo "History: Fixed texture delete logic"
  24. ModuleInfo "History: 1.10 Release"
  25. ModuleInfo "History: Add SetColor/SetClsColor clamping"
  26. ModuleInfo "History: 1.09 Release"
  27. ModuleInfo "History: Fixed DrawPixmap using current blend mode - now always uses SOLIDBLEND"
  28. ModuleInfo "History: 1.08 Release"
  29. ModuleInfo "History: Added MIPMAPPEDIMAGE support"
  30. ModuleInfo "History: 1.07 Release"
  31. ModuleInfo "History: Now default driver for MacOS/Linux only (D3D7 for windows)"
  32. ModuleInfo "History: 1.06 Release"
  33. ModuleInfo "History: Ripped out a bunch of dead code"
  34. ModuleInfo "History: 1.05 Release"
  35. ModuleInfo "History: Added checks to prevent invalid textures deletes"
  36. ?Not opengles And Not nx And Not raspberrypi And Not haiku
  37. Import BRL.Max2D
  38. Import BRL.GLGraphics
  39. Import BRL.Threads
  40. Private
  41. Global _driver:TGLMax2DDriver
  42. Global _BackbufferRenderImageFrame:TGLRenderImageFrame
  43. Global _CurrentRenderImageFrame:TGLRenderImageFrame
  44. Global _GLScissor_BMaxViewport:Rect = New Rect
  45. 'Naughty!
  46. Const GL_BGR:Int = $80E0
  47. Const GL_BGRA:Int = $80E1
  48. Const GL_CLAMP_TO_EDGE:Int = $812F
  49. Const GL_CLAMP_TO_BORDER:Int = $812D
  50. Global ix:Float,iy:Float,jx:Float,jy:Float
  51. Global color4ub:Byte[4]
  52. Global state_blend:Int
  53. Global state_boundtex:Int
  54. Global state_texenabled:Int
  55. Function BindTex( name:Int )
  56. If name = state_boundtex Return
  57. glBindTexture( GL_TEXTURE_2D, name )
  58. state_boundtex = name
  59. End Function
  60. Function EnableTex( name:Int )
  61. BindTex( name )
  62. If state_texenabled Return
  63. glEnable( GL_TEXTURE_2D )
  64. state_texenabled = True
  65. End Function
  66. Function DisableTex()
  67. If Not state_texenabled Return
  68. glDisable( GL_TEXTURE_2D )
  69. state_texenabled = False
  70. End Function
  71. Function Pow2Size:Int( n:Int )
  72. Local t:Int = 1
  73. While t < n
  74. t :* 2
  75. Wend
  76. Return t
  77. End Function
  78. Global dead_texs:TDynamicArray = New TDynamicArray(32)
  79. Global dead_tex_seq:Int
  80. 'Enqueues a texture for deletion, to prevent release textures on wrong thread.
  81. Function DeleteTex( name:Int,seq:Int )
  82. If seq<>dead_tex_seq Return
  83. dead_texs.AddLast(name)
  84. End Function
  85. Function CreateTex:Int( width:Int,height:Int,flags:Int,pixmap:TPixmap )
  86. If pixmap.dds_fmt<>0 Then Return pixmap.tex_name ' if dds texture already exists
  87. 'alloc new tex
  88. Local name:Int
  89. glGenTextures( 1, Varptr name )
  90. 'flush dead texs
  91. If dead_tex_seq=GraphicsSeq
  92. Local n:Int = dead_texs.RemoveLast()
  93. While n <> $FFFFFFFF
  94. glDeleteTextures(1, Varptr n)
  95. n = dead_texs.RemoveLast()
  96. Wend
  97. EndIf
  98. dead_tex_seq = GraphicsSeq
  99. 'bind new tex
  100. BindTex( name )
  101. 'set texture parameters
  102. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE )
  103. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE )
  104. If flags & FILTEREDIMAGE
  105. glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
  106. If flags & MIPMAPPEDIMAGE
  107. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR )
  108. Else
  109. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR )
  110. EndIf
  111. Else
  112. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST )
  113. If flags & MIPMAPPEDIMAGE
  114. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST )
  115. Else
  116. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST )
  117. EndIf
  118. EndIf
  119. Local mip_level:Int
  120. Repeat
  121. glTexImage2D( GL_TEXTURE_2D, mip_level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Null )
  122. If Not ( flags & MIPMAPPEDIMAGE ) Exit
  123. If width = 1 And height = 1 Exit
  124. If width > 1 width :/ 2
  125. If height > 1 height :/ 2
  126. mip_level :+ 1
  127. Forever
  128. Return name
  129. End Function
  130. 'NOTE: Assumes a bound texture.
  131. Function UploadTex( pixmap:TPixmap, flags:Int )
  132. Local mip_level:Int
  133. If pixmap.dds_fmt <> 0 Then Return ' if dds texture already exists
  134. Repeat
  135. glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
  136. glTexSubImage2D GL_TEXTURE_2D,mip_level,0,0,pixmap.width,pixmap.height,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
  137. If Not ( flags & MIPMAPPEDIMAGE ) Then Exit
  138. If pixmap.width > 1 And pixmap.height > 1
  139. pixmap = ResizePixmap( pixmap, pixmap.width / 2, pixmap.height / 2 )
  140. Else If pixmap.width > 1
  141. pixmap = ResizePixmap( pixmap, pixmap.width / 2, pixmap.height )
  142. Else If pixmap.height > 1
  143. pixmap = ResizePixmap( pixmap, pixmap.width, pixmap.height / 2 )
  144. Else
  145. Exit
  146. EndIf
  147. mip_level :+ 1
  148. Forever
  149. glPixelStorei GL_UNPACK_ROW_LENGTH,0
  150. End Function
  151. Function AdjustTexSize( width:Int Var, height:Int Var )
  152. 'calc texture size
  153. width = Pow2Size( width )
  154. height = Pow2Size( height )
  155. Repeat
  156. Local t:Int
  157. glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
  158. glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
  159. If t Then Return
  160. If width = 1 And height = 1 Then RuntimeError "Unable to calculate tex size"
  161. If width > 1 width :/ 2
  162. If height > 1 height :/ 2
  163. Forever
  164. End Function
  165. Type TDynamicArray
  166. Private
  167. Field data:Int Ptr
  168. Field size:Size_T
  169. Field capacity:Size_T
  170. Field guard:TMutex
  171. Public
  172. Method New(initialCapacity:Int = 8)
  173. capacity = initialCapacity
  174. data = malloc_(Size_T(initialCapacity * 4))
  175. guard = CreateMutex()
  176. End Method
  177. Method AddLast(value:Int)
  178. guard.Lock()
  179. If size = capacity Then
  180. capacity :* 2
  181. Local d:Byte Ptr = realloc_(data, capacity * 4)
  182. If Not d Then
  183. Throw "Failed to allocate more memory"
  184. End If
  185. data = d
  186. End If
  187. data[size] = value
  188. size :+ 1
  189. guard.Unlock()
  190. End Method
  191. Method RemoveLast:Int()
  192. guard.Lock()
  193. Local v:Int
  194. If size > 0 Then
  195. size :- 1
  196. v = data[size]
  197. Else
  198. v = $FFFFFFFF
  199. End If
  200. guard.Unlock()
  201. Return v
  202. End Method
  203. Method Delete()
  204. free_(data)
  205. CloseMutex(guard)
  206. End Method
  207. End Type
  208. Global glewIsInit:Int
  209. Public
  210. Type TGLImageFrame Extends TImageFrame
  211. Field u0:Float, v0:Float, u1:Float, v1:Float, uscale:Float, vscale:Float
  212. Field name:Int, seq:Int
  213. Method New()
  214. seq = GraphicsSeq
  215. End Method
  216. Method Delete()
  217. If Not seq Then Return
  218. DeleteTex( name, seq )
  219. seq = 0
  220. End Method
  221. Method Draw( x0:Float,y0:Float,x1:Float,y1:Float,tx:Float,ty:Float,sx:Float,sy:Float,sw:Float,sh:Float ) Override
  222. Assert seq=GraphicsSeq Else "Image does not exist"
  223. Local u0:Float = sx * uscale
  224. Local v0:Float = sy * vscale
  225. Local u1:Float = (sx + sw) * uscale
  226. Local v1:Float = (sy + sh) * vscale
  227. EnableTex name
  228. glBegin GL_QUADS
  229. glTexCoord2f u0,v0
  230. glVertex2f x0*ix+y0*iy+tx,x0*jx+y0*jy+ty
  231. glTexCoord2f u1,v0
  232. glVertex2f x1*ix+y0*iy+tx,x1*jx+y0*jy+ty
  233. glTexCoord2f u1,v1
  234. glVertex2f x1*ix+y1*iy+tx,x1*jx+y1*jy+ty
  235. glTexCoord2f u0,v1
  236. glVertex2f x0*ix+y1*iy+tx,x0*jx+y1*jy+ty
  237. glEnd
  238. End Method
  239. Function CreateFromPixmap:TGLImageFrame( src:TPixmap, flags:Int )
  240. 'determine tex size
  241. Local tex_w:Int = src.width
  242. Local tex_h:Int = src.height
  243. AdjustTexSize( tex_w, tex_h )
  244. 'make sure pixmap fits texture
  245. Local width:Int = Min( src.width, tex_w )
  246. Local height:Int = Min( src.height, tex_h )
  247. If src.width <> width Or src.height <> height Then src = ResizePixmap( src, width, height )
  248. 'create texture pixmap
  249. Local tex:TPixmap = src
  250. '"smear" right/bottom edges if necessary
  251. If width < tex_w Or height < tex_h
  252. tex = TPixmap.Create( tex_w, tex_h, PF_RGBA8888 )
  253. tex.Paste( src, 0, 0 )
  254. If width < tex_w
  255. tex.Paste( src.Window( width - 1, 0, 1, height ), width, 0 )
  256. EndIf
  257. If height < tex_h
  258. tex.Paste( src.Window( 0, height - 1, width, 1 ), 0, height )
  259. If width < tex_w
  260. tex.Paste( src.Window( width - 1, height - 1, 1, 1 ), width, height )
  261. EndIf
  262. EndIf
  263. Else
  264. If tex.dds_fmt = 0 ' not dds
  265. If tex.format <> PF_RGBA8888 Then tex = tex.Convert( PF_RGBA8888 )
  266. EndIf
  267. EndIf
  268. 'create tex
  269. Local name:Int = CreateTex( tex_w, tex_h, flags, tex )
  270. 'upload it
  271. UploadTex( tex, flags )
  272. 'done!
  273. Local frame:TGLImageFrame = New TGLImageFrame
  274. frame.name = name
  275. frame.uscale = 1.0 / tex_w
  276. frame.vscale = 1.0 / tex_h
  277. frame.u1 = width * frame.uscale
  278. frame.v1 = height * frame.vscale
  279. Return frame
  280. End Function
  281. End Type
  282. Type TGLRenderImageFrame Extends TGLImageFrame
  283. Field FBO:Int
  284. Field width:Int
  285. Field height:Int
  286. Method Draw( x0#,y0#,x1#,y1#,tx#,ty#,sx#,sy#,sw#,sh# ) Override
  287. Assert seq=GraphicsSeq Else "Image does not exist"
  288. ' Note for a TGLRenderImage the V texture coordinate is flipped compared to the regular TImageFrame.Draw method
  289. Local u0:Float = sx * uscale
  290. Local v0:Float = (sy + sh) * vscale
  291. Local u1:Float = (sx + sw) * uscale
  292. Local v1:Float = sy * vscale
  293. EnableTex name
  294. glBegin GL_QUADS
  295. glTexCoord2f u0,v0
  296. glVertex2f x0*ix+y0*iy+tx,x0*jx+y0*jy+ty
  297. glTexCoord2f u1,v0
  298. glVertex2f x1*ix+y0*iy+tx,x1*jx+y0*jy+ty
  299. glTexCoord2f u1,v1
  300. glVertex2f x1*ix+y1*iy+tx,x1*jx+y1*jy+ty
  301. glTexCoord2f u0,v1
  302. glVertex2f x0*ix+y1*iy+tx,x0*jx+y1*jy+ty
  303. glEnd
  304. EndMethod
  305. Function Create:TGLRenderImageFrame(width:UInt, height:UInt, flags:Int)
  306. ' Need this to enable frame buffer objects - glGenFramebuffers
  307. Global GlewIsInitialised:Int = False
  308. If Not GlewIsInitialised
  309. GlewInit()
  310. GlewIsInitialised = True
  311. EndIf
  312. ' store so that we can restore once the fbo is created
  313. Local ScissorTestEnabled:Int = GlIsEnabled(GL_SCISSOR_TEST)
  314. glDisable(GL_SCISSOR_TEST)
  315. Local TextureName:Int
  316. glGenTextures(1, Varptr TextureName)
  317. glBindTexture(GL_TEXTURE_2D, TextureName)
  318. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Null)
  319. If flags & FILTEREDIMAGE
  320. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
  321. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR
  322. Else
  323. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST
  324. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST
  325. EndIf
  326. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
  327. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
  328. Local FrameBufferObject:Int
  329. glGenFramebuffers(1, Varptr FrameBufferObject)
  330. glBindFramebuffer(GL_FRAMEBUFFER, FrameBufferObject)
  331. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, TextureName, 0)
  332. Local RenderTarget:TGLRenderImageFrame = New TGLRenderImageFrame
  333. RenderTarget.name = TextureName
  334. RenderTarget.FBO = FrameBufferObject
  335. RenderTarget.width = width
  336. RenderTarget.height = height
  337. RenderTarget.uscale = 1.0 / width
  338. RenderTarget.vscale = 1.0 / height
  339. RenderTarget.u1 = width * RenderTarget.uscale
  340. RenderTarget.v1 = height * RenderTarget.vscale
  341. If ScissorTestEnabled
  342. glEnable(GL_SCISSOR_TEST)
  343. EndIf
  344. Return RenderTarget
  345. EndFunction
  346. Private
  347. Method Delete()
  348. glDeleteFramebuffers(1, Varptr FBO) ' gl ignores 0
  349. EndMethod
  350. Method New()
  351. EndMethod
  352. EndType
  353. Type TGLMax2DDriver Extends TMax2DDriver
  354. Method Create:TGLMax2DDriver()
  355. If Not GLGraphicsDriver() Return Null
  356. Return Self
  357. End Method
  358. 'graphics driver overrides
  359. Method GraphicsModes:TGraphicsMode[]() Override
  360. Return GLGraphicsDriver().GraphicsModes()
  361. End Method
  362. Method AttachGraphics:TMax2DGraphics( widget:Byte Ptr,flags:Long ) Override
  363. Local g:TGLGraphics = GLGraphicsDriver().AttachGraphics( widget,flags )
  364. If g Return TMax2DGraphics.Create( g,Self )
  365. End Method
  366. Method CreateGraphics:TMax2DGraphics( width:Int,height:Int,depth:Int,hertz:Int,flags:Long,x:Int,y:Int ) Override
  367. Local g:TGLGraphics = GLGraphicsDriver().CreateGraphics( width,height,depth,hertz,flags,x,y )
  368. If g Return TMax2DGraphics.Create( g,Self )
  369. End Method
  370. Method SetGraphics( g:TGraphics ) Override
  371. If Not g
  372. TMax2DGraphics.ClearCurrent()
  373. GLGraphicsDriver().SetGraphics(Null)
  374. Return
  375. EndIf
  376. Local t:TMax2DGraphics = TMax2DGraphics( g )
  377. Assert t And TGLGraphics( t._backendGraphics )
  378. GLGraphicsDriver().SetGraphics(t._backendGraphics)
  379. ResetGLContext(t)
  380. t.MakeCurrent()
  381. End Method
  382. Method ResetGLContext( g:TGraphics )
  383. Local gw:Int, gh:Int, gd:Int, gr:Int, gf:Long, gx:Int, gy:Int
  384. g.GetSettings( gw, gh, gd, gr, gf, gx, gy )
  385. state_blend = 0
  386. state_boundtex = 0
  387. state_texenabled = 0
  388. glDisable( GL_TEXTURE_2D )
  389. glMatrixMode GL_PROJECTION
  390. glLoadIdentity
  391. glOrtho 0,gw,gh,0,-1,1
  392. glMatrixMode GL_MODELVIEW
  393. glLoadIdentity
  394. glViewport 0,0,gw,gh
  395. ' Create default back buffer render image - the FBO will be value 0 which is the default for the existing backbuffer
  396. Local BackBufferRenderImageFrame:TGLRenderImageFrame = New TGLRenderImageFrame
  397. BackBufferRenderImageFrame.width = gw
  398. BackBufferRenderImageFrame.height = gh
  399. ' cache it
  400. _BackBufferRenderImageFrame = BackBufferRenderImageFrame
  401. _CurrentRenderImageFrame = _BackBufferRenderImageFrame
  402. End Method
  403. Method Flip:Int( sync:Int ) Override
  404. GLGraphicsDriver().Flip sync
  405. End Method
  406. Method ToString:String() Override
  407. Return "OpenGL"
  408. End Method
  409. Method CreateFrameFromPixmap:TGLImageFrame( pixmap:TPixmap, flags:Int ) Override
  410. Return TGLImageFrame.CreateFromPixmap( pixmap, flags )
  411. End Method
  412. Method SetBlend( blend:Int ) Override
  413. If state_blend = blend Return
  414. state_blend = blend
  415. Select blend
  416. Case MASKBLEND
  417. glDisable( GL_BLEND )
  418. glEnable( GL_ALPHA_TEST )
  419. glAlphaFunc( GL_GEQUAL, 0.5 )
  420. Case SOLIDBLEND
  421. glDisable( GL_BLEND )
  422. glDisable( GL_ALPHA_TEST )
  423. Case ALPHABLEND
  424. glEnable( GL_BLEND )
  425. glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )
  426. glDisable( GL_ALPHA_TEST )
  427. Case LIGHTBLEND
  428. glEnable( GL_BLEND )
  429. glBlendFunc( GL_SRC_ALPHA, GL_ONE )
  430. glDisable( GL_ALPHA_TEST )
  431. Case SHADEBLEND
  432. glEnable( GL_BLEND )
  433. glBlendFunc( GL_DST_COLOR, GL_ZERO )
  434. glDisable( GL_ALPHA_TEST )
  435. Default
  436. glDisable( GL_BLEND )
  437. glDisable( GL_ALPHA_TEST )
  438. End Select
  439. End Method
  440. Method SetAlpha( alpha:Float ) Override
  441. If alpha > 1.0 Then alpha = 1.0
  442. If alpha < 0.0 Then alpha = 0.0
  443. color4ub[3] = alpha * 255
  444. glColor4ubv( color4ub )
  445. End Method
  446. Method SetLineWidth( width:Float ) Override
  447. glLineWidth( width )
  448. End Method
  449. Method SetColor( red:Int,green:Int,blue:Int ) Override
  450. color4ub[0] = Min( Max( red, 0 ), 255 )
  451. color4ub[1] = Min( Max( green, 0 ), 255 )
  452. color4ub[2] = Min( Max( blue, 0 ), 255 )
  453. glColor4ubv( color4ub )
  454. End Method
  455. Method SetClsColor( red:Int, green:Int, blue:Int, alpha:Float ) Override
  456. red = Min(Max(red,0),255)
  457. green = Min(Max(green,0),255)
  458. blue = Min(Max(blue,0),255)
  459. glClearColor(red/255.0, green/255.0, blue/255.0, alpha)
  460. End Method
  461. Method SetViewport( x:Int, y:Int, w:Int, h:Int ) Override
  462. _GLScissor_BMaxViewport.x = x
  463. _GLScissor_BMaxViewport.y = y
  464. _GLScissor_BMaxViewport.width = w
  465. _GLScissor_BMaxViewport.height = h
  466. SetScissor(x, y, w, h)
  467. End Method
  468. Method SetTransform( xx:Float, xy:Float, yx:Float, yy:Float ) Override
  469. ix = xx
  470. iy = xy
  471. jx = yx
  472. jy = yy
  473. End Method
  474. Method Cls() Override
  475. glClear( GL_COLOR_BUFFER_BIT )
  476. End Method
  477. Method Plot( x:Float, y:Float ) Override
  478. DisableTex()
  479. glBegin( GL_POINTS )
  480. glVertex2f( x+.5,y+.5 )
  481. glEnd()
  482. End Method
  483. Method DrawLine( x0:Float, y0:Float, x1:Float, y1:Float, tx:Float, ty:Float ) Override
  484. DisableTex()
  485. glBegin( GL_LINES )
  486. glVertex2f( x0 * ix + y0 * iy + tx + .5, x0 * jx + y0 * jy + ty + .5 )
  487. glVertex2f( x1 * ix + y1 * iy + tx + .5, x1 * jx + y1 * jy + ty + .5 )
  488. glEnd()
  489. End Method
  490. Method DrawRect( x0:Float, y0:Float, x1:Float, y1:Float, tx:Float, ty:Float ) Override
  491. DisableTex()
  492. glBegin( GL_QUADS )
  493. glVertex2f( x0 * ix + y0 * iy + tx, x0 * jx + y0 * jy + ty )
  494. glVertex2f( x1 * ix + y0 * iy + tx, x1 * jx + y0 * jy + ty )
  495. glVertex2f( x1 * ix + y1 * iy + tx, x1 * jx + y1 * jy + ty )
  496. glVertex2f( x0 * ix + y1 * iy + tx, x0 * jx + y1 * jy + ty )
  497. glEnd()
  498. End Method
  499. Method DrawOval( x0:Float,y0:Float,x1:Float,y1:Float,tx:Float,ty:Float ) Override
  500. Local xr:Float=(x1-x0)*.5
  501. Local yr:Float=(y1-y0)*.5
  502. Local segs:Int=Abs(xr)+Abs(yr)
  503. segs=Max(segs,12)&~3
  504. x0:+xr
  505. y0:+yr
  506. DisableTex
  507. glBegin GL_POLYGON
  508. For Local i:Int=0 Until segs
  509. Local th:Float=i*360:Float/segs
  510. Local x:Float=x0+Cos(th)*xr
  511. Local y:Float=y0-Sin(th)*yr
  512. glVertex2f x*ix+y*iy+tx,x*jx+y*jy+ty
  513. =======
  514. Method Plot( x:Float, y:Float ) Override
  515. DisableTex()
  516. glBegin( GL_POINTS )
  517. glVertex2f( x+.5,y+.5 )
  518. glEnd()
  519. End Method
  520. Method DrawLine( x0:Float, y0:Float, x1:Float, y1:Float, tx:Float, ty:Float ) Override
  521. DisableTex()
  522. glBegin( GL_LINES )
  523. glVertex2f( x0 * ix + y0 * iy + tx + .5, x0 * jx + y0 * jy + ty + .5 )
  524. glVertex2f( x1 * ix + y1 * iy + tx + .5, x1 * jx + y1 * jy + ty + .5 )
  525. glEnd()
  526. End Method
  527. Method DrawRect( x0:Float, y0:Float, x1:Float, y1:Float, tx:Float, ty:Float ) Override
  528. DisableTex()
  529. glBegin( GL_QUADS )
  530. glVertex2f( x0 * ix + y0 * iy + tx, x0 * jx + y0 * jy + ty )
  531. glVertex2f( x1 * ix + y0 * iy + tx, x1 * jx + y0 * jy + ty )
  532. glVertex2f( x1 * ix + y1 * iy + tx, x1 * jx + y1 * jy + ty )
  533. glVertex2f( x0 * ix + y1 * iy + tx, x0 * jx + y1 * jy + ty )
  534. glEnd()
  535. End Method
  536. Method DrawOval( x0:Float,y0:Float,x1:Float,y1:Float,tx:Float,ty:Float ) Override
  537. Local xr:Float = ( x1 - x0 ) * 0.5
  538. Local yr:Float = ( y1 - y0 ) * 0.5
  539. Local segs:Int = Abs( xr ) + Abs( yr )
  540. segs = Max( segs, 12 ) &~ 3
  541. x0 :+ xr
  542. y0 :+ yr
  543. DisableTex()
  544. glBegin( GL_POLYGON )
  545. For Local i:Int = 0 Until segs
  546. Local th:Float = i * 360.0 / segs
  547. Local x:Float = x0 +Cos(th) * xr
  548. Local y:Float = y0 -Sin(th) * yr
  549. glVertex2f( x * ix + y * iy + tx, x * jx + y * jy + ty )
  550. Next
  551. glEnd()
  552. End Method
  553. Method DrawPoly( xy:Float[], handle_x:Float, handle_y:Float, origin_x:Float, origin_y:Float, indices:Int[] ) Override
  554. If xy.length < 6 Or ( xy.length & 1 ) Then Return
  555. DisableTex()
  556. glBegin( GL_POLYGON )
  557. For Local i:Int = 0 Until xy.length Step 2
  558. Local x:Float = xy[i + 0] + handle_x
  559. Local y:Float = xy[i + 1] + handle_y
  560. glVertex2f( x * ix + y * iy + origin_x, x * jx + y * jy + origin_y )
  561. Next
  562. glEnd()
  563. End Method
  564. Method DrawPixmap( p:TPixmap, x:Int, y:Int ) Override
  565. Local blend:Int = state_blend
  566. DisableTex()
  567. SetBlend( SOLIDBLEND )
  568. Local t:TPixmap = p
  569. If t.format <> PF_RGBA8888 Then t = ConvertPixmap( t, PF_RGBA8888 )
  570. glPixelZoom( 1, -1 )
  571. glRasterPos2i( 0, 0 )
  572. glBitmap( 0, 0, 0, 0, x, -y, Null)
  573. glPixelStorei( GL_UNPACK_ROW_LENGTH, t.pitch Shr 2 )
  574. glDrawPixels( t.width, t.height, GL_RGBA, GL_UNSIGNED_BYTE, t.pixels )
  575. glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 )
  576. glPixelZoom( 1, 1 )
  577. SetBlend( blend )
  578. End Method
  579. Method GrabPixmap:TPixmap( x:Int, y:Int, w:Int, h:Int ) Override
  580. Local blend:Int = state_blend
  581. SetBlend( SOLIDBLEND )
  582. Local p:TPixmap=CreatePixmap( w, h, PF_RGBA8888 )
  583. 'The default backbuffer in Max2D was opaque so overwrote any
  584. 'trash data of a freshly created pixmap. Potentially transparent
  585. 'backbuffers require a complete transparent pixmap to start with.
  586. p.ClearPixels(0)
  587. If _CurrentRenderImageFrame and _CurrentRenderImageFrame <> _BackbufferRenderImageFrame
  588. glReadPixels(x, _CurrentRenderImageFrame.height - h - y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p.pixels)
  589. Else
  590. glReadPixels(x, _BackbufferRenderImageFrame.height - h - y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p.pixels)
  591. EndIf
  592. p = YFlipPixmap( p )
  593. SetBlend( blend )
  594. Return p
  595. End Method
  596. Method SetResolution( width:Float, height:Float ) Override
  597. glMatrixMode( GL_PROJECTION )
  598. glLoadIdentity()
  599. glOrtho( 0, width, height, 0, -1, 1 )
  600. glMatrixMode( GL_MODELVIEW )
  601. End Method
  602. Method CreateRenderImageFrame:TImageFrame(width:UInt, height:UInt, flags:Int) Override
  603. Return TGLRenderImageFrame.Create(width, height, flags)
  604. EndMethod
  605. Method SetRenderImageFrame(RenderImageFrame:TImageFrame) Override
  606. If RenderImageFrame = _CurrentRenderImageFrame
  607. Return
  608. EndIf
  609. glBindFrameBuffer(GL_FRAMEBUFFER, TGLRenderImageFrame(RenderImageFrame).FBO)
  610. _CurrentRenderImageFrame = TGLRenderImageFrame(RenderImageFrame)
  611. Local vp:Rect = _GLScissor_BMaxViewport
  612. SetScissor(vp.x, vp.y, vp.width, vp.height)
  613. SetMatrixAndViewportToCurrentRenderImage()
  614. EndMethod
  615. Method SetBackbuffer()
  616. SetRenderImageFrame(_BackBufferRenderImageFrame)
  617. EndMethod
  618. Private
  619. Field _glewIsInitialised:Int = False
  620. Method SetMatrixAndViewportToCurrentRenderImage()
  621. glMatrixMode(GL_PROJECTION)
  622. glLoadIdentity()
  623. glOrtho(0, _CurrentRenderImageFrame.width, _CurrentRenderImageFrame.height, 0, -1, 1)
  624. glMatrixMode(GL_MODELVIEW)
  625. glLoadIdentity()
  626. glViewport(0, 0, _CurrentRenderImageFrame.width, _CurrentRenderImageFrame.height)
  627. EndMethod
  628. Method SetScissor(x:Int, y:Int, w:Int, h:Int)
  629. Local ri:TImageFrame = _CurrentRenderImageFrame
  630. If x = 0 And y = 0 And w = _CurrentRenderImageFrame.width And h = _CurrentRenderImageFrame.height
  631. glDisable(GL_SCISSOR_TEST)
  632. Else
  633. glEnable(GL_SCISSOR_TEST)
  634. glScissor(x, _CurrentRenderImageFrame.height - y - h, w, h)
  635. EndIf
  636. EndMethod
  637. End Type
  638. Rem
  639. bbdoc: Get OpenGL Max2D Driver
  640. about:
  641. The returned driver can be used with #SetGraphicsDriver to enable OpenGL Max2D
  642. rendering.
  643. End Rem
  644. Function GLMax2DDriver:TGLMax2DDriver()
  645. Global _done:Int
  646. If Not _done
  647. _driver=New TGLMax2DDriver.Create()
  648. _done=True
  649. EndIf
  650. Return _driver
  651. End Function
  652. Local driver:TGLMax2DDriver=GLMax2DDriver()
  653. If driver SetGraphicsDriver driver
  654. ?