|
@@ -8,12 +8,14 @@ The OpenGL Max2D module provides an SDL-backend OpenGL driver for #Max2D.
|
|
End Rem
|
|
End Rem
|
|
Module SDL.GLSDLMax2D
|
|
Module SDL.GLSDLMax2D
|
|
|
|
|
|
-ModuleInfo "Version: 1.15"
|
|
|
|
|
|
+ModuleInfo "Version: 1.16"
|
|
ModuleInfo "Author: Mark Sibly"
|
|
ModuleInfo "Author: Mark Sibly"
|
|
ModuleInfo "License: zlib/libpng"
|
|
ModuleInfo "License: zlib/libpng"
|
|
ModuleInfo "Copyright: Blitz Research Ltd"
|
|
ModuleInfo "Copyright: Blitz Research Ltd"
|
|
ModuleInfo "Modserver: BRL"
|
|
ModuleInfo "Modserver: BRL"
|
|
|
|
|
|
|
|
+ModuleInfo "History: 1.16"
|
|
|
|
+ModuleInfo "History: Added RenderImages / render2texture"
|
|
ModuleInfo "History: 1.15"
|
|
ModuleInfo "History: 1.15"
|
|
ModuleInfo "History: Changed to SuperStrict"
|
|
ModuleInfo "History: Changed to SuperStrict"
|
|
ModuleInfo "History: Extended flags to Long"
|
|
ModuleInfo "History: Extended flags to Long"
|
|
@@ -42,10 +44,26 @@ ModuleInfo "History: Added checks to prevent invalid textures deletes"
|
|
|
|
|
|
Import BRL.Max2D
|
|
Import BRL.Max2D
|
|
Import SDL.GLSDLGraphics
|
|
Import SDL.GLSDLGraphics
|
|
|
|
+Import BRL.Threads
|
|
|
|
|
|
Private
|
|
Private
|
|
|
|
|
|
|
|
+Struct Rect
|
|
|
|
+ Method New (X:Int, Y:Int, width:Int, height:Int)
|
|
|
|
+ Self.X = X
|
|
|
|
+ Self.Y = Y
|
|
|
|
+ Self.width = width
|
|
|
|
+ Self.height = height
|
|
|
|
+ EndMethod
|
|
|
|
+
|
|
|
|
+ Field X:Int, Y:Int
|
|
|
|
+ Field width:Int, height:Int
|
|
|
|
+EndStruct
|
|
|
|
+
|
|
Global _driver:TGLMax2DDriver
|
|
Global _driver:TGLMax2DDriver
|
|
|
|
+Global _BackbufferRenderImageFrame:TGLSDLRenderImageFrame
|
|
|
|
+Global _CurrentRenderImageFrame:TGLSDLRenderImageFrame
|
|
|
|
+Global _GLScissor_BMaxViewport:Rect = New Rect
|
|
|
|
|
|
'Naughty!
|
|
'Naughty!
|
|
Const GL_BGR:Int=$80E0
|
|
Const GL_BGR:Int=$80E0
|
|
@@ -87,89 +105,79 @@ Function Pow2Size:Int( n:Int )
|
|
Return t
|
|
Return t
|
|
End Function
|
|
End Function
|
|
|
|
|
|
-Global dead_texs:Int[],n_dead_texs:Int,dead_tex_seq:Int,n_live_texs:Int
|
|
|
|
-
|
|
|
|
-Extern
|
|
|
|
- Function bbAtomicAdd:Int( target:Int Ptr,value:Int )="int bbAtomicAdd( int *,int )!"
|
|
|
|
-End Extern
|
|
|
|
|
|
+Global dead_texs:TDynamicArray = New TDynamicArray(32)
|
|
|
|
+Global dead_tex_seq:Int
|
|
|
|
|
|
'Enqueues a texture for deletion, to prevent release textures on wrong thread.
|
|
'Enqueues a texture for deletion, to prevent release textures on wrong thread.
|
|
Function DeleteTex( name:Int,seq:Int )
|
|
Function DeleteTex( name:Int,seq:Int )
|
|
If seq<>dead_tex_seq Return
|
|
If seq<>dead_tex_seq Return
|
|
-
|
|
|
|
- Local n:Int = bbAtomicAdd(Varptr n_dead_texs, 1)
|
|
|
|
- bbAtomicAdd(Varptr n_live_texs, -1)
|
|
|
|
|
|
|
|
- dead_texs[n] = name
|
|
|
|
|
|
+ dead_texs.AddLast(name)
|
|
End Function
|
|
End Function
|
|
|
|
|
|
-Function _ManageDeadTexArray()
|
|
|
|
- If dead_texs.length <= n_live_texs
|
|
|
|
- ' expand array so it's large enough to hold all the current live textures.
|
|
|
|
- dead_texs=dead_texs[..n_live_texs+20]
|
|
|
|
- EndIf
|
|
|
|
-End Function
|
|
|
|
-
|
|
|
|
-Function CreateTex:Int( width:Int,height:Int,flags:Int )
|
|
|
|
|
|
+Function CreateTex:Int( width:Int,height:Int,flags:Int,pixmap:TPixmap )
|
|
|
|
+ If pixmap.dds_fmt<>0 Then Return pixmap.tex_name ' if dds texture already exists
|
|
|
|
+
|
|
'alloc new tex
|
|
'alloc new tex
|
|
Local name:Int
|
|
Local name:Int
|
|
- glGenTextures 1,Varptr name
|
|
|
|
-
|
|
|
|
- n_live_texs :+ 1
|
|
|
|
- _ManageDeadTexArray()
|
|
|
|
-
|
|
|
|
|
|
+ glGenTextures( 1, Varptr name )
|
|
|
|
+
|
|
'flush dead texs
|
|
'flush dead texs
|
|
If dead_tex_seq=GraphicsSeq
|
|
If dead_tex_seq=GraphicsSeq
|
|
- For Local i:Int=0 Until n_dead_texs
|
|
|
|
- glDeleteTextures 1,Varptr dead_texs[i]
|
|
|
|
- Next
|
|
|
|
|
|
+ Local n:Int = dead_texs.RemoveLast()
|
|
|
|
+ While n <> $FFFFFFFF
|
|
|
|
+ glDeleteTextures(1, Varptr n)
|
|
|
|
+ n = dead_texs.RemoveLast()
|
|
|
|
+ Wend
|
|
EndIf
|
|
EndIf
|
|
- n_dead_texs=0
|
|
|
|
- dead_tex_seq=GraphicsSeq
|
|
|
|
|
|
+
|
|
|
|
+ dead_tex_seq = GraphicsSeq
|
|
|
|
|
|
'bind new tex
|
|
'bind new tex
|
|
- BindTex name
|
|
|
|
-
|
|
|
|
|
|
+ BindTex( name )
|
|
|
|
+
|
|
'set texture parameters
|
|
'set texture parameters
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE
|
|
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE
|
|
|
|
-
|
|
|
|
|
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE )
|
|
|
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE )
|
|
|
|
+
|
|
If flags & FILTEREDIMAGE
|
|
If flags & FILTEREDIMAGE
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
|
|
|
|
|
|
+ glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
|
|
If flags & MIPMAPPEDIMAGE
|
|
If flags & MIPMAPPEDIMAGE
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR
|
|
|
|
|
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR )
|
|
Else
|
|
Else
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR
|
|
|
|
|
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR )
|
|
EndIf
|
|
EndIf
|
|
Else
|
|
Else
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST
|
|
|
|
|
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST )
|
|
If flags & MIPMAPPEDIMAGE
|
|
If flags & MIPMAPPEDIMAGE
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST
|
|
|
|
|
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST )
|
|
Else
|
|
Else
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST
|
|
|
|
|
|
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST )
|
|
EndIf
|
|
EndIf
|
|
EndIf
|
|
EndIf
|
|
|
|
|
|
Local mip_level:Int
|
|
Local mip_level:Int
|
|
-
|
|
|
|
Repeat
|
|
Repeat
|
|
- glTexImage2D GL_TEXTURE_2D,mip_level,GL_RGBA8,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
|
|
|
|
- If Not (flags & MIPMAPPEDIMAGE) Exit
|
|
|
|
- If width=1 And height=1 Exit
|
|
|
|
- If width>1 width:/2
|
|
|
|
- If height>1 height:/2
|
|
|
|
- mip_level:+1
|
|
|
|
|
|
+ glTexImage2D( GL_TEXTURE_2D, mip_level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Null )
|
|
|
|
+ If Not ( flags & MIPMAPPEDIMAGE ) Exit
|
|
|
|
+ If width = 1 And height = 1 Exit
|
|
|
|
+ If width > 1 width :/ 2
|
|
|
|
+ If height > 1 height :/ 2
|
|
|
|
+ mip_level :+ 1
|
|
Forever
|
|
Forever
|
|
|
|
|
|
Return name
|
|
Return name
|
|
End Function
|
|
End Function
|
|
|
|
|
|
|
|
+'NOTE: Assumes a bound texture.
|
|
Function UploadTex( pixmap:TPixmap,flags:Int )
|
|
Function UploadTex( pixmap:TPixmap,flags:Int )
|
|
Local mip_level:Int
|
|
Local mip_level:Int
|
|
|
|
+ If pixmap.dds_fmt <> 0 Then Return ' if dds texture already exists
|
|
Repeat
|
|
Repeat
|
|
glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
|
|
glPixelStorei GL_UNPACK_ROW_LENGTH,pixmap.pitch/BytesPerPixel[pixmap.format]
|
|
glTexSubImage2D GL_TEXTURE_2D,mip_level,0,0,pixmap.width,pixmap.height,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
|
|
glTexSubImage2D GL_TEXTURE_2D,mip_level,0,0,pixmap.width,pixmap.height,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.pixels
|
|
- If Not (flags & MIPMAPPEDIMAGE) Exit
|
|
|
|
|
|
+
|
|
|
|
+ If Not (flags & MIPMAPPEDIMAGE) Then Exit
|
|
If pixmap.width>1 And pixmap.height>1
|
|
If pixmap.width>1 And pixmap.height>1
|
|
pixmap=ResizePixmap( pixmap,pixmap.width/2,pixmap.height/2 )
|
|
pixmap=ResizePixmap( pixmap,pixmap.width/2,pixmap.height/2 )
|
|
Else If pixmap.width>1
|
|
Else If pixmap.width>1
|
|
@@ -186,256 +194,77 @@ End Function
|
|
|
|
|
|
Function AdjustTexSize( width:Int Var,height:Int Var )
|
|
Function AdjustTexSize( width:Int Var,height:Int Var )
|
|
'calc texture size
|
|
'calc texture size
|
|
- width=Pow2Size( width )
|
|
|
|
- height=Pow2Size( height )
|
|
|
|
|
|
+ width = Pow2Size( width )
|
|
|
|
+ height = Pow2Size( height )
|
|
Repeat
|
|
Repeat
|
|
Local t:Int
|
|
Local t:Int
|
|
glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
|
|
glTexImage2D GL_PROXY_TEXTURE_2D,0,4,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null
|
|
glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
|
|
glGetTexLevelParameteriv GL_PROXY_TEXTURE_2D,0,GL_TEXTURE_WIDTH,Varptr t
|
|
- If t Return
|
|
|
|
- If width=1 And height=1 RuntimeError "Unable to calculate tex size"
|
|
|
|
- If width>1 width:/2
|
|
|
|
- If height>1 height:/2
|
|
|
|
|
|
+ If t Then Return
|
|
|
|
+ If width=1 And height=1 Then RuntimeError "Unable to calculate tex size"
|
|
|
|
+ If width>1 Then width :/ 2
|
|
|
|
+ If height>1 Then height :/ 2
|
|
Forever
|
|
Forever
|
|
End Function
|
|
End Function
|
|
|
|
|
|
|
|
+Type TDynamicArray
|
|
|
|
|
|
-
|
|
|
|
-Global glewIsInit:Int
|
|
|
|
-
|
|
|
|
-Type TGLRenderImageContext Extends TRenderImageContext
|
|
|
|
- Field _gc:TSDLGraphics
|
|
|
|
- Field _backbuffer:Int
|
|
|
|
- Field _width:Int
|
|
|
|
- Field _height:Int
|
|
|
|
- Field _renderimages:TList
|
|
|
|
-
|
|
|
|
- Field _matrix:Float[16]
|
|
|
|
-
|
|
|
|
- Method Delete()
|
|
|
|
- Destroy()
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method Destroy()
|
|
|
|
- _gc = Null
|
|
|
|
- If _renderimages
|
|
|
|
- For Local ri:TGLRenderImage = EachIn _renderimages
|
|
|
|
- ri.DestroyRenderImage()
|
|
|
|
- Next
|
|
|
|
- EndIf
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method Create:TGLRenderimageContext(gc:TGraphics, driver:TGraphicsDriver)
|
|
|
|
- If Not glewIsInit
|
|
|
|
- glewInit()
|
|
|
|
- glewIsInit = True
|
|
|
|
- EndIf
|
|
|
|
-
|
|
|
|
- _renderimages = New TList
|
|
|
|
- _gc = TSDLGraphics(gc)
|
|
|
|
- _width = GraphicsWidth()
|
|
|
|
- _height = GraphicsHeight()
|
|
|
|
-
|
|
|
|
- ' get the backbuffer - usually 0
|
|
|
|
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, Varptr _backbuffer)
|
|
|
|
- glGetFloatv(GL_PROJECTION_MATRIX, _matrix)
|
|
|
|
-
|
|
|
|
- Return Self
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method GraphicsContext:TGraphics()
|
|
|
|
- Return _gc
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method CreateRenderImage:TRenderImage(width:Int, height:Int, UseImageFiltering:Int)
|
|
|
|
- Local renderimage:TGLRenderImage = New TGLRenderImage.CreateRenderImage(width, height)
|
|
|
|
- renderimage.Init(UseImageFiltering, Null)
|
|
|
|
- Return renderimage
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method CreateRenderImageFromPixmap:TRenderImage(pixmap:TPixmap, UseImageFiltering:Int)
|
|
|
|
- Local renderimage:TGLRenderImage = New TGLRenderImage.CreateRenderImage(pixmap.width, pixmap.height)
|
|
|
|
- renderimage.Init(UseImageFiltering, pixmap)
|
|
|
|
- Return renderimage
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method DestroyRenderImage(renderImage:TRenderImage)
|
|
|
|
- renderImage.DestroyRenderImage()
|
|
|
|
- _renderImages.Remove(renderImage)
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method SetRenderImage(renderimage:TRenderimage)
|
|
|
|
- If Not renderimage
|
|
|
|
- glBindFramebuffer(GL_FRAMEBUFFER,_backbuffer)
|
|
|
|
-
|
|
|
|
- glMatrixMode(GL_PROJECTION)
|
|
|
|
- glLoadMatrixf(_matrix)
|
|
|
|
-
|
|
|
|
- glViewport(0,0,_width,_height)
|
|
|
|
- Else
|
|
|
|
- renderimage.SetRenderImage()
|
|
|
|
- EndIf
|
|
|
|
- EndMethod
|
|
|
|
|
|
+ Private
|
|
|
|
|
|
- Method CreatePixmapFromRenderImage:TPixmap(renderImage:TRenderImage)
|
|
|
|
- Return TGLRenderImage(renderImage).ToPixmap()
|
|
|
|
- EndMethod
|
|
|
|
-EndType
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-Type TGLRenderImageFrame Extends TGLImageFrame
|
|
|
|
- Field _fbo:Int
|
|
|
|
|
|
+ Field data:Int Ptr
|
|
|
|
+ Field size:Size_T
|
|
|
|
+ Field capacity:Size_T
|
|
|
|
|
|
- Method Delete()
|
|
|
|
- DeleteFramebuffer
|
|
|
|
- EndMethod
|
|
|
|
|
|
+ Field guard:TMutex
|
|
|
|
|
|
- Method DeleteFramebuffer()
|
|
|
|
- If _fbo
|
|
|
|
- glDeleteFramebuffers(1, Varptr _fbo)
|
|
|
|
- _fbo = -1 '???
|
|
|
|
- EndIf
|
|
|
|
- EndMethod
|
|
|
|
|
|
+ Public
|
|
|
|
|
|
- Method Clear(r:Int=0, g:Int=0, b:Int=0, a:Float=0.0)
|
|
|
|
- 'backup current
|
|
|
|
- Local c:Float[4]
|
|
|
|
- glGetFloatv(GL_COLOR_CLEAR_VALUE, c)
|
|
|
|
-
|
|
|
|
- glClearColor(r/255.0, g/255.0, b/255.0, a)
|
|
|
|
- glClear(GL_COLOR_BUFFER_BIT)
|
|
|
|
-
|
|
|
|
- glClearColor(c[0], c[1], c[2], c[3])
|
|
|
|
|
|
+ Method New(initialCapacity:Int = 8)
|
|
|
|
+ capacity = initialCapacity
|
|
|
|
+ data = malloc_(Size_T(initialCapacity * 4))
|
|
|
|
+ guard = CreateMutex()
|
|
End Method
|
|
End Method
|
|
-
|
|
|
|
- Method CreateRenderTarget:TGLRenderImageFrame(width:Int, height:Int, UseImageFiltering:Int, pixmap:TPixmap)
|
|
|
|
- If pixmap pixmap = ConvertPixmap(pixmap, PF_RGBA)
|
|
|
|
-
|
|
|
|
- glDisable(GL_SCISSOR_TEST)
|
|
|
|
-
|
|
|
|
- glGenTextures(1, Varptr name)
|
|
|
|
- glBindTexture(GL_TEXTURE_2D, name)
|
|
|
|
- If pixmap
|
|
|
|
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixmap.pixels)
|
|
|
|
- Else
|
|
|
|
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Null)
|
|
|
|
- EndIf
|
|
|
|
|
|
|
|
- If UseImageFiltering
|
|
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
|
|
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR
|
|
|
|
- Else
|
|
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST
|
|
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST
|
|
|
|
- EndIf
|
|
|
|
-
|
|
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE
|
|
|
|
- glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE
|
|
|
|
|
|
+ Method AddLast(value:Int)
|
|
|
|
+ guard.Lock()
|
|
|
|
+ If size = capacity Then
|
|
|
|
+ capacity :* 2
|
|
|
|
+ Local d:Byte Ptr = realloc_(data, capacity * 4)
|
|
|
|
+ If Not d Then
|
|
|
|
+ Throw "Failed to allocate more memory"
|
|
|
|
+ End If
|
|
|
|
+ data = d
|
|
|
|
+ End If
|
|
|
|
|
|
- glGenFramebuffers(1,Varptr _fbo)
|
|
|
|
- glBindFramebuffer GL_FRAMEBUFFER,_fbo
|
|
|
|
-
|
|
|
|
- glBindTexture GL_TEXTURE_2D,name
|
|
|
|
- glFramebufferTexture2D GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,name,0
|
|
|
|
-
|
|
|
|
- If Not pixmap
|
|
|
|
- ' set and clear to a default colour
|
|
|
|
- glClearColor 0, 0, 0, 0
|
|
|
|
- glClear(GL_COLOR_BUFFER_BIT)
|
|
|
|
- EndIf
|
|
|
|
-
|
|
|
|
- uscale = 1.0 / width
|
|
|
|
- vscale = 1.0 / height
|
|
|
|
-
|
|
|
|
- Return Self
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method DestroyRenderTarget()
|
|
|
|
- DeleteFramebuffer()
|
|
|
|
- EndMethod
|
|
|
|
|
|
+ data[size] = value
|
|
|
|
+ size :+ 1
|
|
|
|
+ guard.Unlock()
|
|
|
|
+ End Method
|
|
|
|
|
|
- Method ToPixmap:TPixmap(width:Int, height:Int)
|
|
|
|
- Local prevTexture:Int
|
|
|
|
- Local prevFBO:Int
|
|
|
|
|
|
+ Method RemoveLast:Int()
|
|
|
|
+ guard.Lock()
|
|
|
|
+ Local v:Int
|
|
|
|
|
|
- glGetIntegerv(GL_TEXTURE_BINDING_2D,Varptr prevTexture)
|
|
|
|
- glBindTexture(GL_TEXTURE_2D,name)
|
|
|
|
-
|
|
|
|
- Local pixmap:TPixmap = CreatePixmap(width, height, PF_RGBA8888)
|
|
|
|
- glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixmap.pixels)
|
|
|
|
-
|
|
|
|
- glBindTexture(GL_TEXTURE_2D,prevTexture)
|
|
|
|
-
|
|
|
|
- Return pixmap
|
|
|
|
- EndMethod
|
|
|
|
-EndType
|
|
|
|
-
|
|
|
|
-Type TGLRenderImage Extends TRenderImage
|
|
|
|
- Field _matrix:Float[16]
|
|
|
|
-
|
|
|
|
- Method CreateRenderImage:TGLRenderImage(width:Int, height:Int)
|
|
|
|
- Self.width = width ' TImage.width
|
|
|
|
- Self.height = height ' TImage.height
|
|
|
|
-
|
|
|
|
- _matrix = [ 2.0/width, 0.0, 0.0, 0.0,..
|
|
|
|
- 0.0, 2.0/height, 0.0, 0.0,..
|
|
|
|
- 0.0, 0.0, 1.0, 0.0,..
|
|
|
|
- -1-(1.0/width), -1-(1.0/height), 1.0, 1.0 ]
|
|
|
|
-
|
|
|
|
- Return Self
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method DestroyRenderImage()
|
|
|
|
- TGLRenderImageFrame(frames[0]).DestroyRenderTarget()
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method Init(UseImageFiltering:Int, pixmap:TPixmap)
|
|
|
|
- Local prevFBO:Int
|
|
|
|
- Local prevTexture:Int
|
|
|
|
- Local prevScissorTest:Int
|
|
|
|
-
|
|
|
|
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, Varptr prevFBO)
|
|
|
|
- glGetIntegerv(GL_TEXTURE_BINDING_2D,Varptr prevTexture)
|
|
|
|
- glGetIntegerv(GL_SCISSOR_TEST, Varptr prevScissorTest)
|
|
|
|
|
|
+ If size > 0 Then
|
|
|
|
+ size :- 1
|
|
|
|
+ v = data[size]
|
|
|
|
+ Else
|
|
|
|
+ v = $FFFFFFFF
|
|
|
|
+ End If
|
|
|
|
|
|
- frames = New TGLRenderImageFrame[1]
|
|
|
|
- frames[0] = New TGLRenderImageFrame.CreateRenderTarget(width, height, UseImageFiltering, pixmap)
|
|
|
|
|
|
+ guard.Unlock()
|
|
|
|
|
|
- If prevScissorTest glEnable(GL_SCISSOR_TEST)
|
|
|
|
- glBindTexture GL_TEXTURE_2D,prevTexture
|
|
|
|
- glBindFramebuffer GL_FRAMEBUFFER,prevFBO
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method Clear(r:Int=0, g:Int=0, b:Int=0, a:Float=0.0)
|
|
|
|
- If frames[0] Then TGLRenderImageFrame(frames[0]).Clear(r, g, b, a)
|
|
|
|
|
|
+ Return v
|
|
End Method
|
|
End Method
|
|
|
|
|
|
- Method Frame:TImageFrame(index:Int=0)
|
|
|
|
- Return frames[0]
|
|
|
|
- EndMethod
|
|
|
|
|
|
+ Method Delete()
|
|
|
|
+ free_(data)
|
|
|
|
+ CloseMutex(guard)
|
|
|
|
+ End Method
|
|
|
|
|
|
- Method SetRenderImage()
|
|
|
|
- glBindFrameBuffer(GL_FRAMEBUFFER, TGLRenderImageFrame(frames[0])._fbo)
|
|
|
|
|
|
+End Type
|
|
|
|
|
|
- glMatrixMode(GL_PROJECTION)
|
|
|
|
- glLoadMatrixf(_matrix)
|
|
|
|
-
|
|
|
|
- glViewport 0,0,width,height
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method ToPixmap:TPixmap()
|
|
|
|
- Return TGLRenderImageFrame(frames[0]).ToPixmap(width, height)
|
|
|
|
- EndMethod
|
|
|
|
-
|
|
|
|
- Method SetViewport(x:Int, y:Int, width:Int, height:Int)
|
|
|
|
- If x = 0 And y = 0 And width = Self.width And height = Self.height
|
|
|
|
- glDisable GL_SCISSOR_TEST
|
|
|
|
- Else
|
|
|
|
- glEnable GL_SCISSOR_TEST
|
|
|
|
- glScissor x, y, width, height
|
|
|
|
- EndIf
|
|
|
|
- EndMethod
|
|
|
|
-EndType
|
|
|
|
|
|
+Global glewIsInit:Int
|
|
|
|
|
|
Public
|
|
Public
|
|
|
|
|
|
@@ -458,11 +287,11 @@ Type TGLImageFrame Extends TImageFrame
|
|
Method Draw( x0:Float,y0:Float,x1:Float,y1:Float,tx:Float,ty:Float,sx:Float,sy:Float,sw:Float,sh:Float ) Override
|
|
Method Draw( x0:Float,y0:Float,x1:Float,y1:Float,tx:Float,ty:Float,sx:Float,sy:Float,sw:Float,sh:Float ) Override
|
|
Assert seq=GraphicsSeq Else "Image does not exist"
|
|
Assert seq=GraphicsSeq Else "Image does not exist"
|
|
|
|
|
|
- Local u0:Float=sx * uscale
|
|
|
|
- Local v0:Float=sy * vscale
|
|
|
|
- Local u1:Float=(sx+sw) * uscale
|
|
|
|
- Local v1:Float=(sy+sh) * vscale
|
|
|
|
-
|
|
|
|
|
|
+ Local u0:Float = sx * uscale
|
|
|
|
+ Local v0:Float = sy * vscale
|
|
|
|
+ Local u1:Float = (sx + sw) * uscale
|
|
|
|
+ Local v1:Float = (sy + sh) * vscale
|
|
|
|
+
|
|
EnableTex name
|
|
EnableTex name
|
|
glBegin GL_QUADS
|
|
glBegin GL_QUADS
|
|
glTexCoord2f u0,v0
|
|
glTexCoord2f u0,v0
|
|
@@ -504,11 +333,13 @@ Type TGLImageFrame Extends TImageFrame
|
|
EndIf
|
|
EndIf
|
|
EndIf
|
|
EndIf
|
|
Else
|
|
Else
|
|
- If tex.format<>PF_RGBA8888 tex=tex.Convert( PF_RGBA8888 )
|
|
|
|
|
|
+ If tex.dds_fmt=0 ' not dds
|
|
|
|
+ If tex.format<>PF_RGBA8888 tex=tex.Convert( PF_RGBA8888 )
|
|
|
|
+ EndIf
|
|
EndIf
|
|
EndIf
|
|
|
|
|
|
'create tex
|
|
'create tex
|
|
- Local name:Int=CreateTex( tex_w,tex_h,flags )
|
|
|
|
|
|
+ Local name:Int=CreateTex( tex_w,tex_h,flags,tex )
|
|
|
|
|
|
'upload it
|
|
'upload it
|
|
UploadTex tex,flags
|
|
UploadTex tex,flags
|
|
@@ -526,8 +357,94 @@ Type TGLImageFrame Extends TImageFrame
|
|
|
|
|
|
End Type
|
|
End Type
|
|
|
|
|
|
-Type TGLMax2DDriver Extends TMax2DDriver
|
|
|
|
|
|
+Type TGLSDLRenderImageFrame Extends TGLImageFrame
|
|
|
|
+ Field FBO:Int
|
|
|
|
+ Field width:Int
|
|
|
|
+ Field height:Int
|
|
|
|
+
|
|
|
|
+ Method Draw( x0:Float, y0:Float, x1:Float, y1:Float, tx:Float, ty:Float, sx:Float, sy:Float, sw:Float, sh:Float ) Override
|
|
|
|
+ Assert seq=GraphicsSeq Else "Image does not exist"
|
|
|
|
+
|
|
|
|
+ ' Note for a TGLRenderImage the V texture coordinate is flipped compared to the regular TImageFrame.Draw method
|
|
|
|
+ Local u0:Float = sx * uscale
|
|
|
|
+ Local v0:Float = (sy + sh) * vscale
|
|
|
|
+ Local u1:Float = (sx + sw) * uscale
|
|
|
|
+ Local v1:Float = sy * vscale
|
|
|
|
+
|
|
|
|
+ EnableTex name
|
|
|
|
+ glBegin GL_QUADS
|
|
|
|
+ glTexCoord2f u0,v0
|
|
|
|
+ glVertex2f x0*ix+y0*iy+tx,x0*jx+y0*jy+ty
|
|
|
|
+ glTexCoord2f u1,v0
|
|
|
|
+ glVertex2f x1*ix+y0*iy+tx,x1*jx+y0*jy+ty
|
|
|
|
+ glTexCoord2f u1,v1
|
|
|
|
+ glVertex2f x1*ix+y1*iy+tx,x1*jx+y1*jy+ty
|
|
|
|
+ glTexCoord2f u0,v1
|
|
|
|
+ glVertex2f x0*ix+y1*iy+tx,x0*jx+y1*jy+ty
|
|
|
|
+ glEnd
|
|
|
|
+ End Method
|
|
|
|
+
|
|
|
|
+ Function Create:TGLSDLRenderImageFrame(width:UInt, height:UInt, flags:Int)
|
|
|
|
+ ' Need this to enable frame buffer objects - glGenFramebuffers
|
|
|
|
+ Global GlewIsInitialised:Int = False
|
|
|
|
+ If Not GlewIsInitialised
|
|
|
|
+ GlewInit()
|
|
|
|
+ GlewIsInitialised = True
|
|
|
|
+ EndIf
|
|
|
|
+
|
|
|
|
+ ' store so that we can restore once the fbo is created
|
|
|
|
+ Local ScissorTestEnabled:Int = GlIsEnabled(GL_SCISSOR_TEST)
|
|
|
|
+ glDisable(GL_SCISSOR_TEST)
|
|
|
|
+
|
|
|
|
+ Local TextureName:Int
|
|
|
|
+ glGenTextures(1, Varptr TextureName)
|
|
|
|
+ glBindTexture(GL_TEXTURE_2D, TextureName)
|
|
|
|
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Null)
|
|
|
|
+
|
|
|
|
+ If flags & FILTEREDIMAGE
|
|
|
|
+ glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
|
|
|
|
+ glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR
|
|
|
|
+ Else
|
|
|
|
+ glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST
|
|
|
|
+ glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST
|
|
|
|
+ EndIf
|
|
|
|
+
|
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
|
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
|
|
|
|
+
|
|
|
|
+ Local FrameBufferObject:Int
|
|
|
|
+ glGenFramebuffers(1, Varptr FrameBufferObject)
|
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, FrameBufferObject)
|
|
|
|
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, TextureName, 0)
|
|
|
|
+
|
|
|
|
+ Local RenderTarget:TGLSDLRenderImageFrame = New TGLSDLRenderImageFrame
|
|
|
|
+ RenderTarget.name = TextureName
|
|
|
|
+ RenderTarget.FBO = FrameBufferObject
|
|
|
|
+
|
|
|
|
+ RenderTarget.width = width
|
|
|
|
+ RenderTarget.height = height
|
|
|
|
+ RenderTarget.uscale = 1.0 / width
|
|
|
|
+ RenderTarget.vscale = 1.0 / height
|
|
|
|
+ RenderTarget.u1 = width * RenderTarget.uscale
|
|
|
|
+ RenderTarget.v1 = height * RenderTarget.vscale
|
|
|
|
+
|
|
|
|
+ If ScissorTestEnabled
|
|
|
|
+ glEnable(GL_SCISSOR_TEST)
|
|
|
|
+ EndIf
|
|
|
|
+
|
|
|
|
+ Return RenderTarget
|
|
|
|
+ End Function
|
|
|
|
+
|
|
|
|
+Private
|
|
|
|
+ Method Delete()
|
|
|
|
+ glDeleteFramebuffers(1, Varptr FBO) ' gl ignores 0
|
|
|
|
+ End Method
|
|
|
|
|
|
|
|
+ Method New()
|
|
|
|
+ End Method
|
|
|
|
+EndType
|
|
|
|
+
|
|
|
|
+Type TGLMax2DDriver Extends TMax2DDriver
|
|
Method Create:TGLMax2DDriver()
|
|
Method Create:TGLMax2DDriver()
|
|
If Not SDLGraphicsDriver() Return Null
|
|
If Not SDLGraphicsDriver() Return Null
|
|
|
|
|
|
@@ -551,19 +468,19 @@ Type TGLMax2DDriver Extends TMax2DDriver
|
|
|
|
|
|
Method SetGraphics( g:TGraphics ) Override
|
|
Method SetGraphics( g:TGraphics ) Override
|
|
If Not g
|
|
If Not g
|
|
- TMax2DGraphics.ClearCurrent
|
|
|
|
|
|
+ TMax2DGraphics.ClearCurrent()
|
|
SDLGraphicsDriver().SetGraphics Null
|
|
SDLGraphicsDriver().SetGraphics Null
|
|
Return
|
|
Return
|
|
EndIf
|
|
EndIf
|
|
|
|
|
|
Local t:TMax2DGraphics=TMax2DGraphics(g)
|
|
Local t:TMax2DGraphics=TMax2DGraphics(g)
|
|
- Assert t And TSDLGraphics( t._graphics )
|
|
|
|
|
|
+ Assert t And TSDLGraphics( t._backendGraphics )
|
|
|
|
|
|
- SDLGraphicsDriver().SetGraphics t._graphics
|
|
|
|
|
|
+ SDLGraphicsDriver().SetGraphics(t._backendGraphics)
|
|
|
|
|
|
- ResetGLContext t
|
|
|
|
|
|
+ ResetGLContext(t)
|
|
|
|
|
|
- t.MakeCurrent
|
|
|
|
|
|
+ t.MakeCurrent()
|
|
End Method
|
|
End Method
|
|
|
|
|
|
Method ResetGLContext( g:TGraphics )
|
|
Method ResetGLContext( g:TGraphics )
|
|
@@ -580,6 +497,15 @@ Type TGLMax2DDriver Extends TMax2DDriver
|
|
glMatrixMode GL_MODELVIEW
|
|
glMatrixMode GL_MODELVIEW
|
|
glLoadIdentity
|
|
glLoadIdentity
|
|
glViewport 0,0,gw,gh
|
|
glViewport 0,0,gw,gh
|
|
|
|
+
|
|
|
|
+ ' Create default back buffer render image - the FBO will be value 0 which is the default for the existing backbuffer
|
|
|
|
+ Local BackBufferRenderImageFrame:TGLSDLRenderImageFrame = New TGLSDLRenderImageFrame
|
|
|
|
+ BackBufferRenderImageFrame.width = gw
|
|
|
|
+ BackBufferRenderImageFrame.height = gh
|
|
|
|
+
|
|
|
|
+ ' cache it
|
|
|
|
+ _BackBufferRenderImageFrame = BackBufferRenderImageFrame
|
|
|
|
+ _CurrentRenderImageFrame = _BackBufferRenderImageFrame
|
|
End Method
|
|
End Method
|
|
|
|
|
|
Method Flip:Int( sync:Int ) Override
|
|
Method Flip:Int( sync:Int ) Override
|
|
@@ -590,15 +516,8 @@ Type TGLMax2DDriver Extends TMax2DDriver
|
|
Return "OpenGL"
|
|
Return "OpenGL"
|
|
End Method
|
|
End Method
|
|
|
|
|
|
-
|
|
|
|
- Method CreateRenderImageContext:Object(g:TGraphics) Override
|
|
|
|
- Return new TGLRenderImageContext.Create(g, self)
|
|
|
|
- End Method
|
|
|
|
-
|
|
|
|
Method CreateFrameFromPixmap:TGLImageFrame( pixmap:TPixmap,flags:Int ) Override
|
|
Method CreateFrameFromPixmap:TGLImageFrame( pixmap:TPixmap,flags:Int ) Override
|
|
- Local frame:TGLImageFrame
|
|
|
|
- frame=TGLImageFrame.CreateFromPixmap( pixmap,flags )
|
|
|
|
- Return frame
|
|
|
|
|
|
+ Return TGLImageFrame.CreateFromPixmap( pixmap,flags )
|
|
End Method
|
|
End Method
|
|
|
|
|
|
Method SetBlend( blend:Int ) Override
|
|
Method SetBlend( blend:Int ) Override
|
|
@@ -648,31 +567,20 @@ Type TGLMax2DDriver Extends TMax2DDriver
|
|
glColor4ubv color4ub
|
|
glColor4ubv color4ub
|
|
End Method
|
|
End Method
|
|
|
|
|
|
- Method SetColor( color:SColor8 ) Override
|
|
|
|
- color4ub[0]=color.r
|
|
|
|
- color4ub[1]=color.g
|
|
|
|
- color4ub[2]=color.b
|
|
|
|
- glColor4ubv color4ub
|
|
|
|
- End Method
|
|
|
|
-
|
|
|
|
- Method SetClsColor( red:Int,green:Int,blue:Int ) Override
|
|
|
|
- red=Min(Max(red,0),255)
|
|
|
|
- green=Min(Max(green,0),255)
|
|
|
|
- blue=Min(Max(blue,0),255)
|
|
|
|
- glClearColor red/255.0,green/255.0,blue/255.0,1.0
|
|
|
|
- End Method
|
|
|
|
|
|
+ Method SetClsColor( red:Int, green:Int, blue:Int, alpha:Float ) Override
|
|
|
|
+ red = Min(Max(red,0),255)
|
|
|
|
+ green = Min(Max(green,0),255)
|
|
|
|
+ blue = Min(Max(blue,0),255)
|
|
|
|
|
|
- Method SetClsColor( color:SCOlor8 ) Override
|
|
|
|
- glClearColor color.r/255.0,color.g/255.0,color.b/255.0,1.0
|
|
|
|
|
|
+ glClearColor(red/255.0, green/255.0, blue/255.0, alpha)
|
|
End Method
|
|
End Method
|
|
|
|
|
|
Method SetViewport( x:Int,y:Int,w:Int,h:Int ) Override
|
|
Method SetViewport( x:Int,y:Int,w:Int,h:Int ) Override
|
|
- If x=0 And y=0 And w=GraphicsWidth() And h=GraphicsHeight()
|
|
|
|
- glDisable GL_SCISSOR_TEST
|
|
|
|
- Else
|
|
|
|
- glEnable GL_SCISSOR_TEST
|
|
|
|
- glScissor x,GraphicsHeight()-y-h,w,h
|
|
|
|
- EndIf
|
|
|
|
|
|
+ _GLScissor_BMaxViewport.x = x
|
|
|
|
+ _GLScissor_BMaxViewport.y = y
|
|
|
|
+ _GLScissor_BMaxViewport.width = w
|
|
|
|
+ _GLScissor_BMaxViewport.height = h
|
|
|
|
+ SetScissor(x, y, w, h)
|
|
End Method
|
|
End Method
|
|
|
|
|
|
Method SetTransform( xx:Float,xy:Float,yx:Float,yy:Float ) Override
|
|
Method SetTransform( xx:Float,xy:Float,yx:Float,yy:Float ) Override
|
|
@@ -770,6 +678,12 @@ Type TGLMax2DDriver Extends TMax2DDriver
|
|
Local blend:Int=state_blend
|
|
Local blend:Int=state_blend
|
|
SetBlend SOLIDBLEND
|
|
SetBlend SOLIDBLEND
|
|
Local p:TPixmap=CreatePixmap( w,h,PF_RGBA8888 )
|
|
Local p:TPixmap=CreatePixmap( w,h,PF_RGBA8888 )
|
|
|
|
+
|
|
|
|
+ 'The default backbuffer in Max2D was opaque so overwrote any
|
|
|
|
+ 'trash data of a freshly created pixmap. Potentially transparent
|
|
|
|
+ 'backbuffers require a complete transparent pixmap to start with.
|
|
|
|
+ p.ClearPixels(0)
|
|
|
|
+
|
|
glReadPixels x,GraphicsHeight()-h-y,w,h,GL_RGBA,GL_UNSIGNED_BYTE,p.pixels
|
|
glReadPixels x,GraphicsHeight()-h-y,w,h,GL_RGBA,GL_UNSIGNED_BYTE,p.pixels
|
|
p=YFlipPixmap( p )
|
|
p=YFlipPixmap( p )
|
|
SetBlend blend
|
|
SetBlend blend
|
|
@@ -782,7 +696,49 @@ Type TGLMax2DDriver Extends TMax2DDriver
|
|
glOrtho 0,width,height,0,-1,1
|
|
glOrtho 0,width,height,0,-1,1
|
|
glMatrixMode GL_MODELVIEW
|
|
glMatrixMode GL_MODELVIEW
|
|
End Method
|
|
End Method
|
|
|
|
+
|
|
|
|
+ Method CreateRenderImageFrame:TImageFrame(width:UInt, height:UInt, flags:Int) Override
|
|
|
|
+ Return TGLSDLRenderImageFrame.Create(width, height, flags)
|
|
|
|
+ EndMethod
|
|
|
|
|
|
|
|
+ Method SetRenderImageFrame(RenderImageFrame:TImageFrame) Override
|
|
|
|
+ If RenderImageFrame = _CurrentRenderImageFrame
|
|
|
|
+ Return
|
|
|
|
+ EndIf
|
|
|
|
+
|
|
|
|
+ glBindFrameBuffer(GL_FRAMEBUFFER, TGLSDLRenderImageFrame(RenderImageFrame).FBO)
|
|
|
|
+ _CurrentRenderImageFrame = TGLSDLRenderImageFrame(RenderImageFrame)
|
|
|
|
+
|
|
|
|
+ Local vp:Rect = _GLScissor_BMaxViewport
|
|
|
|
+ SetScissor(vp.x, vp.y, vp.width, vp.height)
|
|
|
|
+ SetMatrixAndViewportToCurrentRenderImage()
|
|
|
|
+ EndMethod
|
|
|
|
+
|
|
|
|
+ Method SetBackbuffer()
|
|
|
|
+ SetRenderImageFrame(_BackBufferRenderImageFrame)
|
|
|
|
+ EndMethod
|
|
|
|
+
|
|
|
|
+Private
|
|
|
|
+ Field _glewIsInitialised:Int = False
|
|
|
|
+
|
|
|
|
+ Method SetMatrixAndViewportToCurrentRenderImage()
|
|
|
|
+ glMatrixMode(GL_PROJECTION)
|
|
|
|
+ glLoadIdentity()
|
|
|
|
+ glOrtho(0, _CurrentRenderImageFrame.width, _CurrentRenderImageFrame.height, 0, -1, 1)
|
|
|
|
+ glMatrixMode(GL_MODELVIEW)
|
|
|
|
+ glLoadIdentity()
|
|
|
|
+ glViewport(0, 0, _CurrentRenderImageFrame.width, _CurrentRenderImageFrame.height)
|
|
|
|
+ EndMethod
|
|
|
|
+
|
|
|
|
+ Method SetScissor(x:Int, y:Int, w:Int, h:Int)
|
|
|
|
+ Local ri:TImageFrame = _CurrentRenderImageFrame
|
|
|
|
+ If x = 0 And y = 0 And w = _CurrentRenderImageFrame.width And h = _CurrentRenderImageFrame.height
|
|
|
|
+ glDisable(GL_SCISSOR_TEST)
|
|
|
|
+ Else
|
|
|
|
+ glEnable(GL_SCISSOR_TEST)
|
|
|
|
+ glScissor(x, _CurrentRenderImageFrame.height - y - h, w, h)
|
|
|
|
+ EndIf
|
|
|
|
+ EndMethod
|
|
End Type
|
|
End Type
|
|
|
|
|
|
Rem
|
|
Rem
|