mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-19 22:53:47 +00:00
Add OpenGL support.
This commit is contained in:
parent
c354f59b72
commit
dd08fd2e7d
55 changed files with 2957 additions and 802 deletions
|
|
@ -26,7 +26,15 @@
|
|||
#include "gfx/gl/gfxGLDevice.h"
|
||||
#include "gfx/gl/gfxGLEnumTranslate.h"
|
||||
#include "gfx/gl/gfxGLUtils.h"
|
||||
#include "gfx/gl/gfxGLVertexAttribLocation.h"
|
||||
|
||||
#include "gfx/gl/gfxGLCircularVolatileBuffer.h"
|
||||
|
||||
GLCircularVolatileBuffer* getCircularVolatileVertexBuffer()
|
||||
{
|
||||
static GLCircularVolatileBuffer sCircularVolatileVertexBuffer(GL_ARRAY_BUFFER);
|
||||
return &sCircularVolatileVertexBuffer;
|
||||
}
|
||||
|
||||
GFXGLVertexBuffer::GFXGLVertexBuffer( GFXDevice *device,
|
||||
U32 numVerts,
|
||||
|
|
@ -34,113 +42,111 @@ GFXGLVertexBuffer::GFXGLVertexBuffer( GFXDevice *device,
|
|||
U32 vertexSize,
|
||||
GFXBufferType bufferType )
|
||||
: GFXVertexBuffer( device, numVerts, vertexFormat, vertexSize, bufferType ),
|
||||
mZombieCache(NULL)
|
||||
mZombieCache(NULL),
|
||||
mBufferOffset(0),
|
||||
mBufferVertexOffset(0)
|
||||
{
|
||||
if( mBufferType == GFXBufferTypeVolatile )
|
||||
{
|
||||
mBuffer = getCircularVolatileVertexBuffer()->getHandle();
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate a buffer
|
||||
glGenBuffers(1, &mBuffer);
|
||||
|
||||
//and allocate the needed memory
|
||||
PRESERVE_VERTEX_BUFFER();
|
||||
// Generate a buffer and allocate the needed memory.
|
||||
glGenBuffers(1, &mBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, numVerts * vertexSize, NULL, GFXGLBufferType[bufferType]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, numVerts * vertexSize, NULL, GFXGLBufferType[bufferType]);
|
||||
}
|
||||
|
||||
GFXGLVertexBuffer::~GFXGLVertexBuffer()
|
||||
{
|
||||
// While heavy handed, this does delete the buffer and frees the associated memory.
|
||||
glDeleteBuffers(1, &mBuffer);
|
||||
|
||||
if( mBufferType != GFXBufferTypeVolatile )
|
||||
glDeleteBuffers(1, &mBuffer);
|
||||
|
||||
if( mZombieCache )
|
||||
delete [] mZombieCache;
|
||||
}
|
||||
|
||||
void GFXGLVertexBuffer::lock( U32 vertexStart, U32 vertexEnd, void **vertexPtr )
|
||||
{
|
||||
PRESERVE_VERTEX_BUFFER();
|
||||
// Bind us, get a pointer into the buffer, then
|
||||
// offset it by vertexStart so we act like the D3D layer.
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, mNumVerts * mVertexSize, NULL, GFXGLBufferType[mBufferType]);
|
||||
*vertexPtr = (void*)((U8*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY) + (vertexStart * mVertexSize));
|
||||
PROFILE_SCOPE(GFXGLVertexBuffer_lock);
|
||||
|
||||
if( mBufferType == GFXBufferTypeVolatile )
|
||||
{
|
||||
AssertFatal(vertexStart == 0, "");
|
||||
if( gglHasExtension(ARB_vertex_attrib_binding) )
|
||||
{
|
||||
getCircularVolatileVertexBuffer()->lock( mNumVerts * mVertexSize, 0, mBufferOffset, *vertexPtr );
|
||||
}
|
||||
else
|
||||
{
|
||||
getCircularVolatileVertexBuffer()->lock( mNumVerts * mVertexSize, mVertexSize, mBufferOffset, *vertexPtr );
|
||||
mBufferVertexOffset = mBufferOffset / mVertexSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mFrameAllocator.lock( mNumVerts * mVertexSize );
|
||||
|
||||
lockedVertexPtr = (void*)(mFrameAllocator.getlockedPtr() + (vertexStart * mVertexSize));
|
||||
*vertexPtr = lockedVertexPtr;
|
||||
}
|
||||
|
||||
lockedVertexStart = vertexStart;
|
||||
lockedVertexEnd = vertexEnd;
|
||||
}
|
||||
|
||||
void GFXGLVertexBuffer::unlock()
|
||||
{
|
||||
PRESERVE_VERTEX_BUFFER();
|
||||
// Unmap the buffer and bind 0 to GL_ARRAY_BUFFER
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
|
||||
bool res = glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
AssertFatal(res, "GFXGLVertexBuffer::unlock - shouldn't fail!");
|
||||
PROFILE_SCOPE(GFXGLVertexBuffer_unlock);
|
||||
|
||||
if( mBufferType == GFXBufferTypeVolatile )
|
||||
{
|
||||
getCircularVolatileVertexBuffer()->unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
U32 offset = lockedVertexStart * mVertexSize;
|
||||
U32 length = (lockedVertexEnd - lockedVertexStart) * mVertexSize;
|
||||
|
||||
PRESERVE_VERTEX_BUFFER();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
|
||||
|
||||
if( !lockedVertexStart && lockedVertexEnd == mNumVerts)
|
||||
glBufferData(GL_ARRAY_BUFFER, mNumVerts * mVertexSize, NULL, GFXGLBufferType[mBufferType]); // orphan the buffer
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, offset, length, mFrameAllocator.getlockedPtr() + offset );
|
||||
|
||||
mFrameAllocator.unlock();
|
||||
}
|
||||
|
||||
lockedVertexStart = 0;
|
||||
lockedVertexEnd = 0;
|
||||
lockedVertexPtr = NULL;
|
||||
}
|
||||
|
||||
void GFXGLVertexBuffer::prepare()
|
||||
{
|
||||
// Bind the buffer...
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
|
||||
U8* buffer = (U8*)getBuffer();
|
||||
AssertFatal(0, "GFXGLVertexBuffer::prepare - use GFXGLVertexBuffer::prepare(U32 stream, U32 divisor)");
|
||||
}
|
||||
|
||||
// Loop thru the vertex format elements adding the array state...
|
||||
U32 texCoordIndex = 0;
|
||||
for ( U32 i=0; i < mVertexFormat.getElementCount(); i++ )
|
||||
{
|
||||
const GFXVertexElement &element = mVertexFormat.getElement( i );
|
||||
|
||||
if ( element.isSemantic( GFXSemantic::POSITION ) )
|
||||
{
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glVertexPointer( element.getSizeInBytes() / 4, GL_FLOAT, mVertexSize, buffer );
|
||||
buffer += element.getSizeInBytes();
|
||||
}
|
||||
else if ( element.isSemantic( GFXSemantic::NORMAL ) )
|
||||
{
|
||||
glEnableClientState( GL_NORMAL_ARRAY );
|
||||
glNormalPointer( GL_FLOAT, mVertexSize, buffer );
|
||||
buffer += element.getSizeInBytes();
|
||||
}
|
||||
else if ( element.isSemantic( GFXSemantic::COLOR ) )
|
||||
{
|
||||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
glColorPointer( element.getSizeInBytes(), GL_UNSIGNED_BYTE, mVertexSize, buffer );
|
||||
buffer += element.getSizeInBytes();
|
||||
}
|
||||
else // Everything else is a texture coordinate.
|
||||
{
|
||||
glClientActiveTexture( GL_TEXTURE0 + texCoordIndex );
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glTexCoordPointer( element.getSizeInBytes() / 4, GL_FLOAT, mVertexSize, buffer );
|
||||
buffer += element.getSizeInBytes();
|
||||
++texCoordIndex;
|
||||
}
|
||||
|
||||
void GFXGLVertexBuffer::prepare(U32 stream, U32 divisor)
|
||||
{
|
||||
if( gglHasExtension(ARB_vertex_attrib_binding) )
|
||||
{
|
||||
glBindVertexBuffer( stream, mBuffer, mBufferOffset, mVertexSize );
|
||||
glVertexBindingDivisor( stream, divisor );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GFXGLVertexBuffer::finish()
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
U32 texCoordIndex = 0;
|
||||
for ( U32 i=0; i < mVertexFormat.getElementCount(); i++ )
|
||||
{
|
||||
const GFXVertexElement &element = mVertexFormat.getElement( i );
|
||||
|
||||
if ( element.isSemantic( GFXSemantic::POSITION ) )
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
else if ( element.isSemantic( GFXSemantic::NORMAL ) )
|
||||
glDisableClientState( GL_NORMAL_ARRAY );
|
||||
else if ( element.isSemantic( GFXSemantic::COLOR ) )
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
else
|
||||
{
|
||||
glClientActiveTexture( GL_TEXTURE0 + texCoordIndex );
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
++texCoordIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLvoid* GFXGLVertexBuffer::getBuffer()
|
||||
|
|
@ -175,3 +181,29 @@ void GFXGLVertexBuffer::resurrect()
|
|||
delete[] mZombieCache;
|
||||
mZombieCache = NULL;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool onGFXDeviceSignal( GFXDevice::GFXDeviceEventType type )
|
||||
{
|
||||
if( GFX->getAdapterType() == OpenGL && GFXDevice::deEndOfFrame == type )
|
||||
getCircularVolatileVertexBuffer()->protectUsedRange();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
MODULE_BEGIN( GFX_GL_VertexBuffer )
|
||||
MODULE_INIT_AFTER( gfx )
|
||||
MODULE_SHUTDOWN_BEFORE( gfx )
|
||||
|
||||
MODULE_INIT
|
||||
{
|
||||
GFXDevice::getDeviceEventSignal().notify( &onGFXDeviceSignal );
|
||||
}
|
||||
|
||||
MODULE_SHUTDOWN
|
||||
{
|
||||
GFXDevice::getDeviceEventSignal( ).remove( &onGFXDeviceSignal );
|
||||
}
|
||||
MODULE_END
|
||||
Loading…
Add table
Add a link
Reference in a new issue