Fixes for video cards unable to use gl{Un,}MapBuffer correctly
Fixes: lp:1685335 * https://bugs.launchpad.net/kicad/+bug/1685335 Fixes: lp:1683041 * https://bugs.launchpad.net/kicad/+bug/1683041
This commit is contained in:
parent
46b5575c51
commit
262fcc91af
|
@ -49,6 +49,8 @@ set( GAL_SRCS
|
|||
gal/opengl/vertex_item.cpp
|
||||
gal/opengl/vertex_container.cpp
|
||||
gal/opengl/cached_container.cpp
|
||||
gal/opengl/cached_container_gpu.cpp
|
||||
gal/opengl/cached_container_ram.cpp
|
||||
gal/opengl/noncached_container.cpp
|
||||
gal/opengl/vertex_manager.cpp
|
||||
gal/opengl/gpu_manager.cpp
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright 2013-2017 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -32,10 +32,8 @@
|
|||
#include <gal/opengl/cached_container.h>
|
||||
#include <gal/opengl/vertex_manager.h>
|
||||
#include <gal/opengl/vertex_item.h>
|
||||
#include <gal/opengl/shader.h>
|
||||
#include <gal/opengl/utils.h>
|
||||
|
||||
#include <confirm.h>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
|
||||
|
@ -47,27 +45,13 @@
|
|||
using namespace KIGFX;
|
||||
|
||||
CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
|
||||
VERTEX_CONTAINER( aSize ), m_item( NULL ),
|
||||
m_chunkSize( 0 ), m_chunkOffset( 0 ), m_isMapped( false ),
|
||||
m_isInitialized( false ), m_glBufferHandle( -1 )
|
||||
VERTEX_CONTAINER( aSize ), m_item( NULL ), m_chunkSize( 0 ), m_chunkOffset( 0 )
|
||||
{
|
||||
// In the beginning there is only free space
|
||||
m_freeChunks.insert( std::make_pair( aSize, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
CACHED_CONTAINER::~CACHED_CONTAINER()
|
||||
{
|
||||
if( m_isMapped )
|
||||
Unmap();
|
||||
|
||||
if( m_isInitialized )
|
||||
{
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
|
||||
{
|
||||
assert( aItem != NULL );
|
||||
|
@ -75,7 +59,6 @@ void CACHED_CONTAINER::SetItem( VERTEX_ITEM* aItem )
|
|||
unsigned int itemSize = aItem->GetSize();
|
||||
m_item = aItem;
|
||||
m_chunkSize = itemSize;
|
||||
m_useCopyBuffer = GLEW_ARB_copy_buffer;
|
||||
|
||||
// Get the previously set offset if the item was stored previously
|
||||
m_chunkOffset = itemSize > 0 ? aItem->GetOffset() : -1;
|
||||
|
@ -120,7 +103,7 @@ void CACHED_CONTAINER::FinishItem()
|
|||
VERTEX* CACHED_CONTAINER::Allocate( unsigned int aSize )
|
||||
{
|
||||
assert( m_item != NULL );
|
||||
assert( m_isMapped );
|
||||
assert( IsMapped() );
|
||||
|
||||
if( m_failed )
|
||||
return NULL;
|
||||
|
@ -211,9 +194,7 @@ void CACHED_CONTAINER::Clear()
|
|||
// Set the size of all the stored VERTEX_ITEMs to 0, so it is clear that they are not held
|
||||
// in the container anymore
|
||||
for( ITEMS::iterator it = m_items.begin(); it != m_items.end(); ++it )
|
||||
{
|
||||
( *it )->setSize( 0 );
|
||||
}
|
||||
|
||||
m_items.clear();
|
||||
|
||||
|
@ -223,51 +204,10 @@ void CACHED_CONTAINER::Clear()
|
|||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::Map()
|
||||
{
|
||||
assert( !IsMapped() );
|
||||
|
||||
if( !m_isInitialized )
|
||||
init();
|
||||
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_glBufferHandle );
|
||||
m_vertices = static_cast<VERTEX*>( glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE ) );
|
||||
checkGlError( "mapping vertices buffer" );
|
||||
|
||||
m_isMapped = true;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::Unmap()
|
||||
{
|
||||
assert( IsMapped() );
|
||||
|
||||
glUnmapBuffer( GL_ARRAY_BUFFER );
|
||||
checkGlError( "unmapping vertices buffer" );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
m_vertices = NULL;
|
||||
checkGlError( "unbinding vertices buffer" );
|
||||
|
||||
m_isMapped = false;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::init()
|
||||
{
|
||||
glGenBuffers( 1, &m_glBufferHandle );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_glBufferHandle );
|
||||
glBufferData( GL_ARRAY_BUFFER, m_currentSize * VertexSize, NULL, GL_DYNAMIC_DRAW );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
checkGlError( "allocating video memory for cached container" );
|
||||
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER::reallocate( unsigned int aSize )
|
||||
{
|
||||
assert( aSize > 0 );
|
||||
assert( m_isMapped );
|
||||
assert( IsMapped() );
|
||||
|
||||
unsigned int itemSize = m_item->GetSize();
|
||||
|
||||
|
@ -336,6 +276,38 @@ bool CACHED_CONTAINER::reallocate( unsigned int aSize )
|
|||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::defragment( VERTEX* aTarget )
|
||||
{
|
||||
// Defragmentation
|
||||
ITEMS::iterator it, it_end;
|
||||
int newOffset = 0;
|
||||
|
||||
for( VERTEX_ITEM* item : m_items )
|
||||
{
|
||||
int itemOffset = item->GetOffset();
|
||||
int itemSize = item->GetSize();
|
||||
|
||||
// Move an item to the new container
|
||||
memcpy( &aTarget[newOffset], &m_vertices[itemOffset], itemSize * VertexSize );
|
||||
|
||||
// Update new offset
|
||||
item->setOffset( newOffset );
|
||||
|
||||
// Move to the next free space
|
||||
newOffset += itemSize;
|
||||
}
|
||||
|
||||
// Move the current item and place it at the end
|
||||
if( m_item->GetSize() > 0 )
|
||||
{
|
||||
memcpy( &aTarget[newOffset], &m_vertices[m_item->GetOffset()],
|
||||
m_item->GetSize() * VertexSize );
|
||||
m_item->setOffset( newOffset );
|
||||
m_chunkOffset = newOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::mergeFreeChunks()
|
||||
{
|
||||
if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged
|
||||
|
@ -395,200 +367,6 @@ void CACHED_CONTAINER::mergeFreeChunks()
|
|||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER::defragmentResize( unsigned int aNewSize )
|
||||
{
|
||||
if( !m_useCopyBuffer )
|
||||
return defragmentResizeMemcpy( aNewSize );
|
||||
|
||||
assert( IsMapped() );
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER",
|
||||
wxT( "Resizing & defragmenting container from %d to %d" ), m_currentSize, aNewSize );
|
||||
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
PROF_COUNTER totalTime;
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
GLuint newBuffer;
|
||||
|
||||
// glCopyBufferSubData requires a buffer to be unmapped
|
||||
glUnmapBuffer( GL_ARRAY_BUFFER );
|
||||
|
||||
// Create the destination buffer
|
||||
glGenBuffers( 1, &newBuffer );
|
||||
|
||||
// It would be best to use GL_COPY_WRITE_BUFFER here,
|
||||
// but it is not available everywhere
|
||||
#ifdef __WXDEBUG__
|
||||
GLint eaBuffer = -1;
|
||||
glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
|
||||
assert( eaBuffer == 0 );
|
||||
#endif /* __WXDEBUG__ */
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VertexSize, NULL, GL_DYNAMIC_DRAW );
|
||||
checkGlError( "creating buffer during defragmentation" );
|
||||
|
||||
ITEMS::iterator it, it_end;
|
||||
int newOffset = 0;
|
||||
|
||||
// Defragmentation
|
||||
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
|
||||
{
|
||||
VERTEX_ITEM* item = *it;
|
||||
int itemOffset = item->GetOffset();
|
||||
int itemSize = item->GetSize();
|
||||
|
||||
// Move an item to the new container
|
||||
glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
|
||||
itemOffset * VertexSize, newOffset * VertexSize, itemSize * VertexSize );
|
||||
|
||||
// Update new offset
|
||||
item->setOffset( newOffset );
|
||||
|
||||
// Move to the next free space
|
||||
newOffset += itemSize;
|
||||
}
|
||||
|
||||
// Move the current item and place it at the end
|
||||
if( m_item->GetSize() > 0 )
|
||||
{
|
||||
glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
|
||||
m_item->GetOffset() * VertexSize, newOffset * VertexSize,
|
||||
m_item->GetSize() * VertexSize );
|
||||
|
||||
m_item->setOffset( newOffset );
|
||||
m_chunkOffset = newOffset;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
// Previously we have unmapped the array buffer, now when it is also
|
||||
// unbound, it may be officially marked as unmapped
|
||||
m_isMapped = false;
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
|
||||
// Switch to the new vertex buffer
|
||||
m_glBufferHandle = newBuffer;
|
||||
Map();
|
||||
checkGlError( "switching buffers during defragmentation" );
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
totalTime.Stop();
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER",
|
||||
"Defragmented container storing %d vertices / %.1f ms",
|
||||
m_currentSize - m_freeSpace, totalTime.msecs() );
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER::defragmentResizeMemcpy( unsigned int aNewSize )
|
||||
{
|
||||
assert( IsMapped() );
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER",
|
||||
wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ),
|
||||
m_currentSize, aNewSize );
|
||||
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
PROF_COUNTER totalTime;
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
GLuint newBuffer;
|
||||
VERTEX* newBufferMem;
|
||||
|
||||
// Create the destination buffer
|
||||
glGenBuffers( 1, &newBuffer );
|
||||
|
||||
// It would be best to use GL_COPY_WRITE_BUFFER here,
|
||||
// but it is not available everywhere
|
||||
#ifdef __WXDEBUG__
|
||||
GLint eaBuffer = -1;
|
||||
glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
|
||||
assert( eaBuffer == 0 );
|
||||
#endif /* __WXDEBUG__ */
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VertexSize, NULL, GL_DYNAMIC_DRAW );
|
||||
newBufferMem = static_cast<VERTEX*>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) );
|
||||
checkGlError( "creating buffer during defragmentation" );
|
||||
|
||||
// Defragmentation
|
||||
ITEMS::iterator it, it_end;
|
||||
int newOffset = 0;
|
||||
|
||||
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
|
||||
{
|
||||
VERTEX_ITEM* item = *it;
|
||||
int itemOffset = item->GetOffset();
|
||||
int itemSize = item->GetSize();
|
||||
|
||||
// Move an item to the new container
|
||||
memcpy( &newBufferMem[newOffset], &m_vertices[itemOffset], itemSize * VertexSize );
|
||||
|
||||
// Update new offset
|
||||
item->setOffset( newOffset );
|
||||
|
||||
// Move to the next free space
|
||||
newOffset += itemSize;
|
||||
}
|
||||
|
||||
// Move the current item and place it at the end
|
||||
if( m_item->GetSize() > 0 )
|
||||
{
|
||||
memcpy( &newBufferMem[newOffset], &m_vertices[m_item->GetOffset()],
|
||||
m_item->GetSize() * VertexSize );
|
||||
m_item->setOffset( newOffset );
|
||||
m_chunkOffset = newOffset;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
glUnmapBuffer( GL_ELEMENT_ARRAY_BUFFER );
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
Unmap();
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
|
||||
// Switch to the new vertex buffer
|
||||
m_glBufferHandle = newBuffer;
|
||||
Map();
|
||||
checkGlError( "switching buffers during defragmentation" );
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
totalTime.Stop();
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER",
|
||||
"Defragmented container storing %d vertices / %.1f ms",
|
||||
m_currentSize - m_freeSpace, totalTime.msecs() );
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER::addFreeChunk( unsigned int aOffset, unsigned int aSize )
|
||||
{
|
||||
assert( aOffset + aSize <= m_currentSize );
|
||||
|
@ -669,4 +447,3 @@ void CACHED_CONTAINER::test()
|
|||
// Overlapping check TODO
|
||||
#endif /* __WXDEBUG__ */
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 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
|
||||
*/
|
||||
|
||||
#include <gal/opengl/cached_container_gpu.h>
|
||||
#include <gal/opengl/vertex_manager.h>
|
||||
#include <gal/opengl/vertex_item.h>
|
||||
#include <gal/opengl/shader.h>
|
||||
#include <gal/opengl/utils.h>
|
||||
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
#include <wx/log.h>
|
||||
#include <profile.h>
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
CACHED_CONTAINER_GPU::CACHED_CONTAINER_GPU( unsigned int aSize ) :
|
||||
CACHED_CONTAINER( aSize ), m_isMapped( false ),
|
||||
m_isInitialized( false ), m_glBufferHandle( -1 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CACHED_CONTAINER_GPU::~CACHED_CONTAINER_GPU()
|
||||
{
|
||||
if( m_isMapped )
|
||||
Unmap();
|
||||
|
||||
if( m_isInitialized )
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER_GPU::Map()
|
||||
{
|
||||
assert( !IsMapped() );
|
||||
|
||||
if( !m_isInitialized )
|
||||
init();
|
||||
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_glBufferHandle );
|
||||
m_vertices = static_cast<VERTEX*>( glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE ) );
|
||||
checkGlError( "mapping vertices buffer" );
|
||||
|
||||
m_isMapped = true;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER_GPU::Unmap()
|
||||
{
|
||||
assert( IsMapped() );
|
||||
|
||||
glUnmapBuffer( GL_ARRAY_BUFFER );
|
||||
checkGlError( "unmapping vertices buffer" );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
m_vertices = NULL;
|
||||
checkGlError( "unbinding vertices buffer" );
|
||||
|
||||
m_isMapped = false;
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER_GPU::init()
|
||||
{
|
||||
m_useCopyBuffer = GLEW_ARB_copy_buffer;
|
||||
|
||||
glGenBuffers( 1, &m_glBufferHandle );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_glBufferHandle );
|
||||
glBufferData( GL_ARRAY_BUFFER, m_currentSize * VertexSize, NULL, GL_DYNAMIC_DRAW );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
checkGlError( "allocating video memory for cached container" );
|
||||
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER_GPU::defragmentResize( unsigned int aNewSize )
|
||||
{
|
||||
if( !m_useCopyBuffer )
|
||||
return defragmentResizeMemcpy( aNewSize );
|
||||
|
||||
assert( IsMapped() );
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER_GPU",
|
||||
wxT( "Resizing & defragmenting container from %d to %d" ), m_currentSize, aNewSize );
|
||||
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
PROF_COUNTER totalTime;
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
GLuint newBuffer;
|
||||
|
||||
// glCopyBufferSubData requires a buffer to be unmapped
|
||||
glUnmapBuffer( GL_ARRAY_BUFFER );
|
||||
|
||||
// Create the destination buffer
|
||||
glGenBuffers( 1, &newBuffer );
|
||||
|
||||
// It would be best to use GL_COPY_WRITE_BUFFER here,
|
||||
// but it is not available everywhere
|
||||
#ifdef __WXDEBUG__
|
||||
GLint eaBuffer = -1;
|
||||
glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
|
||||
assert( eaBuffer == 0 );
|
||||
#endif /* __WXDEBUG__ */
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VertexSize, NULL, GL_DYNAMIC_DRAW );
|
||||
checkGlError( "creating buffer during defragmentation" );
|
||||
|
||||
ITEMS::iterator it, it_end;
|
||||
int newOffset = 0;
|
||||
|
||||
// Defragmentation
|
||||
for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it )
|
||||
{
|
||||
VERTEX_ITEM* item = *it;
|
||||
int itemOffset = item->GetOffset();
|
||||
int itemSize = item->GetSize();
|
||||
|
||||
// Move an item to the new container
|
||||
glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
|
||||
itemOffset * VertexSize, newOffset * VertexSize, itemSize * VertexSize );
|
||||
|
||||
// Update new offset
|
||||
item->setOffset( newOffset );
|
||||
|
||||
// Move to the next free space
|
||||
newOffset += itemSize;
|
||||
}
|
||||
|
||||
// Move the current item and place it at the end
|
||||
if( m_item->GetSize() > 0 )
|
||||
{
|
||||
glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
|
||||
m_item->GetOffset() * VertexSize, newOffset * VertexSize,
|
||||
m_item->GetSize() * VertexSize );
|
||||
|
||||
m_item->setOffset( newOffset );
|
||||
m_chunkOffset = newOffset;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
// Previously we have unmapped the array buffer, now when it is also
|
||||
// unbound, it may be officially marked as unmapped
|
||||
m_isMapped = false;
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
|
||||
// Switch to the new vertex buffer
|
||||
m_glBufferHandle = newBuffer;
|
||||
Map();
|
||||
checkGlError( "switching buffers during defragmentation" );
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
totalTime.Stop();
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER_GPU",
|
||||
"Defragmented container storing %d vertices / %.1f ms",
|
||||
m_currentSize - m_freeSpace, totalTime.msecs() );
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER_GPU::defragmentResizeMemcpy( unsigned int aNewSize )
|
||||
{
|
||||
assert( IsMapped() );
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER_GPU",
|
||||
wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ),
|
||||
m_currentSize, aNewSize );
|
||||
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
PROF_COUNTER totalTime;
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
GLuint newBuffer;
|
||||
VERTEX* newBufferMem;
|
||||
|
||||
// Create the destination buffer
|
||||
glGenBuffers( 1, &newBuffer );
|
||||
|
||||
// It would be best to use GL_COPY_WRITE_BUFFER here,
|
||||
// but it is not available everywhere
|
||||
#ifdef __WXDEBUG__
|
||||
GLint eaBuffer = -1;
|
||||
glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
|
||||
assert( eaBuffer == 0 );
|
||||
#endif /* __WXDEBUG__ */
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
|
||||
glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize * VertexSize, NULL, GL_DYNAMIC_DRAW );
|
||||
newBufferMem = static_cast<VERTEX*>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) );
|
||||
checkGlError( "creating buffer during defragmentation" );
|
||||
|
||||
defragment( newBufferMem );
|
||||
|
||||
// Cleanup
|
||||
glUnmapBuffer( GL_ELEMENT_ARRAY_BUFFER );
|
||||
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
|
||||
Unmap();
|
||||
glDeleteBuffers( 1, &m_glBufferHandle );
|
||||
|
||||
// Switch to the new vertex buffer
|
||||
m_glBufferHandle = newBuffer;
|
||||
Map();
|
||||
checkGlError( "switching buffers during defragmentation" );
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
totalTime.Stop();
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER_GPU",
|
||||
"Defragmented container storing %d vertices / %.1f ms",
|
||||
m_currentSize - m_freeSpace, totalTime.msecs() );
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 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
|
||||
*/
|
||||
|
||||
#include <gal/opengl/cached_container_ram.h>
|
||||
#include <gal/opengl/vertex_manager.h>
|
||||
#include <gal/opengl/vertex_item.h>
|
||||
#include <gal/opengl/shader.h>
|
||||
#include <gal/opengl/utils.h>
|
||||
|
||||
#include <confirm.h>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
#include <wx/log.h>
|
||||
#include <profile.h>
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
CACHED_CONTAINER_RAM::CACHED_CONTAINER_RAM( unsigned int aSize ) :
|
||||
CACHED_CONTAINER( aSize ), m_isInitialized( false ), m_verticesBuffer( 0 )
|
||||
{
|
||||
m_vertices = static_cast<VERTEX*>( malloc( aSize * VertexSize ) );
|
||||
}
|
||||
|
||||
|
||||
CACHED_CONTAINER_RAM::~CACHED_CONTAINER_RAM()
|
||||
{
|
||||
if( m_isInitialized )
|
||||
glDeleteBuffers( 1, &m_verticesBuffer );
|
||||
|
||||
free( m_vertices );
|
||||
}
|
||||
|
||||
|
||||
void CACHED_CONTAINER_RAM::Unmap()
|
||||
{
|
||||
if( !m_dirty )
|
||||
return;
|
||||
|
||||
if( !m_isInitialized )
|
||||
{
|
||||
glGenBuffers( 1, &m_verticesBuffer );
|
||||
checkGlError( "generating vertices buffer" );
|
||||
m_isInitialized = true;
|
||||
}
|
||||
|
||||
// Upload vertices coordinates and shader types to GPU memory
|
||||
glBindBuffer( GL_ARRAY_BUFFER, m_verticesBuffer );
|
||||
checkGlError( "binding vertices buffer" );
|
||||
glBufferData( GL_ARRAY_BUFFER, usedSpace() * VertexSize, m_vertices, GL_STREAM_DRAW );
|
||||
checkGlError( "transferring vertices" );
|
||||
glBindBuffer( GL_ARRAY_BUFFER, 0 );
|
||||
checkGlError( "unbinding vertices buffer" );
|
||||
}
|
||||
|
||||
|
||||
bool CACHED_CONTAINER_RAM::defragmentResize( unsigned int aNewSize )
|
||||
{
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER",
|
||||
wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ),
|
||||
m_currentSize, aNewSize );
|
||||
|
||||
// No shrinking if we cannot fit all the data
|
||||
if( usedSpace() > aNewSize )
|
||||
return false;
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
PROF_COUNTER totalTime;
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
VERTEX* newBufferMem = static_cast<VERTEX*>( malloc( aNewSize * VertexSize ) );
|
||||
|
||||
if( !newBufferMem )
|
||||
return false;
|
||||
|
||||
defragment( newBufferMem );
|
||||
|
||||
// Switch to the new vertex buffer
|
||||
free( m_vertices );
|
||||
m_vertices = newBufferMem;
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
totalTime.Stop();
|
||||
|
||||
wxLogTrace( "GAL_CACHED_CONTAINER",
|
||||
"Defragmented container storing %d vertices / %.1f ms",
|
||||
m_currentSize - m_freeSpace, totalTime.msecs() );
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
m_freeSpace += ( aNewSize - m_currentSize );
|
||||
m_currentSize = aNewSize;
|
||||
|
||||
// Now there is only one big chunk of free memory
|
||||
m_freeChunks.clear();
|
||||
m_freeChunks.insert( std::make_pair( m_freeSpace, m_currentSize - m_freeSpace ) );
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013-2016 CERN
|
||||
* Copyright 2013-2017 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -22,13 +22,9 @@
|
|||
* 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/cached_container_gpu.h>
|
||||
#include <gal/opengl/cached_container_ram.h>
|
||||
#include <gal/opengl/noncached_container.h>
|
||||
#include <gal/opengl/shader.h>
|
||||
#include <gal/opengl/utils.h>
|
||||
|
@ -45,13 +41,10 @@ using namespace KIGFX;
|
|||
|
||||
GPU_MANAGER* GPU_MANAGER::MakeManager( VERTEX_CONTAINER* aContainer )
|
||||
{
|
||||
if( typeid( *aContainer ) == typeid( CACHED_CONTAINER ) )
|
||||
if( aContainer->IsCached() )
|
||||
return new GPU_CACHED_MANAGER( aContainer );
|
||||
else if( typeid( *aContainer ) == typeid( NONCACHED_CONTAINER ) )
|
||||
else
|
||||
return new GPU_NONCACHED_MANAGER( aContainer );
|
||||
|
||||
wxASSERT_MSG( false, wxT( "Not handled container type" ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -87,10 +87,6 @@ OPENGL_GAL::OPENGL_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent,
|
|||
compositor = new OPENGL_COMPOSITOR;
|
||||
compositor->SetAntialiasingMode( options.gl_antialiasing_mode );
|
||||
|
||||
cachedManager = new VERTEX_MANAGER( true );
|
||||
nonCachedManager = new VERTEX_MANAGER( false );
|
||||
overlayManager = new VERTEX_MANAGER( false );
|
||||
|
||||
// Initialize the flags
|
||||
isFramebufferInitialized = false;
|
||||
isBitmapFontInitialized = false;
|
||||
|
@ -154,9 +150,13 @@ OPENGL_GAL::~OPENGL_GAL()
|
|||
ClearCache();
|
||||
|
||||
delete compositor;
|
||||
delete cachedManager;
|
||||
delete nonCachedManager;
|
||||
delete overlayManager;
|
||||
|
||||
if( isInitialized )
|
||||
{
|
||||
delete cachedManager;
|
||||
delete nonCachedManager;
|
||||
delete overlayManager;
|
||||
}
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( glPrivContext );
|
||||
|
||||
|
@ -1251,7 +1251,9 @@ void OPENGL_GAL::DeleteGroup( int aGroupNumber )
|
|||
void OPENGL_GAL::ClearCache()
|
||||
{
|
||||
groups.clear();
|
||||
cachedManager->Clear();
|
||||
|
||||
if( isInitialized )
|
||||
cachedManager->Clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1762,6 +1764,10 @@ void OPENGL_GAL::init()
|
|||
throw;
|
||||
}
|
||||
|
||||
cachedManager = new VERTEX_MANAGER( true );
|
||||
nonCachedManager = new VERTEX_MANAGER( false );
|
||||
overlayManager = new VERTEX_MANAGER( false );
|
||||
|
||||
// Make VBOs use shaders
|
||||
cachedManager->SetShader( *shader );
|
||||
nonCachedManager->SetShader( *shader );
|
||||
|
|
|
@ -28,18 +28,30 @@
|
|||
*/
|
||||
|
||||
#include <gal/opengl/vertex_container.h>
|
||||
#include <gal/opengl/cached_container.h>
|
||||
#include <gal/opengl/cached_container_ram.h>
|
||||
#include <gal/opengl/cached_container_gpu.h>
|
||||
#include <gal/opengl/noncached_container.h>
|
||||
#include <gal/opengl/shader.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace KIGFX;
|
||||
|
||||
VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached )
|
||||
{
|
||||
if( aCached )
|
||||
return new CACHED_CONTAINER;
|
||||
else
|
||||
return new NONCACHED_CONTAINER;
|
||||
{
|
||||
const unsigned char* vendor = glGetString( GL_VENDOR );
|
||||
|
||||
// AMD/ATI cards do not cope well with GPU memory mapping,
|
||||
// so the vertex data has to be kept in RAM
|
||||
if( strstr( (const char*) vendor, "AMD" ) )
|
||||
return new CACHED_CONTAINER_RAM;
|
||||
else
|
||||
return new CACHED_CONTAINER_GPU;
|
||||
}
|
||||
|
||||
return new NONCACHED_CONTAINER;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright 2013-2017 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -22,13 +22,6 @@
|
|||
* 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_
|
||||
|
||||
|
@ -41,11 +34,22 @@ namespace KIGFX
|
|||
class VERTEX_ITEM;
|
||||
class SHADER;
|
||||
|
||||
/**
|
||||
* @brief Class to store VERTEX instances with caching. It associates VERTEX
|
||||
* objects and with VERTEX_ITEMs. Caching vertices data in the memory and a
|
||||
* enables fast reuse of that data.
|
||||
*/
|
||||
|
||||
class CACHED_CONTAINER : public VERTEX_CONTAINER
|
||||
{
|
||||
public:
|
||||
CACHED_CONTAINER( unsigned int aSize = defaultInitSize );
|
||||
~CACHED_CONTAINER();
|
||||
CACHED_CONTAINER( unsigned int aSize = DEFAULT_SIZE );
|
||||
virtual ~CACHED_CONTAINER() {}
|
||||
|
||||
bool IsCached() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
///> @copydoc VERTEX_CONTAINER::SetItem()
|
||||
virtual void SetItem( VERTEX_ITEM* aItem ) override;
|
||||
|
@ -66,25 +70,19 @@ public:
|
|||
* Function GetBufferHandle()
|
||||
* returns handle to the vertex buffer. It might be negative if the buffer is not initialized.
|
||||
*/
|
||||
inline unsigned int GetBufferHandle() const
|
||||
{
|
||||
return m_glBufferHandle;
|
||||
}
|
||||
virtual unsigned int GetBufferHandle() const = 0;
|
||||
|
||||
/**
|
||||
* Function IsMapped()
|
||||
* returns true if vertex buffer is currently mapped.
|
||||
*/
|
||||
inline bool IsMapped() const
|
||||
{
|
||||
return m_isMapped;
|
||||
}
|
||||
virtual bool IsMapped() const = 0;
|
||||
|
||||
///> @copydoc VERTEX_CONTAINER::Map()
|
||||
void Map() override;
|
||||
virtual void Map() override = 0;
|
||||
|
||||
///> @copydoc VERTEX_CONTAINER::Unmap()
|
||||
void Unmap() override;
|
||||
virtual void Unmap() override = 0;
|
||||
|
||||
protected:
|
||||
///> Maps size of free memory chunks to their offsets
|
||||
|
@ -107,25 +105,6 @@ protected:
|
|||
unsigned int m_chunkSize;
|
||||
unsigned int m_chunkOffset;
|
||||
|
||||
///> Flag saying if vertex buffer is currently mapped
|
||||
bool m_isMapped;
|
||||
|
||||
///> Flag saying if the vertex buffer is initialized
|
||||
bool m_isInitialized;
|
||||
|
||||
///> Vertex buffer handle
|
||||
unsigned int m_glBufferHandle;
|
||||
|
||||
///> Flag saying whether it is safe to use glCopyBufferSubData
|
||||
bool m_useCopyBuffer;
|
||||
|
||||
/**
|
||||
* Function init()
|
||||
* performs the GL vertex buffer initialization. It can be invoked only when an OpenGL context
|
||||
* is bound.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Function reallocate()
|
||||
* resizes the chunk that stores the current item to the given size. The current item has
|
||||
|
@ -145,8 +124,14 @@ protected:
|
|||
* @param aNewSize is the new size of container, expressed in number of vertices
|
||||
* @return false in case of failure (e.g. memory shortage)
|
||||
*/
|
||||
bool defragmentResize( unsigned int aNewSize );
|
||||
bool defragmentResizeMemcpy( unsigned int aNewSize );
|
||||
virtual bool defragmentResize( unsigned int aNewSize ) = 0;
|
||||
|
||||
/**
|
||||
* Transfers all stored data to a new buffer, removing empty spaces between the data chunks
|
||||
* in the container.
|
||||
* @param aTarget is the destination for the defragmented data.
|
||||
*/
|
||||
void defragment( VERTEX* aTarget );
|
||||
|
||||
/**
|
||||
* Function mergeFreeChunks()
|
||||
|
@ -155,15 +140,6 @@ protected:
|
|||
*/
|
||||
void mergeFreeChunks();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -192,6 +168,7 @@ private:
|
|||
*/
|
||||
void addFreeChunk( unsigned int aOffset, unsigned int aSize );
|
||||
|
||||
private:
|
||||
/// Debug & test functions
|
||||
void showFreeChunks();
|
||||
void showUsedChunks();
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 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
|
||||
*/
|
||||
|
||||
#ifndef CACHED_CONTAINER_GPU_H_
|
||||
#define CACHED_CONTAINER_GPU_H_
|
||||
|
||||
#include <gal/opengl/cached_container.h>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Specialization of CACHED_CONTAINER that stores data in video memory via memory mapping.
|
||||
*/
|
||||
|
||||
class CACHED_CONTAINER_GPU : public CACHED_CONTAINER
|
||||
{
|
||||
public:
|
||||
CACHED_CONTAINER_GPU( unsigned int aSize = DEFAULT_SIZE );
|
||||
~CACHED_CONTAINER_GPU();
|
||||
|
||||
unsigned int GetBufferHandle() const override
|
||||
{
|
||||
return m_glBufferHandle;
|
||||
}
|
||||
|
||||
bool IsMapped() const override
|
||||
{
|
||||
return m_isMapped;
|
||||
}
|
||||
|
||||
///> @copydoc VERTEX_CONTAINER::Map()
|
||||
void Map() override;
|
||||
|
||||
///> @copydoc VERTEX_CONTAINER::Unmap()
|
||||
void Unmap() override;
|
||||
|
||||
protected:
|
||||
///> Flag saying if vertex buffer is currently mapped
|
||||
bool m_isMapped;
|
||||
|
||||
///> Flag saying if the vertex buffer is initialized
|
||||
bool m_isInitialized;
|
||||
|
||||
///> Vertex buffer handle
|
||||
unsigned int m_glBufferHandle;
|
||||
|
||||
///> Flag saying whether it is safe to use glCopyBufferSubData
|
||||
bool m_useCopyBuffer;
|
||||
|
||||
/**
|
||||
* Function init()
|
||||
* performs the GL vertex buffer initialization. It can be invoked only when an OpenGL context
|
||||
* is bound.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Function defragmentResize()
|
||||
* removes empty spaces between chunks and optionally resizes the container.
|
||||
* After the operation there is continous space for storing vertices at the end of the container.
|
||||
*
|
||||
* @param aNewSize is the new size of container, expressed in number of vertices
|
||||
* @return false in case of failure (e.g. memory shortage)
|
||||
*/
|
||||
bool defragmentResize( unsigned int aNewSize ) override;
|
||||
bool defragmentResizeMemcpy( unsigned int aNewSize );
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* CACHED_CONTAINER_GPU_H_ */
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright 2013-2017 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
|
||||
*/
|
||||
|
||||
#ifndef CACHED_CONTAINER_RAM_H_
|
||||
#define CACHED_CONTAINER_RAM_H_
|
||||
|
||||
#include <gal/opengl/cached_container.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class VERTEX_ITEM;
|
||||
class SHADER;
|
||||
|
||||
/**
|
||||
* @brief Specialization of CACHED_CONTAINER that stores data in RAM. This is mainly for
|
||||
* video cards/drivers that do not cope well with video memory mapping.
|
||||
*/
|
||||
|
||||
class CACHED_CONTAINER_RAM : public CACHED_CONTAINER
|
||||
{
|
||||
public:
|
||||
CACHED_CONTAINER_RAM( unsigned int aSize = DEFAULT_SIZE );
|
||||
~CACHED_CONTAINER_RAM();
|
||||
|
||||
///> @copydoc VERTEX_CONTAINER::Unmap()
|
||||
void Map() override {}
|
||||
|
||||
///> @copydoc VERTEX_CONTAINER::Unmap()
|
||||
void Unmap() override;
|
||||
|
||||
bool IsMapped() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetBufferHandle()
|
||||
* returns handle to the vertex buffer. It might be negative if the buffer is not initialized.
|
||||
*/
|
||||
unsigned int GetBufferHandle() const override
|
||||
{
|
||||
return m_verticesBuffer; // make common with CACHED_CONTAINER_RAM
|
||||
}
|
||||
|
||||
protected:
|
||||
///> Flag saying if the vertex buffer is initialized
|
||||
bool m_isInitialized;
|
||||
|
||||
///> Handle to vertices buffer
|
||||
GLuint m_verticesBuffer;
|
||||
|
||||
/**
|
||||
* Defragments the currently stored data and resizes the buffer.
|
||||
* @param aNewSize is the new buffer vertex buffer size, expressed as the number of vertices.
|
||||
* @return true on success.
|
||||
*/
|
||||
bool defragmentResize( unsigned int aNewSize ) override;
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
#endif /* CACHED_CONTAINER_RAM_H_ */
|
|
@ -22,11 +22,6 @@
|
|||
* 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_
|
||||
|
||||
|
@ -40,6 +35,10 @@ class VERTEX_CONTAINER;
|
|||
class CACHED_CONTAINER;
|
||||
class NONCACHED_CONTAINER;
|
||||
|
||||
/**
|
||||
* @brief Class to handle uploading vertices and indices to GPU in drawing purposes.
|
||||
*/
|
||||
|
||||
class GPU_MANAGER
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -41,9 +41,14 @@ class SHADER;
|
|||
class NONCACHED_CONTAINER : public VERTEX_CONTAINER
|
||||
{
|
||||
public:
|
||||
NONCACHED_CONTAINER( unsigned int aSize = defaultInitSize );
|
||||
NONCACHED_CONTAINER( unsigned int aSize = DEFAULT_SIZE );
|
||||
virtual ~NONCACHED_CONTAINER();
|
||||
|
||||
bool IsCached() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @copydoc VERTEX_CONTAINER::SetItem( VERTEX_ITEM* aItem )
|
||||
virtual void SetItem( VERTEX_ITEM* aItem ) override;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2013 CERN
|
||||
* Copyright 2013-2017 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
|
@ -48,6 +48,12 @@ public:
|
|||
|
||||
virtual ~VERTEX_CONTAINER();
|
||||
|
||||
/**
|
||||
* Returns true if the container caches vertex data in RAM or video memory.
|
||||
* Otherwise it is a single batch draw which is later discarded.
|
||||
*/
|
||||
virtual bool IsCached() const = 0;
|
||||
|
||||
/**
|
||||
* Function Map()
|
||||
* prepares the container for vertices updates.
|
||||
|
@ -58,8 +64,7 @@ public:
|
|||
* Function Unmap()
|
||||
* finishes the vertices updates stage.
|
||||
*/
|
||||
virtual void Unmap()
|
||||
{}
|
||||
virtual void Unmap() {}
|
||||
|
||||
/**
|
||||
* Function SetItem()
|
||||
|
@ -153,7 +158,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
VERTEX_CONTAINER( unsigned int aSize = defaultInitSize );
|
||||
VERTEX_CONTAINER( unsigned int aSize = DEFAULT_SIZE );
|
||||
|
||||
///< How many vertices we can store in the container
|
||||
unsigned int m_freeSpace;
|
||||
|
@ -182,7 +187,7 @@ protected:
|
|||
}
|
||||
|
||||
///< Default initial size of a container (expressed in vertices)
|
||||
static const unsigned int defaultInitSize = 1048576;
|
||||
static constexpr unsigned int DEFAULT_SIZE = 1048576;
|
||||
};
|
||||
} // namespace KIGFX
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ class VERTEX_ITEM
|
|||
{
|
||||
public:
|
||||
friend class CACHED_CONTAINER;
|
||||
friend class CACHED_CONTAINER_GPU;
|
||||
friend class VERTEX_MANAGER;
|
||||
|
||||
explicit VERTEX_ITEM( const VERTEX_MANAGER& aManager );
|
||||
|
|
Loading…
Reference in New Issue