Vertices are stored in GPU memory (OpenGL GAL).
This commit is contained in:
parent
01912aaabd
commit
702be4903f
|
@ -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() );
|
||||
|
||||
m_viewControls->UpdateScrollbars();
|
||||
|
||||
m_gal->BeginUpdate();
|
||||
m_view->UpdateItems();
|
||||
m_gal->EndUpdate();
|
||||
|
||||
m_gal->BeginDrawing();
|
||||
m_gal->ClearScreen( settings->GetBackgroundColor() );
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <gal/opengl/vertex_manager.h>
|
||||
#include <gal/opengl/vertex_item.h>
|
||||
#include <gal/opengl/shader.h>
|
||||
#include <gal/opengl/utils.h>
|
||||
|
||||
#include <confirm.h>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
|
@ -45,7 +47,8 @@
|
|||
using namespace KIGFX;
|
||||
|
||||
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
|
||||
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 )
|
||||
{
|
||||
assert( aItem != NULL );
|
||||
|
@ -103,6 +118,7 @@ void CACHED_CONTAINER::FinishItem()
|
|||
VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
|
||||
{
|
||||
assert( m_item != NULL );
|
||||
assert( m_isMapped );
|
||||
|
||||
if( m_failed )
|
||||
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
|
||||
if( m_freeSpace > ( 0.75 * m_currentSize ) && m_currentSize > m_initialSize )
|
||||
{
|
||||
resizeContainer( 0.5 * m_currentSize );
|
||||
defragmentResize( 0.5 * m_currentSize );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -189,6 +205,10 @@ void CACHED_CONTAINER::Delete( VERTEX_ITEM* aItem )
|
|||
|
||||
void CACHED_CONTAINER::Clear()
|
||||
{
|
||||
Map();
|
||||
glInvalidateBufferData( GL_ARRAY_BUFFER );
|
||||
Unmap();
|
||||
|
||||
m_freeSpace = m_currentSize;
|
||||
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 )
|
||||
{
|
||||
assert( aSize > 0 );
|
||||
assert( m_isMapped );
|
||||
|
||||
#if CACHED_CONTAINER_TEST > 2
|
||||
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 )
|
||||
{
|
||||
// Yes: exponential growing
|
||||
result = resizeContainer( m_currentSize * 2 );
|
||||
result = defragmentResize( m_currentSize * 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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 )
|
||||
|
@ -243,7 +305,7 @@ unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
|
|||
{
|
||||
// In the case when there is enough space to store the vertices,
|
||||
// but the free space is not continous we should defragment the container
|
||||
if( !defragment() )
|
||||
if( !defragmentResize( m_currentSize ) )
|
||||
return UINT_MAX;
|
||||
|
||||
// Update the current offset
|
||||
|
@ -288,72 +350,12 @@ unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
|
|||
m_freeSpace -= aSize;
|
||||
// mergeFreeChunks(); // veery slow and buggy
|
||||
|
||||
m_item->setOffset( 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()
|
||||
{
|
||||
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
|
||||
wxLogDebug( wxT( "Resizing container from %d to %d" ), m_currentSize, aNewSize );
|
||||
#endif
|
||||
|
||||
VERTEX* newContainer;
|
||||
|
||||
if( aNewSize < m_currentSize )
|
||||
{
|
||||
// Shrinking container
|
||||
// Sanity check, no shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( aNewSize < m_currentSize && usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
int size = aNewSize * sizeof( VERTEX );
|
||||
newContainer = static_cast<VERTEX*>( malloc( size ) );
|
||||
#if CACHED_CONTAINER_TEST > 0
|
||||
wxLogDebug( wxT( "Defragmenting" ) );
|
||||
prof_counter totalTime;
|
||||
prof_start( &totalTime );
|
||||
#endif
|
||||
|
||||
if( newContainer == NULL )
|
||||
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 )
|
||||
{
|
||||
DisplayError( NULL, wxString::Format(
|
||||
wxT( "CACHED_CONTAINER::resizeContainer:\n"
|
||||
"Run out of memory (malloc %d bytes)" ),
|
||||
size ) );
|
||||
return false;
|
||||
VERTEX_ITEM* item = *it;
|
||||
int itemOffset = item->GetOffset();
|
||||
int itemSize = item->GetSize();
|
||||
|
||||
// Move an item to the new container
|
||||
glCopyBufferSubData( GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER,
|
||||
itemOffset * VertexSize, newOffset * VertexSize, itemSize * VertexSize );
|
||||
|
||||
// Update new offset
|
||||
item->setOffset( newOffset );
|
||||
|
||||
// Move to the next free space
|
||||
newOffset += itemSize;
|
||||
}
|
||||
|
||||
// Defragment directly to the new, smaller container
|
||||
defragment( 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();
|
||||
|
||||
// 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 CACHED_CONTAINER_TEST > 0
|
||||
prof_end( &totalTime );
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ GPU_MANAGER::~GPU_MANAGER()
|
|||
void GPU_MANAGER::SetShader( SHADER& aShader )
|
||||
{
|
||||
m_shader = &aShader;
|
||||
|
||||
m_shaderAttrib = m_shader->GetAttribute( "attrShaderParams" );
|
||||
|
||||
if( m_shaderAttrib == -1 )
|
||||
|
@ -82,7 +81,7 @@ void GPU_MANAGER::SetShader( SHADER& aShader )
|
|||
// Cached manager
|
||||
GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
|
||||
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
|
||||
resizeIndices( aContainer->GetSize() );
|
||||
|
@ -94,33 +93,24 @@ GPU_CACHED_MANAGER::~GPU_CACHED_MANAGER()
|
|||
if( m_buffersInitialized )
|
||||
{
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
glDeleteBuffers( 1, &m_verticesBuffer );
|
||||
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()
|
||||
{
|
||||
wxASSERT( !m_isDrawing );
|
||||
|
||||
if( !m_buffersInitialized )
|
||||
{
|
||||
glGenBuffers( 1, &m_indicesBuffer );
|
||||
checkGlError( "generating vertices buffer" );
|
||||
m_buffersInitialized = true;
|
||||
}
|
||||
|
||||
if( m_container->IsDirty() )
|
||||
uploadToGpu();
|
||||
resizeIndices( m_container->GetSize() );
|
||||
|
||||
// Number of vertices to be drawn in the EndDrawing()
|
||||
m_indicesSize = 0;
|
||||
|
@ -160,6 +150,11 @@ void GPU_CACHED_MANAGER::EndDrawing()
|
|||
|
||||
wxASSERT( m_isDrawing );
|
||||
|
||||
CACHED_CONTAINER* cached = static_cast<CACHED_CONTAINER*>( m_container );
|
||||
|
||||
if( cached->IsMapped() )
|
||||
cached->Unmap();
|
||||
|
||||
if( m_indicesSize == 0 )
|
||||
{
|
||||
m_isDrawing = false;
|
||||
|
@ -171,7 +166,7 @@ void GPU_CACHED_MANAGER::EndDrawing()
|
|||
glEnableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
// Bind vertices data buffers
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_verticesBuffer );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, cached->GetBufferHandle() );
|
||||
glVertexPointer( CoordStride, GL_FLOAT, VertexSize, 0 );
|
||||
glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, (GLvoid*) ColorOffset );
|
||||
|
||||
|
@ -185,7 +180,7 @@ void GPU_CACHED_MANAGER::EndDrawing()
|
|||
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indicesBuffer );
|
||||
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 );
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
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()
|
||||
{
|
||||
// Nothing has to be prepared
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
|
||||
#include <gal/opengl/noncached_container.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
@ -36,11 +37,14 @@ using namespace KIGFX;
|
|||
NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) :
|
||||
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()
|
||||
{
|
||||
free( m_vertices );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
const VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#include <gal/opengl/cached_container.h>
|
||||
#include <gal/opengl/noncached_container.h>
|
||||
#include <gal/opengl/shader.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
|
@ -47,14 +45,11 @@ VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached )
|
|||
|
||||
VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int 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()
|
||||
{
|
||||
free( m_vertices );
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
assert( m_reservedSpace == 0 && m_reserved == NULL );
|
||||
|
|
|
@ -422,9 +422,11 @@ void VIEW::UpdateLayerColor( int aLayer )
|
|||
|
||||
r.SetMaximum();
|
||||
|
||||
m_gal->BeginUpdate();
|
||||
updateItemsColor visitor( aLayer, m_painter, m_gal );
|
||||
m_layers[aLayer].items->Query( r, visitor );
|
||||
MarkTargetDirty( m_layers[aLayer].target );
|
||||
m_gal->EndUpdate();
|
||||
}
|
||||
|
||||
|
||||
|
@ -433,6 +435,7 @@ void VIEW::UpdateAllLayersColor()
|
|||
BOX2I r;
|
||||
|
||||
r.SetMaximum();
|
||||
m_gal->BeginUpdate();
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
m_gal->EndUpdate();
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
|
@ -482,8 +486,11 @@ void VIEW::ChangeLayerDepth( int aLayer, int aDepth )
|
|||
|
||||
r.SetMaximum();
|
||||
|
||||
m_gal->BeginUpdate();
|
||||
changeItemsDepth visitor( aLayer, aDepth, m_gal );
|
||||
m_layers[aLayer].items->Query( r, visitor );
|
||||
m_gal->EndUpdate();
|
||||
|
||||
MarkTargetDirty( m_layers[aLayer].target );
|
||||
}
|
||||
|
||||
|
@ -1009,6 +1016,8 @@ void VIEW::RecacheAllItems( bool aImmediately )
|
|||
prof_start( &totalRealTime );
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
m_gal->BeginUpdate();
|
||||
|
||||
for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i )
|
||||
{
|
||||
VIEW_LAYER* l = &( ( *i ).second );
|
||||
|
@ -1023,6 +1032,8 @@ void VIEW::RecacheAllItems( bool aImmediately )
|
|||
}
|
||||
}
|
||||
|
||||
m_gal->EndUpdate();
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
prof_end( &totalRealTime );
|
||||
wxLogTrace( "GAL_PROFILE", wxT( "RecacheAllItems::immediately: %u %.1f ms" ),
|
||||
|
|
|
@ -79,6 +79,12 @@ public:
|
|||
/// @brief End the drawing, needs to be called for every new frame.
|
||||
virtual void EndDrawing() {};
|
||||
|
||||
/// @brief Enables item update mode.
|
||||
virtual void BeginUpdate() {}
|
||||
|
||||
/// @brief Disables item update mode.
|
||||
virtual void EndUpdate() {}
|
||||
|
||||
/**
|
||||
* @brief Draw a line.
|
||||
*
|
||||
|
|
|
@ -48,6 +48,7 @@ class CACHED_CONTAINER : public VERTEX_CONTAINER
|
|||
{
|
||||
public:
|
||||
CACHED_CONTAINER( unsigned int aSize = defaultInitSize );
|
||||
~CACHED_CONTAINER();
|
||||
|
||||
///> @copydoc VERTEX_CONTAINER::SetItem()
|
||||
virtual void SetItem( VERTEX_ITEM* aItem );
|
||||
|
@ -64,6 +65,30 @@ public:
|
|||
///> @copydoc VERTEX_CONTAINER::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:
|
||||
///> Maps size of free memory chunks to their offsets
|
||||
typedef std::pair<unsigned int, unsigned int> CHUNK;
|
||||
|
@ -86,6 +111,17 @@ protected:
|
|||
unsigned int m_chunkOffset;
|
||||
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()
|
||||
* resizes the chunk that stores the current item to the given size.
|
||||
|
@ -96,32 +132,21 @@ protected:
|
|||
unsigned int reallocate( unsigned int aSize );
|
||||
|
||||
/**
|
||||
* Function defragment()
|
||||
* removes empty spaces between chunks, so after that there is a long continous space
|
||||
* for storing vertices at the and of the container.
|
||||
* Function defragmentResize()
|
||||
* removes empty spaces between chunks and optionally resizes 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
|
||||
* at least of the same size as the current container. If left NULL, it will be allocated
|
||||
* inside the defragment() function.
|
||||
* @return false in case of failure (eg. memory shortage)
|
||||
* @param aNewSize is the new size of container, expressed in number of vertices
|
||||
* @return false in case of failure (e.g. memory shortage)
|
||||
*/
|
||||
virtual bool defragment( VERTEX* aTarget = NULL );
|
||||
bool defragmentResize( unsigned int aNewSize );
|
||||
|
||||
/**
|
||||
* Function mergeFreeChunks()
|
||||
* looks for consecutive free memory chunks and merges them, decreasing fragmentation of
|
||||
* memory.
|
||||
*/
|
||||
virtual 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 );
|
||||
void mergeFreeChunks();
|
||||
|
||||
/**
|
||||
* Function getPowerOf2()
|
||||
|
|
|
@ -47,12 +47,6 @@ public:
|
|||
|
||||
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()
|
||||
* Prepares the stored data to be drawn.
|
||||
|
@ -109,9 +103,6 @@ public:
|
|||
GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer );
|
||||
~GPU_CACHED_MANAGER();
|
||||
|
||||
///> @copydoc GPU_MANAGER::Initialize()
|
||||
virtual void Initialize();
|
||||
|
||||
///> @copydoc GPU_MANAGER::BeginDrawing()
|
||||
virtual void BeginDrawing();
|
||||
|
||||
|
@ -124,14 +115,13 @@ public:
|
|||
///> @copydoc GPU_MANAGER::EndDrawing()
|
||||
virtual void EndDrawing();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Function uploadToGpu
|
||||
* Rebuilds vertex buffer object using stored VERTEX_ITEMs and sends it to the graphics card
|
||||
* memory.
|
||||
*/
|
||||
virtual void uploadToGpu();
|
||||
///> Maps vertex buffer stored in GPU memory.
|
||||
void Map();
|
||||
|
||||
///> Unmaps vertex buffer.
|
||||
void Unmap();
|
||||
|
||||
protected:
|
||||
///> Resizes the indices buffer to aNewSize if necessary
|
||||
void resizeIndices( unsigned int aNewSize );
|
||||
|
||||
|
@ -144,9 +134,6 @@ protected:
|
|||
///> Pointer to the first free cell in the indices buffer
|
||||
GLuint* m_indicesPtr;
|
||||
|
||||
///> Handle to vertices buffer
|
||||
GLuint m_verticesBuffer;
|
||||
|
||||
///> Handle to indices buffer
|
||||
GLuint m_indicesBuffer;
|
||||
|
||||
|
@ -163,9 +150,6 @@ class GPU_NONCACHED_MANAGER : public GPU_MANAGER
|
|||
public:
|
||||
GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer );
|
||||
|
||||
///> @copydoc GPU_MANAGER::Initialize()
|
||||
virtual void Initialize();
|
||||
|
||||
///> @copydoc GPU_MANAGER::BeginDrawing()
|
||||
virtual void BeginDrawing();
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <gal/opengl/shader.h>
|
||||
#include <gal/opengl/vertex_manager.h>
|
||||
#include <gal/opengl/vertex_item.h>
|
||||
#include <gal/opengl/cached_container.h>
|
||||
#include <gal/opengl/noncached_container.h>
|
||||
#include <gal/opengl/opengl_compositor.h>
|
||||
|
||||
|
@ -95,6 +96,12 @@ public:
|
|||
/// @copydoc GAL::EndDrawing()
|
||||
virtual void EndDrawing();
|
||||
|
||||
/// @copydoc GAL::BeginUpdate()
|
||||
virtual void BeginUpdate();
|
||||
|
||||
/// @copydoc GAL::EndUpdate()
|
||||
virtual void EndUpdate();
|
||||
|
||||
/// @copydoc GAL::DrawLine()
|
||||
virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
|
||||
|
||||
|
|
|
@ -48,6 +48,19 @@ public:
|
|||
|
||||
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()
|
||||
* sets the item in order to modify or finishes its current modifications.
|
||||
|
|
|
@ -58,6 +58,18 @@ public:
|
|||
*/
|
||||
VERTEX_MANAGER( bool aCached );
|
||||
|
||||
/**
|
||||
* Function Map()
|
||||
* maps vertex buffer.
|
||||
*/
|
||||
void Map();
|
||||
|
||||
/**
|
||||
* Function Unmap()
|
||||
* unmaps vertex buffer.
|
||||
*/
|
||||
void Unmap();
|
||||
|
||||
/**
|
||||
* Function Reserve()
|
||||
* allocates space for vertices, so it will be used with subsequent Vertex() calls.
|
||||
|
|
Loading…
Reference in New Issue