Browse Source

SDL.SDLRenderMax2D. Initial import.

Brucey 3 years ago
parent
commit
1ad8bf29b3
4 changed files with 509 additions and 1 deletions
  1. 20 0
      sdl.mod/common.bmx
  2. 39 0
      sdlrender.mod/common.bmx
  3. 35 1
      sdlrender.mod/sdlrender.bmx
  4. 415 0
      sdlrendermax2d.mod/sdlrendermax2d.bmx

+ 20 - 0
sdl.mod/common.bmx

@@ -335,3 +335,23 @@ Const SDL_PIXELFORMAT_BGRA32:UInt = SDL_PIXELFORMAT_ARGB8888
 Const SDL_PIXELFORMAT_ABGR32:UInt = SDL_PIXELFORMAT_RGBA8888
 ?
 
+Enum SDL_BlendOperation
+	SDL_BLENDOPERATION_ADD              = $1   ' dst + src: supported by all renderers
+    SDL_BLENDOPERATION_SUBTRACT         = $2   ' dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES
+    SDL_BLENDOPERATION_REV_SUBTRACT     = $3   ' src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES
+    SDL_BLENDOPERATION_MINIMUM          = $4   ' min(dst, src) : supported by D3D11
+    SDL_BLENDOPERATION_MAXIMUM          = $5   ' max(dst, src) : supported by D3D11 
+End Enum
+
+Enum SDL_BlendFactor
+	SDL_BLENDFACTOR_ZERO                = $1  ' 0, 0, 0, 0
+    SDL_BLENDFACTOR_ONE                 = $2  ' 1, 1, 1, 1
+    SDL_BLENDFACTOR_SRC_COLOR           = $3  ' srcR, srcG, srcB, srcA
+    SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = $4  ' 1-srcR, 1-srcG, 1-srcB, 1-srcA
+    SDL_BLENDFACTOR_SRC_ALPHA           = $5  ' srcA, srcA, srcA, srcA
+    SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = $6  ' 1-srcA, 1-srcA, 1-srcA, 1-srcA
+    SDL_BLENDFACTOR_DST_COLOR           = $7  ' dstR, dstG, dstB, dstA
+    SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = $8  ' 1-dstR, 1-dstG, 1-dstB, 1-dstA
+    SDL_BLENDFACTOR_DST_ALPHA           = $9  ' dstA, dstA, dstA, dstA
+    SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = $A  ' 1-dstA, 1-dstA, 1-dstA, 1-dstA
+End Enum

+ 39 - 0
sdlrender.mod/common.bmx

@@ -90,6 +90,8 @@ Extern
 	Function SDL_SetRenderDrawColor:Int(handle:Byte Ptr, r:Byte, g:Byte, b:Byte, a:Byte)
 	Function SDL_SetRenderTarget:Int(handle:Byte Ptr, texture:Byte Ptr)
 	Function SDL_GetRenderer:Byte Ptr(window:Byte Ptr)
+	Function SDL_RenderGeometry:Int(handle:Byte Ptr, texture:Byte Ptr, vertices:SDLVertex Ptr, numVertices:Int, indices:Int Ptr, numIndices:Int)
+	Function SDL_GetRendererInfo(handle:Byte Ptr, info:SDLRendererInfo Var)
 
 	Function SDL_GetTextureAlphaMod:Int(handle:Byte Ptr, alpha:Byte Ptr)
 	Function SDL_GetTextureBlendMode:Int(handle:Byte Ptr, blendMode:Int Ptr)
@@ -166,3 +168,40 @@ bbdoc: the renderer supports rendering to texture
 End Rem
 Const SDL_RENDERER_TARGETTEXTURE:Int = $08
 
+Struct SDLFPoint
+	Field x:Float
+	Field y:Float
+End Struct
+
+Struct SDLColor
+	Field r:Byte
+	Field g:Byte
+	Field b:Byte
+	Field a:Byte
+
+	Method New(r:Byte, g:Byte, b:Byte, a:Byte)
+		self.r = r
+		self.g = g
+		self.b = b
+		self.a = a
+	End Method
+End Struct
+
+Struct SDLVertex
+	Field position:SDLFPoint
+    Field color:SDLColor
+    Field texCoord:SDLFPoint
+End Struct
+
+Struct SDLRendererInfo
+	Field name:Byte Ptr
+	Field flags:UInt
+	Field numTextureFormats:UInt
+	Field StaticArray textureFormats:UInt[16]
+	Field maxTextureWidth:Int
+	Field maxTextureHeight:Int
+
+	Method GetName:String()
+		Return String.FromUTF8String(name)
+	End Method
+End Struct

