Browse Source

WIP vertex/index buffer changes.

Mark Sibly 8 years ago
parent
commit
979f0844d2

+ 0 - 4
modules/mojo/app/glwindow.monkey2

@@ -3,10 +3,6 @@ Namespace mojo.app
 
 Class GLWindow Extends Window
 
-	Method New()
-		Init()
-	End
-	
 	Method New( title:String="Window",width:Int=640,height:Int=480,flags:WindowFlags=Null )
 		Super.New( title,width,height,flags )
 		Init()

+ 0 - 4
modules/mojo/app/window.monkey2

@@ -32,10 +32,6 @@ End
 #end
 Class Window Extends View
 
-	Method New()
-		Init( "Window",New Recti( 0,0,640,480 ),WindowFlags.Center )
-	End
-	
 	Method New( title:String="Window",width:Int=640,height:Int=480,flags:WindowFlags=Null )
 		Init( title,New Recti( 0,0,width,height ),flags|WindowFlags.Center )
 	End

+ 56 - 20
modules/mojo/graphics/canvas.monkey2

@@ -1142,17 +1142,19 @@ Class Canvas
 		DebugAssert( _lighting,"Canvas.AddLight() can only be used while lighting" )
 		If Not _lighting Return
 		
+		If _lightNV+4>_lightVB.Length Return
+		
 		Local lx:=_matrix.i.x * tx + _matrix.j.x * ty + _matrix.t.x
 		Local ly:=_matrix.i.y * tx + _matrix.j.y * ty + _matrix.t.y
 		
-		_vp=Cast<Vertex2f Ptr>( _lightVB.AddVertices( 4 ) )
-		If Not _vp Return
-
 		Local op:=New LightOp
 		op.light=light
 		op.lightPos=New Vec2f( lx,ly )
-		op.primOffset=_lightVB.Length-4
+		op.primOffset=_lightNV
 		_lightOps.Push( op )
+
+		_vp=_lightVP0+_lightNV
+		_lightNV+=4
 		
 		Local vs:=light.Vertices
 		Local ts:=light.TexCoords
@@ -1291,6 +1293,10 @@ Class Canvas
 		
 		If _drawOps.Empty Return
 		
+		_drawVB.Invalidate( 0,_drawNV )
+		
+		_drawVB.Unlock()
+		
 		'Render ambient
 		'		
 		RenderDrawOps( 0 )
@@ -1312,9 +1318,11 @@ Class Canvas
 			'back to rendertarget
 			'			
 			_device.RenderTarget=_rtarget
+			
 		Endif
 		
-		_drawVB.Clear()
+		_drawVP0=Cast<Vertex2f Ptr>( _drawVB.Lock() )
+		_drawNV=0
 		_drawOps.Clear()
 		_drawOp=New DrawOp
 	End
@@ -1397,9 +1405,14 @@ Class Canvas
 		
 		Flush()
 		
+		_lightVB.Invalidate( 0,_lightNV )
+		
+		_lightVB.Unlock()
+		
 		RenderLighting()
 	
-		_lightVB.Clear()
+		_lightVP0=Cast<Vertex2f Ptr>( _lightVB.Lock() )
+		_lightNV=0
 		_lightOps.Clear()
 		
 		_shadowOps.Clear()
@@ -1516,10 +1529,14 @@ Class Canvas
 	Field _vp:Vertex2f Ptr
 
 	Field _drawVB:VertexBuffer
+	Field _drawVP0:Vertex2f Ptr
+	Field _drawNV:Int
 	Field _drawOps:=New Stack<DrawOp>
 	Field _drawOp:=New DrawOp
 
 	Field _lightVB:VertexBuffer
+	Field _lightVP0:Vertex2f Ptr
+	Field _lightNV:Int
 	Field _lightOps:=New Stack<LightOp>
 	
 	Field _shadowOps:=New Stack<ShadowOp>
@@ -1535,8 +1552,11 @@ Class Canvas
 		inited=True
 
 		Local nquads:=MaxVertices/4
+		
 		_quadIndices=New IndexBuffer( IndexFormat.UINT16,nquads*6 )
-		Local ip:=Cast<UShort Ptr>( _quadIndices.AddIndices( nquads*6 ) )
+		
+		Local ip:=Cast<UShort Ptr>( _quadIndices.Lock() )
+		
 		For Local i:=0 Until nquads*4 Step 4
 			ip[0]=i
 			ip[1]=i+1
