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

This commit is contained in:
Maciej Suminski 2013-07-22 10:41:12 +02:00
parent 4d7db7171c
commit 5242fff9d7
22 changed files with 2326 additions and 1378 deletions

View File

@ -36,8 +36,12 @@ set(GAL_SRCS
gal/color4d.cpp
gal/opengl/opengl_gal.cpp
gal/opengl/shader.cpp
gal/opengl/vbo_item.cpp
gal/opengl/vbo_container.cpp
gal/opengl/vertex_item.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
view/wx_view_controls.cpp
)

View File

@ -132,7 +132,7 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect )
#endif /* __WXDEBUG__ */
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->DrawGrid();

View File

@ -37,7 +37,7 @@ using namespace KiGfx;
CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
wxEvtHandler* aPaintListener, const wxString& aName ) :
wxWindow( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxEXPAND, aName )
wxWindow( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxEXPAND, aName )
{
// Default values
fillColor = COLOR4D( 0, 0, 0, 1 );
@ -141,7 +141,7 @@ void CAIRO_GAL::initSurface()
cairoSurface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer,
CAIRO_FORMAT_RGB24, clientRectangle.width,
clientRectangle.height, stride );
cairoImage = cairo_create ( cairoSurface );
cairoImage = cairo_create( cairoSurface );
#ifdef __WXDEBUG__
cairo_status_t status = cairo_status( cairoImage );
wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" );
@ -194,10 +194,10 @@ void CAIRO_GAL::deinitSurface()
}
unsigned int CAIRO_GAL::getGroupNumber()
unsigned int CAIRO_GAL::getNewGroupNumber()
{
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" ) );
while( groups.find( groupCounter ) != groups.end() )
{
@ -230,6 +230,7 @@ void CAIRO_GAL::EndDrawing()
// Now translate the raw image data from the format stored
// by cairo into a format understood by wxImage.
unsigned char* wxOutputPtr = wxOutput;
for( size_t count = 0; count < bufferSize; 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 )
{
@ -317,7 +319,6 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo
cairo_line_to( cairoImage, lineLength, -aWidth / 2.0 );
cairo_restore( cairoImage );
}
isElementAdded = true;
@ -351,7 +352,8 @@ void CAIRO_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
bool isFirstPoint = true;
// 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 )
{
@ -373,7 +375,8 @@ void CAIRO_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
bool isFirstPoint = true;
// 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 )
{
@ -644,10 +647,10 @@ int CAIRO_GAL::BeginGroup()
storePath();
Group group;
int groupNumber = getGroupNumber();
int groupNumber = getNewGroupNumber();
groups.insert( std::make_pair( groupNumber, group ) );
currentGroup = &groups[groupNumber];
isGrouping = true;
isGrouping = true;
return groupNumber;
}
@ -677,6 +680,7 @@ void CAIRO_GAL::DeleteGroup( int aGroupNumber )
// Delete the Cairo paths
std::deque<GroupElement>::iterator it, end;
for( it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end(); it != end; ++it )
{
if( it->command == CMD_FILL_PATH || it->command == CMD_STROKE_PATH )

View File

@ -23,171 +23,67 @@
*/
/**
* @file vbo_container.cpp
* @brief Class to store VBO_ITEMs.
* @file cached_container.cpp
* @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 <algorithm>
#include <list>
#include <gal/opengl/cached_container.h>
#include <gal/opengl/vertex_manager.h>
#include <gal/opengl/vertex_item.h>
#include <gal/opengl/shader.h>
#include <wx/log.h>
#include <list>
#ifdef __WXDEBUG__
#include <profile.h>
#endif /* __WXDEBUG__ */
using namespace KiGfx;
VBO_CONTAINER::VBO_CONTAINER( unsigned int aSize ) :
m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), m_transform( NULL ),
m_failed( false )
CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
VERTEX_CONTAINER( aSize )
{
// 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
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 )
{
m_item = aItem;
m_itemSize = aItem->GetSize();
m_chunkSize = m_itemSize;
// 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();
}
if( m_itemSize == 0 )
m_items.insert( m_item ); // The item was not stored before
m_item = NULL;
}
else
m_chunkOffset = m_item->GetOffset();
}
void VBO_CONTAINER::EndItem()
{
if( m_itemSize < m_chunkSize )
{
// 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 = aItem;
m_itemSize = m_item->GetSize();
m_chunkSize = m_itemSize;
m_item = NULL;
}
void VBO_CONTAINER::Add( const VBO_VERTEX* aVertex, unsigned int aSize )
{
// Pointer to the vertex that we are currently adding
VBO_VERTEX* vertexPtr = allocate( aSize );
if( vertexPtr == NULL )
return;
for( unsigned int i = 0; i < aSize; ++i )
{
// Modify the vertex according to the currently used transformations
if( m_transform != NULL )
{
// Apply transformations
glm::vec4 vertex( aVertex[i].x, aVertex[i].y, aVertex[i].z, 1.0f );
vertex = *m_transform * vertex;
// Replace only coordinates, leave color as it is
vertexPtr->x = vertex.x;
vertexPtr->y = vertex.y;
vertexPtr->z = vertex.z;
}
if( m_itemSize == 0 )
m_items.insert( m_item ); // The item was not stored before
else
{
// Simply copy coordinates
vertexPtr->x = aVertex[i].x;
vertexPtr->y = aVertex[i].y;
vertexPtr->z = aVertex[i].z;
}
// Apply currently used color
vertexPtr->r = m_color[0];
vertexPtr->g = m_color[1];
vertexPtr->b = m_color[2];
vertexPtr->a = m_color[3];
// Apply currently used shader
for( unsigned int j = 0; j < VBO_ITEM::ShaderStride; ++j )
{
vertexPtr->shader[j] = m_shader[j];
}
vertexPtr++;
}
}
void VBO_CONTAINER::Clear()
{
// Change size to the default one
m_vertices = static_cast<VBO_VERTEX*>( realloc( m_vertices,
m_initialSize * sizeof( VBO_VERTEX ) ) );
// Set the size of all the stored VERTEX_ITEMs to 0, so it is clear that they are not held
// in the container anymore
Items::iterator it;
for( it = m_items.begin(); it != m_items.end(); ++it )
{
( *it )->setSize( 0 );
}
m_items.clear();
// Reset state variables
m_transform = NULL;
m_failed = false;
// By default no shader is used
m_shader[0] = 0;
// In the beginning there is only free space
m_freeSpace = m_initialSize;
m_currentSize = m_initialSize;
m_freeChunks.clear();
m_freeChunks.insert( Chunk( m_freeSpace, 0 ) );
}
void VBO_CONTAINER::Free( VBO_ITEM* aItem )
{
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 );
m_chunkOffset = m_item->GetOffset();
}
}
VBO_VERTEX* VBO_CONTAINER::GetAllVertices() const
{
return m_vertices;
}
VBO_VERTEX* VBO_CONTAINER::GetVertices( const VBO_ITEM* aItem ) const
{
int offset = aItem->GetOffset();
return &m_vertices[offset];
}
VBO_VERTEX* VBO_CONTAINER::allocate( unsigned int aSize )
VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
{
wxASSERT( m_item != NULL );
@ -198,8 +94,9 @@ VBO_VERTEX* VBO_CONTAINER::allocate( unsigned int aSize )
{
// There is not enough space in the currently reserved chunk, so we have to resize it
// Reserve a bigger memory chunk for the current item
m_chunkSize = std::max( ( 2 * m_itemSize ) + aSize, (unsigned) 3 );
// Reserve a bigger memory chunk for the current item and
// 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 );
@ -210,16 +107,81 @@ VBO_VERTEX* VBO_CONTAINER::allocate( unsigned int aSize )
}
}
VBO_VERTEX* reserved = &m_vertices[m_chunkOffset + m_itemSize];
VERTEX* reserved = &m_vertices[m_chunkOffset + m_itemSize];
m_itemSize += aSize;
m_item->setSize( m_itemSize );
// The content has to be updated
m_dirty = true;
#if CACHED_CONTAINER_TEST > 1
test();
#endif
return reserved;
}
unsigned int VBO_CONTAINER::reallocate( unsigned int aSize )
void CACHED_CONTAINER::Erase()
{
wxASSERT( m_item != NULL );
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 CACHED_CONTAINER::Clear()
{
// Change size to the default one
m_vertices = static_cast<VERTEX*>( realloc( m_vertices,
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
// in the container anymore
Items::iterator it;
for( it = m_items.begin(); it != m_items.end(); ++it )
{
( *it )->setSize( 0 );
}
m_items.clear();
// Now there is only free space left
m_freeChunks.clear();
m_freeChunks.insert( Chunk( m_freeSpace, 0 ) );
}
VERTEX* CACHED_CONTAINER::GetVertices( const VERTEX_ITEM* aItem ) const
{
int offset = aItem->GetOffset();
return &m_vertices[offset];
}
unsigned int CACHED_CONTAINER::reallocate( unsigned int aSize )
{
#if CACHED_CONTAINER_TEST > 2
wxLogDebug( wxT( "Resize 0x%08x to %d" ), (int) m_item, aSize );
showFreeChunks();
showReservedChunks();
#endif
// Is there enough space to store vertices?
if( m_freeSpace < aSize )
{
@ -260,7 +222,7 @@ unsigned int VBO_CONTAINER::reallocate( unsigned int aSize )
}
// Parameters of the allocated cuhnk
unsigned int chunkSize = newChunk->first;
unsigned int chunkSize = newChunk->first;
unsigned int chunkOffset = newChunk->second;
wxASSERT( chunkSize >= aSize );
@ -269,37 +231,57 @@ unsigned int VBO_CONTAINER::reallocate( unsigned int aSize )
// Check if the item was previously stored in the container
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
memcpy( &m_vertices[chunkOffset], &m_vertices[m_chunkOffset],
m_itemSize * VBO_ITEM::VertByteSize );
m_itemSize * VertexSize );
// Free the space previously used by the chunk
m_freeChunks.insert( Chunk( m_itemSize, m_chunkOffset ) );
m_freeSpace += m_itemSize;
}
// Remove the allocated chunk from the free space pool
m_freeChunks.erase( newChunk );
m_freeSpace -= chunkSize;
// If there is some space left, return it to the pool - add an entry for it
if( chunkSize > aSize )
{
m_freeChunks.insert( Chunk( chunkSize - aSize, chunkOffset + aSize ) );
m_freeSpace += chunkSize - aSize;
}
m_freeSpace -= aSize;
// mergeFreeChunks();
m_item->setOffset( chunkOffset );
#if CACHED_CONTAINER_TEST > 2
showFreeChunks();
showReservedChunks();
#endif
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 )
{
// 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 )
{
wxLogError( wxT( "Run out of memory" ) );
@ -309,16 +291,17 @@ bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )
int newOffset = 0;
Items::iterator it, it_end;
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
{
VBO_ITEM* item = *it;
int itemOffset = item->GetOffset();
int itemSize = item->GetSize();
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 * VBO_ITEM::VertByteSize );
memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VertexSize );
// Update its offset
// Update new offset
item->setOffset( newOffset );
// 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
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;
}
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;
#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
std::list<Chunk> freeChunks;
@ -349,6 +344,7 @@ void VBO_CONTAINER::mergeFreeChunks()
{
freeChunks.push_back( std::make_pair( it->second, it->first ) );
}
m_freeChunks.clear();
freeChunks.sort();
@ -356,6 +352,7 @@ void VBO_CONTAINER::mergeFreeChunks()
unsigned int offset = freeChunks.front().first;
unsigned int size = freeChunks.front().second;
freeChunks.pop_front();
for( itf = freeChunks.begin(), itf_end = freeChunks.end(); itf != itf_end; ++itf )
{
if( itf->first == offset + size )
@ -371,17 +368,30 @@ void VBO_CONTAINER::mergeFreeChunks()
// and let's check the next chunk
offset = itf->first;
size = itf->second;
}
}
// Add the last one
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 )
{
@ -390,7 +400,8 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
if( reservedSpace() > aNewSize )
return false;
newContainer = static_cast<VBO_VERTEX*>( malloc( aNewSize * sizeof( VBO_VERTEX ) ) );
newContainer = static_cast<VERTEX*>( malloc( aNewSize * sizeof( VERTEX ) ) );
if( newContainer == NULL )
{
wxLogError( wxT( "Run out of memory" ) );
@ -407,7 +418,8 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
else
{
// 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 )
{
wxLogError( wxT( "Run out of memory" ) );
@ -420,35 +432,94 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
m_vertices = newContainer;
m_freeSpace += ( aNewSize - m_currentSize );
m_freeSpace += ( aNewSize - m_currentSize );
m_currentSize = aNewSize;
return true;
}
void VBO_CONTAINER::freeItem( VBO_ITEM* aItem )
void CACHED_CONTAINER::freeItem( VERTEX_ITEM* aItem )
{
int size = aItem->GetSize();
int offset = aItem->GetOffset();
int size = aItem->GetSize();
int offset = aItem->GetOffset();
// Insert a free memory chunk entry in the place where item was stored
m_freeChunks.insert( Chunk( size, offset ) );
m_freeSpace += size;
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 );
}
void VBO_CONTAINER::test() const
unsigned int CACHED_CONTAINER::getPowerOf2( unsigned int aNumber ) const
{
unsigned int freeSpace = 0;
FreeChunkMap::const_iterator it, it_end;
unsigned int power = 1;
// Check if the amount of free memory stored as chunks is the same as reported by m_freeSpace
for( it = m_freeChunks.begin(), it_end = m_freeChunks.end(); it != it_end; ++it )
freeSpace += it->first;
while( power < aNumber && power != 0 )
power <<= 1;
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 );
// 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 */

View File

@ -0,0 +1,283 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file gpu_manager.cpp
* @brief Class to handle uploading vertices and indices to GPU in drawing purposes.
*/
#include <gal/opengl/gpu_manager.h>
#include <gal/opengl/cached_container.h>
#include <gal/opengl/noncached_container.h>
#include <gal/opengl/shader.h>
#include <typeinfo>
#include <wx/log.h>
#ifdef __WXDEBUG__
#include <profile.h>
#endif
using namespace KiGfx;
GPU_MANAGER* GPU_MANAGER::MakeManager( VERTEX_CONTAINER* aContainer )
{
if( typeid( *aContainer ) == typeid( CACHED_CONTAINER ) )
return new GPU_CACHED_MANAGER( aContainer );
else if( typeid( *aContainer ) == typeid( NONCACHED_CONTAINER ) )
return new GPU_NONCACHED_MANAGER( aContainer );
wxASSERT_MSG( false, "Not handled container type" );
return NULL;
}
GPU_MANAGER::GPU_MANAGER( VERTEX_CONTAINER* aContainer ) :
m_container( aContainer ), m_shader( NULL )
{
}
GPU_MANAGER::~GPU_MANAGER()
{
}
void GPU_MANAGER::SetShader( SHADER& aShader )
{
m_shader = &aShader;
m_shaderAttrib = m_shader->GetAttribute( "attrShaderParams" );
if( m_shaderAttrib == -1 )
{
wxLogFatalError( wxT( "Could not get the shader attribute location" ) );
}
}
// Cached manager
GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
GPU_MANAGER( aContainer ), m_buffersInitialized( false ), m_indicesPtr( NULL ),
m_indicesSize( 0 )
{
}
GPU_CACHED_MANAGER::~GPU_CACHED_MANAGER()
{
if( m_buffersInitialized )
{
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDeleteBuffers( 1, &m_verticesBuffer );
}
}
void GPU_CACHED_MANAGER::Initialize()
{
wxASSERT( !m_buffersInitialized );
if( !m_buffersInitialized )
{
glGenBuffers( 1, &m_verticesBuffer );
m_buffersInitialized = true;
}
}
void GPU_CACHED_MANAGER::BeginDrawing()
{
wxASSERT( !m_isDrawing );
if( m_container->isDirty() )
uploadToGpu();
// Number of vertices to be drawn in the EndDrawing()
m_indicesSize = 0;
// Set the indices pointer to the beginning of the indices-to-draw buffer
m_indicesPtr = m_indices.get();
m_isDrawing = true;
}
void GPU_CACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
{
wxASSERT( m_isDrawing );
// Copy indices of items that should be drawn to GPU memory
for( unsigned int i = aOffset; i < aOffset + aSize; *m_indicesPtr++ = i++ );
m_indicesSize += aSize;
}
void GPU_CACHED_MANAGER::DrawAll()
{
wxASSERT( m_isDrawing );
m_indicesSize = m_container->GetSize();
for( unsigned int i = 0; i < m_indicesSize; *m_indicesPtr++ = i++ );
}
void GPU_CACHED_MANAGER::EndDrawing()
{
wxASSERT( m_isDrawing );
// Prepare buffers
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
// Bind vertices data buffers
glBindBuffer( GL_ARRAY_BUFFER, m_verticesBuffer );
glVertexPointer( CoordStride, GL_FLOAT, VertexSize, 0 );
glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, (GLvoid*) ColorOffset );
if( m_shader != NULL ) // Use shader if applicable
{
m_shader->Use();
glEnableVertexAttribArray( m_shaderAttrib );
glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE,
VertexSize, (GLvoid*) ShaderOffset );
}
glDrawElements( GL_TRIANGLES, m_indicesSize, GL_UNSIGNED_INT, (GLvoid*) m_indices.get() );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
// Deactivate vertex array
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
if( m_shader != NULL )
{
glDisableVertexAttribArray( m_shaderAttrib );
m_shader->Deactivate();
}
m_isDrawing = false;
}
void GPU_CACHED_MANAGER::uploadToGpu()
{
#ifdef __WXDEBUG__
prof_counter totalTime;
prof_start( &totalTime, false );
#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 );
glBufferData( GL_ARRAY_BUFFER, bufferSize * VertexSize, vertices, GL_DYNAMIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
// Allocate the biggest possible buffer for indices
m_indices.reset( new GLuint[bufferSize] );
if( glGetError() != GL_NO_ERROR )
{
wxLogError( wxT( "Error during data upload to the GPU memory" ) );
}
#ifdef __WXDEBUG__
prof_end( &totalTime );
wxLogDebug( wxT( "Uploading %d vertices to GPU / %.1f ms" ),
bufferSize, (double) totalTime.value / 1000.0 );
#endif /* __WXDEBUG__ */
}
// Noncached manager
GPU_NONCACHED_MANAGER::GPU_NONCACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
GPU_MANAGER( aContainer )
{
}
void GPU_NONCACHED_MANAGER::Initialize()
{
// Nothing has to be intialized
}
void GPU_NONCACHED_MANAGER::BeginDrawing()
{
// Nothing has to be prepared
}
void GPU_NONCACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
{
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
}
void GPU_NONCACHED_MANAGER::DrawAll()
{
// This is the default use case, nothing has to be done
// The real rendering takes place in the EndDrawing() function
}
void GPU_NONCACHED_MANAGER::EndDrawing()
{
VERTEX* vertices = m_container->GetAllVertices();
GLfloat* coordinates = (GLfloat*) ( vertices );
GLubyte* colors = (GLubyte*) ( vertices ) + ColorOffset;
GLfloat* shaders = (GLfloat*) ( vertices ) + ShaderOffset / sizeof(GLfloat);
// Prepare buffers
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( CoordStride, GL_FLOAT, VertexSize, coordinates );
glColorPointer( ColorStride, GL_UNSIGNED_BYTE, VertexSize, colors );
if( m_shader != NULL ) // Use shader if applicable
{
m_shader->Use();
glEnableVertexAttribArray( m_shaderAttrib );
glVertexAttribPointer( m_shaderAttrib, ShaderStride, GL_FLOAT, GL_FALSE,
VertexSize, shaders );
}
glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
// Deactivate vertex array
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
if( m_shader != NULL )
{
glDisableVertexAttribArray( m_shaderAttrib );
m_shader->Deactivate();
}
}

View File

@ -0,0 +1,94 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file noncached_container.cpp
* @brief Class to store instances of VERTEX without caching. It allows a fast one-frame drawing
* and then clearing the buffer and starting from scratch.
*/
#include <gal/opengl/noncached_container.h>
#include <cstdlib>
using namespace KiGfx;
NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) :
VERTEX_CONTAINER( aSize ), m_freePtr( 0 )
{
}
NONCACHED_CONTAINER::~NONCACHED_CONTAINER()
{
}
void NONCACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
{
// Nothing has to be done, as the noncached container
// does not care about VERTEX_ITEMs ownership
}
VERTEX* NONCACHED_CONTAINER::Allocate( unsigned int aSize )
{
if( m_freeSpace < aSize )
{
// Double the space
VERTEX* newVertices = static_cast<VERTEX*>( realloc( m_vertices,
m_currentSize * 2 *
sizeof(VERTEX) ) );
if( newVertices != NULL )
{
m_vertices = newVertices;
m_freeSpace += m_currentSize;
m_currentSize *= 2;
}
else
{
return NULL;
}
}
VERTEX* freeVertex = &m_vertices[m_freePtr];
// Move to the next free chunk
m_freePtr += aSize;
m_freeSpace -= aSize;
return freeVertex;
}
void NONCACHED_CONTAINER::Erase()
{
}
void NONCACHED_CONTAINER::Clear()
{
m_freePtr = 0;
m_freeSpace = m_currentSize;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,116 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vbo_item.cpp
* @brief Class to handle an item held in a Vertex Buffer Object.
*/
#include <gal/opengl/vbo_container.h>
#include <gal/opengl/vbo_item.h>
#include <cstring>
using namespace KiGfx;
VBO_ITEM::VBO_ITEM( VBO_CONTAINER* aContainer ) :
m_offset( 0 ),
m_size( 0 ),
m_container( aContainer ),
m_isDirty( true )
{
// The item's size is not known yet, so we just start an item in the container
aContainer->StartItem( this );
}
VBO_ITEM::~VBO_ITEM()
{
m_container->Free( this );
}
void VBO_ITEM::PushVertex( const VBO_VERTEX* aVertex )
{
m_container->Add( aVertex );
m_isDirty = true;
}
void VBO_ITEM::PushVertices( const VBO_VERTEX* aVertices, GLuint aSize )
{
for( unsigned int i = 0; i < aSize; ++i )
{
PushVertex( &aVertices[i] );
}
}
VBO_VERTEX* VBO_ITEM::GetVertices()
{
if( m_isDirty )
Finish();
return m_container->GetVertices( m_offset );
}
void VBO_ITEM::ChangeColor( const COLOR4D& aColor )
{
VBO_VERTEX* vertexPtr = GetVertices();
for( unsigned int i = 0; i < m_size; ++i )
{
vertexPtr->r = aColor.r * 255;
vertexPtr->g = aColor.g * 255;
vertexPtr->b = aColor.b * 255;
vertexPtr->a = aColor.a * 255;
// Move on to the next vertex
vertexPtr++;
}
}
void VBO_ITEM::ChangeDepth( int aDepth )
{
VBO_VERTEX* vertexPtr = GetVertices();
for( unsigned int i = 0; i < m_size; ++i )
{
vertexPtr->z = aDepth;
// Move on to the next vertex
vertexPtr++;
}
}
void VBO_ITEM::Finish()
{
// The unknown-sized item has just ended, so we need to inform the container about it
m_container->EndItem();
m_isDirty = false;
}

View File

@ -0,0 +1,57 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vertex_container.cpp
* @brief Class to store vertices and handle transfers between system memory and GPU memory.
*/
#include <gal/opengl/vertex_container.h>
#include <gal/opengl/cached_container.h>
#include <gal/opengl/noncached_container.h>
#include <gal/opengl/shader.h>
#include <wx/log.h>
using namespace KiGfx;
VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached )
{
if( aCached )
return new CACHED_CONTAINER;
else
return new NONCACHED_CONTAINER;
}
VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) :
m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), m_failed( false )
{
m_vertices = static_cast<VERTEX*>( malloc( aSize * sizeof( VERTEX ) ) );
}
VERTEX_CONTAINER::~VERTEX_CONTAINER()
{
free( m_vertices );
}

