Vertices are stored in GPU memory (OpenGL GAL).

This commit is contained in:
Maciej Suminski 2016-05-02 16:12:16 +02:00
parent 01912aaabd
commit 702be4903f
14 changed files with 267 additions and 216 deletions

View File

@ -152,7 +152,11 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
KIGFX::PCB_RENDER_SETTINGS* settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( m_painter->GetSettings() ); KIGFX::PCB_RENDER_SETTINGS* settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( m_painter->GetSettings() );
m_viewControls->UpdateScrollbars(); m_viewControls->UpdateScrollbars();
m_gal->BeginUpdate();
m_view->UpdateItems(); m_view->UpdateItems();
m_gal->EndUpdate();
m_gal->BeginDrawing(); m_gal->BeginDrawing();
m_gal->ClearScreen( settings->GetBackgroundColor() ); m_gal->ClearScreen( settings->GetBackgroundColor() );

View File

@ -33,6 +33,8 @@
#include <gal/opengl/vertex_manager.h> #include <gal/opengl/vertex_manager.h>
#include <gal/opengl/vertex_item.h> #include <gal/opengl/vertex_item.h>
#include <gal/opengl/shader.h> #include <gal/opengl/shader.h>
#include <gal/opengl/utils.h>
#include <confirm.h> #include <confirm.h>
#include <list> #include <list>
#include <cassert> #include <cassert>
@ -45,7 +47,8 @@
using namespace KIGFX; using namespace KIGFX;
CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) : CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
VERTEX_CONTAINER( aSize ), m_item( NULL ) VERTEX_CONTAINER( aSize ), m_item( NULL ), m_isMapped( false ),
m_isInitialized( false ), m_glBufferHandle( -1 )
{ {
// In the beginning there is only free space // In the beginning there is only free space
m_freeChunks.insert( CHUNK( aSize, 0 ) ); m_freeChunks.insert( CHUNK( aSize, 0 ) );
@ -57,6 +60,18 @@ CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
} }
CACHED_CONTAINER::~CACHED_CONTAINER()
{
if( m_isMapped )
Unmap();
if( m_isInitialized )
{
glDeleteBuffers( 1, &m_glBufferHandle );
}
}
void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem ) void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
{ {
assert( aItem != NULL ); assert( aItem != NULL );
@ -103,6 +118,7 @@ void CACHED_CONTAINER::FinishItem()
VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize ) VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
{ {
assert( m_item != NULL ); assert( m_item != NULL );
assert( m_isMapped );
if( m_failed ) if( m_failed )
return NULL; return NULL;
@ -181,7 +197,7 @@ void CACHED_CONTAINER::Delete( VERTEX_ITEM* aItem )
// a large amount of memory when there is no use for it // a large amount of memory when there is no use for it
if( m_freeSpace > ( 0.75 * m_currentSize ) && m_currentSize > m_initialSize ) if( m_freeSpace > ( 0.75 * m_currentSize ) && m_currentSize > m_initialSize )
{ {
resizeContainer( 0.5 * m_currentSize ); defragmentResize( 0.5 * m_currentSize );
} }
#endif #endif
} }
@ -189,6 +205,10 @@ void CACHED_CONTAINER::Delete( VERTEX_ITEM* aItem )
void CACHED_CONTAINER::Clear() void CACHED_CONTAINER::Clear()
{ {
Map();
glInvalidateBufferData( GL_ARRAY_BUFFER );
Unmap();
m_freeSpace = m_currentSize; m_freeSpace = m_currentSize;
m_failed = false; m_failed = false;
@ -207,9 +227,51 @@ void CACHED_CONTAINER::Clear()
} }
void CACHED_CONTAINER::Map()
{
assert( !IsMapped() );
if( !m_isInitialized )
init();
glBindBuffer( GL_ARRAY_BUFFER, m_glBufferHandle );
m_vertices = static_cast<VERTEX*>( glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE ) );
checkGlError( "mapping vertices buffer" );
m_isMapped = true;
}
void CACHED_CONTAINER::Unmap()
{
assert( IsMapped() );
glUnmapBuffer( GL_ARRAY_BUFFER );
checkGlError( "unmapping vertices buffer" );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
m_vertices = NULL;
checkGlError( "unbinding vertices buffer" );
m_isMapped = false;
}
void CACHED_CONTAINER::init()
{
glGenBuffers( 1, &m_glBufferHandle );
glBindBuffer( GL_COPY_WRITE_BUFFER, m_glBufferHandle );
glBufferData( GL_COPY_WRITE_BUFFER, m_currentSize * VertexSize, NULL, GL_DYNAMIC_DRAW );
glBindBuffer( GL_COPY_WRITE_BUFFER, 0 );
checkGlError( "allocating video memory for cached container" );
m_isInitialized = true;
}
unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize ) unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
{ {
assert( aSize > 0 ); assert( aSize > 0 );
assert( m_isMapped );
#if CACHED_CONTAINER_TEST > 2 #if CACHED_CONTAINER_TEST > 2
wxLogDebug( wxT( "Resize 0x%08lx from %d to %d" ), (long) m_item, m_itemSize, aSize ); wxLogDebug( wxT( "Resize 0x%08lx from %d to %d" ), (long) m_item, m_itemSize, aSize );
@ -224,12 +286,12 @@ unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
if( aSize < m_freeSpace + m_currentSize ) if( aSize < m_freeSpace + m_currentSize )
{ {
// Yes: exponential growing // Yes: exponential growing
result = resizeContainer( m_currentSize * 2 ); result = defragmentResize( m_currentSize * 2 );
} }
else else
{ {
// No: grow to the nearest greater power of 2 // No: grow to the nearest greater power of 2
result = resizeContainer( pow( 2, ceil( log2( m_currentSize * 2 + aSize ) ) ) ); result = defragmentResize( pow( 2, ceil( log2( m_currentSize * 2 + aSize ) ) ) );
} }
if( !result ) if( !result )
@ -243,7 +305,7 @@ unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
{ {
// In the case when there is enough space to store the vertices, // In the case when there is enough space to store the vertices,
// but the free space is not continous we should defragment the container // but the free space is not continous we should defragment the container
if( !defragment() ) if( !defragmentResize( m_currentSize ) )
return UINT_MAX; return UINT_MAX;
// Update the current offset // Update the current offset
@ -288,72 +350,12 @@ unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
m_freeSpace -= aSize; m_freeSpace -= aSize;
// mergeFreeChunks(); // veery slow and buggy // mergeFreeChunks(); // veery slow and buggy
m_item->setOffset( newChunkOffset );
return newChunkOffset; return newChunkOffset;
} }
bool CACHED_CONTAINER::defragment( VERTEX* aTarget )
{
#if CACHED_CONTAINER_TEST > 0
wxLogDebug( wxT( "Defragmenting" ) );
prof_counter totalTime;
prof_start( &totalTime );
#endif
if( aTarget == NULL )
{
// No target was specified, so we have to reallocate our own space
int size = m_currentSize * sizeof( VERTEX );
aTarget = static_cast<VERTEX*>( malloc( size ) );
if( aTarget == NULL )
{
DisplayError( NULL, wxString::Format(
wxT( "CACHED_CONTAINER::defragment: Run out of memory (malloc %d bytes)" ),
size ) );
return false;
}
}
int newOffset = 0;
ITEMS::iterator it, it_end;
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
{
VERTEX_ITEM* item = *it;
int itemOffset = item->GetOffset();
int itemSize = item->GetSize();
// Move an item to the new container
memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VertexSize );
// Update new offset
item->setOffset( newOffset );
// Move to the next free space
newOffset += itemSize;
}
free( m_vertices );
m_vertices = aTarget;
// Now there is only one big chunk of free memory
m_freeChunks.clear();
wxASSERT( m_freeSpace > 0 );
m_freeChunks.insert( CHUNK( m_freeSpace, m_currentSize - m_freeSpace ) );
#if CACHED_CONTAINER_TEST > 0
prof_end( &totalTime );
wxLogDebug( wxT( "Defragmented the container storing %d vertices / %.1f ms" ),
m_currentSize - m_freeSpace, totalTime.msecs() );
#endif
return true;
}
void CACHED_CONTAINER::mergeFreeChunks() void CACHED_CONTAINER::mergeFreeChunks()
{ {
if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged
@ -415,65 +417,72 @@ void CACHED_CONTAINER::mergeFreeChunks()
} }
bool CACHED_CONTAINER::resizeContainer( unsigned int aNewSize ) bool CACHED_CONTAINER::defragmentResize( unsigned int aNewSize )
{ {
#if CACHED_CONTAINER_TEST > 0 #if CACHED_CONTAINER_TEST > 0
wxLogDebug( wxT( "Resizing container from %d to %d" ), m_currentSize, aNewSize ); wxLogDebug( wxT( "Resizing container from %d to %d" ), m_currentSize, aNewSize );
#endif #endif
VERTEX* newContainer; // No shrinking if we cannot fit all the data
if( aNewSize < m_currentSize && usedSpace() > aNewSize )
return false;
if( aNewSize < m_currentSize ) #if CACHED_CONTAINER_TEST > 0
wxLogDebug( wxT( "Defragmenting" ) );
prof_counter totalTime;
prof_start( &totalTime );
#endif
GLuint newBuffer;
Unmap();
glGenBuffers( 1, &newBuffer );
glBindBuffer( GL_COPY_WRITE_BUFFER, newBuffer );
glBufferData( GL_COPY_WRITE_BUFFER, aNewSize * VertexSize, NULL, GL_DYNAMIC_DRAW );
glBindBuffer( GL_COPY_READ_BUFFER, m_glBufferHandle );
checkGlError( "resizing vertex buffer" );
int newOffset = 0;
ITEMS::iterator it, it_end;
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
{ {
// Shrinking container VERTEX_ITEM* item = *it;
// Sanity check, no shrinking if we cannot fit all the data int itemOffset = item->GetOffset();
if( usedSpace() > aNewSize ) int itemSize = item->GetSize();
return false;
int size = aNewSize * sizeof( VERTEX ); // Move an item to the new container
newContainer = static_cast<VERTEX*>( malloc( size ) ); glCopyBufferSubData( GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
itemOffset * VertexSize, newOffset * VertexSize, itemSize * VertexSize );
if( newContainer == NULL ) // Update new offset
{ item->setOffset( newOffset );
DisplayError( NULL, wxString::Format(
wxT( "CACHED_CONTAINER::resizeContainer:\n"
"Run out of memory (malloc %d bytes)" ),
size ) );
return false;
}
// Defragment directly to the new, smaller container // Move to the next free space
defragment( newContainer ); newOffset += itemSize;
// We have to correct freeChunks after defragmentation
m_freeChunks.clear();
wxASSERT( aNewSize - usedSpace() > 0 );
m_freeChunks.insert( CHUNK( aNewSize - usedSpace(), usedSpace() ) );
}
else
{
// Enlarging container
int size = aNewSize * sizeof( VERTEX );
newContainer = static_cast<VERTEX*>( realloc( m_vertices, size ) );
if( newContainer == NULL )
{
DisplayError( NULL, wxString::Format(
wxT( "CACHED_CONTAINER::resizeContainer:\n"
"Run out of memory (realloc from %d to %d bytes)" ),
m_currentSize * sizeof( VERTEX ), size ) );
return false;
}
// Add an entry for the new memory chunk at the end of the container
m_freeChunks.insert( CHUNK( aNewSize - m_currentSize, m_currentSize ) );
} }
m_vertices = newContainer; glBindBuffer( GL_COPY_WRITE_BUFFER, 0 );
glBindBuffer( GL_COPY_READ_BUFFER, 0 );
glDeleteBuffers( 1, &m_glBufferHandle );
m_glBufferHandle = newBuffer;
checkGlError( "switching buffers during defragmentation" );
Map();
m_freeSpace += ( aNewSize - m_currentSize ); #if CACHED_CONTAINER_TEST > 0
prof_end( &totalTime );
wxLogDebug( wxT( "Defragmented the container storing %d vertices / %.1f ms" ),
m_currentSize - m_freeSpace, totalTime.msecs() );
#endif
m_freeSpace += ( aNewSize - m_currentSize );
m_currentSize = aNewSize; m_currentSize = aNewSize;
// Now there is only one big chunk of free memory
m_freeChunks.clear();
m_freeChunks.insert( CHUNK( m_freeSpace, m_currentSize - m_freeSpace ) );
return true; return true;
} }

View File

@ -69,7 +69,6 @@ GPU_MANAGER::~GPU_MANAGER()
void GPU_MANAGER::SetShader( SHADER& aShader ) void GPU_MANAGER::SetShader( SHADER& aShader )
{ {
m_shader = &aShader; m_shader = &aShader;
m_shaderAttrib = m_shader->GetAttribute( "attrShaderParams" ); m_shaderAttrib = m_shader->GetAttribute( "attrShaderParams" );
if( m_shaderAttrib == -1 ) if( m_shaderAttrib == -1 )
@ -82,7 +81,7 @@ void GPU_MANAGER::SetShader( SHADER& aShader )
// Cached manager // Cached manager
GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) : GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
GPU_MANAGER( aContainer ), m_buffersInitialized( false ), m_indicesPtr( NULL ), GPU_MANAGER( aContainer ), m_buffersInitialized( false ), m_indicesPtr( NULL ),
m_verticesBuffer( 0 ), m_indicesBuffer( 0 ), m_indicesSize( 0 ), m_indicesCapacity( 0 ) m_indicesBuffer( 0 ), m_indicesSize( 0 ), m_indicesCapacity( 0 )
{ {
// Allocate the biggest possible buffer for indices // Allocate the biggest possible buffer for indices
resizeIndices( aContainer->GetSize() ); resizeIndices( aContainer->GetSize() );
@ -94,33 +93,24 @@ GPU_CACHED_MANAGER::~GPU_CACHED_MANAGER()
if( m_buffersInitialized ) if( m_buffersInitialized )
{ {
glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDeleteBuffers( 1, &m_verticesBuffer );
glDeleteBuffers( 1, &m_indicesBuffer ); glDeleteBuffers( 1, &m_indicesBuffer );
} }
} }
void GPU_CACHED_MANAGER::Initialize()
{
wxASSERT( !m_buffersInitialized );
if( !m_buffersInitialized )
{
glGenBuffers( 1, &m_indicesBuffer );
checkGlError( "generating vertices buffer" );
glGenBuffers( 1, &m_verticesBuffer );
checkGlError( "generating vertices buffer" );
m_buffersInitialized = true;
}
}
void GPU_CACHED_MANAGER::BeginDrawing() void GPU_CACHED_MANAGER::BeginDrawing()
{ {
wxASSERT( !m_isDrawing ); wxASSERT( !m_isDrawing );
if( !m_buffersInitialized )
{
glGenBuffers( 1, &m_indicesBuffer );
checkGlError( "generating vertices buffer" );
m_buffersInitialized = true;
}
if( m_container->IsDirty() ) if( m_container->IsDirty() )
uploadToGpu(); resizeIndices( m_container->GetSize() );
// Number of vertices to be drawn in the EndDrawing() // Number of vertices to be drawn in the EndDrawing()
m_indicesSize = 0; m_indicesSize = 0;
@ -160,6 +150,11 @@ void GPU_CACHED_MANAGER::EndDrawing()
wxASSERT( m_isDrawing ); wxASSERT( m_isDrawing );
CACHED_CONTAINER* cached = static_cast<CACHED_CONTAINER*>( m_container );
if( cached->IsMapped() )
cached->Unmap();
if( m_indicesSize == 0 ) if( m_indicesSize == 0 )
{ {
m_isDrawing = false; m_isDrawing = false;
@ -171,7 +166,7 @@ void GPU_CACHED_MANAGER::EndDrawing()
glEnableClientState( GL_COLOR_ARRAY ); glEnableClientState( GL_COLOR_ARRAY );
// Bind vertices data buffers // Bind vertices data buffers
glBindBuffer( GL_ARRAY_BUFFER, m_verticesBuffer ); glBindBuffer( GL_ARRAY_BUFFER, cached->GetBufferHandle() );
glVertexPointer( CoordStride, GL_FLOAT, VertexSize, 0 ); glVertexPointer( CoordStride, GL_FLOAT, VertexSize, 0 );
glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, (GLvoid*) ColorOffset ); glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, (GLvoid*) ColorOffset );
@ -185,7 +180,7 @@ void GPU_CACHED_MANAGER::EndDrawing()
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indicesBuffer ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indicesBuffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_indicesSize * sizeof(int), glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_indicesSize * sizeof(int),
(GLvoid*) m_indices.get(), GL_STATIC_DRAW ); (GLvoid*) m_indices.get(), GL_DYNAMIC_DRAW );
glDrawElements( GL_TRIANGLES, m_indicesSize, GL_UNSIGNED_INT, 0 ); glDrawElements( GL_TRIANGLES, m_indicesSize, GL_UNSIGNED_INT, 0 );
@ -216,38 +211,6 @@ void GPU_CACHED_MANAGER::EndDrawing()
} }
void GPU_CACHED_MANAGER::uploadToGpu()
{
#ifdef __WXDEBUG__
prof_counter totalTime;
prof_start( &totalTime );
#endif /* __WXDEBUG__ */
if( !m_buffersInitialized )
Initialize();
int bufferSize = m_container->GetSize();
GLfloat* vertices = (GLfloat*) m_container->GetAllVertices();
// Upload vertices coordinates and shader types to GPU memory
glBindBuffer( GL_ARRAY_BUFFER, m_verticesBuffer );
checkGlError( "binding vertices buffer" );
glBufferData( GL_ARRAY_BUFFER, bufferSize * VertexSize, vertices, GL_STATIC_DRAW );
checkGlError( "transferring vertices" );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
checkGlError( "unbinding vertices buffer" );
// Allocate the biggest possible buffer for indices
resizeIndices( bufferSize );
#ifdef __WXDEBUG__
prof_end( &totalTime );
wxLogTrace( "GAL_PROFILE",
wxT( "Uploading %d vertices to GPU / %.1f ms" ), bufferSize, totalTime.msecs() );
#endif /* __WXDEBUG__ */
}
void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize ) void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
{ {
if( aNewSize > m_indicesCapacity ) if( aNewSize > m_indicesCapacity )
@ -265,12 +228,6 @@ GPU_NONCACHED_MANAGER::GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
} }
void GPU_NONCACHED_MANAGER::Initialize()
{
// Nothing has to be intialized
}
void GPU_NONCACHED_MANAGER::BeginDrawing() void GPU_NONCACHED_MANAGER::BeginDrawing()
{ {
// Nothing has to be prepared // Nothing has to be prepared

View File

@ -29,6 +29,7 @@
*/ */
#include <gal/opengl/noncached_container.h> #include <gal/opengl/noncached_container.h>
#include <cstring>
#include <cstdlib> #include <cstdlib>
using namespace KIGFX; using namespace KIGFX;
@ -36,11 +37,14 @@ using namespace KIGFX;
NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) : NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) :
VERTEX_CONTAINER( aSize ), m_freePtr( 0 ) VERTEX_CONTAINER( aSize ), m_freePtr( 0 )
{ {
m_vertices = static_cast<VERTEX*>( malloc( aSize * sizeof( VERTEX ) ) );
memset( m_vertices, 0x00, aSize * sizeof( VERTEX ) );
} }
NONCACHED_CONTAINER::~NONCACHED_CONTAINER() NONCACHED_CONTAINER::~NONCACHED_CONTAINER()
{ {
free( m_vertices );
} }