@@ -1546,8 +1566,12 @@ Class Canvas
 			ip[5]=i+3
 			ip+=6
 		Next
+
+		_quadIndices.Invalidate( 0,nquads*6 )
+		
+		_quadIndices.Unlock()
 		
-		_shadowVB=New VertexBuffer( Vertex2fFormat.Instance,MaxShadowVertices )
+		_shadowVB=New VertexBuffer( Vertex2f.Format,MaxShadowVertices )
 
 		_defaultFont=mojo.graphics.Font.Load( "font::DejaVuSans.ttf",16 )
 	End
@@ -1567,9 +1591,15 @@ Class Canvas
 		_uniforms=New UniformBlock( 1 )
 		_device.BindUniformBlock( _uniforms )
 
-		_drawVB=New VertexBuffer( Vertex2fFormat.Instance,MaxVertices )
-		_lightVB=New VertexBuffer( Vertex2fFormat.Instance,MaxLights*4 )
-		_shadowVB=New VertexBuffer( Vertex2fFormat.Instance,65536 )
+		_drawVB=New VertexBuffer( Vertex2f.Format,MaxVertices )
+		_drawVP0=Cast<Vertex2f Ptr>( _drawVB.Lock() )
+		_drawNV=0
+		
+		_lightVB=New VertexBuffer( Vertex2f.Format,MaxLights*4 )
+		_lightVP0=Cast<Vertex2f Ptr>( _lightVB.Lock() )
+		_lightNV=0
+		
+		_shadowVB=New VertexBuffer( Vertex2f.Format,65536 )
 		
 		_device.IndexBuffer=_quadIndices
 
@@ -1656,8 +1686,8 @@ Class Canvas
 	'Drawing
 	'	
 	Method AddDrawOp( shader:Shader,material:UniformBlock,blendMode:BlendMode,primOrder:int,primCount:Int )
-	
-		If _drawVB.Length+primCount*primOrder>_drawVB.Capacity
+
+		If _drawNV+primCount*primOrder>_drawVB.Length
 			Flush()
 		Endif
 		
@@ -1666,8 +1696,8 @@ Class Canvas
 		If shader<>_drawOp.shader Or material<>_drawOp.material Or blendMode<>_drawOp.blendMode Or primOrder<>_drawOp.primOrder
 		
 			'pad quads so primOffset always on a 4 vert boundary
-			If primOrder=4 And _drawVB.Length & 3 
-				_drawVB.AddVertices( 4-(_drawVB.Length&3) )
+			If primOrder=4 And _drawNV & 3
+				_drawNV+=4-(_drawNV&3)
 			Endif
 			
 			_drawOp=New DrawOp
@@ -1676,13 +1706,14 @@ Class Canvas
 			_drawOp.blendMode=blendMode
 			_drawOp.primOrder=primOrder
 			_drawOp.primCount=primCount
-			_drawOp.primOffset=_drawVB.Length
+			_drawOp.primOffset=_drawNV
 			_drawOps.Push( _drawOp )
 		Else
 			_drawOp.primCount+=primCount
 		Endif
 		
-		_vp=Cast<Vertex2f Ptr>( _drawVB.AddVertices( primOrder*primCount ) )
+		_vp=_drawVP0+_drawNV
+		_drawNV+=primCount*primOrder
 	End
 	
 	Method Validate()
@@ -1766,7 +1797,8 @@ Class Canvas
 		
 		Local lv:=lightOp.lightPos
 
-		_shadowVB.Clear()
+		Local vp0:=Cast<Vertex2f Ptr>( _shadowVB.Lock() )
+		Local n:=0
 		
 		For Local op:=Eachin _shadowOps
 		
@@ -1787,8 +1819,9 @@ Class Canvas
 				Local d:=lv.Dot( nv )+pd
 				If d<0 Continue
 				
-				Local tp:=Cast<Vertex2f Ptr>( _shadowVB.AddVertices( 9 ) )
-				If Not tp Exit
+				If n+9>_shadowVB.Length Exit
+				Local tp:=vp0+n
+				n+=9
 			
 				Local hv:=(pv+tv)/2
 				
@@ -1805,6 +1838,8 @@ Class Canvas
 			
 		Next
 		