View File

@ -0,0 +1,53 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vertex_item.cpp
* @brief Class to handle an item held in a container.
*/
#include <gal/opengl/vertex_item.h>
#include <gal/opengl/vertex_manager.h>
#include <cstring>
using namespace KiGfx;
VERTEX_ITEM::VERTEX_ITEM( const VERTEX_MANAGER& aManager ) :
m_manager( aManager ), m_offset( 0 ), m_size( 0 )
{
// As the item is created, we are going to modify it, so call to SetItem() is needed
m_manager.SetItem( *this );
}
VERTEX_ITEM::~VERTEX_ITEM()
{
m_manager.FreeItem( *this );
}
VERTEX* VERTEX_ITEM::GetVertices() const
{
return m_manager.GetVertices( *this );
}

View File

@ -0,0 +1,203 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vertex_manager.cpp
* @brief Class to control vertex container and GPU with possibility of emulating old-style OpenGL
* 1.0 state machine using modern OpenGL methods.
*/
#include <gal/opengl/vertex_manager.h>
#include <gal/opengl/cached_container.h>
#include <gal/opengl/noncached_container.h>
#include <gal/opengl/gpu_manager.h>
#include <gal/opengl/vertex_item.h>
using namespace KiGfx;
VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) :
m_noTransform( true ), m_transform( 1.0f )
{
m_container.reset( VERTEX_CONTAINER::MakeContainer( aCached ) );
m_gpu.reset( GPU_MANAGER::MakeManager( m_container.get() ) );
// There is no shader used by default
for( unsigned int i = 0; i < ShaderStride; ++i )
m_shader[i] = 0.0f;
}
void VERTEX_MANAGER::Vertex( GLfloat aX, GLfloat aY, GLfloat aZ ) const
{
// Obtain the pointer to the vertex in the currently used container
VERTEX* newVertex = m_container->Allocate( 1 );
if( newVertex == NULL )
{
wxLogError( wxT( "Vertex allocation error" ) );
return;
}
putVertex( *newVertex, aX, aY, aZ );
}
void VERTEX_MANAGER::Vertices( const VERTEX aVertices[], unsigned int aSize ) const
{
// Obtain pointer to the vertex in currently used container
VERTEX* newVertex = m_container->Allocate( aSize );
if( newVertex == NULL )
{
wxLogError( wxT( "Vertex allocation error" ) );
return;
}
// Put vertices in already allocated memory chunk
for( unsigned int i = 0; i < aSize; ++i )
{
putVertex( newVertex[i], aVertices[i].x, aVertices[i].y, aVertices[i].z );
}
}
void VERTEX_MANAGER::SetItem( VERTEX_ITEM& aItem ) const
{
m_container->SetItem( &aItem );
}
void VERTEX_MANAGER::FreeItem( VERTEX_ITEM& aItem ) const
{
m_container->SetItem( &aItem );
m_container->Erase();
}
void VERTEX_MANAGER::ChangeItemColor( const VERTEX_ITEM& aItem, const COLOR4D& aColor ) const
{
unsigned int size = aItem.GetSize();
unsigned int offset = aItem.GetOffset();
VERTEX* vertex = m_container->GetVertices( offset );
for( unsigned int i = 0; i < size; ++i )
{
vertex->r = aColor.r;
vertex->g = aColor.g;
vertex->b = aColor.b;
vertex->a = aColor.a;
vertex++;
}
}
void VERTEX_MANAGER::ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth ) const
{
unsigned int size = aItem.GetSize();
unsigned int offset = aItem.GetOffset();
VERTEX* vertex = m_container->GetVertices( offset );
for( unsigned int i = 0; i < size; ++i )
{
vertex->z = aDepth;
vertex++;
}
}
VERTEX* VERTEX_MANAGER::GetVertices( const VERTEX_ITEM& aItem ) const
{
if( aItem.GetSize() == 0 )
return NULL; // The item is not stored in the container
return m_container->GetVertices( aItem.GetOffset() );
}
void VERTEX_MANAGER::SetShader( SHADER& aShader ) const
{
m_gpu->SetShader( aShader );
}
void VERTEX_MANAGER::Clear() const
{
m_container->Clear();
}
void VERTEX_MANAGER::BeginDrawing() const
{
m_gpu->BeginDrawing();
}
void VERTEX_MANAGER::DrawItem( const VERTEX_ITEM& aItem ) const
{
int size = aItem.GetSize();
if( size > 0 )
{
int offset = aItem.GetOffset();
m_gpu->DrawIndices( offset, size );
}
}
void VERTEX_MANAGER::EndDrawing() const
{
m_gpu->EndDrawing();
}
void VERTEX_MANAGER::putVertex( VERTEX& aTarget, GLfloat aX, GLfloat aY, GLfloat aZ ) const
{
// Modify the vertex according to the currently used transformations
if( m_noTransform )
{
// Simply copy coordinates, when the transform matrix is the identity matrix
aTarget.x = aX;
aTarget.y = aY;
aTarget.z = aZ;
}
else
{
// Apply transformations
glm::vec4 transVertex( aX, aY, aZ, 1.0f );
transVertex = m_transform * transVertex;
aTarget.x = transVertex.x;
aTarget.y = transVertex.y;
aTarget.z = transVertex.z;
}
// Apply currently used color
aTarget.r = m_color[0];
aTarget.g = m_color[1];
aTarget.b = m_color[2];
aTarget.a = m_color[3];
// Apply currently used shader
for( unsigned int j = 0; j < ShaderStride; ++j )
{
aTarget.shader[j] = m_shader[j];
}
}

