glmax2d.bmx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. Strict
  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.13"
  9. ModuleInfo "Author: Mark Sibly"
  10. ModuleInfo "License: zlib/libpng"
  11. ModuleInfo "Copyright: Blitz Research Ltd"
  12. ModuleInfo "Modserver: BRL"
  13. ModuleInfo "History: 1.13 Release"
  14. ModuleInfo "History: Cleaned up SetGraphics"
  15. ModuleInfo "History: 1.12 Release"
  16. ModuleInfo "History: Fixed filtered image min filters"
  17. ModuleInfo "History: 1.11 Release"
  18. ModuleInfo "History: Fixed texture delete logic"
  19. ModuleInfo "History: 1.10 Release"
  20. ModuleInfo "History: Add SetColor/SetClsColor clamping"
  21. ModuleInfo "History: 1.09 Release"
  22. ModuleInfo "History: Fixed DrawPixmap using current blend mode - now always uses SOLIDBLEND"
  23. ModuleInfo "History: 1.08 Release"
  24. ModuleInfo "History: Added MIPMAPPEDIMAGE support"
  25. ModuleInfo "History: 1.07 Release"
  26. ModuleInfo "History: Now default driver for MacOS/Linux only (D3D7 for windows)"
  27. ModuleInfo "History: 1.06 Release"
  28. ModuleInfo "History: Ripped out a bunch of dead code"
  29. ModuleInfo "History: 1.05 Release"
  30. ModuleInfo "History: Added checks to prevent invalid textures deletes"
  31. ?Not opengles And Not nx
  32. Import BRL.Max2D
  33. Import BRL.GLGraphics
  34. Private
  35. Global _driver:TGLMax2DDriver
  36. 'Naughty!
  37. Const GL_BGR=$80E0
  38. Const GL_BGRA=$80E1
  39. Const GL_CLAMP_TO_EDGE=$812F
  40. Const GL_CLAMP_TO_BORDER=$812D
  41. Global ix#,iy#,jx#,jy#
  42. Global color4ub:Byte[4]
  43. Global state_blend
  44. Global state_boundtex
  45. Global state_texenabled
  46. Function BindTex( name )
  47. If name=state_boundtex Return
  48. glBindTexture GL_TEXTURE_2D,name
  49. state_boundtex=name
  50. End Function
  51. Function EnableTex( name )
  52. BindTex name
  53. If state_texenabled Return
  54. glEnable GL_TEXTURE_2D
  55. state_texenabled=True
  56. End Function
  57. Function DisableTex()
  58. If Not state_texenabled Return
  59. glDisable GL_TEXTURE_2D
  60. state_texenabled=False
  61. End Function
  62. Function Pow2Size( n )
  63. Local t=1
  64. While t<n
  65. t:*2
  66. Wend
  67. Return t
  68. End Function
  69. Global dead_texs:TDynamicArray = New TDynamicArray(32),dead_tex_seq
  70. Extern
  71. Function bbAtomicAdd:Int( target:Int Ptr,value:Int )="int bbAtomicAdd( int *,int )!"
  72. End Extern
  73. 'Enqueues a texture for deletion, to prevent release textures on wrong thread.
  74. Function DeleteTex( name,seq )
  75. If seq<>dead_tex_seq Return
  76. dead_texs.AddLast(name)
  77. End Function
  78. Function CreateTex( width,height,flags )
  79. 'alloc new tex
  80. Local name
  81. glGenTextures 1,Varptr name
  82. 'flush dead texs
  83. If dead_tex_seq=GraphicsSeq
  84. Local n:Int = dead_texs.RemoveLast()
  85. While n <> $FFFFFFFF
  86. glDeleteTextures 1, Varptr n
  87. n = dead_texs.RemoveLast()
  88. Wend
  89. EndIf
  90. dead_tex_seq=GraphicsSeq
  91. 'bind new tex
  92. BindTex name
  93. 'set texture parameters
  94. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE
  95. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE
  96. If flags & FILTEREDIMAGE
  97. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
  98. If flags & MIPMAPPEDIMAGE
  99. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR
  100. Else
  101. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR
  102. EndIf
  103. Else
  104. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST
  105. If flags & MIPMAPPEDIMAGE
  106. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST
  107. Else
  108. glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST
  109. EndIf
  110. EndIf
  111. Local mip_level
  112. Repeat
  113. glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
  114. If Not (flags & MIPMAPPEDIMAGE) Exit
  115. If width=1 And height=1 Exit
  116. If width>1 width:/2
  117. If height>1 height:/2
  118. mip_level:+1
  119. Forever
  120. Return name
  121. End Function
  122. Function UploadTex( pixmap:TPixmap,flags )
  123. Local mip_level
  124. Repeat
  125. glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
  126. glTexSubImage2D GL_TEXTURE_2D,mip_level,0,0,pixmap.width,pixmap.height,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
  127. If Not (flags & MIPMAPPEDIMAGE) Exit
  128. If pixmap.width>1 And pixmap.height>1
  129. pixmap=ResizePixmap( pixmap,pixmap.width/2,pixmap.height/2 )
  130. Else If pixmap.width>1
  131. pixmap=ResizePixmap( pixmap,pixmap.width/2,pixmap.height )
  132. Else If pixmap.height>1
  133. pixmap=ResizePixmap( pixmap,pixmap.width,pixmap.height/2 )
  134. Else
  135. Exit
  136. EndIf
  137. mip_level:+1
  138. Forever
  139. glPixelStorei GL_UNPACK_ROW_LENGTH,0
  140. End Function
  141. Function AdjustTexSize( width Var,height Var )
  142. 'calc texture size
  143. width=Pow2Size( width )
  144. height=Pow2Size( height )
  145. Repeat
  146. Local t
  147. glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
  148. glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
  149. If t Return
  150. If width=1 And height=1 RuntimeError "Unable to calculate tex size"
  151. If width>1 width:/2
  152. If height>1 height:/2
  153. Forever
  154. End Function
  155. Type TDynamicArray
  156. Private
  157. Field data:Int Ptr
  158. Field size:Size_T
  159. Field capacity:Size_T
  160. Field guard:TMutex
  161. Public
  162. Method New(initialCapacity:Int = 8)
  163. capacity = initialCapacity
  164. data = malloc_(Size_T(initialCapacity * 4))
  165. guard = CreateMutex()
  166. End Method
  167. Method AddLast(value:Int)
  168. guard.Lock()
  169. If size = capacity Then
  170. capacity :* 2
  171. Local d:Byte Ptr = realloc_(data, capacity * 4)
  172. If Not d Then
  173. Throw "Failed to allocate more memory"
  174. End If
  175. data = d
  176. End If
  177. data[size] = value
  178. size :+ 1
  179. guard.Unlock()
  180. End Method
  181. Method RemoveLast:Int()
  182. guard.Lock()
  183. Local v:Int
  184. If size > 0 Then
  185. size :- 1
  186. v = data[size]
  187. Else
  188. v = $FFFFFFFF
  189. End If
  190. guard.Unlock()
  191. Return v
  192. End Method
  193. Method Delete()
  194. free_(data)
  195. CloseMutex(guard)
  196. End Method
  197. End Type
  198. Public
  199. Type TGLImageFrame Extends TImageFrame
  200. Field u0#,v0#,u1#,v1#,uscale#,vscale#
  201. Field name,seq
  202. Method New()
  203. seq=GraphicsSeq
  204. End Method
  205. Method Delete()
  206. If Not seq Return
  207. DeleteTex name,seq
  208. seq=0
  209. End Method
  210. Method Draw( x0#,y0#,x1#,y1#,tx#,ty#,sx#,sy#,sw#,sh# )
  211. Assert seq=GraphicsSeq Else "Image does not exist"
  212. Local u0#=sx * uscale
  213. Local v0#=sy * vscale
  214. Local u1#=(sx+sw) * uscale
  215. Local v1#=(sy+sh) * vscale
  216. EnableTex name
  217. glBegin GL_QUADS
  218. glTexCoord2f u0,v0
  219. glVertex2f x0*ix+y0*iy+tx,x0*jx+y0*jy+ty
  220. glTexCoord2f u1,v0
  221. glVertex2f x1*ix+y0*iy+tx,x1*jx+y0*jy+ty
  222. glTexCoord2f u1,v1
  223. glVertex2f x1*ix+y1*iy+tx,x1*jx+y1*jy+ty
  224. glTexCoord2f u0,v1
  225. glVertex2f x0*ix+y1*iy+tx,x0*jx+y1*jy+ty
  226. glEnd
  227. End Method
  228. Function CreateFromPixmap:TGLImageFrame( src:TPixmap,flags )
  229. 'determine tex size
  230. Local tex_w=src.width
  231. Local tex_h=src.height
  232. AdjustTexSize tex_w,tex_h
  233. 'make sure pixmap fits texture
  234. Local width=Min( src.width,tex_w )
  235. Local height=Min( src.height,tex_h )
  236. If src.width<>width Or src.height<>height src=ResizePixmap( src,width,height )
  237. 'create texture pixmap
  238. Local tex:TPixmap=src
  239. '"smear" right/bottom edges if necessary
  240. If width<tex_w Or height<tex_h
  241. tex=TPixmap.Create( tex_w,tex_h,PF_RGBA8888 )
  242. tex.Paste src,0,0
  243. If width<tex_w
  244. tex.Paste src.Window( width-1,0,1,height ),width,0
  245. EndIf
  246. If height<tex_h
  247. tex.Paste src.Window( 0,height-1,width,1 ),0,height
  248. If width<tex_w
  249. tex.Paste src.Window( width-1,height-1,1,1 ),width,height
  250. EndIf
  251. EndIf
  252. Else
  253. If tex.format<>PF_RGBA8888 tex=tex.Convert( PF_RGBA8888 )
  254. EndIf
  255. 'create tex
  256. Local name=CreateTex( tex_w,tex_h,flags )
  257. 'upload it
  258. UploadTex tex,flags
  259. 'done!
  260. Local frame:TGLImageFrame=New TGLImageFrame
  261. frame.name=name
  262. frame.uscale=1.0/tex_w
  263. frame.vscale=1.0/tex_h
  264. frame.u1=width * frame.uscale
  265. frame.v1=height * frame.vscale
  266. Return frame
  267. End Function
  268. End Type
  269. Type TGLMax2DDriver Extends TMax2DDriver
  270. Method Create:TGLMax2DDriver()
  271. If Not GLGraphicsDriver() Return Null
  272. Return Self
  273. End Method
  274. 'graphics driver overrides
  275. Method GraphicsModes:TGraphicsMode[]()
  276. Return GLGraphicsDriver().GraphicsModes()
  277. End Method
  278. Method AttachGraphics:TMax2DGraphics( widget:Byte Ptr,flags )
  279. Local g:TGLGraphics=GLGraphicsDriver().AttachGraphics( widget,flags )
  280. If g Return TMax2DGraphics.Create( g,Self )
  281. End Method
  282. Method CreateGraphics:TMax2DGraphics( width,height,depth,hertz,flags )
  283. Local g:TGLGraphics=GLGraphicsDriver().CreateGraphics( width,height,depth,hertz,flags )
  284. If g Return TMax2DGraphics.Create( g,Self )
  285. End Method
  286. Method SetGraphics( g:TGraphics )
  287. If Not g
  288. TMax2DGraphics.ClearCurrent
  289. GLGraphicsDriver().SetGraphics Null
  290. Return
  291. EndIf
  292. Local t:TMax2DGraphics=TMax2DGraphics(g)
  293. Assert t And TGLGraphics( t._graphics )
  294. GLGraphicsDriver().SetGraphics t._graphics
  295. ResetGLContext t
  296. t.MakeCurrent
  297. End Method
  298. Method ResetGLContext( g:TGraphics )
  299. Local gw,gh,gd,gr,gf
  300. g.GetSettings gw,gh,gd,gr,gf
  301. state_blend=0
  302. state_boundtex=0
  303. state_texenabled=0
  304. glDisable GL_TEXTURE_2D
  305. glMatrixMode GL_PROJECTION
  306. glLoadIdentity
  307. glOrtho 0,gw,gh,0,-1,1
  308. glMatrixMode GL_MODELVIEW
  309. glLoadIdentity
  310. glViewport 0,0,gw,gh
  311. End Method
  312. Method Flip( sync )
  313. GLGraphicsDriver().Flip sync
  314. End Method
  315. Method ToString$()
  316. Return "OpenGL"
  317. End Method
  318. Method CreateFrameFromPixmap:TGLImageFrame( pixmap:TPixmap,flags )
  319. Local frame:TGLImageFrame
  320. frame=TGLImageFrame.CreateFromPixmap( pixmap,flags )
  321. Return frame
  322. End Method
  323. Method SetBlend( blend )
  324. If blend=state_blend Return
  325. state_blend=blend
  326. Select blend
  327. Case MASKBLEND
  328. glDisable GL_BLEND
  329. glEnable GL_ALPHA_TEST
  330. glAlphaFunc GL_GEQUAL,.5
  331. Case SOLIDBLEND
  332. glDisable GL_BLEND
  333. glDisable GL_ALPHA_TEST
  334. Case ALPHABLEND
  335. glEnable GL_BLEND
  336. glBlendFunc GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA
  337. glDisable GL_ALPHA_TEST
  338. Case LIGHTBLEND
  339. glEnable GL_BLEND
  340. glBlendFunc GL_SRC_ALPHA,GL_ONE
  341. glDisable GL_ALPHA_TEST
  342. Case SHADEBLEND
  343. glEnable GL_BLEND
  344. glBlendFunc GL_DST_COLOR,GL_ZERO
  345. glDisable GL_ALPHA_TEST
  346. Default
  347. glDisable GL_BLEND
  348. glDisable GL_ALPHA_TEST
  349. End Select
  350. End Method
  351. Method SetAlpha( alpha# )
  352. If alpha>1.0 alpha=1.0
  353. If alpha<0.0 alpha=0.0
  354. color4ub[3]=alpha*255
  355. glColor4ubv color4ub
  356. End Method
  357. Method SetLineWidth( width# )
  358. glLineWidth width
  359. End Method
  360. Method SetColor( red,green,blue )
  361. color4ub[0]=Min(Max(red,0),255)
  362. color4ub[1]=Min(Max(green,0),255)
  363. color4ub[2]=Min(Max(blue,0),255)
  364. glColor4ubv color4ub
  365. End Method
  366. Method SetClsColor( red,green,blue )
  367. red=Min(Max(red,0),255)
  368. green=Min(Max(green,0),255)
  369. blue=Min(Max(blue,0),255)
  370. glClearColor red/255.0,green/255.0,blue/255.0,1.0
  371. End Method
  372. Method SetViewport( x,y,w,h )
  373. If x=0 And y=0 And w=GraphicsWidth() And h=GraphicsHeight()
  374. glDisable GL_SCISSOR_TEST
  375. Else
  376. glEnable GL_SCISSOR_TEST
  377. glScissor x,GraphicsHeight()-y-h,w,h
  378. EndIf
  379. End Method
  380. Method SetTransform( xx#,xy#,yx#,yy# )
  381. ix=xx
  382. iy=xy
  383. jx=yx
  384. jy=yy
  385. End Method
  386. Method Cls()
  387. glClear GL_COLOR_BUFFER_BIT
  388. End Method
  389. Method Plot( x#,y# )
  390. DisableTex
  391. glBegin GL_POINTS
  392. glVertex2f x+.5,y+.5
  393. glEnd
  394. End Method
  395. Method DrawLine( x0#,y0#,x1#,y1#,tx#,ty# )
  396. DisableTex
  397. glBegin GL_LINES
  398. glVertex2f x0*ix+y0*iy+tx+.5,x0*jx+y0*jy+ty+.5
  399. glVertex2f x1*ix+y1*iy+tx+.5,x1*jx+y1*jy+ty+.5
  400. glEnd
  401. End Method
  402. Method DrawRect( x0#,y0#,x1#,y1#,tx#,ty# )
  403. DisableTex
  404. glBegin GL_QUADS
  405. glVertex2f x0*ix+y0*iy+tx,x0*jx+y0*jy+ty
  406. glVertex2f x1*ix+y0*iy+tx,x1*jx+y0*jy+ty
  407. glVertex2f x1*ix+y1*iy+tx,x1*jx+y1*jy+ty
  408. glVertex2f x0*ix+y1*iy+tx,x0*jx+y1*jy+ty
  409. glEnd
  410. End Method
  411. Method DrawOval( x0#,y0#,x1#,y1#,tx#,ty# )
  412. Local xr#=(x1-x0)*.5
  413. Local yr#=(y1-y0)*.5
  414. Local segs=Abs(xr)+Abs(yr)
  415. segs=Max(segs,12)&~3
  416. x0:+xr
  417. y0:+yr
  418. DisableTex
  419. glBegin GL_POLYGON
  420. For Local i=0 Until segs
  421. Local th#=i*360#/segs
  422. Local x#=x0+Cos(th)*xr
  423. Local y#=y0-Sin(th)*yr
  424. glVertex2f x*ix+y*iy+tx,x*jx+y*jy+ty
  425. Next
  426. glEnd
  427. End Method
  428. Method DrawPoly( xy#[],handle_x#,handle_y#,origin_x#,origin_y# )
  429. If xy.length<6 Or (xy.length&1) Return
  430. DisableTex
  431. glBegin GL_POLYGON
  432. For Local i=0 Until Len xy Step 2
  433. Local x#=xy[i+0]+handle_x
  434. Local y#=xy[i+1]+handle_y
  435. glVertex2f x*ix+y*iy+origin_x,x*jx+y*jy+origin_y
  436. Next
  437. glEnd
  438. End Method
  439. Method DrawPixmap( p:TPixmap,x,y )
  440. Local blend=state_blend
  441. DisableTex
  442. SetBlend SOLIDBLEND
  443. Local t:TPixmap=p
  444. If t.format<>PF_RGBA8888 t=ConvertPixmap( t,PF_RGBA8888 )
  445. glPixelZoom 1,-1
  446. glRasterPos2i 0,0
  447. glBitmap 0,0,0,0,x,-y,Null
  448. glPixelStorei GL_UNPACK_ROW_LENGTH, t.pitch Shr 2
  449. glDrawPixels t.width,t.height,GL_RGBA,GL_UNSIGNED_BYTE,t.pixels
  450. glPixelStorei GL_UNPACK_ROW_LENGTH,0
  451. glPixelZoom 1,1
  452. SetBlend blend
  453. End Method
  454. Method GrabPixmap:TPixmap( x,y,w,h )
  455. Local blend=state_blend
  456. SetBlend SOLIDBLEND
  457. Local p:TPixmap=CreatePixmap( w,h,PF_RGBA8888 )
  458. glReadPixels x,GraphicsHeight()-h-y,w,h,GL_RGBA,GL_UNSIGNED_BYTE,p.pixels
  459. p=YFlipPixmap( p )
  460. SetBlend blend
  461. Return p
  462. End Method
  463. Method SetResolution( width#,height# )
  464. glMatrixMode GL_PROJECTION
  465. glLoadIdentity
  466. glOrtho 0,width,height,0,-1,1
  467. glMatrixMode GL_MODELVIEW
  468. End Method
  469. End Type
  470. Rem
  471. bbdoc: Get OpenGL Max2D Driver
  472. about:
  473. The returned driver can be used with #SetGraphicsDriver to enable OpenGL Max2D
  474. rendering.
  475. End Rem
  476. Function GLMax2DDriver:TGLMax2DDriver()
  477. Global _done
  478. If Not _done
  479. _driver=New TGLMax2DDriver.Create()
  480. _done=True
  481. EndIf
  482. Return _driver
  483. End Function
  484. Local driver:TGLMax2DDriver=GLMax2DDriver()
  485. If driver SetGraphicsDriver driver
  486. ?