+		_shadowVB.Unlock()
+		
 	End
 		
 	'Lighting
@@ -1812,6 +1847,7 @@ Class Canvas
 	Method RenderLighting()
 	
 		_device.BlendMode=BlendMode.Additive
+		
 		_device.VertexBuffer=_lightVB
 		
 		For Local op:=Eachin _lightOps

+ 119 - 81
modules/mojo/graphics/indexbuffer.monkey2

@@ -2,146 +2,184 @@
 Namespace mojo.graphics
 
 Enum IndexFormat
-	UINT16=1
-	UINT32=2
+	UINT8=1
+	UINT16=2
+	UINT32=4
 End
 
-#rem monkeydoc @hidden
-#end	
-Class IndexBuffer
-
-	Method New( format:IndexFormat,capacity:Int )
-
+Class IndexBuffer Extends Resource
+	
+	Method New( format:IndexFormat,length:Int=0 )
+		
 		_format=format
-		_capacity=capacity
-		_pitch=_format=IndexFormat.UINT16 ? 2 Else 4
-		_data=New UByte[_capacity*_pitch]
+		_length=length
+		_pitch=Int( _format )
+		_managed=New UByte[_length*_pitch]
+		_dirtyMin=_length
+		_dirtyMax=0
 	End
-	
-	Method New( indices:IndexBuffer )
 
-		_format=indices._format
-		_capacity=indices._capacity
-		_pitch=indices._pitch
-		_length=indices._length
-		_data=indices._data.Slice( 0 )
-	End
-	
 	Method New( indices:UInt[] )
-		
 		Self.New( IndexFormat.UINT32,indices.Length )
 		
-		If _capacity libc.memcpy( AddIndices( _capacity ),indices.Data,_capacity*_pitch )
+		SetIndices( indices.Data,0,indices.Length )
 	End
 	
-	Method New( indices:UShort[] )
-		
-		Self.New( IndexFormat.UINT16,indices.Length )
+	Property Format:IndexFormat()
 		
-		If _capacity libc.memcpy( AddIndices( _capacity ),indices.Data,_capacity*_pitch )
+		Return _format
 	End
 	
-	Property Data:UByte Ptr()
+	Property Length:Int()
 		
-		Return _data.Data
+		Return _length
 	End
 	
-	Property Format:IndexFormat()
+	Property Pitch:Int()
 		
-		Return _format
+		Return _pitch
 	End
 	
-	Property Capacity:Int()
-	
-		Return _capacity
+	#rem monkeydoc Resizes the index buffer.
+	#end
+	Method Resize( length:Int )
+
+		If length=_length Return
+		
+		Local managed:=New UByte[length*_pitch]
+		
+		Local n:=Min( length,_length )
+		
+		If n libc.memcpy( managed.Data,_managed.Data,n*_pitch )
+			
+		_managed=managed
+		
+		_length=length
+		
+		If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
+			
+		_glSeq=0
 	End
+	
+	#rem monkeydoc Sets a range of indices.
+	#end
+	Method SetIndices( indices:Void Ptr,first:Int,count:Int )
 
-	Property Pitch:Int()
+		DebugAssert( Not _locked,"IndexBuffer is locked" )
+
+		DebugAssert( first>=0 And count>=0 And first<=_length And first+count<=_length,"Invalid index range" )
 		
-		Return _pitch
+		libc.memcpy( _managed.Data+first*_pitch,indices,count*_pitch )
+		
+		Invalidate( first,count )
 	End
 	
-	Property Length:Int()
+	#rem monkeydoc Locks indices.
 	
-		Return _length
+	Make sure to invalidate any indices you modify by using [[Invalidate]].
+	
+	#end
+	Method Lock:UByte ptr()
+		
+		DebugAssert( Not _locked,"IndexBuffer is already locked" )
+		
+		_locked=_managed.Data
+		
+		Return _locked
 	End
 	
-	Method Clear()
+	#rem onkeydoc Invalidates indices.
+	
+	You should use this method to invalidate any indices you have modified by writing to a locked index buffer.
+	
+	#End
+	Method Invalidate( first:Int,count:Int )
+		
+'		DebugAssert( _locked,"Index buffer is not locked" )
+		
+		DebugAssert( first>=0 And count>=0 And first<=_length And first+count<=_length,"Invalid index range" )
 		