View File

@ -401,11 +401,11 @@ private:
void deinitSurface();
/**
* @brief Returns a valid key that can be used as a group number.
* @brief Returns a valid key that can be used as a new group number.
*
* @return An unique group number that is not used by any other group.
*/
unsigned int getGroupNumber();
unsigned int getNewGroupNumber();
};
} // namespace KiGfx

View File

@ -0,0 +1,185 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file cached_container.h
* @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.
*/
#ifndef CACHED_CONTAINER_H_
#define CACHED_CONTAINER_H_
#include <gal/opengl/vertex_container.h>
#include <map>
#include <set>
#ifdef __WXDEBUG__
// Debug messages verbosity level
// #define CACHED_CONTAINER_TEST 2
#endif
namespace KiGfx
{
class VERTEX_ITEM;
class SHADER;
class CACHED_CONTAINER : public VERTEX_CONTAINER
{
public:
CACHED_CONTAINER( unsigned int aSize = defaultInitSize );
///< @copydoc VERTEX_CONTAINER::SetItem()
virtual void SetItem( VERTEX_ITEM* aItem );
///< @copydoc VERTEX_CONTAINER::Allocate()
virtual VERTEX* Allocate( unsigned int aSize );
///< @copydoc VERTEX_CONTAINER::Erase()
virtual void Erase();
///< @copydoc VERTEX_CONTAINER::Clear()
virtual void Clear();
/**
* Function GetVertices()
* returns the vertices stored by the specific item.
*
* @param aItem is the item.
*/
virtual VERTEX* GetVertices( const VERTEX_ITEM* aItem ) const;
protected:
///< Maps size of free memory chunks to their offsets
typedef std::pair<unsigned int, unsigned int> Chunk;
typedef std::multimap<unsigned int, unsigned int> FreeChunkMap;
/// List of all the stored items
typedef std::set<VERTEX_ITEM*> Items;
///< Stores size & offset of free chunks.
FreeChunkMap m_freeChunks;
///< Stored VERTEX_ITEMs
Items m_items;
///< Currently modified item
VERTEX_ITEM* m_item;
///< Properties of currently modified chunk & item
unsigned int m_chunkSize;
unsigned int m_chunkOffset;
unsigned int m_itemSize;
/**
* Function reallocate()
* resizes the chunk that stores the current item to the given size.
*
* @param aSize is the number of vertices to be stored.
* @return offset of the new chunk.
*/
virtual 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.
*
* @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)
*/
virtual bool defragment( VERTEX* aTarget = NULL );
/**
* 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 );
/**
* Function freeItem()
* frees the space occupied by the item and returns it to the free space pool.
*
* @param aItem is the item to be freed.
*/
virtual void freeItem( VERTEX_ITEM* aItem );
/**
* Function getPowerOf2()
* returns the nearest power of 2, bigger than aNumber.
*
* @param aNumber is the number for which we look for a bigger power of 2.
*/
unsigned int getPowerOf2( unsigned int aNumber ) const;
private:
/**
* Function getChunkSize()
* returns size of the given chunk.
*
* @param aChunk is the chunk.
*/
inline int getChunkSize( const Chunk& aChunk ) const
{
return aChunk.first;
}
/**
* Function getChunkOffset()
* returns offset of the chunk.
*
* @param aChunk is the chunk.
*/
inline unsigned int getChunkOffset( const Chunk& aChunk ) const
{
return aChunk.second;
}
/// Debug & test functions
#ifdef CACHED_CONTAINER_TEST
void showFreeChunks();
void showReservedChunks();
void test();
#else
inline void showFreeChunks() {}
inline void showReservedChunks() {}
inline void test() {}
#endif /* CACHED_CONTAINER_TEST */
};
} // namespace KiGfx
#endif /* CACHED_CONTAINER_H_ */

