123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- ' Copyright (c) 2021-2022 Bruce A Henderson
- '
- ' This software is provided 'as-is', without any express or implied
- ' warranty. In no event will the authors be held liable for any damages
- ' arising from the use of this software.
- '
- ' Permission is granted to anyone to use this software for any purpose,
- ' including commercial applications, and to alter it and redistribute it
- ' freely, subject to the following restrictions:
- '
- ' 1. The origin of this software must not be misrepresented; you must not
- ' claim that you wrote the original software. If you use this software
- ' in a product, an acknowledgment in the product documentation would be
- ' appreciated but is not required.
- '
- ' 2. Altered source versions must be plainly marked as such, and must not be
- ' misrepresented as being the original software.
- '
- ' 3. This notice may not be removed or altered from any source
- ' distribution.
- '
- SuperStrict
- Rem
- bbdoc: Graphics/SDLRender Max2D
- about:
- The SDLRender Max2D module provides an SDL-backend SDLRender driver for #Max2D.
- End Rem
- Module SDL.SDLRenderMax2D
- ModuleInfo "Version: 1.00"
- ModuleInfo "License: zlib/libpng"
- ModuleInfo "History: 1.00"
- ModuleInfo "History: Initial release"
- Import BRL.Max2D
- Import SDL.SDLGraphics
- Import SDL.SDLRender
- Import Math.Polygon
- Private
- Global _driver:TSDLRenderMax2DDriver
- Global _preferredRenderer:Int = -1
- Function Pow2Size:Int( n:Int )
- Local t:Int = 1
- While t < n
- t :* 2
- Wend
- Return t
- End Function
- Function AdjustTexSize( width:Int Var, height:Int Var )
- 'calc texture size
- width = Pow2Size( width )
- height = Pow2Size( height )
- End Function
- Public
- Type TSDLRenderImageFrame Extends TImageFrame
- Field u0#, v0#, u1#, v1#, uscale#, vscale#
- Field pixmap:TPixmap
- Field surface:TSDLSurface
- Field texture:TSDLTexture
- Field renderer:TSDLRenderer
-
- Method New()
- End Method
-
- Method Delete()
- If texture Then
- texture.Destroy()
- texture = Null
- End If
- If surface Then
- surface.Free()
- surface = Null
- End If
- pixmap = Null
- End Method
-
- Method Draw( x0#,y0#,x1#,y1#,tx#,ty#,sx#,sy#,sw#,sh# ) Override
- Local u0# = sx * uscale
- Local v0# = sy * vscale
- Local u1# = ( sx + sw ) * uscale
- Local v1# = ( sy + sh ) * vscale
- _driver.DrawTexture( texture, u0, v0, u1, v1, x0, y0, x1, y1, tx, ty, Self )
- End Method
-
- Function CreateFromPixmap:TSDLRenderImageFrame( src:TPixmap,flags:Int )
-
- Local tex_w:Int = src.width
- Local tex_h:Int = src.height
-
- Local width:Int = Min( src.width, tex_w )
- Local height:Int = Min( src.height, tex_h )
-
- If src.format <> PF_RGBA8888 And src.format <> PF_RGB888 Then
- src = src.Convert( PF_RGBA8888 )
- End If
- 'done!
- Local frame:TSDLRenderImageFrame=New TSDLRenderImageFrame
- frame.renderer = _driver.renderer
- frame.pixmap = src
- frame.surface = TSDLSurface.CreateRGBFrom(src.pixels, src.width, src.height, BitsPerPixel[src.format], src.pitch, $000000ff:UInt, $0000ff00:UInt, $00ff0000:UInt, $ff000000:UInt)
- frame.texture = frame.renderer.CreateTextureFromSurface(frame.surface)
- frame.uscale = 1.0 / tex_w
- frame.vscale = 1.0 / tex_h
- frame.u1 = width * frame.uscale
- frame.v1 = height * frame.vscale
- Return frame
- End Function
- End Type
- Type TSDLRenderMax2DDriver Extends TMax2DDriver
- Field drawColor:SDLColor = New SDLColor(255, 255, 255, 255)
- Field clsColor:SDLColor = New SDLColor(0, 0, 0, 255)
- Field renderer:TSDLRenderer
- Field ix#,iy#,jx#,jy#
- Field state_blend:Int
- Method Create:TSDLRenderMax2DDriver()
- If Not SDLGraphicsDriver() Return Null
-
- Return Self
- End Method
- 'graphics driver overrides
- Method GraphicsModes:TGraphicsMode[]() Override
- Return SDLGraphicsDriver().GraphicsModes()
- End Method
-
- Method AttachGraphics:TMax2DGraphics( widget:Byte Ptr,flags:Long ) Override
- Local g:TSDLGraphics=SDLGraphicsDriver().AttachGraphics( widget,flags )
- If g Return TMax2DGraphics.Create( g,Self )
- End Method
-
- Method CreateGraphics:TMax2DGraphics( width:Int,height:Int,depth:Int,hertz:Int,flags:Long,x:Int,y:Int ) Override
- Local g:TSDLGraphics=SDLGraphicsDriver().CreateGraphics( width,height,depth,hertz,flags,x,y )
- If g Return TMax2DGraphics.Create( g,Self )
- End Method
-
- Method SetGraphics( g:TGraphics ) Override
- If Not g
- TMax2DGraphics.ClearCurrent
- SDLGraphicsDriver().SetGraphics Null
- Return
- EndIf
-
- Local t:TMax2DGraphics=TMax2DGraphics(g)
- Assert t And TSDLGraphics( t._graphics )
- Local gfx:TSDLGraphics = TSDLGraphics( t._graphics )
- SDLGraphicsDriver().SetGraphics gfx
- Local flags:UInt
- If gfx._context.flags & GRAPHICS_SWAPINTERVAL1 Then
- flags :| SDL_RENDERER_PRESENTVSYNC
- End If
- renderer = TSDLRenderer.Create(gfx._context.window, _preferredRenderer, flags)
-
- t.MakeCurrent
- End Method
- Method Flip:Int( sync:Int ) Override
- renderer.Present()
- End Method
-
- Method ToString$() Override
- Return "SDLRenderer"
- End Method
- Method CreateFrameFromPixmap:TSDLRenderImageFrame( pixmap:TPixmap,flags:Int ) Override
- Local frame:TSDLRenderImageFrame
- frame=TSDLRenderImageFrame.CreateFromPixmap( pixmap,flags )
- Return frame
- End Method
- Method SetBlend( blend:Int ) Override
- If blend=state_blend Return
- state_blend=blend
- Select blend
- Case MASKBLEND
- renderer.SetDrawBlendMode(SDL_BLENDMODE_BLEND)
- Case SOLIDBLEND
- renderer.SetDrawBlendMode(SDL_BLENDMODE_NONE)
- Case ALPHABLEND
- renderer.SetDrawBlendMode(SDL_BLENDMODE_BLEND)
- Case LIGHTBLEND
- renderer.SetDrawBlendMode(SDL_BLENDMODE_ADD)
- Case SHADEBLEND
- renderer.SetDrawBlendMode(SDL_BLENDMODE_MOD)
- Default
- renderer.SetDrawBlendMode(SDL_BLENDMODE_NONE)
- End Select
- End Method
- Method SetAlpha( alpha# ) Override
- If alpha>1.0 alpha=1.0
- If alpha<0.0 alpha=0.0
- drawColor.a=alpha*255
- End Method
- Method SetLineWidth( width# ) Override
- 'glLineWidth width
- End Method
-
- Method SetColor( red:Int,green:Int,blue:Int ) Override
- drawColor.r = Min(Max(red,0),255)
- drawColor.g = Min(Max(green,0),255)
- drawColor.b = Min(Max(blue,0),255)
- renderer.SetDrawColor(drawColor.r, drawColor.g, drawColor.b, drawColor.a)
- End Method
- Method SetColor( color:SColor8 ) Override
- drawColor.r=color.r
- drawColor.g=color.g
- drawColor.b=color.b
- renderer.SetDrawColor(drawColor.r, drawColor.g, drawColor.b, drawColor.a)
- End Method
- Method SetClsColor( red:Int,green:Int,blue:Int ) Override
- clsColor.r = Min(Max(red,0),255)
- clsColor.g = Min(Max(green,0),255)
- clsColor.b = Min(Max(blue,0),255)
- clsColor.a = 255
- End Method
- Method SetClsColor( color:SColor8 ) Override
- clsColor.r=color.r
- clsColor.g=color.g
- clsColor.b=color.b
- clsColor.a = 255
- End Method
-
- Method SetViewport( x:Int,y:Int,w:Int,h:Int ) Override
- If x=0 And y=0 And w=GraphicsWidth() And h=GraphicsHeight()
- renderer.SetClipRect()
- Else
- renderer.SetClipRect(x, y, w, h)
- EndIf
- End Method
- Method SetTransform( xx#,xy#,yx#,yy# ) Override
- ix=xx
- iy=xy
- jx=yx
- jy=yy
- End Method
- Method Cls() Override
- renderer.SetDrawColor(clsColor.r, clsColor.g, clsColor.b, clsColor.a)
- renderer.Clear()
- renderer.SetDrawColor(drawColor.r, drawColor.g, drawColor.b, drawColor.a)
- End Method
- Method Plot( x#,y# ) Override
- renderer.DrawPoint(Int(x+.5),Int(y+.5))
- End Method
- Method DrawLine( x0#,y0#,x1#,y1#,tx#,ty# ) Override
- 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))
- End Method
- Method DrawRect( x0#,y0#,x1#,y1#,tx#,ty# ) Override
- Local StaticArray vertices:SDLVertex[4]
- Local vert:SDLVertex Ptr = vertices
- vert.position.x = x0 * ix + y0 * iy + tx
- vert.position.y = x0 * jx + y0 * jy + ty
- vert.color = _driver.drawColor
- vert :+ 1
- vert.position.x = x1 * ix + y0 * iy + tx
- vert.position.y = x1 * jx + y0 * jy + ty
- vert.color = _driver.drawColor
- vert :+ 1
- vert.position.x = x1 * ix + y1 * iy + tx
- vert.position.y = x1 * jx + y1 * jy + ty
- vert.color = _driver.drawColor
- vert :+ 1
- vert.position.x = x0 * ix + y1 * iy + tx
- vert.position.y = x0 * jx + y1 * jy + ty
- vert.color = _driver.drawColor
- Local StaticArray indices:Int[6]
- indices[0] = 0
- indices[1] = 2
- indices[2] = 1
- indices[3] = 0
- indices[4] = 3
- indices[5] = 2
- renderer.Geometry(Null, vertices, 4, indices, 6)
- End Method
-
- Method DrawOval( x0#,y0#,x1#,y1#,tx#,ty# ) Override
- Local StaticArray vertices:SDLVertex[50]
- Local vert:SDLVertex Ptr = vertices
- Local vc:int
- Local StaticArray indices:Int[147]
- local ic:int
- Local xr#=(x1-x0)*.5
- Local yr#=(y1-y0)*.5
- local r:Float = (xr + yr) * 0.5
- Local segs:Int = Min(49, 360 / acos(2 * (1 - 0.5 / r)^2 - 1))
- x0:+xr
- y0:+yr
- ' center
- vert.position.x = x0 * ix + y0 * iy + tx
- vert.position.y = x0 * jx + y0 * jy + ty
- vert.color = _driver.drawColor
- vert :+ 1
- vc :+ 1
-
- For Local i:Int=0 Until segs
- Local th#=i*360#/segs
- Local x#=x0+Cos(th)*xr
- Local y#=y0-Sin(th)*yr
- vert.position.x = x * ix + y * iy + tx
- vert.position.y = x * jx + y * jy + ty
- vert.color = _driver.drawColor
- vert :+ 1
- vc :+ 1
- Next
- For Local i:Int=0 Until segs - 1
- indices[i * 3] = 0
- indices[i * 3 + 1] = i + 1
- indices[i * 3 + 2] = i + 2
- ic :+ 3
- Next
- ' connect last & first
- Local i:Int = segs - 1
- indices[i * 3] = 0
- indices[i * 3 + 1] = i + 1
- indices[i * 3 + 2] = 1
- ic :+ 3
- renderer.Geometry(Null, vertices, vc, indices, ic)
- End Method
-
- Method DrawPoly( xy#[],handle_x#,handle_y#,origin_x#,origin_y#, indices:Int[] ) Override
- If xy.length<6 Or (xy.length&1) Return
-
- If Not indices Then
- indices = TriangulatePoly(xy)
- End If
- Local verts:Int = xy.Length / 2
- Local v:Byte Ptr = StackAlloc(verts * SizeOf(SDLVertex))
- Local vertPtr:SDLVertex Ptr = bmx_SDL_bptr_to_SDLVertexPtr(v)
- Local vert:SDLVertex Ptr = vertPtr
- For Local i:Int=0 Until verts
- Local x:Float = xy[i * 2] + handle_x
- Local y:Float = xy[i * 2 + 1] + handle_y
- vert.position.x = x*ix+y*iy+origin_x
- vert.position.y = x*jx+y*jy+origin_y
- vert.color = _driver.drawColor
- vert :+ 1
- Next
- renderer.Geometry(Null, vertPtr, verts, indices, indices.Length)
- End Method
-
- Method DrawPixmap( p:TPixmap,x:Int,y:Int ) Override
- Local img:TImage = LoadImage(p, 0)
- DrawImage(img, x, y)
- End Method
- Method DrawTexture( texture:TSDLTexture, u0#, v0#, u1#, v1#, x0#, y0#, x1#, y1#, tx#, ty#, img:TImageFrame = Null )
- Local StaticArray vertices:SDLVertex[4]
- Local vert:SDLVertex Ptr = vertices
- vert.position.x = x0 * ix + y0 * iy + tx
- vert.position.y = x0 * jx + y0 * jy + ty
- vert.color = _driver.drawColor
- vert.texCoord.x = u0
- vert.texCoord.y = v0
- vert :+ 1
- vert.position.x = x1 * ix + y0 * iy + tx
- vert.position.y = x1 * jx + y0 * jy + ty
- vert.color = _driver.drawColor
- vert.texCoord.x = u1
- vert.texCoord.y = v0
- vert :+ 1
- vert.position.x = x1 * ix + y1 * iy + tx
- vert.position.y = x1 * jx + y1 * jy + ty
- vert.color = _driver.drawColor
- vert.texCoord.x = u1
- vert.texCoord.y = v1
- vert :+ 1
- vert.position.x = x0 * ix + y1 * iy + tx
- vert.position.y = x0 * jx + y1 * jy + ty
- vert.color = _driver.drawColor
- vert.texCoord.x = u0
- vert.texCoord.y = v1
- Local StaticArray indices:Int[6]
- indices[0] = 0
- indices[1] = 2
- indices[2] = 1
- indices[3] = 0
- indices[4] = 3
- indices[5] = 2
- Select state_blend
- Case ALPHABLEND
- texture.SetBlendMode(SDL_BLENDMODE_BLEND)
- Case MASKBLEND
- texture.SetBlendMode(SDL_BLENDMODE_BLEND)
- Case SOLIDBLEND
- texture.SetBlendMode(SDL_BLENDMODE_NONE)
- Case LIGHTBLEND
- texture.SetBlendMode(SDL_BLENDMODE_ADD)
- Case SHADEBLEND
- texture.SetBlendMode(SDL_BLENDMODE_MOD)
- Default
- texture.SetBlendMode(SDL_BLENDMODE_NONE)
- End Select
- renderer.Geometry(texture, vertices, 4, indices, 6)
- End Method
- Method GrabPixmap:TPixmap( x:Int,y:Int,w:Int,h:Int ) Override
- Local blend:Int = state_blend
- SetBlend SOLIDBLEND
- Local p:TPixmap = CreatePixmap( w,h,PF_RGBA8888 )
- renderer.ReadPixels(SDL_PIXELFORMAT_ABGR8888, p.pixels, p.pitch, x, y, w, h)
- SetBlend blend
- Return p
- End Method
-
- Method SetResolution( width#,height# ) Override
- renderer.SetLogicalSize(Int(width), Int(height))
- End Method
-
- End Type
- Rem
- bbdoc: Get SDLRender Max2D Driver
- about:
- The returned driver can be used with #SetGraphicsDriver to enable SDLRender Max2D
- rendering.
- End Rem
- Function SDLRenderMax2DDriver:TSDLRenderMax2DDriver()
- Global _done:Int
- If Not _done
- _driver=New TSDLRenderMax2DDriver.Create()
- _done=True
- EndIf
- Return _driver
- End Function
- Local driver:TSDLRenderMax2DDriver=SDLRenderMax2DDriver()
- If driver SetGraphicsDriver driver
- Rem
- bbdoc: Defines the preferred renderer, by name.
- about: Available renderers vary by platform. If @renderer is not found, default will be used.
- End Rem
- Function SDLSetPreferredRenderer( renderer:String )
- For Local i:int = 0 Until SDLGetNumRenderDrivers()
- Local info:SDLRendererInfo
- SDLGetRenderDriverInfo(i, info)
- If info.GetName() = renderer Then
- _preferredRenderer = i
- Return
- End If
- Next
- _preferredRenderer = -1
- End Function
- Rem
- bbdoc: Marks a renderer to be prioritized over others, by name.
- about: Available renderers vary by platform. If @renderer is not found or
- cannot be initialized later then, normal default will be used.
- End Rem
- Function SDLPrioritizeRenderer( renderer:String, priority:ESDLHintPriority = ESDLHintPriority.SDL_HINT_DEFAULT)
- For Local i:Int = 0 Until SDLGetNumRenderDrivers()
- Local info:SDLRendererInfo
- SDLGetRenderDriverInfo(i, info)
- If info.GetName() = renderer Then
- SDLSetHintWithPriority("SDL_RENDER_DRIVER", renderer, priority)
- Exit
- End If
- Next
- End Function
|