-		_length=0
-		_clean=0
+		_dirtyMin=Min( _dirtyMin,first )
+		
+		_dirtyMax=Max( _dirtyMax,first+count )
 	End
 	
 	Method Invalidate()
 		
-		_clean=0
+		Invalidate( 0,_length )
 	End
 	
-	Method AddIndices:UByte Ptr( count:Int )
-		
-		Reserve( _length+count )
+	#rem monkeydoc Unlocks indices.
+	#end
+	Method Unlock:Void()
 		
-		Local p:=_data.Data+_length*_pitch
+		DebugAssert( _locked,"Index buffer is not locked" )
 		
-		_length+=count
+		_locked=Null
+	End
+	
+	Protected
+	
+	Method OnDiscard() Override
 		
-		Return p
+		If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
+			
+		_glSeq=-1
 	End
 	
-	'***** INTERNAL *****
+	Method OnFinalize() Override
+
+		If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
+	End
 	
-	Method Bind()
+	Internal
 	
+	Method Bind()
+		
+		DebugAssert( Not _locked,"IndexBuffer.Bind() failed, IndexBuffer is locked" )
+		
 		If _glSeq<>glGraphicsSeq
 			
 			glGenBuffers( 1,Varptr _glBuffer )
 			glBindBuffer( GL_ELEMENT_ARRAY_BUFFER,_glBuffer )
 			
-			glBufferData( GL_ELEMENT_ARRAY_BUFFER,_capacity*_pitch,Null,GL_DYNAMIC_DRAW )
-'			Print "bound ib "+_glBuffer
-		
+			glBufferData( GL_ELEMENT_ARRAY_BUFFER,_length*_pitch,_managed.Data,GL_DYNAMIC_DRAW )
+			_dirtyMin=_length
+			_dirtyMax=0
+
 			_glSeq=glGraphicsSeq
-			_clean=0
+			
 		Else
+
 			glBindBuffer( GL_ELEMENT_ARRAY_BUFFER,_glBuffer )
-'			Print "bound ib "+_glBuffer
 		Endif
-
+	
 	End
 	
 	Method Validate()
 		
-		If _length=_clean Return
-		
-		glBufferData( GL_ELEMENT_ARRAY_BUFFER,_length*_pitch,_data.Data,GL_DYNAMIC_DRAW )
-'		Print "updated ib "+_glBuffer
-		
-		_clean=_length
+		If _dirtyMax>_dirtyMin
+			
+			glBufferSubData( GL_ELEMENT_ARRAY_BUFFER,_dirtyMin*_pitch,(_dirtyMax-_dirtyMin)*_pitch,_managed.Data )
+			
+			_dirtyMin=_length
+			_dirtyMax=0
+		Endif
 	End
-		
+	
 	Private
 	
 	Field _format:IndexFormat
-	Field _capacity:Int
-	Field _pitch:Int
 	Field _length:Int
-	Field _clean:Int
-	Field _data:UByte[]
-
+	Field _pitch:Int
+	
+	Field _managed:UByte[]
+	Field _dirtyMin:Int
+	Field _dirtyMax:Int
+	
+	Field _locked:UByte Ptr
+	
 	Field _glSeq:Int
 	Field _glBuffer:GLuint
-
-	Method Reserve( capacity:Int )
-		
-		If _capacity>=capacity Return
-		
-		_capacity=Max( _length*2+_length,capacity )
-		
-		Local data:=New UByte[_capacity*_pitch]
-		
-		If _length libc.memcpy( data.Data,_data.Data,_length*_pitch )
-		
-		_data=data
-	End
-
+	
 End

+ 5 - 3
modules/mojo/graphics/vertex2f.monkey2

@@ -2,6 +2,10 @@
 Namespace mojo.graphics
 
 Struct Vertex2f
+	
+	Const Format:=New Vertex2fFormat
+	
+	Const Pitch:=28
 
 	Field position:Vec2f
 	Field texCoord0:Vec2f
@@ -36,11 +40,9 @@ End
 
 Class Vertex2fFormat Extends VertexFormat
 	
-	Const Instance:=New Vertex2fFormat
-	
 	Property Pitch:Int() Override
 		
-		Return 28
+		Return Vertex2f.Pitch
 	End
 
 	Method UpdateGLAttribs() Override

+ 5 - 5
modules/mojo/graphics/vertex3f.monkey2