View File

@ -0,0 +1,164 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file gpu_manager.h
* @brief Class to handle uploading vertices and indices to GPU in drawing purposes.
*/
#ifndef GPU_MANAGER_H_
#define GPU_MANAGER_H_
#include <gal/opengl/vertex_common.h>
#include <boost/scoped_array.hpp>
namespace KiGfx
{
class SHADER;
class VERTEX_CONTAINER;
class CACHED_CONTAINER;
class NONCACHED_CONTAINER;
class GPU_MANAGER
{
public:
static GPU_MANAGER* MakeManager( VERTEX_CONTAINER* aContainer );
virtual ~GPU_MANAGER();
// TODO docs
/**
* @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.
*/
virtual void BeginDrawing() = 0;
/**
* Function DrawIndices()
* Makes the GPU draw given range of vertices.
* @param aOffset is the beginning of the range.
* @param aSize is the number of vertices to be drawn.
*/
virtual void DrawIndices( unsigned int aOffset, unsigned int aSize ) = 0;
/**
* Function DrawIndices()
* Makes the GPU draw all the vertices stored in the container.
*/
virtual void DrawAll() = 0;
/**
* Function EndDrawing()
* Clears the container after drawing routines.
*/
virtual void EndDrawing() = 0;
/**
* Function SetShader()
* Allows using shaders with the stored data.
* @param aShader is the object that allows using shaders.
*/
virtual void SetShader( SHADER& aShader );
protected:
GPU_MANAGER( VERTEX_CONTAINER* aContainer );
///< Drawing status flag.
bool m_isDrawing;
///< Container that stores vertices data.
VERTEX_CONTAINER* m_container;
///< Shader handling
SHADER* m_shader;
int m_shaderAttrib; ///< Location of shader attributes (for glVertexAttribPointer)
};
class GPU_CACHED_MANAGER : public GPU_MANAGER
{
public:
GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer );
~GPU_CACHED_MANAGER();
///< @copydoc GPU_MANAGER::Initialize()
virtual void Initialize();
///< @copydoc GPU_MANAGER::BeginDrawing()
virtual void BeginDrawing();
///< @copydoc GPU_MANAGER::DrawIndices()
virtual void DrawIndices( unsigned int aOffset, unsigned int aSize );
///< @copydoc GPU_MANAGER::DrawAll()
virtual void DrawAll();
///< @copydoc GPU_MANAGER::EndDrawing()
virtual void EndDrawing();
/**
* Function uploadToGpu
* Rebuilds vertex buffer object using stored VERTEX_ITEMs and sends it to the graphics card
* memory.
*/
virtual void uploadToGpu();
protected:
bool m_buffersInitialized;
boost::scoped_array<GLuint> m_indices;
GLuint* m_indicesPtr;
GLuint m_verticesBuffer;
unsigned int m_indicesSize;
};
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();
///< @copydoc GPU_MANAGER::DrawIndices()
virtual void DrawIndices( unsigned int aOffset, unsigned int aSize );
///< @copydoc GPU_MANAGER::DrawAll()
virtual void DrawAll();
///< @copydoc GPU_MANAGER::EndDrawing()
virtual void EndDrawing();
};
} // namespace KiGfx
#endif /* GPU_MANAGER_H_ */

View File

@ -0,0 +1,73 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file noncached_container.h
* @brief Class to store instances of VERTEX without caching. It allows a fast one-frame drawing
* and then clearing the buffer and starting from scratch.
*/
#ifndef NONCACHED_CONTAINER_H_
#define NONCACHED_CONTAINER_H_
#include <gal/opengl/vertex_container.h>
namespace KiGfx
{
class VERTEX_ITEM;
class SHADER;
class NONCACHED_CONTAINER : public VERTEX_CONTAINER
{
public:
NONCACHED_CONTAINER( unsigned int aSize = defaultInitSize );
virtual ~NONCACHED_CONTAINER();
///< @copydoc VERTEX_CONTAINER::SetItem()
virtual void SetItem( VERTEX_ITEM* aItem );
///< @copydoc VERTEX_CONTAINER::Allocate()
virtual VERTEX* Allocate( unsigned int aSize );
///< @copydoc VERTEX_CONTAINER::Erase()
virtual void Erase();
///< @copydoc VERTEX_CONTAINER::Clear()
virtual void Clear();
///< @copydoc VERTEX_CONTAINER::GetSize()
virtual inline unsigned int GetSize() const
{
// As the m_freePtr points to the first free space, we can safely assume
// that this is the number of vertices stored inside
return m_freePtr;
}
protected:
///< Index of the free first space where a vertex can be stored
unsigned int m_freePtr;
};
} // namespace KiGfx
#endif /* NONCACHED_CONTAINER_H_ */

