Add OpenGL support.

This commit is contained in:
LuisAntonRebollo 2014-11-08 17:41:17 +01:00
parent c354f59b72
commit dd08fd2e7d
55 changed files with 2957 additions and 802 deletions

View file

@ -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