+ 35 - 1
sdlrender.mod/sdlrender.bmx

@@ -181,12 +181,25 @@ Type TSDLRenderer
 	End Method
 	
 	Rem
-	bbdoc: 
+	bbdoc: Fills some number of rectangles on the current rendering target with the drawing color.
+	returns: 0 on success or a negative error code on failure; call #SDLGetError for more information.
 	End Rem
 	Method FillRects:Int(rects:Int Ptr, count:Int)
 		Return SDL_RenderFillRects(rendererPtr, rects, count)
 	End Method
 	
+	Rem
+	bbdoc: Renders a list of triangles, optionally using a texture and indices into the vertex array Color and alpha modulation is done per vertex.
+	returns: 0 on success, or -1 if the operation is not supported
+	End Rem
+	Method Geometry:Int(texture:TSDLTexture, vertices:SDLVertex Ptr, numVertices:Int, indices:Int Ptr, numIndices:Int)
+		If texture Then
+			Return SDL_RenderGeometry(rendererPtr, texture.texturePtr, vertices, numVertices, indices, numIndices)
+		Else
+			Return SDL_RenderGeometry(rendererPtr, Null, vertices, numVertices, indices, numIndices)
+		End If
+	End Method
+
 	Rem
 	bbdoc: 
 	End Rem
@@ -194,6 +207,15 @@ Type TSDLRenderer
 		bmx_SDL_RenderGetClipRect(rendererPtr, Varptr x, Varptr y, Varptr w, Varptr h)
 	End Method
 	
+	Rem
+	bbdoc: Gets information about the rendering context.
+	End Rem
+	Method GetInfo:SDLRendererInfo()
+		Local info:SDLRendererInfo
+		SDL_GetRendererInfo(rendererPtr, VarPtr info)
+		return info
+	End Method
+
 	Rem
 	bbdoc: Gets whether integer scales are forced for resolution-independent rendering.
 	End Rem
@@ -252,6 +274,8 @@ Type TSDLRenderer
 	
 	Rem
 	bbdoc: Sets whether to force integer scales for resolution-independent rendering.
+	about: Restricts the logical viewport to integer values - that is, when a resolution is between two multiples
+	of a logical size, the viewport size is rounded down to the lower multiple.
 	End Rem
 	Method SetIntegerScale:Int(enable:Int)
 		Return SDL_RenderSetIntegerScale(rendererPtr, enable)
@@ -259,6 +283,15 @@ Type TSDLRenderer
 	
 	Rem
 	bbdoc: Sets a device independent resolution for rendering.
+	about: Uses the viewport and scaling functionality to allow a fixed logical resolution for rendering, 
+	regardless of the actual output resolution. If the actual output resolution doesn't have the same aspect ratio 
+	the output rendering will be centered within the output display.
+
+	If the output display is a window, mouse and touch events in the window will be filtered and scaled so they
+	seem to arrive within the logical resolution. The SDL_HINT_MOUSE_RELATIVE_SCALING hint controls whether relative motion
+	events are also scaled.
+
+	If this method results in scaling or subpixel drawing by the rendering backend, it will be handled using the appropriate quality hints.
 	End Rem
 	Method SetLogicalSize:Int(w:Int, h:Int)
 		Return SDL_RenderSetLogicalSize(rendererPtr, w, h)
@@ -273,6 +306,7 @@ Type TSDLRenderer
 	
 	Rem
 	bbdoc: Sets the drawing area for rendering on the current target.
+	about: Use defaults (-1) to set viewport to entire target.
 	End Rem
 	Method SetViewport:Int(x:Int = -1, y:Int = -1, w:Int = -1, h:Int = -1)
 		Return bmx_SDL_RenderSetViewport(rendererPtr, x, y, w, h)

+ 415 - 0
sdlrendermax2d.mod/sdlrendermax2d.bmx