View File

@ -31,25 +31,21 @@
// GAL imports
#include <gal/graphics_abstraction_layer.h>
#include <GL/glew.h>
// OpenGL mathematics library
#define GLM_FORCE_RADIANS
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
#include <gal/opengl/vbo_container.h>
#include <gal/opengl/shader.h>
#include <gal/opengl/vertex_manager.h>
#include <gal/opengl/vertex_item.h>
#include <gal/opengl/noncached_container.h>
// wxWidgets imports
#include <wx/wx.h>
#include <wx/glcanvas.h>
// STL imports
#include <cmath>
#include <iterator>
#include <vector>
#include <algorithm>
#include <boost/unordered_map.hpp>
#include <memory>
#include <map>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <stdlib.h>
#include <iostream>
@ -312,7 +308,7 @@ public:
///< Parameters passed to the GLU tesselator
typedef struct
{
VBO_ITEM* vboItem; ///< VBO_ITEM for storing new vertices
VERTEX_MANAGER* vboManager; ///< VERTEX_ITEM for storing new vertices
std::vector<GLdouble*>& intersectPoints; ///< Intersect points, that have to be freed
} TessParams;
@ -325,11 +321,6 @@ private:
static const int CIRCLE_POINTS = 64; ///< The number of points for circle approximation
static const int CURVE_POINTS = 32; ///< The number of points for curve approximation
static const double MITER_LIMIT = 1.5; ///< Limit for mitered edges ( * lineWidth )
/// This factor is used to for correct merging of antialiased edges,
/// a very small value is required
static const double DEPTH_ADJUST_FACTOR = ( 1.0 / (1 << 23) );
wxClientDC* clientDC; ///< Drawing context
wxGLContext* glContext; ///< OpenGL context of wxWidgets
@ -338,43 +329,22 @@ private:
wxEvtHandler* paintListener;
// VBO buffered vertices for faster circle & semicircle drawing
VBO_CONTAINER precomputedContainer; ///< Container for storing display lists
VBO_ITEM verticesCircle; ///< Buffer for circle & semicircle vertices
NONCACHED_CONTAINER circleContainer; ///< Container for storing circle vertices
// Vertex buffer objects related fields
typedef boost::unordered_map<unsigned int, VBO_ITEM*> GroupsMap;
typedef std::map< unsigned int, boost::shared_ptr<VERTEX_ITEM> > GroupsMap;
GroupsMap groups; ///< Stores informations about VBO objects (groups)
unsigned int groupCounter; ///< Counter used for generating keys for groups
VBO_ITEM* currentItem; ///< Currently used VBO_ITEM (for grouping)
VBO_CONTAINER* currentContainer; ///< Currently used VBO_CONTAINER (for storing VBO_ITEMs)
VBO_CONTAINER cachedVbo; ///< Container for storing VBO_ITEMs
GLuint cachedVerts; ///< Currently used vertices VBO handle
GLuint cachedInds; ///< Currently used indices VBO handle
bool vboNeedsUpdate; ///< Flag indicating if VBO should be rebuilt
VBO_CONTAINER nonCachedVbo; ///< Container for storing non-cached VBO_ITEMs
VBO_ITEM* nonCachedItem; ///< Item that is gathering non-cached vertices
glm::mat4 transform; ///< Current transformation matrix
std::stack<glm::mat4> transformStack; ///< Stack of transformation matrices
int indicesSize; ///< Number of indices to be drawn
GLuint* indicesPtr; ///< Pointer to mapped GPU memory
VERTEX_MANAGER* currentManager; ///< Currently used VERTEX_MANAGER (for storing VERTEX_ITEMs)
VERTEX_MANAGER cachedManager; ///< Container for storing cached VERTEX_ITEMs
VERTEX_MANAGER nonCachedManager; ///< Container for storing non-cached VERTEX_ITEMs
// Polygon tesselation
GLUtesselator* tesselator; ///< Pointer to the tesselator
GLUtesselator* tesselator; ///< Pointer to the tesselator
std::vector<GLdouble*> tessIntersects; ///< Storage of intersecting points
// Shader
// Possible types of shaders
typedef enum
{
SHADER_NONE = 0,
SHADER_LINE,
SHADER_FILLED_CIRCLE,
SHADER_STROKED_CIRCLE,
} SHADER_TYPE;
SHADER shader; ///< There is only one shader used for different objects
int shaderAttrib; ///< Location of shader attributes (for glVertexAttribPointer)
// Cursor
int cursorSize; ///< Size of the cursor in pixels
@ -394,7 +364,6 @@ private:
// Internal flags
bool isGlewInitialized; ///< Is GLEW initialized?
bool isFrameBufferInitialized; ///< Are the frame buffers initialized?
bool isVboInitialized;
bool isShaderInitialized; ///< Was the shader initialized?
bool isUseShader; ///< Should the shaders be used?
bool isGrouping; ///< Was a group started?
@ -430,8 +399,8 @@ private:
*/
void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
/// Compute the points of an unit circle & semicircle and store them in VBO.
void computeCircleVbo();
/// Compute the points of the unit circle and store them in VBO.
void computeCircle();
// Event handling
/**
@ -493,22 +462,6 @@ private:
*/
void deleteFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer, GLuint* aTexture );
/**
* @brief Initializes everything needed to use vertex buffer objects.
*/
void initVertexBufferObjects();
/**
* @brief Deinitializes everything when vertex buffer objects are not used anymore.
*/
void deleteVertexBufferObjects();
/**
* @brief Rebuilds vertex buffer object using stored VBO_ITEMS and sends it to
* the graphics card memory.
*/
void rebuildVbo();
/**
* @brief Draw a quad for the line.
*
@ -518,76 +471,11 @@ private:
inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
/**
* @brief Returns a valid key that can be used as a group number.
* @brief Returns a valid key that can be used as a new group number.
*
* @return An unique group number that is not used by any other group.
*/
unsigned int getGroupNumber();
/**
* @brief Adds vertex to the current item or draws it in immediate mode.
* @param aX is X coordinate.
* @param aY is Y coordinate.
* @param aZ is Z coordinate.
*/
inline void vertex3( double aX, double aY, double aZ )
{
// New vertex coordinates for VBO
const VBO_VERTEX vertex = { aX, aY, aZ };
currentItem->PushVertex( &vertex );
}
/**
* @brief Function that replaces glTranslate. It modifies transformation matrix.
*
* @param aX is translation in X axis direction.
* @param aY is translation in Y axis direction.
* @param aZ is translation in Z axis direction.
*/
inline void translate3( double aX, double aY, double aZ )
{
transform = glm::translate( transform, glm::vec3( aX, aY, aZ ) );
}
/**
* @brief Function that replaces glColor. It modifies color used by current VBO_ITEM.
*
* @param aR is red component.
* @param aG is green component.
* @param aB is blue component.
* @param aA is alpha component.
*/
inline void color4( double aRed, double aGreen, double aBlue, double aAlpha )
{
currentContainer->UseColor( aRed, aGreen, aBlue, aAlpha );
}
/**
* @brief Function that replaces glColor. It modifies color used by current VBO_ITEM.
*
* @param aColor is the new color.
*/
inline void color4( const COLOR4D& aColor )
{
currentContainer->UseColor( aColor );
}
/**
* @brief Function that sets shader and its parameters for the currently used VBO_ITEM.
* It should be used before adding any vertices that have to be shaded.
* @param aShader is the type of shader used for vertices.
* @param aParam[1..3] are shader's parameters. Their meaning depends on the type of used shader.
* For more information you may check shaders' source code.
*/
inline void setShader( SHADER_TYPE aShader, GLfloat aParam1 = 0.0f,
GLfloat aParam2 = 0.0f, GLfloat aParam3 = 0.0f )
{
if( isUseShader )
{
const GLfloat shader[] = { aShader, aParam1, aParam2, aParam3 };
currentContainer->UseShader( shader );
}
}
unsigned int getNewGroupNumber();
};
} // namespace KiGfx

View File

