Commit 5242fff9 authored by Maciej Suminski's avatar Maciej Suminski
Browse files

Code refactorization. VBO_CONTAINER is split to [NON]CACHED_MANAGER,...

Code refactorization. VBO_CONTAINER is split to [NON]CACHED_MANAGER, GPU_MANAGER and VERTEX_MANAGER.
parent 4d7db717
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -36,8 +36,12 @@ set(GAL_SRCS
    gal/color4d.cpp
    gal/color4d.cpp
    gal/opengl/opengl_gal.cpp
    gal/opengl/opengl_gal.cpp
    gal/opengl/shader.cpp
    gal/opengl/shader.cpp
    gal/opengl/vbo_item.cpp
    gal/opengl/vertex_item.cpp
    gal/opengl/vbo_container.cpp
    gal/opengl/vertex_container.cpp
    gal/opengl/cached_container.cpp
    gal/opengl/noncached_container.cpp
    gal/opengl/vertex_manager.cpp
    gal/opengl/gpu_manager.cpp
    gal/cairo/cairo_gal.cpp
    gal/cairo/cairo_gal.cpp
    view/wx_view_controls.cpp
    view/wx_view_controls.cpp
    )
    )
+1 −1
Original line number Original line Diff line number Diff line
@@ -132,7 +132,7 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect )
#endif /* __WXDEBUG__ */
#endif /* __WXDEBUG__ */


    m_gal->BeginDrawing();
    m_gal->BeginDrawing();
    m_gal->SetBackgroundColor( KiGfx::COLOR4D( 0, 0, 0, 1.0 ) );
    m_gal->SetBackgroundColor( KiGfx::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
    m_gal->ClearScreen();
    m_gal->ClearScreen();


    m_gal->DrawGrid();
    m_gal->DrawGrid();
+14 −10
Original line number Original line Diff line number Diff line
@@ -194,7 +194,7 @@ void CAIRO_GAL::deinitSurface()
}
}




unsigned int CAIRO_GAL::getGroupNumber()
unsigned int CAIRO_GAL::getNewGroupNumber()
{
{
    wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),
    wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),
                  wxT( "There are no free slots to store a group" ) );
                  wxT( "There are no free slots to store a group" ) );
@@ -230,6 +230,7 @@ void CAIRO_GAL::EndDrawing()
    // Now translate the raw image data from the format stored
    // Now translate the raw image data from the format stored
    // by cairo into a format understood by wxImage.
    // by cairo into a format understood by wxImage.
    unsigned char* wxOutputPtr = wxOutput;
    unsigned char* wxOutputPtr = wxOutput;

    for( size_t count = 0; count < bufferSize; count++ )
    for( size_t count = 0; count < bufferSize; count++ )
    {
    {
        unsigned int value = bitmapBuffer[count];
        unsigned int value = bitmapBuffer[count];
@@ -287,7 +288,8 @@ void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint
}
}




