glmax2d.bmx 12 KB

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