@ -1,344 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vbo_container.h
* @brief Class to store VBO_ITEMs.
*/
#ifndef VBO_CONTAINER_H_
#define VBO_CONTAINER_H_
#include <GL/gl.h>
#include <gal/opengl/glm/glm.hpp>
#include <gal/opengl/vbo_item.h>
#include <gal/color4d.h>
#include <map>
#include <set>
namespace KiGfx
{
class VBO_ITEM;
typedef struct VBO_VERTEX VBO_VERTEX;
class VBO_CONTAINER
{
public:
VBO_CONTAINER( unsigned int aSize = defaultInitSize );
virtual ~VBO_CONTAINER();
///< Maps size of free memory chunks to their offsets
typedef std::pair<const unsigned int, unsigned int> Chunk;
typedef std::multimap<const unsigned int, unsigned int> FreeChunkMap;
/// List of all the stored items
typedef std::set<VBO_ITEM*> Items;
/**
* Function StartItem()
* Sets an item to start its modifications. After calling the function it is possible to add
* vertices using function Add().
* @param aItem is the item that is going to store vertices in the container.
*/
void StartItem( VBO_ITEM* aItem );
/**
* Function EndItem()
* Marks current item as finished and returns unused memory to the pool. StartItem() function
* has to be called first.
*/
void EndItem();
/**
* Function Add()
* Stores given number of vertices in the container for the specific VBO_ITEM (started by
* StartItem() function).
* @param aItem is the owner of the vertices.
* @param aVertex are vertices data to be stored.
* @param aSize is the number of vertices to be added.
*/
void Add( const VBO_VERTEX* aVertex, unsigned int aSize = 1 );
/**
* Function Free()
* Frees the chunk reserved by the aItem.
* @param aItem is the owner of the chunk to be freed.
*/
void Free( VBO_ITEM* aItem );
/**
* Function Clear()
* Removes all the data stored in the container.
*/
void Clear();
/**
* Function GetAllVertices()
* Returns all vertices stored in the container. It is especially useful for transferring
* data to the GPU memory.
*/
VBO_VERTEX* GetAllVertices() const;
/**
* Function GetVertices()
* Returns vertices stored by the specific item.
* @aItem is the specific item.
*/
VBO_VERTEX* GetVertices( const VBO_ITEM* aItem ) const;
/**
* Function GetVertices()
* Returns vertices stored at the specific offset.
* @aOffset is the specific offset.
*/
inline VBO_VERTEX* GetVertices( unsigned int aOffset ) const
{
return &m_vertices[aOffset];
}
/**
* Function GetSize()
* Returns amount of vertices currently stored in the container.
*/
inline int GetSize() const
{
return m_currentSize;
}
/**
* Function SetTransformMatrix()
* Sets transformation matrix for vertices that are added to VBO_ITEM. If you do not want to
* transform vertices at all, pass NULL as the argument.
* @param aMatrix is the new transform matrix or NULL if you do not want to use transformation
* matrix.
*/
inline void SetTransformMatrix( const glm::mat4* aMatrix )
{
m_transform = aMatrix;
}
/**
* Function UseColor()
* Sets color used for all added vertices.
* @param aColor is the color used for added vertices.
*/
inline void UseColor( const COLOR4D& aColor )
{
m_color[0] = aColor.r * 255;
m_color[1] = aColor.g * 255;
m_color[2] = aColor.b * 255;
m_color[3] = aColor.a * 255;
}
/**
* Function UseColor()
* Sets color used for all added vertices.
* @param aColor is the color used for added vertices.
*/
inline void UseColor( const GLfloat aColor[VBO_ITEM::ColorStride] )
{
for( unsigned int i = 0; i < VBO_ITEM::ColorStride; ++i )
{
m_color[i] = aColor[i] * 255;
}
}
/**
* Function UseColor()
* Sets color used for all added vertices.
* @param aR is the red component of the color.
* @param aG is the green component of the color.
* @param aB is the blue component of the color.
* @param aA is the alpha component of the color.
*/
inline void UseColor( GLfloat aR, GLfloat aG, GLfloat aB, GLfloat aA )
{
m_color[0] = aR * 255;
m_color[1] = aG * 255;
m_color[2] = aB * 255;
m_color[3] = aA * 255;
}
/**
* Function UseShader()
* Sets shader and its parameters used for all added vertices.
* @param aShader is the array that contains shader number followed by its parameters.
*/
inline void UseShader( const GLfloat aShader[VBO_ITEM::ShaderStride] )
{
for( unsigned int i = 0; i < VBO_ITEM::ShaderStride; ++i )
{
m_shader[i] = aShader[i];
}
}
private:
///< Stores size & offset of free chunks.
FreeChunkMap m_freeChunks;
///< Stored VERTEX_ITEMs
Items m_items;
/**
* Function allocate()
* Allocates the given amount of memory for the current VBO_ITEM (set by StartItem() function).
* @param aSize is the number of vertices that are requested to be allocated.
* @return Pointer to the allocated space.
*/
VBO_VERTEX* allocate( unsigned int aSize );
/**
* Function reallocate()
* Resizes the chunk that stores the current item to the given size.
* @param aSize is the number of vertices to be stored.
* @return Offset of the new chunk.
*/
unsigned int reallocate( unsigned int aSize );
/**
* Function getChunkSize()
* Returns size of the given chunk.
* @param aChunk is the chunk.
* @return Size of the chunk.
*/
inline unsigned int getChunkSize( const Chunk& aChunk ) const
{
return aChunk.first;
}
/**
* Function getChunkOffset()
* Returns offset of the given chunk.
* @param aChunk is the chunk.
* @return Offset of the chunk.
*/
inline unsigned int getChunkOffset( const Chunk& aChunk ) const
{
return aChunk.second;
}
/**
* Function setChunkOffset()
* Updates offset of the given chunk.
* !! IMPORTANT: it does not reallocate the chunk, it just changes its properties.
* @param aChunk is the chunk.
*/
inline void setChunkOffset( Chunk& aChunk, unsigned int aOffset ) const
{
aChunk.second = aOffset;
}
/**
* 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.
* @return false in case of failure (eg. memory shortage).
*/
bool defragment( VBO_VERTEX* aTarget = NULL );
/**
* Function mergeFreeChunks()
* Looks for consecutive free memory chunks and merges them, decreasing fragmentation of
* memory.
*/
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).
*/
bool resizeContainer( unsigned int aNewSize );
/**
* Function freeItem()
* Frees the space occupied by the item and returns it to the free space pool.
* @param aItem is the item to be freed.
*/
void freeItem( VBO_ITEM* aItem );
/**
* Function reservedSpace()
* Returns size of the reserved memory space.
* @return Size of the reserved memory space (expressed as a number of vertices).
*/
unsigned int reservedSpace()
{
return m_currentSize - m_freeSpace;
}
///< How many vertices we can store in the container
unsigned int m_freeSpace;
///< How big is the current container, expressed in vertices
unsigned int m_currentSize;
///< Actual storage memory
VBO_VERTEX* m_vertices;
///< Initial size, used on clearing the container
unsigned int m_initialSize;
///< Variables holding the state of the item currently being modified
unsigned int m_itemSize;
unsigned int m_chunkSize;
unsigned int m_chunkOffset;
VBO_ITEM* m_item;
///< Color used for the new vertices pushed.
GLubyte m_color[VBO_ITEM::ColorStride];
///< Shader and its parameters used for new vertices pushed
GLfloat m_shader[VBO_ITEM::ShaderStride];
///< Current transform matrix applied for every new vertex pushed.
const glm::mat4* m_transform;
///< Failure flag
bool m_failed;
/**
* Function getPowerOf2()
* Returns the nearest power of 2, bigger than aNumber.
* @param aNumber is the number for which we look for a bigger power of 2.
*/
unsigned int getPowerOf2( unsigned int aNumber ) const
{
unsigned int power = 1;
while( power < aNumber && power )
power <<= 1;
return power;
}
///< Default initial size of a container (expressed in vertices)
static const unsigned int defaultInitSize = 1048576;
///< Basic tests for the container, use only for debugging.
void test() const;
};
} // namespace KiGfx
#endif /* VBO_CONTAINER_H_ */

View File