@@ -3,6 +3,10 @@ Namespace mojo.graphics
 
 Struct Vertex3f
 
+	Const Format:=New Vertex3fFormat
+	
+	Const Pitch:=76			'76
+	
 	Field position:Vec3f	'0
 	Field texCoord0:Vec2f	'12
 	Field texCoord1:Vec2f	'20
@@ -11,8 +15,6 @@ Struct Vertex3f
 	Field weights:Vec4f		'56
 	Field bones:UInt		'72
 
-	Const Pitch:=76			'76
-	
 	Method New()
 	End
 	
@@ -95,10 +97,8 @@ End
 
 Class Vertex3fFormat Extends VertexFormat
 
-	Const Instance:=New Vertex3fFormat
-	
 	Property Pitch:Int() Override
-		
+
 		Return Vertex3f.Pitch
 	End
 

+ 129 - 72
modules/mojo/graphics/vertexbuffer.monkey2

@@ -5,142 +5,199 @@ Namespace mojo.graphics
 #end	
 Class VertexFormat
 	
-	Property Pitch:Int() Abstract
+	Method New()
+	End
+	
+	Property Pitch:Int() Virtual
+		Return 0
+	End
 
-	Method UpdateGLAttribs() Abstract
+	Method UpdateGLAttribs() Virtual
+	End
 End
 
-#rem monkeydoc @hidden
-#end	
-Class VertexBuffer
+#rem
+
+Vertex buffers can 'grow' stack-like.
+
+Use Resize or AddVertices to grow a vertex buffer.
 
-	Method New( format:VertexFormat,capacity:Int )
+#end
+Class VertexBuffer Extends Resource
+	
+	Method New( format:VertexFormat,length:Int=0 )
 		
 		_format=format
-		_capacity=capacity
+		_length=length
 		_pitch=_format.Pitch
-		_data=New UByte[_capacity*_pitch]
+		_managed=New UByte[_length*_pitch]
+		_dirtyMin=_length
+		_dirtyMax=0
 	End
 	
-	Method New( vertices:VertexBuffer )
+	Method New( vertices:Vertex3f[] )
+		Self.New( Vertex3f.Format,vertices.Length )
 		
-		_format=vertices._format
-		_capacity=vertices._capacity
-		_pitch=vertices._pitch
-		_length=vertices._length
-		_data=vertices._data.Slice( 0 )
+		SetVertices( vertices.Data,0,vertices.Length )
 	End
 	
-	Method New( vertices:Vertex3f[] )
-		
-		Self.New( Vertex3fFormat.Instance,vertices.Length )
+	Property Format:VertexFormat()
 		
-		If _capacity libc.memcpy( AddVertices( _capacity ),vertices.Data,_capacity*_pitch )
+		Return _format
 	End
 	
-	Property Data:UByte Ptr()
+	Property Length:Int()
 		
-		Return _data.Data
+		Return _length
 	End
 	
-	Property Format:VertexFormat()
+	Property Pitch:Int()
 		
-		Return _format
+		Return _pitch
 	End
 	
-	Property Capacity:Int()
-	
-		Return _capacity
+	#rem monkeydoc Resizes the vertex buffer.
+	#end
+	Method Resize( length:Int )
+		
+		If length=_length Return
+		
+		Local managed:=New UByte[length*_pitch]
+		
+		Local n:=Min( length,_length )
+		
+		If n libc.memcpy( managed.Data,_managed.Data,n*_pitch )
+
+		_managed=managed
+		
+		_length=length
+
+		If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
+			
+		_glSeq=0
 	End
 	
-	Property Pitch:Int()
+	#rem monkeydoc Sets a range of vertices.
+	#end
+	Method SetVertices( vertices:Void Ptr,first:Int,count:Int )
 		
-		Return _pitch
+		DebugAssert( Not _locked,"VertexBuffer is locked" )
+		
+		DebugAssert( first>=0 And count>=0 And first<=_length And first+count<=_length,"Invalid vertex range" )
+		
+		libc.memcpy( _managed.Data+first*_pitch,vertices,count*_pitch )
+		
+		Invalidate( first,count )
 	End
 	
-	Property Length:Int()
+	#rem monkeydoc Locks vertices.
 	
