Code refactorization. VBO_CONTAINER is split to [NON]CACHED_MANAGER, GPU_MANAGER and VERTEX_MANAGER.
This commit is contained in:
parent
4d7db7171c
commit
5242fff9d7
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 */
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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_ */
|
|
@ -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¶m} (@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_ */
|
|
@ -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¶m} (@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_ */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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_ */
|
Loading…
Reference in New Issue