void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth )
void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
                             double aWidth )
{
{
    if( isFillEnabled )
    if( isFillEnabled )
    {
    {
@@ -317,7 +319,6 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo
        cairo_line_to( cairoImage, lineLength, -aWidth / 2.0 );
        cairo_line_to( cairoImage, lineLength, -aWidth / 2.0 );


        cairo_restore( cairoImage );
        cairo_restore( cairoImage );

    }
    }


    isElementAdded = true;
    isElementAdded = true;
@@ -351,7 +352,8 @@ void CAIRO_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
    bool isFirstPoint = true;
    bool isFirstPoint = true;


    // Iterate over the point list and draw the segments
    // Iterate over the point list and draw the segments
    for( std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); it != aPointList.end(); ++it )
    std::deque<VECTOR2D>::const_iterator it;
    for( it = aPointList.begin(); it != aPointList.end(); ++it )
    {
    {
        if( isFirstPoint )
        if( isFirstPoint )
        {
        {
@@ -373,7 +375,8 @@ void CAIRO_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
    bool isFirstPoint = true;
    bool isFirstPoint = true;


    // Iterate over the point list and draw the polygon
    // Iterate over the point list and draw the polygon
    for( std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); it != aPointList.end(); ++it )
    std::deque<VECTOR2D>::const_iterator it;
    for( it = aPointList.begin(); it != aPointList.end(); ++it )
    {
    {
        if( isFirstPoint )
        if( isFirstPoint )
        {
        {
@@ -644,7 +647,7 @@ int CAIRO_GAL::BeginGroup()
    storePath();
    storePath();


    Group group;
    Group group;
    int groupNumber = getGroupNumber();
    int groupNumber = getNewGroupNumber();
    groups.insert( std::make_pair( groupNumber, group ) );
    groups.insert( std::make_pair( groupNumber, group ) );
    currentGroup = &groups[groupNumber];
    currentGroup = &groups[groupNumber];
    isGrouping   = true;
    isGrouping   = true;
@@ -677,6 +680,7 @@ void CAIRO_GAL::DeleteGroup( int aGroupNumber )


    // Delete the Cairo paths
    // Delete the Cairo paths
    std::deque<GroupElement>::iterator it, end;
    std::deque<GroupElement>::iterator it, end;

    for( it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end(); it != end; ++it )
    for( it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end(); it != end; ++it )
    {
    {
        if( it->command == CMD_FILL_PATH || it->command == CMD_STROKE_PATH )
        if( it->command == CMD_FILL_PATH || it->command == CMD_STROKE_PATH )
+218 −147
Original line number Original line Diff line number Diff line
@@ -23,44 +23,56 @@
 */
 */


/**
/**
 * @file vbo_container.cpp
 * @file cached_container.cpp
 * @brief Class to store VBO_ITEMs.
 * @brief Class to store instances of VERTEX with caching. It allows storing VERTEX objects and
 * associates them with VERTEX_ITEMs. This leads to a possibility of caching vertices data in the
 * GPU memory and a fast reuse of that data.
 */
 */


#include <gal/opengl/vbo_container.h>
#include <gal/opengl/cached_container.h>
#include <algorithm>
#include <gal/opengl/vertex_manager.h>
#include <list>
#include <gal/opengl/vertex_item.h>
#include <gal/opengl/shader.h>
#include <wx/log.h>
#include <wx/log.h>
#include <list>
#ifdef __WXDEBUG__
#ifdef __WXDEBUG__
#include <profile.h>
#include <profile.h>
#endif /* __WXDEBUG__ */
#endif /* __WXDEBUG__ */


using namespace KiGfx;
using namespace KiGfx;


VBO_CONTAINER::VBO_CONTAINER( unsigned int aSize ) :
CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
        m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), m_transform( NULL ),
    VERTEX_CONTAINER( aSize )
        m_failed( false )
{
{
    // By default no shader is used
    m_shader[0] = 0;

    m_vertices = static_cast<VBO_VERTEX*>( malloc( aSize * sizeof( VBO_VERTEX ) ) );

    // 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 ) );
}
}




VBO_CONTAINER::~VBO_CONTAINER()
void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
{
{
    free( m_vertices );
    if( aItem == NULL )
}
    {
        wxASSERT( m_item != NULL );


        // Finishing the item
        if( m_itemSize < m_chunkSize )
        {
            // There is some not used but reserved memory left, so we should return it to the pool
            int itemOffset = m_item->GetOffset();


void VBO_CONTAINER::StartItem( VBO_ITEM* aItem )
            // Add the not used memory back to the pool
            m_freeChunks.insert( Chunk( m_chunkSize - m_itemSize, itemOffset + m_itemSize ) );
            m_freeSpace += ( m_chunkSize - m_itemSize );
            // mergeFreeChunks();
        }

        m_item = NULL;
    }
    else
    {
    {
        m_item      = aItem;
        m_item      = aItem;
    m_itemSize  = aItem->GetSize();
        m_itemSize  = m_item->GetSize();
        m_chunkSize = m_itemSize;
        m_chunkSize = m_itemSize;


        if( m_itemSize == 0 )
        if( m_itemSize == 0 )
@@ -68,158 +80,108 @@ void VBO_CONTAINER::StartItem( VBO_ITEM* aItem )
        else
        else
            m_chunkOffset = m_item->GetOffset();
            m_chunkOffset = m_item->GetOffset();
    }
    }
}




void VBO_CONTAINER::EndItem()
VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
{
{
    if( m_itemSize < m_chunkSize )
    wxASSERT( m_item != NULL );
    {
        // Add the not used memory back to the pool
        m_freeChunks.insert( Chunk( m_chunkSize - m_itemSize, m_chunkOffset + m_itemSize ) );
        m_freeSpace += ( m_chunkSize - m_itemSize );
    }

    m_item = NULL;
}


    if( m_failed )
        return NULL;


void VBO_CONTAINER::Add( const VBO_VERTEX* aVertex, unsigned int aSize )
    if( m_itemSize + aSize > m_chunkSize )
    {
    {
    // Pointer to the vertex that we are currently adding
        // There is not enough space in the currently reserved chunk, so we have to resize it
    VBO_VERTEX* vertexPtr = allocate( aSize );


    if( vertexPtr == NULL )
        // Reserve a bigger memory chunk for the current item and
        return;
        // make it multiple of 3 to store triangles
        m_chunkSize = ( 2 * m_itemSize ) + aSize + ( 3 - aSize % 3 );
        // Save the current size before reallocating
        m_chunkOffset = reallocate( m_chunkSize );


    for( unsigned int i = 0; i < aSize; ++i )
        if( m_chunkOffset > m_currentSize )
    {
        // Modify the vertex according to the currently used transformations
        if( m_transform != NULL )
        {
        {
            // Apply transformations
            m_failed = true;
            glm::vec4 vertex( aVertex[i].x, aVertex[i].y, aVertex[i].z, 1.0f );
            return NULL;
            vertex = *m_transform * vertex;

            // Replace only coordinates, leave color as it is
            vertexPtr->x = vertex.x;
            vertexPtr->y = vertex.y;
            vertexPtr->z = vertex.z;
        }
        }
        else
        {
            // Simply copy coordinates
            vertexPtr->x = aVertex[i].x;
            vertexPtr->y = aVertex[i].y;
            vertexPtr->z = aVertex[i].z;
    }
    }


        // Apply currently used color
    VERTEX* reserved = &m_vertices[m_chunkOffset + m_itemSize];
        vertexPtr->r = m_color[0];
    m_itemSize += aSize;
        vertexPtr->g = m_color[1];
    m_item->setSize( m_itemSize );
        vertexPtr->b = m_color[2];

        vertexPtr->a = m_color[3];
    // The content has to be updated
    m_dirty = true;

#if CACHED_CONTAINER_TEST > 1
    test();
#endif

    return reserved;
}



        // Apply currently used shader
void CACHED_CONTAINER::Erase()
        for( unsigned int j = 0; j < VBO_ITEM::ShaderStride; ++j )
{
{
            vertexPtr->shader[j] = m_shader[j];
    wxASSERT( m_item != NULL );
        }


        vertexPtr++;
    freeItem( m_item );
    }


    // Dynamic memory freeing, there is no point in holding
    // a large amount of memory when there is no use for it
    if( m_freeSpace > ( m_currentSize / 2 ) && m_currentSize > m_initialSize )
    {
        resizeContainer( m_currentSize / 2 );
    }
}
}




void VBO_CONTAINER::Clear()
void CACHED_CONTAINER::Clear()
{
{
    // Change size to the default one
    // Change size to the default one
    m_vertices = static_cast<VBO_VERTEX*>( realloc( m_vertices,
    m_vertices = static_cast<VERTEX*>( realloc( m_vertices,
                                           m_initialSize * sizeof( VBO_VERTEX ) ) );
                                                m_initialSize * sizeof( VERTEX ) ) );

    // Reset state variables
    m_freeSpace     = m_initialSize;
    m_currentSize   = m_initialSize;
    m_failed = false;


    // Set the size of all the stored VERTEX_ITEMs to 0, so it is clear that they are not held
    // Set the size of all the stored VERTEX_ITEMs to 0, so it is clear that they are not held
    // in the container anymore
    // in the container anymore
    Items::iterator it;
    Items::iterator it;

    for( it = m_items.begin(); it != m_items.end(); ++it )
    for( it = m_items.begin(); it != m_items.end(); ++it )
    {
    {
        ( *it )->setSize( 0 );
        ( *it )->setSize( 0 );
    }
    }
    m_items.clear();


    // Reset state variables
    m_items.clear();
    m_transform = NULL;
    m_failed = false;


    // By default no shader is used
    m_shader[0] = 0;


    // In the beginning there is only free space
    // Now there is only free space left
    m_freeSpace = m_initialSize;
    m_currentSize = m_initialSize;
    m_freeChunks.clear();
    m_freeChunks.clear();
    m_freeChunks.insert( Chunk( m_freeSpace, 0 ) );
    m_freeChunks.insert( Chunk( m_freeSpace, 0 ) );
}
}




void VBO_CONTAINER::Free( VBO_ITEM* aItem )
VERTEX* CACHED_CONTAINER::GetVertices( const VERTEX_ITEM* aItem ) const
{
    freeItem( aItem );

    // Dynamic memory freeing, there is no point in holding
    // a large amount of memory when there is no use for it
    if( m_freeSpace > ( m_currentSize / 2 ) && m_currentSize > defaultInitSize )
    {
        resizeContainer( m_currentSize / 2 );
    }
}


VBO_VERTEX* VBO_CONTAINER::GetAllVertices() const
{
    return m_vertices;
}


VBO_VERTEX* VBO_CONTAINER::GetVertices( const VBO_ITEM* aItem ) const
{
{
    int offset = aItem->GetOffset();
    int offset = aItem->GetOffset();


    return &m_vertices[offset];
    return &m_vertices[offset];
}
}


VBO_VERTEX* VBO_CONTAINER::allocate( unsigned int aSize )
{
    wxASSERT( m_item != NULL );

    if( m_failed )
        return NULL;


    if( m_itemSize + aSize > m_chunkSize )
unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
{
{
        // There is not enough space in the currently reserved chunk, so we have to resize it
#if CACHED_CONTAINER_TEST > 2

    wxLogDebug( wxT( "Resize 0x%08x to %d" ), (int) m_item, aSize );
        // Reserve a bigger memory chunk for the current item
    showFreeChunks();
        m_chunkSize = std::max( ( 2 * m_itemSize ) + aSize, (unsigned) 3 );
    showReservedChunks();
        // Save the current size before reallocating
#endif
        m_chunkOffset = reallocate( m_chunkSize );

        if( m_chunkOffset > m_currentSize )
        {
            m_failed = true;
            return NULL;
        }
    }

    VBO_VERTEX* reserved = &m_vertices[m_chunkOffset + m_itemSize];
    m_itemSize += aSize;
    m_item->setSize( m_itemSize );

    return reserved;
}



unsigned int VBO_CONTAINER::reallocate( unsigned int aSize )
{
    // Is there enough space to store vertices?
    // Is there enough space to store vertices?
    if( m_freeSpace < aSize )
    if( m_freeSpace < aSize )
    {
    {
@@ -269,37 +231,57 @@ unsigned int VBO_CONTAINER::reallocate( unsigned int aSize )
    // Check if the item was previously stored in the container
    // Check if the item was previously stored in the container
    if( m_itemSize > 0 )
    if( m_itemSize > 0 )
    {
    {
#if CACHED_CONTAINER_TEST > 3
        wxLogDebug( wxT( "Moving 0x%08x from 0x%08x to 0x%08x" ),
                    (int) m_item, oldChunkOffset, chunkOffset );
#endif
        // The item was reallocated, so we have to copy all the old data to the new place
        // The item was reallocated, so we have to copy all the old data to the new place
        memcpy( &m_vertices[chunkOffset], &m_vertices[m_chunkOffset],
        memcpy( &m_vertices[chunkOffset], &m_vertices[m_chunkOffset],
                m_itemSize * VBO_ITEM::VertByteSize );
                m_itemSize * VertexSize );


        // Free the space previously used by the chunk
        // Free the space previously used by the chunk
        m_freeChunks.insert( Chunk( m_itemSize, m_chunkOffset ) );
        m_freeChunks.insert( Chunk( m_itemSize, m_chunkOffset ) );
        m_freeSpace += m_itemSize;
        m_freeSpace += m_itemSize;
    }
    }

    // Remove the allocated chunk from the free space pool
    // Remove the allocated chunk from the free space pool
    m_freeChunks.erase( newChunk );
    m_freeChunks.erase( newChunk );
    m_freeSpace -= chunkSize;


    // If there is some space left, return it to the pool - add an entry for it
    // If there is some space left, return it to the pool - add an entry for it
    if( chunkSize > aSize )
    if( chunkSize > aSize )
    {
    {
        m_freeChunks.insert( Chunk( chunkSize - aSize, chunkOffset + aSize ) );
        m_freeChunks.insert( Chunk( chunkSize - aSize, chunkOffset + aSize ) );
        m_freeSpace += chunkSize - aSize;
    }
    }


    m_freeSpace -= aSize;
    // mergeFreeChunks();

    m_item->setOffset( chunkOffset );
    m_item->setOffset( chunkOffset );


#if CACHED_CONTAINER_TEST > 2
    showFreeChunks();
    showReservedChunks();
#endif

    return chunkOffset;
    return chunkOffset;
}
}




bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )
bool CACHED_CONTAINER::defragment( VERTEX* aTarget )
{
{
#if CACHED_CONTAINER_TEST > 0
    wxLogDebug( wxT( "Defragmenting" ) );
#endif
#ifdef __WXDEBUG__
    prof_counter totalTime;
    prof_start( &totalTime, false );
#endif /* __WXDEBUG__ */

    if( aTarget == NULL )
    if( aTarget == NULL )
    {
    {
        // No target was specified, so we have to reallocate our own space
        // No target was specified, so we have to reallocate our own space
        aTarget = static_cast<VBO_VERTEX*>( malloc( m_currentSize * sizeof( VBO_VERTEX ) ) );
        aTarget = static_cast<VERTEX*>( malloc( m_currentSize * sizeof( VERTEX ) ) );

        if( aTarget == NULL )
        if( aTarget == NULL )
        {
        {
            wxLogError( wxT( "Run out of memory" ) );
            wxLogError( wxT( "Run out of memory" ) );
@@ -309,16 +291,17 @@ bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )


    int newOffset = 0;
    int newOffset = 0;
    Items::iterator it, it_end;
    Items::iterator it, it_end;

    for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
    for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
    {
    {
        VBO_ITEM* item = *it;
        VERTEX_ITEM* item = *it;
        int itemOffset    = item->GetOffset();
        int itemOffset    = item->GetOffset();
        int itemSize      = item->GetSize();
        int itemSize      = item->GetSize();


        // Move an item to the new container
        // Move an item to the new container
        memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VBO_ITEM::VertByteSize );
        memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VertexSize );


        // Update its offset
        // Update new offset
        item->setOffset( newOffset );
        item->setOffset( newOffset );


        // Move to the next free space
        // Move to the next free space
@@ -330,17 +313,29 @@ bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )


    // Now there is only one big chunk of free memory
    // Now there is only one big chunk of free memory
    m_freeChunks.clear();
    m_freeChunks.clear();
    m_freeChunks.insert( Chunk( m_freeSpace, reservedSpace() ) );
    m_freeChunks.insert( Chunk( m_freeSpace, m_currentSize - m_freeSpace ) );

#ifdef __WXDEBUG__
    prof_end( &totalTime );

    wxLogDebug( wxT( "Defragmented the container storing %d vertices / %.1f ms" ),
                m_currentSize - m_freeSpace, (double) totalTime.value / 1000.0 );
#endif /* __WXDEBUG__ */


    return true;
    return true;
}
}




void VBO_CONTAINER::mergeFreeChunks()
void CACHED_CONTAINER::mergeFreeChunks()
{
{
    if( m_freeChunks.size() < 2 )  // There are no chunks that can be merged
    if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged
        return;
        return;


#ifdef __WXDEBUG__
    prof_counter totalTime;
    prof_start( &totalTime, false );
#endif /* __WXDEBUG__ */

    // Reversed free chunks map - this one stores chunk size with its offset as the key
    // Reversed free chunks map - this one stores chunk size with its offset as the key
    std::list<Chunk> freeChunks;
    std::list<Chunk> freeChunks;


@@ -349,6 +344,7 @@ void VBO_CONTAINER::mergeFreeChunks()
    {
    {
        freeChunks.push_back( std::make_pair( it->second, it->first ) );
        freeChunks.push_back( std::make_pair( it->second, it->first ) );
    }
    }

    m_freeChunks.clear();
    m_freeChunks.clear();
    freeChunks.sort();
    freeChunks.sort();


@@ -356,6 +352,7 @@ void VBO_CONTAINER::mergeFreeChunks()
    unsigned int offset = freeChunks.front().first;
    unsigned int offset = freeChunks.front().first;
    unsigned int size   = freeChunks.front().second;
    unsigned int size   = freeChunks.front().second;
    freeChunks.pop_front();
    freeChunks.pop_front();

    for( itf = freeChunks.begin(), itf_end = freeChunks.end(); itf != itf_end; ++itf )
    for( itf = freeChunks.begin(), itf_end = freeChunks.end(); itf != itf_end; ++itf )
    {
    {
        if( itf->first == offset + size )
        if( itf->first == offset + size )
@@ -371,17 +368,30 @@ void VBO_CONTAINER::mergeFreeChunks()
            // and let's check the next chunk
            // and let's check the next chunk
            offset = itf->first;
            offset = itf->first;
            size   = itf->second;
            size   = itf->second;

        }
        }
    }
    }


    // Add the last one
    // Add the last one
    m_freeChunks.insert( std::make_pair( size, offset ) );
    m_freeChunks.insert( std::make_pair( size, offset ) );

#ifdef __WXDEBUG__
    prof_end( &totalTime );

    wxLogDebug( wxT( "Merged free chunks / %.1f ms" ), (double) totalTime.value / 1000.0 );
#endif /* __WXDEBUG__ */

    test();
}
}




bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
bool CACHED_CONTAINER::resizeContainer( unsigned int aNewSize )
{
{
    VBO_VERTEX* newContainer;
#if CACHED_CONTAINER_TEST > 0
    wxLogDebug( wxT( "Resizing container from %d to %d" ), m_currentSize, aNewSize );
#endif

    VERTEX* newContainer;


    if( aNewSize < m_currentSize )
    if( aNewSize < m_currentSize )
    {
    {
@@ -390,7 +400,8 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
        if( reservedSpace() > aNewSize )
        if( reservedSpace() > aNewSize )
            return false;
            return false;


        newContainer = static_cast<VBO_VERTEX*>( malloc( aNewSize * sizeof( VBO_VERTEX ) ) );
        newContainer = static_cast<VERTEX*>( malloc( aNewSize * sizeof( VERTEX ) ) );

        if( newContainer == NULL )
        if( newContainer == NULL )
        {
        {
            wxLogError( wxT( "Run out of memory" ) );
            wxLogError( wxT( "Run out of memory" ) );
@@ -407,7 +418,8 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
    else
    else
    {
    {
        // Enlarging container
        // Enlarging container
        newContainer = static_cast<VBO_VERTEX*>( realloc( m_vertices, aNewSize * sizeof( VBO_VERTEX ) ) );
        newContainer = static_cast<VERTEX*>( realloc( m_vertices, aNewSize * sizeof( VERTEX ) ) );

        if( newContainer == NULL )
        if( newContainer == NULL )
        {
        {
            wxLogError( wxT( "Run out of memory" ) );
            wxLogError( wxT( "Run out of memory" ) );
@@ -427,28 +439,87 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
}
}




void VBO_CONTAINER::freeItem( VBO_ITEM* aItem )
void CACHED_CONTAINER::freeItem( VERTEX_ITEM* aItem )
{
{
    int size   = aItem->GetSize();
    int size   = aItem->GetSize();
    int offset = aItem->GetOffset();
    int offset = aItem->GetOffset();


    // Insert a free memory chunk entry in the place where item was stored
    m_freeChunks.insert( Chunk( size, offset ) );
    m_freeChunks.insert( Chunk( size, offset ) );
    m_freeSpace += size;
    m_freeSpace += size;
    m_items.erase( aItem );
    m_items.erase( aItem );


    // Item size is set to 0, so it means that it is not stored in the container
    // Indicate that the item is not stored in the container anymore
    aItem->setSize( 0 );
    aItem->setSize( 0 );
}
}




void VBO_CONTAINER::test() const
unsigned int CACHED_CONTAINER::getPowerOf2( unsigned int aNumber ) const
{
{
    unsigned int freeSpace = 0;
    unsigned int power = 1;
    FreeChunkMap::const_iterator it, it_end;


    // Check if the amount of free memory stored as chunks is the same as reported by m_freeSpace
    while( power < aNumber && power != 0 )
    for( it = m_freeChunks.begin(), it_end = m_freeChunks.end(); it != it_end; ++it )
        power <<= 1;
        freeSpace += it->first;

    return power;
}


#ifdef CACHED_CONTAINER_TEST
void CACHED_CONTAINER::showFreeChunks()
{
    FreeChunkMap::iterator it;

    wxLogDebug( wxT( "Free chunks:" ) );

    for( it = m_freeChunks.begin(); it != m_freeChunks.end(); ++it )
    {
        unsigned int offset = getChunkOffset( *it );
        unsigned int size   = getChunkSize( *it );

        wxLogDebug( wxT( "[0x%08x-0x%08x] (size %d)" ),
                    offset, offset + size - 1, size );
    }
}


void CACHED_CONTAINER::showReservedChunks()
{
    Items::iterator it;

    wxLogDebug( wxT( "Reserved chunks:" ) );

    for( it = m_items.begin(); it != m_items.end(); ++it )
    {
        VERTEX_ITEM* item   = *it;
        unsigned int offset = item->GetOffset();
        unsigned int size   = item->GetSize();

        wxLogDebug( wxT( "[0x%08x-0x%08x] @ 0x%08x (size %d)" ),
                    offset, offset + size - 1, (int) item, size );
    }
}


void CACHED_CONTAINER::test()
{
    // Free space check
    unsigned int freeSpace = 0;
    FreeChunkMap::iterator itf;
    for( itf = m_freeChunks.begin(); itf != m_freeChunks.end(); ++itf )
        freeSpace += getChunkSize( *itf );


    wxASSERT( freeSpace == m_freeSpace );
    wxASSERT( freeSpace == m_freeSpace );

    // Reserved space check
    /*unsigned int reservedSpace = 0;
    Items::iterator itr;
    for( itr = m_items.begin(); itr != m_items.end(); ++itr )
        reservedSpace += ( *itr )->GetSize();
    reservedSpace += m_itemSize;    // Add the current chunk size

    wxASSERT( ( freeSpace + reservedSpace ) == m_currentSize );*/

    // Overlapping check TBD
}
}
#endif /* CACHED_CONTAINER_TEST */
Loading