sdlrendermax2d.bmx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. ' Copyright (c) 2021-2022 Bruce A Henderson
  2. '
  3. ' This software is provided 'as-is', without any express or implied
  4. ' warranty. In no event will the authors be held liable for any damages
  5. ' arising from the use of this software.
  6. '
  7. ' Permission is granted to anyone to use this software for any purpose,
  8. ' including commercial applications, and to alter it and redistribute it
  9. ' freely, subject to the following restrictions:
  10. '
  11. ' 1. The origin of this software must not be misrepresented; you must not
  12. ' claim that you wrote the original software. If you use this software
  13. ' in a product, an acknowledgment in the product documentation would be
  14. ' appreciated but is not required.
  15. '
  16. ' 2. Altered source versions must be plainly marked as such, and must not be
  17. ' misrepresented as being the original software.
  18. '
  19. ' 3. This notice may not be removed or altered from any source
  20. ' distribution.
  21. '
  22. SuperStrict
  23. Rem
  24. bbdoc: Graphics/SDLRender Max2D
  25. about:
  26. The SDLRender Max2D module provides an SDL-backend SDLRender driver for #Max2D.
  27. End Rem
  28. Module SDL.SDLRenderMax2D
  29. ModuleInfo "Version: 1.00"
  30. ModuleInfo "License: zlib/libpng"
  31. ModuleInfo "History: 1.00"
  32. ModuleInfo "History: Initial release"
  33. Import BRL.Max2D
  34. Import SDL.SDLGraphics
  35. Import SDL.SDLRender
  36. Private
  37. Global _driver:TSDLRenderMax2DDriver
  38. Function Pow2Size:Int( n:Int )
  39. Local t:Int = 1
  40. While t < n
  41. t :* 2
  42. Wend
  43. Return t
  44. End Function
  45. Function AdjustTexSize( width:Int Var, height:Int Var )
  46. 'calc texture size
  47. width = Pow2Size( width )
  48. height = Pow2Size( height )
  49. End Function
  50. Public
  51. Type TSDLRenderImageFrame Extends TImageFrame
  52. Field u0#, v0#, u1#, v1#, uscale#, vscale#
  53. Field pixmap:TPixmap
  54. Field surface:TSDLSurface
  55. Field texture:TSDLTexture
  56. Field renderer:TSDLRenderer
  57. Method New()
  58. End Method
  59. Method Delete()
  60. If texture Then
  61. texture.Destroy()
  62. texture = Null
  63. End If
  64. If surface Then
  65. surface.Free()
  66. surface = Null
  67. End If
  68. pixmap = Null
  69. End Method
  70. Method Draw( x0#,y0#,x1#,y1#,tx#,ty#,sx#,sy#,sw#,sh# ) Override
  71. Local u0# = sx * uscale
  72. Local v0# = sy * vscale
  73. Local u1# = ( sx + sw ) * uscale
  74. Local v1# = ( sy + sh ) * vscale
  75. _driver.DrawTexture( texture, u0, v0, u1, v1, x0, y0, x1, y1, tx, ty, Self )
  76. End Method
  77. Function CreateFromPixmap:TSDLRenderImageFrame( src:TPixmap,flags:Int )
  78. Local tex_w:Int = src.width
  79. Local tex_h:Int = src.height
  80. Local width:Int = Min( src.width, tex_w )
  81. Local height:Int = Min( src.height, tex_h )
  82. If src.format <> PF_RGBA8888 And src.format <> PF_RGB888 Then
  83. src = src.Convert( PF_RGBA8888 )
  84. End If
  85. 'done!
  86. Local frame:TSDLRenderImageFrame=New TSDLRenderImageFrame
  87. frame.renderer = _driver.renderer
  88. frame.pixmap = src
  89. frame.surface = TSDLSurface.CreateRGBFrom(src.pixels, src.width, src.height, BitsPerPixel[src.format], src.pitch, $000000ff:UInt, $0000ff00:UInt, $00ff0000:UInt, $ff000000:UInt)
  90. frame.texture = frame.renderer.CreateTextureFromSurface(frame.surface)
  91. frame.uscale = 1.0 / tex_w
  92. frame.vscale = 1.0 / tex_h
  93. frame.u1 = width * frame.uscale
  94. frame.v1 = height * frame.vscale
  95. Return frame
  96. End Function
  97. End Type
  98. Type TSDLRenderMax2DDriver Extends TMax2DDriver
  99. Field drawColor:SDLColor = New SDLColor(255, 255, 255, 255)
  100. Field clsColor:SDLColor = New SDLColor(0, 0, 0, 255)
  101. Field renderer:TSDLRenderer
  102. Field ix#,iy#,jx#,jy#
  103. Field state_blend:Int
  104. Method Create:TSDLRenderMax2DDriver()
  105. If Not SDLGraphicsDriver() Return Null
  106. Return Self
  107. End Method
  108. 'graphics driver overrides
  109. Method GraphicsModes:TGraphicsMode[]() Override
  110. Return SDLGraphicsDriver().GraphicsModes()
  111. End Method
  112. Method AttachGraphics:TMax2DGraphics( widget:Byte Ptr,flags:Long ) Override
  113. Local g:TSDLGraphics=SDLGraphicsDriver().AttachGraphics( widget,flags )
  114. If g Return TMax2DGraphics.Create( g,Self )
  115. End Method
  116. Method CreateGraphics:TMax2DGraphics( width:Int,height:Int,depth:Int,hertz:Int,flags:Long,x:Int,y:Int ) Override
  117. Local g:TSDLGraphics=SDLGraphicsDriver().CreateGraphics( width,height,depth,hertz,flags,x,y )
  118. If g Return TMax2DGraphics.Create( g,Self )
  119. End Method
  120. Method SetGraphics( g:TGraphics ) Override
  121. If Not g
  122. TMax2DGraphics.ClearCurrent
  123. SDLGraphicsDriver().SetGraphics Null
  124. Return
  125. EndIf
  126. Local t:TMax2DGraphics=TMax2DGraphics(g)
  127. Assert t And TSDLGraphics( t._graphics )
  128. Local gfx:TSDLGraphics = TSDLGraphics( t._graphics )
  129. SDLGraphicsDriver().SetGraphics gfx
  130. renderer = TSDLRenderer.Create(gfx._context.window)
  131. 'ResetGLContext t
  132. t.MakeCurrent
  133. End Method
  134. Method Flip:Int( sync:Int ) Override
  135. renderer.Present()
  136. End Method
  137. Method ToString$() Override
  138. Return "SDLRenderer"
  139. End Method
  140. Method CreateFrameFromPixmap:TSDLRenderImageFrame( pixmap:TPixmap,flags:Int ) Override
  141. Local frame:TSDLRenderImageFrame
  142. frame=TSDLRenderImageFrame.CreateFromPixmap( pixmap,flags )
  143. Return frame
  144. End Method
  145. Method SetBlend( blend:Int ) Override
  146. If blend=state_blend Return
  147. state_blend=blend
  148. Select blend
  149. Case MASKBLEND
  150. renderer.SetDrawBlendMode(SDL_BLENDMODE_BLEND)
  151. Case SOLIDBLEND
  152. renderer.SetDrawBlendMode(SDL_BLENDMODE_NONE)
  153. Case ALPHABLEND
  154. renderer.SetDrawBlendMode(SDL_BLENDMODE_BLEND)
  155. Case LIGHTBLEND
  156. renderer.SetDrawBlendMode(SDL_BLENDMODE_ADD)
  157. Case SHADEBLEND
  158. renderer.SetDrawBlendMode(SDL_BLENDMODE_MOD)
  159. Default
  160. renderer.SetDrawBlendMode(SDL_BLENDMODE_NONE)
  161. End Select
  162. End Method
  163. Method SetAlpha( alpha# ) Override
  164. If alpha>1.0 alpha=1.0
  165. If alpha<0.0 alpha=0.0
  166. drawColor.a=alpha*255
  167. End Method
  168. Method SetLineWidth( width# ) Override
  169. 'glLineWidth width
  170. End Method
  171. Method SetColor( red:Int,green:Int,blue:Int ) Override
  172. drawColor.r = Min(Max(red,0),255)
  173. drawColor.g = Min(Max(green,0),255)
  174. drawColor.b = Min(Max(blue,0),255)
  175. renderer.SetDrawColor(drawColor.r, drawColor.g, drawColor.b, drawColor.a)
  176. End Method
  177. Method SetColor( color:SColor8 ) Override
  178. drawColor.r=color.r
  179. drawColor.g=color.g
  180. drawColor.b=color.b
  181. renderer.SetDrawColor(drawColor.r, drawColor.g, drawColor.b, drawColor.a)
  182. End Method
  183. Method SetClsColor( red:Int,green:Int,blue:Int ) Override
  184. clsColor.r = Min(Max(red,0),255)
  185. clsColor.g = Min(Max(green,0),255)
  186. clsColor.b = Min(Max(blue,0),255)
  187. clsColor.a = 255
  188. End Method
  189. Method SetClsColor( color:SColor8 ) Override
  190. clsColor.r=color.r
  191. clsColor.g=color.g
  192. clsColor.b=color.b
  193. clsColor.a = 255
  194. End Method
  195. Method SetViewport( x:Int,y:Int,w:Int,h:Int ) Override
  196. If x=0 And y=0 And w=GraphicsWidth() And h=GraphicsHeight()
  197. renderer.SetViewport()
  198. Else
  199. renderer.SetViewport(x, y, w, h)
  200. EndIf
  201. End Method
  202. Method SetTransform( xx#,xy#,yx#,yy# ) Override
  203. ix=xx
  204. iy=xy
  205. jx=yx
  206. jy=yy
  207. End Method
  208. Method Cls() Override
  209. renderer.SetDrawColor(clsColor.r, clsColor.g, clsColor.b, clsColor.a)
  210. renderer.Clear()
  211. renderer.SetDrawColor(drawColor.r, drawColor.g, drawColor.b, drawColor.a)
  212. End Method
  213. Method Plot( x#,y# ) Override
  214. renderer.DrawPoint(Int(x+.5),Int(y+.5))
  215. End Method
  216. Method DrawLine( x0#,y0#,x1#,y1#,tx#,ty# ) Override
  217. renderer.DrawLine(Int(x0*ix+y0*iy+tx+.5), Int(x0*jx+y0*jy+ty+.5), Int(x1*ix+y1*iy+tx+.5), Int(x1*jx+y1*jy+ty+.5))
  218. End Method
  219. Method DrawRect( x0#,y0#,x1#,y1#,tx#,ty# ) Override
  220. Local StaticArray vertices:SDLVertex[4]
  221. Local vert:SDLVertex Ptr = vertices
  222. vert.position.x = x0 * ix + y0 * iy + tx
  223. vert.position.y = x0 * jx + y0 * jy + ty
  224. vert.color = _driver.drawColor
  225. vert :+ 1
  226. vert.position.x = x1 * ix + y0 * iy + tx
  227. vert.position.y = x1 * jx + y0 * jy + ty
  228. vert.color = _driver.drawColor
  229. vert :+ 1
  230. vert.position.x = x1 * ix + y1 * iy + tx
  231. vert.position.y = x1 * jx + y1 * jy + ty
  232. vert.color = _driver.drawColor
  233. vert :+ 1
  234. vert.position.x = x0 * ix + y1 * iy + tx
  235. vert.position.y = x0 * jx + y1 * jy + ty
  236. vert.color = _driver.drawColor
  237. Local StaticArray indices:Int[6]
  238. indices[0] = 0
  239. indices[1] = 2
  240. indices[2] = 1
  241. indices[3] = 0
  242. indices[4] = 3
  243. indices[5] = 2
  244. renderer.Geometry(Null, vertices, 4, indices, 6)
  245. End Method
  246. Method DrawOval( x0#,y0#,x1#,y1#,tx#,ty# ) Override
  247. Local StaticArray vertices:SDLVertex[50]
  248. Local vert:SDLVertex Ptr = vertices
  249. Local vc:int
  250. Local StaticArray indices:Int[147]
  251. local ic:int
  252. Local xr#=(x1-x0)*.5
  253. Local yr#=(y1-y0)*.5
  254. local r:Float = (xr + yr) * 0.5
  255. Local segs:Int = Min(49, 360 / acos(2 * (1 - 0.5 / r)^2 - 1))
  256. x0:+xr
  257. y0:+yr
  258. ' center
  259. vert.position.x = x0 * ix + y0 * iy + tx
  260. vert.position.y = x0 * jx + y0 * jy + ty
  261. vert.color = _driver.drawColor
  262. vert :+ 1
  263. vc :+ 1
  264. For Local i:Int=0 Until segs
  265. Local th#=i*360#/segs
  266. Local x#=x0+Cos(th)*xr
  267. Local y#=y0-Sin(th)*yr
  268. vert.position.x = x * ix + y * iy + tx
  269. vert.position.y = x * jx + y * jy + ty
  270. vert.color = _driver.drawColor
  271. vert :+ 1
  272. vc :+ 1
  273. Next
  274. For Local i:Int=0 Until segs - 1
  275. indices[i * 3] = 0
  276. indices[i * 3 + 1] = i + 1
  277. indices[i * 3 + 2] = i + 2
  278. ic :+ 3
  279. Next
  280. ' connect last & first
  281. Local i:Int = segs - 1
  282. indices[i * 3] = 0
  283. indices[i * 3 + 1] = i + 1
  284. indices[i * 3 + 2] = 1
  285. ic :+ 3
  286. renderer.Geometry(Null, vertices, vc, indices, ic)
  287. End Method
  288. Method DrawPoly( xy#[],handle_x#,handle_y#,origin_x#,origin_y# ) Override
  289. rem
  290. If xy.length<6 Or (xy.length&1) Return
  291. DisableTex
  292. glBegin GL_POLYGON
  293. For Local i:Int=0 Until Len xy Step 2
  294. Local x#=xy[i+0]+handle_x
  295. Local y#=xy[i+1]+handle_y
  296. glVertex2f x*ix+y*iy+origin_x,x*jx+y*jy+origin_y
  297. Next
  298. glEnd
  299. end rem
  300. End Method
  301. Method DrawPixmap( p:TPixmap,x:Int,y:Int ) Override
  302. rem
  303. Local blend:Int=state_blend
  304. DisableTex
  305. SetBlend SOLIDBLEND
  306. Local t:TPixmap=p
  307. If t.format<>PF_RGBA8888 t=ConvertPixmap( t,PF_RGBA8888 )
  308. glPixelZoom 1,-1
  309. glRasterPos2i 0,0
  310. glBitmap 0,0,0,0,x,-y,Null
  311. glPixelStorei GL_UNPACK_ROW_LENGTH, t.pitch Shr 2
  312. glDrawPixels t.width,t.height,GL_RGBA,GL_UNSIGNED_BYTE,t.pixels
  313. glPixelStorei GL_UNPACK_ROW_LENGTH,0
  314. glPixelZoom 1,1
  315. SetBlend blend
  316. end rem
  317. End Method
  318. Method DrawTexture( texture:TSDLTexture, u0#, v0#, u1#, v1#, x0#, y0#, x1#, y1#, tx#, ty#, img:TImageFrame = Null )
  319. Local StaticArray vertices:SDLVertex[4]
  320. Local vert:SDLVertex Ptr = vertices
  321. vert.position.x = x0 * ix + y0 * iy + tx
  322. vert.position.y = x0 * jx + y0 * jy + ty
  323. vert.color = _driver.drawColor
  324. vert.texCoord.x = u0
  325. vert.texCoord.y = v0
  326. vert :+ 1
  327. vert.position.x = x1 * ix + y0 * iy + tx
  328. vert.position.y = x1 * jx + y0 * jy + ty
  329. vert.color = _driver.drawColor
  330. vert.texCoord.x = u1
  331. vert.texCoord.y = v0
  332. vert :+ 1
  333. vert.position.x = x1 * ix + y1 * iy + tx
  334. vert.position.y = x1 * jx + y1 * jy + ty
  335. vert.color = _driver.drawColor
  336. vert.texCoord.x = u1
  337. vert.texCoord.y = v1
  338. vert :+ 1
  339. vert.position.x = x0 * ix + y1 * iy + tx
  340. vert.position.y = x0 * jx + y1 * jy + ty
  341. vert.color = _driver.drawColor
  342. vert.texCoord.x = u0
  343. vert.texCoord.y = v1
  344. Local StaticArray indices:Int[6]
  345. indices[0] = 0
  346. indices[1] = 2
  347. indices[2] = 1
  348. indices[3] = 0
  349. indices[4] = 3
  350. indices[5] = 2
  351. Select state_blend
  352. Case ALPHABLEND
  353. texture.SetBlendMode(SDL_BLENDMODE_BLEND)
  354. Case MASKBLEND
  355. texture.SetBlendMode(SDL_BLENDMODE_BLEND)
  356. Case SOLIDBLEND
  357. texture.SetBlendMode(SDL_BLENDMODE_NONE)
  358. Case LIGHTBLEND
  359. texture.SetBlendMode(SDL_BLENDMODE_ADD)
  360. Case SHADEBLEND
  361. texture.SetBlendMode(SDL_BLENDMODE_MOD)
  362. Default
  363. texture.SetBlendMode(SDL_BLENDMODE_NONE)
  364. End Select
  365. renderer.Geometry(texture, vertices, 4, indices, 6)
  366. End Method
  367. Method GrabPixmap:TPixmap( x:Int,y:Int,w:Int,h:Int ) Override
  368. rem
  369. Local blend:Int=state_blend
  370. SetBlend SOLIDBLEND
  371. Local p:TPixmap=CreatePixmap( w,h,PF_RGBA8888 )
  372. glReadPixels x,GraphicsHeight()-h-y,w,h,GL_RGBA,GL_UNSIGNED_BYTE,p.pixels
  373. p=YFlipPixmap( p )
  374. SetBlend blend
  375. Return p
  376. end rem
  377. End Method
  378. Method SetResolution( width#,height# ) Override
  379. renderer.SetLogicalSize(Int(width), Int(height))
  380. End Method
  381. End Type
  382. Rem
  383. bbdoc: Get SDLRender Max2D Driver
  384. about:
  385. The returned driver can be used with #SetGraphicsDriver to enable SDLRender Max2D
  386. rendering.
  387. End Rem
  388. Function SDLRenderMax2DDriver:TSDLRenderMax2DDriver()
  389. Global _done:Int
  390. If Not _done
  391. _driver=New TSDLRenderMax2DDriver.Create()
  392. _done=True
  393. EndIf
  394. Return _driver
  395. End Function
  396. Local driver:TSDLRenderMax2DDriver=SDLRenderMax2DDriver()
  397. If driver SetGraphicsDriver driver