diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index c66397b78f..c68ea182dc 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -511,6 +511,7 @@ void OPENGL_GAL::rebuildVbo() // Upload vertices coordinates and indices to GPU memory glBindBuffer( GL_ARRAY_BUFFER, curVboVertId ); glBufferData( GL_ARRAY_BUFFER, vboSize * VBO_ITEM::VertSize, verticesBuffer, GL_DYNAMIC_DRAW ); + glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, curVboIndId ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, vboSize * VBO_ITEM::IndSize, diff --git a/common/gal/opengl/vbo_item.cpp b/common/gal/opengl/vbo_item.cpp index c44e32a056..8778780f59 100644 --- a/common/gal/opengl/vbo_item.cpp +++ b/common/gal/opengl/vbo_item.cpp @@ -40,11 +40,25 @@ VBO_ITEM::VBO_ITEM() : m_isDirty( true ), m_transform( NULL ) { + // Prepare a block for storing vertices & indices + useNewBlock(); } VBO_ITEM::~VBO_ITEM() { + if( m_isDirty ) + { + // Data is still stored in blocks + std::list::const_iterator v_it, v_end; + for( v_it = m_vertBlocks.begin(), v_end = m_vertBlocks.end(); v_it != v_end; ++v_it ) + delete[] *v_it; + + std::list::const_iterator i_it, i_end; + for( i_it = m_indBlocks.begin(), i_end = m_indBlocks.end(); i_it != i_end; ++i_it ) + delete[] *i_it; + } + if( m_vertices ) delete m_vertices; @@ -55,20 +69,11 @@ VBO_ITEM::~VBO_ITEM() void VBO_ITEM::PushVertex( const GLfloat* aVertex ) { - GLfloat* newVertices = new GLfloat[( m_size + 1 ) * VertStride]; - GLuint* newIndices = new GLuint[( m_size + 1 ) * IndStride]; - - // Handle a new vertex - if( m_vertices ) - { - // Copy all previous vertices data - memcpy( newVertices, m_vertices, m_size * VertSize ); - delete m_vertices; - } - m_vertices = newVertices; + if( m_spaceLeft == 0 ) + useNewBlock(); // Add the new vertex - memcpy( &newVertices[m_size * VertStride], aVertex, VertSize ); + memcpy( m_vertPtr, aVertex, VertSize ); if( m_transform != NULL ) { @@ -78,89 +83,45 @@ void VBO_ITEM::PushVertex( const GLfloat* aVertex ) glm::vec4 transVertex = *m_transform * origVertex; // Replace only coordinates, leave color as it is - memcpy( &newVertices[m_size * VertStride], &transVertex[0], 3 * sizeof(GLfloat) ); + memcpy( m_vertPtr, &transVertex[0], 3 * sizeof(GLfloat) ); } - // Handle a new index - if( m_indices ) - { - // Copy all previous vertices data - memcpy( newIndices, m_indices, m_size * IndSize ); - delete m_indices; - } - m_indices = newIndices; + // Move to the next free space + m_vertPtr += VertStride; - // Add the new vertex - m_indices[m_size] = m_offset + m_size; + // Add the new index + *m_indPtr = m_offset + m_size; + m_indPtr++; m_size++; m_isDirty = true; + m_spaceLeft--; } void VBO_ITEM::PushVertices( const GLfloat* aVertices, GLuint aSize ) { - int newSize = m_size + aSize; - GLfloat* newVertices = new GLfloat[newSize * VertStride]; - GLuint* newIndices = new GLuint[newSize * IndStride]; - - // Handle new vertices - if( m_vertices ) + for( unsigned int i = 0; i < aSize; ++i ) { - // Copy all previous vertices data - memcpy( newVertices, m_vertices, ( m_size ) * VertSize ); - delete m_vertices; + PushVertex( &aVertices[i * VertStride] ); } - m_vertices = newVertices; - - // Add new vertices - memcpy( &newVertices[m_size * VertStride], aVertices, aSize * VertSize ); - - if( m_transform != NULL ) - { - const GLfloat* vertexPtr = aVertices; - - for( unsigned int i = 0; i < aSize; ++i ) - { - // Apply transformations - // X, Y, Z coordinates - glm::vec4 origVertex( vertexPtr[0], vertexPtr[1], vertexPtr[2], 1.0f ); - glm::vec4 transVertex = *m_transform * origVertex; - - // Replace only coordinates, leave color as it is - memcpy( &newVertices[(m_size + i) * VertStride], &transVertex[0], 3 * sizeof(GLfloat) ); - - // Move on to the next vertex - vertexPtr += VertStride; - } - } - - // Handle new indices - if( m_indices ) - { - // Copy all previous vertices data - memcpy( newIndices, m_indices, ( m_size ) * IndSize ); - delete m_indices; - } - m_indices = newIndices; - - // Add the new vertex - for( int i = m_size; i < newSize; ++i ) - m_indices[i] = m_offset + i; - - m_size += aSize; - m_isDirty = true; } -GLfloat* VBO_ITEM::GetVertices() const +GLfloat* VBO_ITEM::GetVertices() { + if( m_isDirty ) + prepareFinal(); + return m_vertices; } -GLuint* VBO_ITEM::GetIndices() const +GLuint* VBO_ITEM::GetIndices() { + if( m_isDirty ) + prepareFinal(); + return m_indices; } @@ -202,6 +163,9 @@ void VBO_ITEM::SetTransformMatrix( const glm::mat4* aMatrix ) void VBO_ITEM::ChangeColor( const COLOR4D& aColor ) { + if( m_isDirty ) + prepareFinal(); + // Point to color of vertices GLfloat* vertexPtr = m_vertices + ColorOffset; const GLfloat newColor[] = { aColor.r, aColor.g, aColor.b, aColor.a }; @@ -237,3 +201,64 @@ int GetVbo() const { } */ + + +void VBO_ITEM::useNewBlock() +{ + GLfloat* newVertBlock = new GLfloat[BLOCK_SIZE * VertStride]; + GLuint* newIndBlock = new GLuint[BLOCK_SIZE]; + + m_vertPtr = newVertBlock; + m_indPtr = newIndBlock; + + m_vertBlocks.push_back( newVertBlock ); + m_indBlocks.push_back( newIndBlock ); + + m_spaceLeft = BLOCK_SIZE; +} + + +void VBO_ITEM::prepareFinal() +{ + if( m_vertices ) + delete m_vertices; + + // Allocate memory that would store all of vertices + m_vertices = new GLfloat[m_size * VertStride]; + // Set the pointer that will move along the buffer + GLfloat* vertPtr = m_vertices; + + // Copy blocks of vertices one after another to m_vertices + std::list::const_iterator v_it; + for( v_it = m_vertBlocks.begin(); *v_it != m_vertBlocks.back(); ++v_it ) + { + memcpy( vertPtr, *v_it, BLOCK_SIZE * VertSize ); + delete[] *v_it; + vertPtr += ( BLOCK_SIZE * VertStride ); + } + + // In the last block we need to copy only used vertices + memcpy( vertPtr, *v_it, ( BLOCK_SIZE - m_spaceLeft ) * VertSize ); + + if( m_indices ) + delete m_indices; + + // Allocate memory that would store all of indices + m_indices = new GLuint[m_size * IndStride]; + // Set the pointer that will move along the buffer + GLuint* indPtr = m_indices; + + // Copy blocks of indices one after another to m_indices + std::list::const_iterator i_it; + for( i_it = m_indBlocks.begin(); *i_it != m_indBlocks.back(); ++i_it ) + { + memcpy( indPtr, *i_it, BLOCK_SIZE * IndSize ); + delete[] *i_it; + indPtr += ( BLOCK_SIZE * IndStride ); + } + + // In the last block we need to copy only used indices + memcpy( indPtr, *i_it, ( BLOCK_SIZE - m_spaceLeft ) * IndSize ); + + m_isDirty = false; +} diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h index 234a19c4ea..eb52a1ecf3 100644 --- a/include/gal/opengl/opengl_gal.h +++ b/include/gal/opengl/opengl_gal.h @@ -448,7 +448,6 @@ private: * @brief Blit the main texture to the screen. * * @param aIsClearFrameBuffer if true, the frame buffer is cleared as well. - * */ void blitMainTexture( bool aIsClearFrameBuffer ); @@ -485,7 +484,7 @@ private: /** * @brief Rebuilds vertex buffer object using stored VBO_ITEMS and sends it to - * the graphic card memory. + * the graphics card memory. */ void rebuildVbo(); @@ -529,6 +528,14 @@ private: * @param aA is alpha component. */ inline void color4( double aRed, double aGreen, double aBlue, double aAlpha ); + + /** + * @brief Function that replaces glColor and behaves according to isGrouping variable. + * In case isGrouping==false, it is simply glColor, in other case it + * modifies color used by current VBO_ITEM. + * + * @param aColor is the new color. + */ inline void color4( const COLOR4D& aColor ); inline void selectShader( int aIndex ); diff --git a/include/gal/opengl/vbo_item.h b/include/gal/opengl/vbo_item.h index 3fd97a33f6..a7592ab6be 100644 --- a/include/gal/opengl/vbo_item.h +++ b/include/gal/opengl/vbo_item.h @@ -27,8 +27,6 @@ * @brief Class to handle an item held in a Vertex Buffer Object. */ -// TODO comments - #ifndef VBO_ITEM_H_ #define VBO_ITEM_H_ @@ -36,6 +34,8 @@ #include #include +#include + namespace KiGfx { @@ -68,9 +68,14 @@ public: * Returns a pointer to the array containing all vertices. * @return Pointer to vertices packed in format {X, Y, Z, R, G, B, A}. */ - GLfloat* GetVertices() const; + GLfloat* GetVertices(); - GLuint* GetIndices() const; + /** + * Function GetIndices() + * Returns a pointer to the array containing all indices of vertices. + * @return Pointer to indices. + */ + GLuint* GetIndices(); /** * Function GetSize() @@ -120,7 +125,7 @@ public: //void SetVbo( int aVboId ); //int GetVbo() const; - ///< Data organization information for vertices. + ///< Data organization information for vertices {X,Y,Z,R,G,B,A}. // Each vertex consists of 7 floats static const int VertStride = 7; static const int VertSize = VertStride * sizeof(GLfloat); @@ -128,7 +133,7 @@ public: static const int IndStride = 1; static const int IndSize = IndStride * sizeof(GLuint); - // Offset of color data from the beginning of vertex data + // Offset of color data from the beginning of each vertex data static const int ColorOffset = 3; static const int ColorByteOffset = ColorOffset * sizeof(GLfloat); static const int ColorStride = 4; @@ -145,6 +150,21 @@ private: ///< Indices of vertices GLuint* m_indices; + ///< Lists of blocks + std::list m_vertBlocks; + std::list m_indBlocks; + ///< Pointers to current blocks that can be used for storing data + GLfloat* m_vertPtr; + GLuint* m_indPtr; + ///< How many vertices can be stored in the current buffer + int m_spaceLeft; + ///< Number of vertices & indices stored in a single block + static const int BLOCK_SIZE = 8; + ///< Creates a new block for storing vertices data + void useNewBlock(); + ///< Prepares a continuous block of data that can be copied to graphics card buffer. + void prepareFinal(); + ///< Offset and size of data in VBO. int m_offset; int m_size; diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 650cd53c7d..69e740fffc 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -168,7 +168,7 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard ) // Load zones for( int i = 0; i < m_Pcb->GetAreaCount(); ++i ) { - //view->Add( (KiGfx::VIEW_ITEM*) ( m_Pcb->GetArea( i ) ) ); + view->Add( (KiGfx::VIEW_ITEM*) ( m_Pcb->GetArea( i ) ) ); } // Load drawings