@ -1,177 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vbo_item.h
* @brief Class to handle an item held in a Vertex Buffer Object.
*/
#ifndef VBO_ITEM_H_
#define VBO_ITEM_H_
#include <GL/gl.h>
#include <gal/color4d.h>
#include <cstddef>
namespace KiGfx
{
typedef struct VBO_VERTEX
{
GLfloat x, y, z; // Coordinates
GLubyte r, g, b, a; // Color
GLfloat shader[4]; // Shader type & params
} VBO_VERTEX;
class VBO_CONTAINER;
class VBO_ITEM
{
friend class VBO_CONTAINER;
public:
VBO_ITEM( VBO_CONTAINER* aContainer );
~VBO_ITEM();
/**
* Function PushVertex()
* Adds a single vertex to the VBO_ITEM. Vertex contains information about coordinates and
* colors and has to follow the specified format {X,Y,Z,R,G,B,A}.
* @param aVertex is a vertex to be added.
* @param aShader is an attribute for shader.
*/
void PushVertex( const VBO_VERTEX* aVertex );
/**
* Function PushVertices()
* Adds multiple vertices to the VBO_ITEM. This function is recommended over multiple calls to
* PushVertex, as it does less memory reallocations. Vertices contain information about
* coordinates and colors and has to follow the specified format {X,Y,Z,R,G,B,A}.
* @param aVertices are vertices to be added.
* @param aSize is an amount of vertices to be added.
* @param aShader is an attribute for shader.
*/
void PushVertices( const VBO_VERTEX* aVertices, GLuint aSize );
/**
* Function GetVertices()
* Returns a pointer to the array containing all vertices.
* @return Pointer to vertices packed in format {X, Y, Z, R, G, B, A}.
*/
VBO_VERTEX* GetVertices();
/**
* Function GetSize()
* Returns information about number of vertices stored.
* @param Amount of vertices.
*/
inline unsigned int GetSize() const
{
return m_size;
}
/**
* Function GetOffset()
* Returns data offset in the VBO.
* @return Data offset expressed as a number of vertices.
*/
inline unsigned int GetOffset() const
{
return m_offset;
}
/**
* Function ChangeColor()
* Colors all vertices to the specified color.
* @param aColor is the new color for vertices.
*/
void ChangeColor( const COLOR4D& aColor );
/**
* Function ChangeDepth()
* Moves all vertices to the specified depth.
* @param aDepth is the new depth for vertices.
*/
void ChangeDepth( int aDepth );
///< Informs the container that there will be no more vertices for the current VBO_ITEM
void Finish();
///< Data structure for vertices {X,Y,Z,R,G,B,A,shader&param} (@see VBO_VERTEX).
static const unsigned int VertByteSize = sizeof(VBO_VERTEX);
static const unsigned int VertStride = VertByteSize / sizeof(GLfloat);
static const unsigned int CoordByteSize = sizeof(VBO_VERTEX().x) + sizeof(VBO_VERTEX().y) +
sizeof(VBO_VERTEX().z);
static const unsigned int CoordStride = CoordByteSize / sizeof(GLfloat);
// Offset of color data from the beginning of each vertex data
static const unsigned int ColorByteOffset = offsetof(VBO_VERTEX, r);
static const unsigned int ColorOffset = ColorByteOffset / sizeof(GLubyte);
static const unsigned int ColorByteSize = sizeof(VBO_VERTEX().r) + sizeof(VBO_VERTEX().g) +
sizeof(VBO_VERTEX().b) + sizeof(VBO_VERTEX().a);
static const unsigned int ColorStride = ColorByteSize / sizeof(GLubyte);
// Shader attributes
static const unsigned int ShaderByteOffset = offsetof(VBO_VERTEX, shader);
static const unsigned int ShaderOffset = ShaderByteOffset / sizeof(GLfloat);
static const unsigned int ShaderByteSize = sizeof(VBO_VERTEX().shader);
static const unsigned int ShaderStride = ShaderByteSize / sizeof(GLfloat);
static const unsigned int IndByteSize = sizeof(GLuint);
protected:
///< Offset and size of data stored in the VBO_CONTAINER.
unsigned int m_offset;
unsigned int m_size;
///< Storage for vertices.
VBO_CONTAINER* m_container;
///< Flag telling if the item should be recached in VBO or not.
bool m_isDirty;
/**
* Function setSize()
* Sets data size in the VBO.
* @param aSize is the size expressed as a number of vertices.
*/
void setSize( unsigned int aSize )
{
m_size = aSize;
}
/**
* Function setOffset()
* Sets data offset in the VBO.
* @param aOffset is the offset expressed as a number of vertices.
*/
inline void setOffset( unsigned int aOffset )
{
m_offset = aOffset;
}
};
} // namespace KiGfx
#endif /* VBO_ITEM_H_ */

View File

@ -0,0 +1,75 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vertex_common.h
* @brief Common defines and consts used in vertex related classes.
*/
#ifndef VERTEX_COMMON_H_
#define VERTEX_COMMON_H_
#include <GL/glew.h>
namespace KiGfx
{
// Possible types of shaders
enum SHADER_TYPE
{
SHADER_NONE = 0,
SHADER_LINE,
SHADER_FILLED_CIRCLE,
SHADER_STROKED_CIRCLE,
};
typedef struct VERTEX
{
GLfloat x, y, z; // Coordinates
GLubyte r, g, b, a; // Color
GLfloat shader[4]; // Shader type & params
} VERTEX;
///< Data structure for vertices {X,Y,Z,R,G,B,A,shader&param} (@see VERTEX).
const unsigned int VertexSize = sizeof(VERTEX);
const unsigned int VertexStride = VertexSize / sizeof(GLfloat);
const unsigned int CoordSize = sizeof(VERTEX().x) + sizeof(VERTEX().y) + sizeof(VERTEX().z);
const unsigned int CoordStride = CoordSize / sizeof(GLfloat);
// Offset of color data from the beginning of each vertex data
const unsigned int ColorOffset = offsetof(VERTEX, r);
const unsigned int ColorSize = sizeof(VERTEX().r) + sizeof(VERTEX().g) +
sizeof(VERTEX().b) + sizeof(VERTEX().a);
const unsigned int ColorStride = ColorSize / sizeof(GLubyte);
// Shader attributes
const unsigned int ShaderOffset = offsetof(VERTEX, shader);
const unsigned int ShaderSize = sizeof(VERTEX().shader);
const unsigned int ShaderStride = ShaderSize / sizeof(GLfloat);
const unsigned int IndexSize = sizeof(GLuint);
} // namespace KiGfx
#endif /* VERTEX_COMMON_H_ */

View File

@ -0,0 +1,158 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vertex_container.h
* @brief Class to store vertices and handle transfers between system memory and GPU memory.
*/
#ifndef VERTEX_CONTAINER_H_
#define VERTEX_CONTAINER_H_
#include <gal/opengl/vertex_common.h>
namespace KiGfx
{
class VERTEX;
class VERTEX_ITEM;
class SHADER;
class VERTEX_CONTAINER
{
public:
/**
* Function MakeContainer()
* Returns a pointer to a new container of an appropriate type.
*/
static VERTEX_CONTAINER* MakeContainer( bool aCached );
virtual ~VERTEX_CONTAINER();
/**
* Function SetItem()
* sets the item in order to modify or finishes its current modifications.
* @param aItem is the item or NULL in case of finishing the item.
*/
virtual void SetItem( VERTEX_ITEM* aItem ) = 0;
/**
* Function Allocate()
* returns allocated space (possibly resizing the reserved memory chunk or allocating a new
* chunk if it was not stored before) for the given number of vertices associated with the
* current item (set by SetItem()). The newly allocated space is added at the end of the chunk
* used by the current item and may serve to store new vertices.
* @param aSize is the number of vertices to be allocated.
* @return Pointer to the allocated space or NULL in case of failure.
*/
virtual VERTEX* Allocate( unsigned int aSize ) = 0;
/**
* Function Erase()
* erases all vertices associated with the current item (set by SetItem()).
*/
virtual void Erase() = 0;
/**
* Function Clear()
* removes all the data stored in the container and restores its original state.
*/
virtual void Clear() = 0;
/**
* Function GetAllVertices()
* returns all the vertices stored in the container. It is especially useful for transferring
* data to the GPU memory.
*/
inline virtual VERTEX* GetAllVertices() const
{
return m_vertices;
}
/**
* Function GetVertices()
* returns vertices stored at the specific offset.
* @aOffset is the offset.
*/
virtual inline VERTEX* GetVertices( unsigned int aOffset ) const
{
return &m_vertices[aOffset];
}
/**
* Function GetSize()
* returns amount of vertices currently stored in the container.
*/
virtual inline unsigned int GetSize() const
{
return m_currentSize;
}
/**
* Function IsDirty()
* returns information about container cache state. Clears the flag after calling the function.
* @return true in case the vertices have to be reuploaded.
*/
inline bool isDirty()
{
bool state = m_dirty;
m_dirty = false;
return state;
}
protected:
VERTEX_CONTAINER( unsigned int aSize = defaultInitSize );
///< How many vertices we can store in the container
unsigned int m_freeSpace;
///< How big is the current container, expressed in vertices
unsigned int m_currentSize;
///< Store the initial size, so it can be resized to this on Clear()
unsigned int m_initialSize;
///< Actual storage memory (should be handled using malloc/realloc/free to speed up resizing)
VERTEX* m_vertices;
///< State flags
bool m_failed;
bool m_dirty;
/**
* Function reservedSpace()
* returns size of the reserved memory space.
* @return Size of the reserved memory space (expressed as a number of vertices).
*/
unsigned int reservedSpace()
{
return m_currentSize - m_freeSpace;
}
///< Default initial size of a container (expressed in vertices)
static const unsigned int defaultInitSize = 1048576;
};
} // namespace KiGfx
#endif /* VERTEX_CONTAINER_H_ */

View File

@ -0,0 +1,103 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vertex_item.h
* @brief Class to handle an item held in a container.
*/
#ifndef VERTEX_ITEM_H_
#define VERTEX_ITEM_H_
#include <gal/opengl/vertex_common.h>
#include <gal/color4d.h>
#include <cstddef>
namespace KiGfx
{
class VERTEX_MANAGER;
class VERTEX_ITEM
{
public:
friend class CACHED_CONTAINER;
friend class VERTEX_MANAGER;
VERTEX_ITEM( const VERTEX_MANAGER& aManager );
virtual ~VERTEX_ITEM();
/**
* Function GetSize()
* Returns information about number of vertices stored.
* @param Number of vertices.
*/
inline unsigned int GetSize() const
{
return m_size;
}
/**
* Function GetOffset()
* Returns data offset in the container.
* @return Data offset expressed as a number of vertices.
*/
inline unsigned int GetOffset() const
{
return m_offset;
}
/**
* Function GetVertices()
* Returns pointer to the data used by the VERTEX_ITEM.
*/
VERTEX* GetVertices() const;
private:
const VERTEX_MANAGER& m_manager;
unsigned int m_offset;
unsigned int m_size;
/**
* Function SetOffset()
* Sets data offset in the container.
* @param aOffset is the offset expressed as a number of vertices.
*/
inline void setOffset( unsigned int aOffset )
{
m_offset = aOffset;
}
/**
* Function SetSize()
* Sets data size in the container.
* @param aSize is the size expressed as a number of vertices.
*/
inline void setSize( unsigned int aSize )
{
m_size = aSize;
}
};
} // namespace KiGfx
#endif /* VERTEX_ITEM_H_ */

View File