-		Return _length
+	Make sure to invalidate any vertices you modify by using [[Invalidate]].
+	
+	#end
+	Method Lock:UByte ptr()
+		
+		DebugAssert( Not _locked,"VertexBuffer is already locked" )
+		
+		_locked=_managed.Data
+		
+		Return _locked
 	End
 	
-	Method Clear()
+	#rem onkeydoc Invalidates vertices.
+	
+	You should use this method to invalidate any vertices you have modified by writing to a locked vertex buffer.
+	
+	#End
+	Method Invalidate( first:Int,count:Int )
+		
+'		DebugAssert( _locked,"Vertex buffer is not locked" )
+		
+		DebugAssert( first>=0 And count>=0 And first<=_length And first+count<=_length,"Invalid vertex range" )
 		
-		_length=0
-		_clean=0
+		_dirtyMin=Min( _dirtyMin,first )
+		
+		_dirtyMax=Max( _dirtyMax,first+count )
 	End
 	
 	Method Invalidate()
 		
-		_clean=0
+		Invalidate( 0,_length )
 	End
 	
-	Method AddVertices:UByte Ptr( count:Int )
+	#rem monkeydoc Unlocks vertices.
+	#end
+	Method Unlock:Void()
 		
-		Reserve( _length+count )
-
-		Local p:=_data.Data+_length*_pitch
+		DebugAssert( _locked,"Vertex buffer is not locked" )
 		
-		_length+=count
+		_locked=Null
+	End
+	
+	Protected
+	
+	Method OnDiscard() Override
 		
-		Return p
+		If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
+			
+		_glSeq=-1
 	End
+	
+	Method OnFinalize() Override
 
-	'***** INTERNAL *****
+		If _glSeq=glGraphicsSeq glDeleteBuffers( 1,Varptr _glBuffer )
+	End
+	
+	Internal
 	
 	Method Bind()
 		
+		DebugAssert( Not _locked,"VertexBuffer.Bind() failed, VertexBuffer is locked" )
+		
 		If _glSeq<>glGraphicsSeq
 			
 			glGenBuffers( 1,Varptr _glBuffer )
 			glBindBuffer( GL_ARRAY_BUFFER,_glBuffer )
 			
-			glBufferData( GL_ARRAY_BUFFER,_capacity*_pitch,Null,GL_DYNAMIC_DRAW )
-'			Print "bound vb "+_glBuffer
-			
+			glBufferData( GL_ARRAY_BUFFER,_length*_pitch,_managed.Data,GL_DYNAMIC_DRAW )
+			_dirtyMin=_length
+			_dirtyMax=0
+
 			_glSeq=glGraphicsSeq
-			_clean=0
+			
 		Else
+
 			glBindBuffer( GL_ARRAY_BUFFER,_glBuffer )
-'			Print "bound vb "+_glBuffer
 		Endif
 		
-		_format.UpdateGLAttribs()
-			
+		If _format _format.UpdateGLAttribs()
 	End
 	
 	Method Validate()
-	
-		If _length=_clean Return
 		
-		glBufferData( GL_ARRAY_BUFFER,_length*_pitch,_data.Data,GL_DYNAMIC_DRAW )
-'		Print "updated vb "+_glBuffer
-
-		_clean=_length
-	End
+		If _dirtyMax>_dirtyMin
+			
+			glBufferSubData( GL_ARRAY_BUFFER,_dirtyMin*_pitch,(_dirtyMax-_dirtyMin)*_pitch,_managed.Data )
+			
+			_dirtyMin=_length
+			_dirtyMax=0
 		
+		Endif
+	End
+	
 	Private
 	
 	Field _format:VertexFormat
-	Field _capacity:Int
-	Field _pitch:int
 	Field _length:Int
-	Field _clean:Int
-	Field _data:UByte[]
+	Field _pitch:Int
+	
+	Field _managed:UByte[]
+	Field _dirtyMin:Int
+	Field _dirtyMax:Int
+	
+	Field _locked:UByte Ptr
 	
 	Field _glSeq:Int
 	Field _glBuffer:GLuint
-
-	Method Reserve( capacity:Int )
-		
-		If _capacity>=capacity Return
-		
-		_capacity=Max( _length*2+_length,capacity )
-		
-		Local data:=New UByte[_capacity*_pitch]
-		
-		If _length libc.memcpy( data.Data,_data.Data,_length*_pitch )
-		
-		_data=data
-	End
-
+	
 End