View File

@ -299,6 +299,18 @@ void OPENGL_GAL::EndDrawing()
} }
void OPENGL_GAL::BeginUpdate()
{
cachedManager.Map();
}
void OPENGL_GAL::EndUpdate()
{
cachedManager.Unmap();
}
void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{ {
const VECTOR2D startEndVector = aEndPoint - aStartPoint; const VECTOR2D startEndVector = aEndPoint - aStartPoint;

View File

@ -31,8 +31,6 @@
#include <gal/opengl/cached_container.h> #include <gal/opengl/cached_container.h>
#include <gal/opengl/noncached_container.h> #include <gal/opengl/noncached_container.h>
#include <gal/opengl/shader.h> #include <gal/opengl/shader.h>
#include <cstdlib>
#include <cstring>
using namespace KIGFX; using namespace KIGFX;
@ -47,14 +45,11 @@ VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached )
VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) : VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) :
m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ),
m_failed( false ), m_dirty( true ) m_vertices( NULL ), m_failed( false ), m_dirty( true )
{ {
m_vertices = static_cast<VERTEX*>( malloc( aSize * sizeof( VERTEX ) ) );
memset( m_vertices, 0x00, aSize * sizeof( VERTEX ) );
} }
VERTEX_CONTAINER::~VERTEX_CONTAINER() VERTEX_CONTAINER::~VERTEX_CONTAINER()
{ {
free( m_vertices );
} }