@@ -0,0 +1,415 @@
+
+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
+
+Private
+
+Global _driver:TSDLRenderMax2DDriver
+
+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#
+
+	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
+
+		renderer = TSDLRenderer.Create(gfx._context.window)
+		'ResetGLContext t
+		
+		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
+		rem
+		If blend=state_blend Return
+		state_blend=blend
+		Select blend
+		Case MASKBLEND
+			glDisable GL_BLEND
+			glEnable GL_ALPHA_TEST
+			glAlphaFunc GL_GEQUAL,.5
+		Case SOLIDBLEND
+			glDisable GL_BLEND
+			glDisable GL_ALPHA_TEST
+		Case ALPHABLEND
+			glEnable GL_BLEND
+			glBlendFunc GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA
+			glDisable GL_ALPHA_TEST
+		Case LIGHTBLEND
+			glEnable GL_BLEND
+			glBlendFunc GL_SRC_ALPHA,GL_ONE
+			glDisable GL_ALPHA_TEST
+		Case SHADEBLEND
+			glEnable GL_BLEND
+			glBlendFunc GL_DST_COLOR,GL_ZERO
+			glDisable GL_ALPHA_TEST
+		Default
+			glDisable GL_BLEND
+			glDisable GL_ALPHA_TEST
+		End Select
+		end rem
+	End Method
+
+	Method SetAlpha( alpha# ) Override
+		If alpha>1.0 alpha=1.0
+		If alpha<0.0 alpha=0.0
+		drawColor.a=alpha*255
+		print "alpha = " + drawColor.a
+	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)
+	End Method
+
+	Method SetColor( color:SColor8 ) Override
+		drawColor.r=color.r
+		drawColor.g=color.g
+		drawColor.b=color.b
+	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.SetViewport()
+		Else
+			renderer.SetViewport(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 points:Float[8]
+		points[0] = x0*ix+y0*iy+tx
+		points[1] = x0*jx+y0*jy+ty
+		points[2] = x1*ix+y0*iy+tx
+		points[3] = x1*jx+y0*jy+ty
+		points[4] = x1*ix+y1*iy+tx
+		points[5] = x1*jx+y1*jy+ty
+		points[6] = x0*ix+y1*iy+tx
+		points[7] = x0*jx+y1*jy+ty
+		renderer.DrawLines(points, 4)
+	End Method
+	
+	Method DrawOval( x0#,y0#,x1#,y1#,tx#,ty# ) Override
+		Local StaticArray points:Float[24]
+
+		Local xr#=(x1-x0)*.5
+		Local yr#=(y1-y0)*.5
+		Local segs:Int=Abs(xr)+Abs(yr)
+		
+		segs=Max(segs,12)&~3
+
+		x0:+xr
+		y0:+yr
+		
+		For Local i:Int=0 Until segs
+			Local th#=i*360#/segs
+			Local x#=x0+Cos(th)*xr
+			Local y#=y0-Sin(th)*yr
+			points[i * 2] = x*ix+y*iy+tx
+			points[i * 2 + 1] = x*jx+y*jy+ty
+		Next
+		renderer.DrawLines(points, segs)
+		
+	End Method
+	
+	Method DrawPoly( xy#[],handle_x#,handle_y#,origin_x#,origin_y# ) Override
+		rem
+		If xy.length<6 Or (xy.length&1) Return
+		
+		DisableTex
+		glBegin GL_POLYGON
+		For Local i:Int=0 Until Len xy Step 2
+			Local x#=xy[i+0]+handle_x
+			Local y#=xy[i+1]+handle_y
+			glVertex2f x*ix+y*iy+origin_x,x*jx+y*jy+origin_y
+		Next
+		glEnd
+		end rem
+	End Method
+		
+	Method DrawPixmap( p:TPixmap,x:Int,y:Int ) Override
+		rem
+		Local blend:Int=state_blend
+		DisableTex
+		SetBlend SOLIDBLEND
+	
+		Local t:TPixmap=p
+		If t.format<>PF_RGBA8888 t=ConvertPixmap( t,PF_RGBA8888 )
+
+		glPixelZoom 1,-1
+		glRasterPos2i 0,0
+		glBitmap 0,0,0,0,x,-y,Null
+		glPixelStorei GL_UNPACK_ROW_LENGTH, t.pitch Shr 2
+		glDrawPixels t.width,t.height,GL_RGBA,GL_UNSIGNED_BYTE,t.pixels
+		glPixelStorei GL_UNPACK_ROW_LENGTH,0
+		glPixelZoom 1,1
+		
+		SetBlend blend
+		end rem
+	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
+
+		renderer.Geometry(texture, vertices, 4, indices, 6)
+	End Method
+
+	Method GrabPixmap:TPixmap( x:Int,y:Int,w:Int,h:Int ) Override
+		rem
+		Local blend:Int=state_blend
+		SetBlend SOLIDBLEND
+		Local p:TPixmap=CreatePixmap( w,h,PF_RGBA8888 )
+		glReadPixels x,GraphicsHeight()-h-y,w,h,GL_RGBA,GL_UNSIGNED_BYTE,p.pixels
+		p=YFlipPixmap( p )
+		SetBlend blend
+		Return p
+		end rem
+	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