@ -0,0 +1,341 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vertex_manager.h
* @brief Class to control vertex container and GPU with possibility of emulating old-style OpenGL
* 1.0 state machine using modern OpenGL methods.
*/
#ifndef VERTEX_MANAGER_H_
#define VERTEX_MANAGER_H_
#define GLM_FORCE_RADIANS
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
#include <gal/opengl/glm/glm.hpp>
#include <gal/opengl/vertex_common.h>
#include <gal/color4d.h>
#include <stack>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <wx/log.h>
namespace KiGfx
{
class SHADER;
class VERTEX_ITEM;
class VERTEX_CONTAINER;
class GPU_MANAGER;
class VERTEX_MANAGER
{
public:
/**
* @brief Constructor.
*
* @param aCached says if vertices should be cached in GPU or system memory. For data that
* does not change every frame, it is better to store vertices in GPU memory.
*/
VERTEX_MANAGER( bool aCached );
/**
* Function Vertex()
* adds a vertex with the given coordinates to the currently set item. Color & shader
* parameters stored in aVertex are ignored, instead color & shader set by Color() and
* Shader() functions are used. Vertex coordinates will have the current transformation
* matrix applied.
*
* @param aVertex contains vertex coordinates.
*/
inline void Vertex( const VERTEX& aVertex ) const
{
Vertex( aVertex.x, aVertex.y, aVertex.z );
}
/**
* Function Vertex()
* adds a vertex with the given coordinates to the currently set item. Vertex coordinates will
* have the current transformation matrix applied.
*
* @param aX is the X coordinate of the new vertex.
* @param aY is the Y coordinate of the new vertex.
* @param aZ is the Z coordinate of the new vertex.
*/
void Vertex( GLfloat aX, GLfloat aY, GLfloat aZ ) const;
/**
* Function Vertices()
* adds one or more vertices to the currently set item. It takes advantage of allocating memory
* in advance, so should be faster than adding vertices one by one. Color & shader
* parameters stored in aVertices are ignored, instead color & shader set by Color() and
* Shader() functions are used. All the vertex coordinates will have the current
* transformation matrix applied.
*
* @param aVertices contains vertices to be added
* @param aSize is the number of vertices to be added.
*/
void Vertices( const VERTEX aVertices[], unsigned int aSize ) const;
/**
* Function Color()
* changes currently used color that will be applied to newly added vertices.
*
* @param aColor is the new color.
*/
inline void Color( const COLOR4D& aColor )
{
m_color[0] = aColor.r * 255.0;
m_color[1] = aColor.g * 255.0;
m_color[2] = aColor.b * 255.0;
m_color[3] = aColor.a * 255.0;
}
/**
* Function Color()
* changes currently used color that will be applied to newly added vertices. It is the
* equivalent of glColor4f() function.
* @param aRed is the red component of the new color.
* @param aGreen is the green component of the new color.
* @param aBlue is the blue component of the new color.
* @param aAlpha is the alpha component of the new color.
*/
inline void Color( GLfloat aRed, GLfloat aGreen, GLfloat aBlue, GLfloat aAlpha )
{
m_color[0] = aRed * 255.0;
m_color[1] = aGreen * 255.0;
m_color[2] = aBlue * 255.0;
m_color[3] = aAlpha * 255.0;
}
/**
* Function Shader()
* changes currently used shader and its parameters that will be applied to newly added
* vertices. Parameters depend on shader, for more information have a look at shaders source
* code.
* @see SHADER_TYPE
*
* @param aShaderType is the a shader type to be applied.
* @param aParam1 is the optional parameter for a shader.
* @param aParam2 is the optional parameter for a shader.
* @param aParam3 is the optional parameter for a shader.
*/
inline void Shader( GLfloat aShaderType, GLfloat aParam1 = 0.0f,
GLfloat aParam2 = 0.0f, GLfloat aParam3 = 0.0f )
{
m_shader[0] = aShaderType;
m_shader[1] = aParam1;
m_shader[2] = aParam2;
m_shader[3] = aParam3;
}
/**
* Function Translate()
* multiplies the current matrix by a translation matrix, so newly vertices will be
* translated by the given vector. It is the equivalent of the glTranslatef() function.
*
* @param aX is the X coordinate of a translation vector.
* @param aY is the X coordinate of a translation vector.
* @param aZ is the X coordinate of a translation vector.
*/
inline void Translate( GLfloat aX, GLfloat aY, GLfloat aZ )
{
m_transform = glm::translate( m_transform, glm::vec3( aX, aY, aZ ) );
}
/**
* Function Rotate()
* multiplies the current matrix by a rotation matrix, so the newly vertices will be
* rotated by the given angles. It is the equivalent of the glRotatef() function.
*
* @param aAngle is the angle of rotation, in radians.
* @param aX is a multiplier for the X axis
* @param aY is a multiplier for the Y axis
* @param aZ is a multiplier for the Z axis.
*/
inline void Rotate( GLfloat aAngle, GLfloat aX, GLfloat aY, GLfloat aZ )
{
m_transform = glm::rotate( m_transform, aAngle, glm::vec3( aX, aY, aZ ) );
}
/**
* Function Scale()
* multiplies the current matrix by a scaling matrix, so the newly vertices will be
* scaled by the given factors. It is the equivalent of the glScalef() function.
*
* @param aX is the X axis scaling factor.
* @param aY is the Y axis scaling factor.
* @param aZ is the Z axis scaling factor.
*/
inline void Scale( GLfloat aX, GLfloat aY, GLfloat aZ )
{
m_transform = glm::scale( m_transform, glm::vec3( aX, aY, aZ ) );
}
/**
* Function PushMatrix()
* pushes the current transformation matrix stack. It is the equivalent of the glPushMatrix()
* function.
*/
inline void PushMatrix()
{
m_transformStack.push( m_transform );
// Every transformation starts with PushMatrix
m_noTransform = false;
}
/**
* Function PopMatrix()
* pops the current transformation matrix stack. It is the equivalent of the glPopMatrix()
* function.
*/
void PopMatrix()
{
wxASSERT( !m_transformStack.empty() );
m_transform = m_transformStack.top();
m_transformStack.pop();
if( m_transformStack.empty() )
{
// We return back to the identity matrix, thus no vertex transformation is needed
m_noTransform = true;
}
}
/**
* Function SetItem()
* sets an item to start its modifications. After calling the function it is possible to add
* vertices using function Add().
*
* @param aItem is the item that is going to store vertices in the container.
*/
void SetItem( VERTEX_ITEM& aItem ) const;
/**
* Function FreeItem()
* frees the memory occupied by the item, so it is no longer stored in the container.
*
* @param aItem is the item to be freed
*/
void FreeItem( VERTEX_ITEM& aItem ) const;
/**
* Function ChangeItemColor()
* changes the color of all vertices owned by an item.
*
* @param aItem is the item to change.
* @param aColor is the new color to be applied.
*/
void ChangeItemColor( const VERTEX_ITEM& aItem, const COLOR4D& aColor ) const;
/**
* Function ChangeItemDepth()
* changes the depth of all vertices owned by an item.
*
* @param aItem is the item to change.
* @param aDepth is the new color to be applied.
*/
void ChangeItemDepth( const VERTEX_ITEM& aItem, GLfloat aDepth ) const;
/**
* Function GetVertices()
* returns a pointer to the vertices owned by an item.
*
* @param aItem is the owner of vertices that are going to be returned.
* @return Pointer to the vertices or NULL if the item is not stored at the container.
*/
VERTEX* GetVertices( const VERTEX_ITEM& aItem ) const;
const glm::mat4& GetTransformation() const
{
return m_transform;
}
/**
* Function SetShader()
* sets a shader program that is going to be used during rendering.
* @param aShader is the object containing compiled and linked shader program.
*/
void SetShader( SHADER& aShader ) const;
/**
* Function Clear()
* removes all the stored vertices from the container.
*/
void Clear() const;
/**
* Function BeginDrawing()
* prepares buffers and items to start drawing.
*/
void BeginDrawing() const;
/**
* Function DrawItem()
* draws an item to the buffer.
*
* @param aItem is the item to be drawn.
*/
void DrawItem( const VERTEX_ITEM& aItem ) const;
/**
* Function EndDrawing()
* finishes drawing operations.
*/
void EndDrawing() const;
protected:
/**
* Function putVertex()
* applies all transformation to the given coordinates and store them at the specified target.
*
* @param aTarget is the place where the new vertex is going to be stored (it has to be
* allocated first).
* @param aX is the X coordinate of the new vertex.
* @param aY is the Y coordinate of the new vertex.
* @param aZ is the Z coordinate of the new vertex.
*/
void putVertex( VERTEX& aTarget, GLfloat aX, GLfloat aY, GLfloat aZ ) const;
/// Container for vertices, may be cached or noncached
boost::shared_ptr<VERTEX_CONTAINER> m_container;
/// GPU manager for data transfers and drawing operations
boost::shared_ptr<GPU_MANAGER> m_gpu;
/// State machine variables
/// True in case there is no need to transform vertices
bool m_noTransform;
/// Currently used transform matrix
glm::mat4 m_transform;
/// Stack of transformation matrices, used for Push/PopMatrix
std::stack<glm::mat4> m_transformStack;
/// Currently used color
GLubyte m_color[ColorStride];
/// Currently used shader and its parameters
GLfloat m_shader[ShaderStride];
};
} // namespace KiGfx
#endif /* VERTEX_MANAGER_H_ */