View File

@ -49,6 +49,18 @@ VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) :
} }
void VERTEX_MANAGER::Map()
{
m_container->Map();
}
void VERTEX_MANAGER::Unmap()
{
m_container->Unmap();
}
bool VERTEX_MANAGER::Reserve( unsigned int aSize ) bool VERTEX_MANAGER::Reserve( unsigned int aSize )
{ {
assert( m_reservedSpace == 0 && m_reserved == NULL ); assert( m_reservedSpace == 0 && m_reserved == NULL );

View File

@ -422,9 +422,11 @@ void VIEW::UpdateLayerColor( int aLayer )
r.SetMaximum(); r.SetMaximum();
m_gal->BeginUpdate();
updateItemsColor visitor( aLayer, m_painter, m_gal ); updateItemsColor visitor( aLayer, m_painter, m_gal );
m_layers[aLayer].items->Query( r, visitor ); m_layers[aLayer].items->Query( r, visitor );
MarkTargetDirty( m_layers[aLayer].target ); MarkTargetDirty( m_layers[aLayer].target );
m_gal->EndUpdate();
} }
@ -433,6 +435,7 @@ void VIEW::UpdateAllLayersColor()
BOX2I r; BOX2I r;
r.SetMaximum(); r.SetMaximum();
m_gal->BeginUpdate();
for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i ) for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i )
{ {
@ -446,6 +449,7 @@ void VIEW::UpdateAllLayersColor()
l->items->Query( r, visitor ); l->items->Query( r, visitor );
} }
m_gal->EndUpdate();
MarkDirty(); MarkDirty();
} }
@ -482,8 +486,11 @@ void VIEW::ChangeLayerDepth( int aLayer, int aDepth )
r.SetMaximum(); r.SetMaximum();
m_gal->BeginUpdate();
changeItemsDepth visitor( aLayer, aDepth, m_gal ); changeItemsDepth visitor( aLayer, aDepth, m_gal );
m_layers[aLayer].items->Query( r, visitor ); m_layers[aLayer].items->Query( r, visitor );
m_gal->EndUpdate();
MarkTargetDirty( m_layers[aLayer].target ); MarkTargetDirty( m_layers[aLayer].target );
} }
@ -1009,6 +1016,8 @@ void VIEW::RecacheAllItems( bool aImmediately )
prof_start( &totalRealTime ); prof_start( &totalRealTime );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
m_gal->BeginUpdate();
for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i ) for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i )
{ {
VIEW_LAYER* l = &( ( *i ).second ); VIEW_LAYER* l = &( ( *i ).second );
@ -1023,6 +1032,8 @@ void VIEW::RecacheAllItems( bool aImmediately )
} }
} }
m_gal->EndUpdate();
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
prof_end( &totalRealTime ); prof_end( &totalRealTime );
wxLogTrace( "GAL_PROFILE", wxT( "RecacheAllItems::immediately: %u %.1f ms" ), wxLogTrace( "GAL_PROFILE", wxT( "RecacheAllItems::immediately: %u %.1f ms" ),

View File

@ -79,6 +79,12 @@ public:
/// @brief End the drawing, needs to be called for every new frame. /// @brief End the drawing, needs to be called for every new frame.
virtual void EndDrawing() {}; virtual void EndDrawing() {};
/// @brief Enables item update mode.
virtual void BeginUpdate() {}
/// @brief Disables item update mode.
virtual void EndUpdate() {}
/** /**
* @brief Draw a line. * @brief Draw a line.
* *

View File

@ -48,6 +48,7 @@ class CACHED_CONTAINER : public VERTEX_CONTAINER
{ {
public: public:
CACHED_CONTAINER( unsigned int aSize = defaultInitSize ); CACHED_CONTAINER( unsigned int aSize = defaultInitSize );
~CACHED_CONTAINER();
///> @copydoc VERTEX_CONTAINER::SetItem() ///> @copydoc VERTEX_CONTAINER::SetItem()
virtual void SetItem( VERTEX_ITEM* aItem ); virtual void SetItem( VERTEX_ITEM* aItem );
@ -64,6 +65,30 @@ public:
///> @copydoc VERTEX_CONTAINER::Clear() ///> @copydoc VERTEX_CONTAINER::Clear()
virtual void Clear(); virtual void Clear();
/**
* Function GetBufferHandle()
* returns handle to the vertex buffer. It might be negative if the buffer is not initialized.
*/
inline unsigned int GetBufferHandle() const
{
return m_glBufferHandle;
}
/**
* Function IsMapped()
* returns true if vertex buffer is currently mapped.
*/
inline bool IsMapped() const
{
return m_isMapped;
}
///> @copydoc VERTEX_CONTAINER::Map()
void Map();
///> @copydoc VERTEX_CONTAINER::Unmap()
void Unmap();
protected: protected:
///> Maps size of free memory chunks to their offsets ///> Maps size of free memory chunks to their offsets
typedef std::pair<unsigned int, unsigned int> CHUNK; typedef std::pair<unsigned int, unsigned int> CHUNK;
@ -86,6 +111,17 @@ protected:
unsigned int m_chunkOffset; unsigned int m_chunkOffset;
unsigned int m_itemSize; unsigned int m_itemSize;
bool m_isMapped;
bool m_isInitialized;
unsigned int m_glBufferHandle;
/**
* Function init()
* performs the GL vertex buffer initialization. It can be invoked only when an OpenGL context
* is bound.
*/
void init();
/** /**
* Function reallocate() * Function reallocate()
* resizes the chunk that stores the current item to the given size. * resizes the chunk that stores the current item to the given size.
@ -96,32 +132,21 @@ protected:
unsigned int reallocate( unsigned int aSize ); unsigned int reallocate( unsigned int aSize );
/** /**
* Function defragment() * Function defragmentResize()
* removes empty spaces between chunks, so after that there is a long continous space * removes empty spaces between chunks and optionally resizes the container.
* for storing vertices at the and of the container. * After the operation there is continous space for storing vertices at the end of the container.
* *
* @param aTarget is the already allocated destination for defragmented data. It has to be * @param aNewSize is the new size of container, expressed in number of vertices
* at least of the same size as the current container. If left NULL, it will be allocated * @return false in case of failure (e.g. memory shortage)
* inside the defragment() function.
* @return false in case of failure (eg. memory shortage)
*/ */
virtual bool defragment( VERTEX* aTarget = NULL ); bool defragmentResize( unsigned int aNewSize );
/** /**
* Function mergeFreeChunks() * Function mergeFreeChunks()
* looks for consecutive free memory chunks and merges them, decreasing fragmentation of * looks for consecutive free memory chunks and merges them, decreasing fragmentation of
* memory. * memory.
*/ */
virtual void mergeFreeChunks(); void mergeFreeChunks();
/**
* Function resizeContainer()
*
* prepares a bigger container of a given size.
* @param aNewSize is the new size of container, expressed in vertices
* @return false in case of failure (eg. memory shortage)
*/
virtual bool resizeContainer( unsigned int aNewSize );
/** /**
* Function getPowerOf2() * Function getPowerOf2()

View File

@ -47,12 +47,6 @@ public:
virtual ~GPU_MANAGER(); virtual ~GPU_MANAGER();
/**
* @brief Initializes everything needed to use vertex buffer objects (should be called when
* there is an OpenGL context available).
*/
virtual void Initialize() = 0;
/** /**
* Function BeginDrawing() * Function BeginDrawing()
* Prepares the stored data to be drawn. * Prepares the stored data to be drawn.
@ -109,9 +103,6 @@ public:
GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ); GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer );
~GPU_CACHED_MANAGER(); ~GPU_CACHED_MANAGER();
///> @copydoc GPU_MANAGER::Initialize()
virtual void Initialize();
///> @copydoc GPU_MANAGER::BeginDrawing() ///> @copydoc GPU_MANAGER::BeginDrawing()
virtual void BeginDrawing(); virtual void BeginDrawing();
@ -124,14 +115,13 @@ public:
///> @copydoc GPU_MANAGER::EndDrawing() ///> @copydoc GPU_MANAGER::EndDrawing()
virtual void EndDrawing(); virtual void EndDrawing();
protected: ///> Maps vertex buffer stored in GPU memory.
/** void Map();
* Function uploadToGpu
* Rebuilds vertex buffer object using stored VERTEX_ITEMs and sends it to the graphics card
* memory.
*/
virtual void uploadToGpu();
///> Unmaps vertex buffer.
void Unmap();
protected:
///> Resizes the indices buffer to aNewSize if necessary ///> Resizes the indices buffer to aNewSize if necessary
void resizeIndices( unsigned int aNewSize ); void resizeIndices( unsigned int aNewSize );
@ -144,9 +134,6 @@ protected:
///> Pointer to the first free cell in the indices buffer ///> Pointer to the first free cell in the indices buffer
GLuint* m_indicesPtr; GLuint* m_indicesPtr;
///> Handle to vertices buffer
GLuint m_verticesBuffer;
///> Handle to indices buffer ///> Handle to indices buffer
GLuint m_indicesBuffer; GLuint m_indicesBuffer;
@ -163,9 +150,6 @@ class GPU_NONCACHED_MANAGER : public GPU_MANAGER
public: public:
GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer ); GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer );
///> @copydoc GPU_MANAGER::Initialize()
virtual void Initialize();
///> @copydoc GPU_MANAGER::BeginDrawing() ///> @copydoc GPU_MANAGER::BeginDrawing()
virtual void BeginDrawing(); virtual void BeginDrawing();

View File

@ -34,6 +34,7 @@
#include <gal/opengl/shader.h> #include <gal/opengl/shader.h>
#include <gal/opengl/vertex_manager.h> #include <gal/opengl/vertex_manager.h>
#include <gal/opengl/vertex_item.h> #include <gal/opengl/vertex_item.h>
#include <gal/opengl/cached_container.h>
#include <gal/opengl/noncached_container.h> #include <gal/opengl/noncached_container.h>
#include <gal/opengl/opengl_compositor.h> #include <gal/opengl/opengl_compositor.h>
@ -95,6 +96,12 @@ public:
/// @copydoc GAL::EndDrawing() /// @copydoc GAL::EndDrawing()
virtual void EndDrawing(); virtual void EndDrawing();
/// @copydoc GAL::BeginUpdate()
virtual void BeginUpdate();
/// @copydoc GAL::EndUpdate()
virtual void EndUpdate();
/// @copydoc GAL::DrawLine() /// @copydoc GAL::DrawLine()
virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );

View File

@ -48,6 +48,19 @@ public:
virtual ~VERTEX_CONTAINER(); virtual ~VERTEX_CONTAINER();
/**
* Function Map()
* prepares the container for vertices updates.
*/
virtual void Map() {}
/**
* Function Unmap()
* finishes the vertices updates stage.
*/
virtual void Unmap()
{}
/** /**
* Function SetItem() * Function SetItem()
* sets the item in order to modify or finishes its current modifications. * sets the item in order to modify or finishes its current modifications.

View File

@ -58,6 +58,18 @@ public:
*/ */
VERTEX_MANAGER( bool aCached ); VERTEX_MANAGER( bool aCached );
/**
* Function Map()
* maps vertex buffer.
*/
void Map();
/**
* Function Unmap()
* unmaps vertex buffer.
*/
void Unmap();
/** /**
* Function Reserve() * Function Reserve()
* allocates space for vertices, so it will be used with subsequent Vertex() calls. * allocates space for vertices, so it will be used with subsequent Vertex() calls.