Commit 43ae1cb9 authored by Maciej Suminski's avatar Maciej Suminski

Smarter way of the overlay rendering (overlay is always refreshed, while...

Smarter way of the overlay rendering (overlay is always refreshed, while cached&noncached targets only if the viewport or items have changed).
parent e87eea7a
...@@ -127,6 +127,8 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) ) ...@@ -127,6 +127,8 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
void EDA_DRAW_PANEL_GAL::onSize( wxSizeEvent& aEvent ) void EDA_DRAW_PANEL_GAL::onSize( wxSizeEvent& aEvent )
{ {
m_gal->ResizeScreen( aEvent.GetSize().x, aEvent.GetSize().y ); m_gal->ResizeScreen( aEvent.GetSize().x, aEvent.GetSize().y );
m_view->SetTargetDirty( KiGfx::TARGET_CACHED );
m_view->SetTargetDirty( KiGfx::TARGET_NONCACHED );
} }
...@@ -134,24 +136,19 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect ) ...@@ -134,24 +136,19 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect )
{ {
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
prof_counter time; prof_counter time;
prof_start( &time, false ); prof_start( &time, false );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
printf("Refresh!\n");
m_gal->BeginDrawing(); m_gal->BeginDrawing();
m_gal->SetBackgroundColor( KiGfx::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) ); m_gal->SetBackgroundColor( KiGfx::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
m_gal->ClearScreen(); m_gal->ClearScreen();
m_gal->DrawGrid();
m_view->Redraw(); m_view->Redraw();
m_gal->EndDrawing(); m_gal->EndDrawing();
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
prof_end( &time ); prof_end( &time );
wxLogDebug( wxT( "EDA_DRAW_PANEL_GAL::Refresh: %.0f ms (%.0f fps)" ), wxLogDebug( wxT( "EDA_DRAW_PANEL_GAL::Refresh: %.0f ms (%.0f fps)" ),
static_cast<double>( time.value ) / 1000.0, 1000000.0 / static_cast<double>( time.value ) ); static_cast<double>( time.value ) / 1000.0, 1000000.0 / static_cast<double>( time.value ) );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
...@@ -184,6 +181,9 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) ...@@ -184,6 +181,9 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
m_gal->SetScreenDPI( 106 ); // Display resolution setting m_gal->SetScreenDPI( 106 ); // Display resolution setting
m_gal->ComputeWorldScreenMatrix(); m_gal->ComputeWorldScreenMatrix();
wxSize size = GetClientSize();
m_gal->ResizeScreen( size.GetX(), size.GetY() );
if( m_painter ) if( m_painter )
m_painter->SetGAL( m_gal ); m_painter->SetGAL( m_gal );
...@@ -193,9 +193,6 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) ...@@ -193,9 +193,6 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
m_view->RecacheAllItems( true ); m_view->RecacheAllItems( true );
} }
wxSize size = GetClientSize();
m_gal->ResizeScreen( size.GetX(), size.GetY() );
m_currentGal = aGalType; m_currentGal = aGalType;
} }
......
...@@ -36,8 +36,6 @@ using namespace KiGfx; ...@@ -36,8 +36,6 @@ using namespace KiGfx;
CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) : CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) :
m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext ) m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext )
{ {
// Obtain the transformation matrix used in the main context
cairo_get_matrix( m_mainContext, &m_matrix );
} }
...@@ -65,11 +63,10 @@ void CAIRO_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight ) ...@@ -65,11 +63,10 @@ void CAIRO_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
} }
unsigned int CAIRO_COMPOSITOR::GetBuffer() unsigned int CAIRO_COMPOSITOR::CreateBuffer()
{ {
// Pixel storage // Pixel storage
BitmapPtr bitmap( new unsigned int[m_bufferSize] ); BitmapPtr bitmap( new unsigned int[m_bufferSize] );
memset( bitmap.get(), 0x00, m_bufferSize * sizeof(int) ); memset( bitmap.get(), 0x00, m_bufferSize * sizeof(int) );
// Create the Cairo surface // Create the Cairo surface
...@@ -78,10 +75,10 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer() ...@@ -78,10 +75,10 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer()
CAIRO_FORMAT_ARGB32, m_width, CAIRO_FORMAT_ARGB32, m_width,
m_height, m_stride ); m_height, m_stride );
cairo_t* context = cairo_create( surface ); cairo_t* context = cairo_create( surface );
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
cairo_status_t status = cairo_status( context ); cairo_status_t status = cairo_status( context );
wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" ); wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
// Set default settings for the buffer // Set default settings for the buffer
cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL ); cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL );
...@@ -89,6 +86,7 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer() ...@@ -89,6 +86,7 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer()
cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND ); cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
// Use the same transformation matrix as the main context // Use the same transformation matrix as the main context
cairo_get_matrix( m_mainContext, &m_matrix );
cairo_set_matrix( context, &m_matrix ); cairo_set_matrix( context, &m_matrix );
// Store the new buffer // Store the new buffer
...@@ -101,53 +99,41 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer() ...@@ -101,53 +99,41 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer()
void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
{ {
if( aBufferHandle <= usedBuffers() ) wxASSERT_MSG( aBufferHandle <= usedBuffers(), wxT( "Tried to use a not existing buffer" ) );
{
m_current = aBufferHandle - 1;
*m_currentContext = m_buffers[m_current].context;
}
#ifdef __WXDEBUG__ // Get currently used transformation matrix, so it can be applied to the new buffer
else cairo_get_matrix( *m_currentContext, &m_matrix );
wxLogDebug( wxT( "Tried to use a not existing buffer" ) );
#endif m_current = aBufferHandle - 1;
*m_currentContext = m_buffers[m_current].context;
// Apply the current transformation matrix
cairo_set_matrix( *m_currentContext, &m_matrix );
} }
void CAIRO_COMPOSITOR::ClearBuffer() void CAIRO_COMPOSITOR::ClearBuffer()
{ {
// Reset the transformation matrix, so it is possible to composite images using // Clear the pixel storage
// screen coordinates instead of world coordinates memset( m_buffers[m_current].bitmap.get(), 0x00, m_bufferSize * sizeof(int) );
cairo_identity_matrix( m_buffers[m_current].context );
cairo_set_source_rgba( m_buffers[m_current].context, 0.0, 0.0, 0.0, 0.0 );
cairo_rectangle( m_buffers[m_current].context, 0.0, 0.0, m_width, m_height );
cairo_fill( m_buffers[m_current].context );
// Restore the transformation matrix
cairo_set_matrix( m_buffers[m_current].context, &m_matrix );
} }
void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
{ {
if( aBufferHandle <= usedBuffers() ) wxASSERT_MSG( aBufferHandle <= usedBuffers(), wxT( "Tried to use a not existing buffer" ) );
{
// Reset the transformation matrix, so it is possible to composite images using
// screen coordinates instead of world coordinates
cairo_identity_matrix( m_mainContext );
cairo_set_source_surface( m_mainContext, m_buffers[aBufferHandle - 1].surface, 0.0, 0.0 ); // Reset the transformation matrix, so it is possible to composite images using
cairo_paint( m_mainContext ); // screen coordinates instead of world coordinates
cairo_get_matrix( m_mainContext, &m_matrix );
cairo_identity_matrix( m_mainContext );
// Restore the transformation matrix // Draw the selected buffer contents
cairo_set_matrix( m_mainContext, &m_matrix ); cairo_set_source_surface( m_mainContext, m_buffers[aBufferHandle - 1].surface, 0.0, 0.0 );
} cairo_paint( m_mainContext );
#ifdef __WXDEBUG__ // Restore the transformation matrix
else cairo_set_matrix( m_mainContext, &m_matrix );
wxLogDebug( wxT( "Tried to use a not existing buffer" ) );
#endif
} }
......
...@@ -48,6 +48,7 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, ...@@ -48,6 +48,7 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
isGrouping = false; isGrouping = false;
isInitialized = false; isInitialized = false;
isDeleteSavedPixels = false; isDeleteSavedPixels = false;
validCompositor = false;
groupCounter = 0; groupCounter = 0;
// Connecting the event handlers // Connecting the event handlers
...@@ -90,7 +91,11 @@ CAIRO_GAL::~CAIRO_GAL() ...@@ -90,7 +91,11 @@ CAIRO_GAL::~CAIRO_GAL()
void CAIRO_GAL::BeginDrawing() void CAIRO_GAL::BeginDrawing()
{ {
initSurface(); initSurface();
setCompositor(); if( !validCompositor )
setCompositor();
compositor->SetMainContext( context );
compositor->SetBuffer( mainBuffer );
// Cairo grouping prevents display of overlapping items on the same layer in the lighter color // Cairo grouping prevents display of overlapping items on the same layer in the lighter color
cairo_push_group( currentContext ); cairo_push_group( currentContext );
...@@ -120,9 +125,9 @@ void CAIRO_GAL::EndDrawing() ...@@ -120,9 +125,9 @@ void CAIRO_GAL::EndDrawing()
for( size_t count = 0; count < bufferSize; count++ ) for( size_t count = 0; count < bufferSize; count++ )
{ {
unsigned int value = bitmapBuffer[count]; unsigned int value = bitmapBuffer[count];
*wxOutputPtr++ = (value >> 16) & 0xff; // Red pixel *wxOutputPtr++ = ( value >> 16 ) & 0xff; // Red pixel
*wxOutputPtr++ = (value >> 8) & 0xff; // Green pixel *wxOutputPtr++ = ( value >> 8 ) & 0xff; // Green pixel
*wxOutputPtr++ = value & 0xff; // Blue pixel *wxOutputPtr++ = value & 0xff; // Blue pixel
} }
wxImage img( (int) screenSize.x, (int) screenSize.y, (unsigned char*) wxOutput, true ); wxImage img( (int) screenSize.x, (int) screenSize.y, (unsigned char*) wxOutput, true );
...@@ -273,6 +278,10 @@ void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight ) ...@@ -273,6 +278,10 @@ void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight )
deleteBitmaps(); deleteBitmaps();
allocateBitmaps(); allocateBitmaps();
if( validCompositor )
compositor->Resize( aWidth, aHeight );
validCompositor = false;
SetSize( wxSize( aWidth, aHeight ) ); SetSize( wxSize( aWidth, aHeight ) );
} }
...@@ -719,7 +728,7 @@ void CAIRO_GAL::SetTarget( RenderTarget aTarget ) ...@@ -719,7 +728,7 @@ void CAIRO_GAL::SetTarget( RenderTarget aTarget )
{ {
// If the compositor is not set, that means that there is a recaching process going on // If the compositor is not set, that means that there is a recaching process going on
// and we do not need the compositor now // and we do not need the compositor now
if( !compositor ) if( !validCompositor )
return; return;
// Cairo grouping prevents display of overlapping items on the same layer in the lighter color // Cairo grouping prevents display of overlapping items on the same layer in the lighter color
...@@ -751,6 +760,31 @@ RenderTarget CAIRO_GAL::GetTarget() const ...@@ -751,6 +760,31 @@ RenderTarget CAIRO_GAL::GetTarget() const
} }
void CAIRO_GAL::ClearTarget( RenderTarget aTarget )
{
// Save the current state
unsigned int currentBuffer = compositor->GetBuffer();
switch( aTarget )
{
// Cached and noncached items are rendered to the same buffer
default:
case TARGET_CACHED:
case TARGET_NONCACHED:
compositor->SetBuffer( mainBuffer );
break;
case TARGET_OVERLAY:
compositor->SetBuffer( overlayBuffer );
break;
}
compositor->ClearBuffer();
// Restore the previous state
compositor->SetBuffer( currentBuffer );
}
VECTOR2D CAIRO_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) VECTOR2D CAIRO_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition )
{ {
MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse(); MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse();
...@@ -972,8 +1006,10 @@ void CAIRO_GAL::setCompositor() ...@@ -972,8 +1006,10 @@ void CAIRO_GAL::setCompositor()
compositor->Resize( screenSize.x, screenSize.y ); compositor->Resize( screenSize.x, screenSize.y );
// Prepare buffers // Prepare buffers
mainBuffer = compositor->GetBuffer(); mainBuffer = compositor->CreateBuffer();
overlayBuffer = compositor->GetBuffer(); overlayBuffer = compositor->CreateBuffer();
validCompositor = true;
} }
......
...@@ -74,7 +74,7 @@ void OPENGL_COMPOSITOR::Initialize() ...@@ -74,7 +74,7 @@ void OPENGL_COMPOSITOR::Initialize()
GL_RENDERBUFFER, m_depthBuffer ); GL_RENDERBUFFER, m_depthBuffer );
// Unbind the framebuffer, so by default all the rendering goes directly to the display // Unbind the framebuffer, so by default all the rendering goes directly to the display
glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, DIRECT_RENDERING );
m_currentFbo = 0; m_currentFbo = 0;
m_initialized = true; m_initialized = true;
...@@ -91,7 +91,7 @@ void OPENGL_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight ) ...@@ -91,7 +91,7 @@ void OPENGL_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
} }
unsigned int OPENGL_COMPOSITOR::GetBuffer() unsigned int OPENGL_COMPOSITOR::CreateBuffer()
{ {
wxASSERT( m_initialized ); wxASSERT( m_initialized );
...@@ -169,8 +169,8 @@ unsigned int OPENGL_COMPOSITOR::GetBuffer() ...@@ -169,8 +169,8 @@ unsigned int OPENGL_COMPOSITOR::GetBuffer()
ClearBuffer(); ClearBuffer();
glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, DIRECT_RENDERING );
m_currentFbo = 0; m_currentFbo = DIRECT_RENDERING;
// Store the new buffer // Store the new buffer
OPENGL_BUFFER buffer = { textureTarget, attachmentPoint }; OPENGL_BUFFER buffer = { textureTarget, attachmentPoint };
...@@ -186,10 +186,10 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) ...@@ -186,10 +186,10 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
return; return;
// Change the rendering destination to the selected attachment point // Change the rendering destination to the selected attachment point
if( aBufferHandle == 0 ) if( aBufferHandle == DIRECT_RENDERING )
{ {
glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, DIRECT_RENDERING );
m_currentFbo = 0; m_currentFbo = DIRECT_RENDERING;
} }
else if( m_currentFbo != m_framebuffer ) else if( m_currentFbo != m_framebuffer )
{ {
...@@ -197,7 +197,7 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) ...@@ -197,7 +197,7 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
m_currentFbo = m_framebuffer; m_currentFbo = m_framebuffer;
} }
if( m_currentFbo != 0 && m_current != aBufferHandle - 1 ) if( m_currentFbo != DIRECT_RENDERING )
{ {
m_current = aBufferHandle - 1; m_current = aBufferHandle - 1;
glDrawBuffer( m_buffers[m_current].attachmentPoint ); glDrawBuffer( m_buffers[m_current].attachmentPoint );
...@@ -219,8 +219,8 @@ void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) ...@@ -219,8 +219,8 @@ void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
wxASSERT( m_initialized ); wxASSERT( m_initialized );
// Switch to the main framebuffer and blit the scene // Switch to the main framebuffer and blit the scene
glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glBindFramebuffer( GL_FRAMEBUFFER, DIRECT_RENDERING );
m_currentFbo = 0; m_currentFbo = DIRECT_RENDERING;
// Depth test has to be disabled to make transparency working // Depth test has to be disabled to make transparency working
glDisable( GL_DEPTH_TEST ); glDisable( GL_DEPTH_TEST );
...@@ -279,4 +279,4 @@ void OPENGL_COMPOSITOR::clean() ...@@ -279,4 +279,4 @@ void OPENGL_COMPOSITOR::clean()
} }
GLuint OPENGL_COMPOSITOR::m_currentFbo = 0; GLuint OPENGL_COMPOSITOR::m_currentFbo = DIRECT_RENDERING;
...@@ -130,8 +130,8 @@ void OPENGL_GAL::BeginDrawing() ...@@ -130,8 +130,8 @@ void OPENGL_GAL::BeginDrawing()
// Prepare rendering target buffers // Prepare rendering target buffers
compositor.Initialize(); compositor.Initialize();
mainBuffer = compositor.GetBuffer(); mainBuffer = compositor.CreateBuffer();
overlayBuffer = compositor.GetBuffer(); overlayBuffer = compositor.CreateBuffer();
isFramebufferInitialized = true; isFramebufferInitialized = true;
} }
...@@ -187,13 +187,10 @@ void OPENGL_GAL::BeginDrawing() ...@@ -187,13 +187,10 @@ void OPENGL_GAL::BeginDrawing()
SetFillColor( fillColor ); SetFillColor( fillColor );
SetStrokeColor( strokeColor ); SetStrokeColor( strokeColor );
// Prepare buffers for drawing // Unbind buffers - set compositor for direct drawing
compositor.SetBuffer( mainBuffer ); compositor.SetBuffer( OPENGL_COMPOSITOR::DIRECT_RENDERING );
compositor.ClearBuffer();
compositor.SetBuffer( overlayBuffer );
compositor.ClearBuffer();
compositor.SetBuffer( 0 ); // Unbind buffers
// Remove all previously stored items
nonCachedManager.Clear(); nonCachedManager.Clear();
overlayManager.Clear(); overlayManager.Clear();
...@@ -711,6 +708,31 @@ RenderTarget OPENGL_GAL::GetTarget() const ...@@ -711,6 +708,31 @@ RenderTarget OPENGL_GAL::GetTarget() const
} }
void OPENGL_GAL::ClearTarget( RenderTarget aTarget )
{
// Save the current state
unsigned int oldTarget = compositor.GetBuffer();
switch( aTarget )
{
// Cached and noncached items are rendered to the same buffer
default:
case TARGET_CACHED:
case TARGET_NONCACHED:
compositor.SetBuffer( mainBuffer );
break;
case TARGET_OVERLAY:
compositor.SetBuffer( overlayBuffer );
break;
}
compositor.ClearBuffer();
// Restore the previous state
compositor.SetBuffer( oldTarget );
}
VECTOR2D OPENGL_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) VECTOR2D OPENGL_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition )
{ {
VECTOR2D cursorPosition = aCursorPosition; VECTOR2D cursorPosition = aCursorPosition;
......
...@@ -39,6 +39,28 @@ ...@@ -39,6 +39,28 @@
using namespace KiGfx; using namespace KiGfx;
VIEW::VIEW( bool aIsDynamic ) :
m_enableOrderModifier( false ),
m_scale( 1.0 ),
m_painter( NULL ),
m_gal( NULL ),
m_dynamic( aIsDynamic )
{
// Redraw everything at the beginning
for( int i = 0; i < TARGETS_NUMBER; ++i )
SetTargetDirty( i );
}
VIEW::~VIEW()
{
BOOST_FOREACH( LayerMap::value_type& l, m_layers )
{
delete l.second.items;
}
}
void VIEW::AddLayer( int aLayer, bool aDisplayOnly ) void VIEW::AddLayer( int aLayer, bool aDisplayOnly )
{ {
if( m_layers.find( aLayer ) == m_layers.end() ) if( m_layers.find( aLayer ) == m_layers.end() )
...@@ -197,25 +219,6 @@ int VIEW::Query( const BOX2I& aRect, std::vector<LayerItemPair>& aResult ) ...@@ -197,25 +219,6 @@ int VIEW::Query( const BOX2I& aRect, std::vector<LayerItemPair>& aResult )
} }
VIEW::VIEW( bool aIsDynamic ) :
m_enableOrderModifier( false ),
m_scale( 1.0 ),
m_painter( NULL ),
m_gal( NULL ),
m_dynamic( aIsDynamic )
{
}
VIEW::~VIEW()
{
BOOST_FOREACH( LayerMap::value_type& l, m_layers )
{
delete l.second.items;
}
}
VECTOR2D VIEW::ToWorld( const VECTOR2D& aCoord, bool aAbsolute ) const VECTOR2D VIEW::ToWorld( const VECTOR2D& aCoord, bool aAbsolute ) const
{ {
MATRIX3x3D matrix = m_gal->GetWorldScreenMatrix().Inverse(); MATRIX3x3D matrix = m_gal->GetWorldScreenMatrix().Inverse();
...@@ -267,6 +270,11 @@ void VIEW::SetGAL( GAL* aGal ) ...@@ -267,6 +270,11 @@ void VIEW::SetGAL( GAL* aGal )
// clear group numbers, so everything is going to be recached // clear group numbers, so everything is going to be recached
clearGroupCache(); clearGroupCache();
// every target has to be refreshed
SetTargetDirty( TARGET_CACHED );
SetTargetDirty( TARGET_NONCACHED );
SetTargetDirty( TARGET_OVERLAY );
// force the new GAL to display the current viewport. // force the new GAL to display the current viewport.
SetCenter( m_center ); SetCenter( m_center );
SetScale( m_scale ); SetScale( m_scale );
...@@ -326,6 +334,10 @@ void VIEW::SetScale( double aScale, const VECTOR2D& aAnchor ) ...@@ -326,6 +334,10 @@ void VIEW::SetScale( double aScale, const VECTOR2D& aAnchor )
SetCenter( m_center - delta ); SetCenter( m_center - delta );
m_scale = aScale; m_scale = aScale;
// Redraw everything after the viewport has changed
SetTargetDirty( TARGET_CACHED );
SetTargetDirty( TARGET_NONCACHED );
} }
...@@ -334,6 +346,10 @@ void VIEW::SetCenter( const VECTOR2D& aCenter ) ...@@ -334,6 +346,10 @@ void VIEW::SetCenter( const VECTOR2D& aCenter )
m_center = aCenter; m_center = aCenter;
m_gal->SetLookAtPoint( m_center ); m_gal->SetLookAtPoint( m_center );
m_gal->ComputeWorldScreenMatrix(); m_gal->ComputeWorldScreenMatrix();
// Redraw everything after the viewport has changed
SetTargetDirty( TARGET_CACHED );
SetTargetDirty( TARGET_NONCACHED );
} }
...@@ -347,6 +363,8 @@ void VIEW::sortLayers() ...@@ -347,6 +363,8 @@ void VIEW::sortLayers()
m_orderedLayers[n++] = &i->second; m_orderedLayers[n++] = &i->second;
sort( m_orderedLayers.begin(), m_orderedLayers.end(), compareRenderingOrder ); sort( m_orderedLayers.begin(), m_orderedLayers.end(), compareRenderingOrder );
SetTargetDirty( TARGET_CACHED );
} }
...@@ -554,15 +572,15 @@ void VIEW::redrawRect( const BOX2I& aRect ) ...@@ -554,15 +572,15 @@ void VIEW::redrawRect( const BOX2I& aRect )
{ {
BOOST_FOREACH( VIEW_LAYER* l, m_orderedLayers ) BOOST_FOREACH( VIEW_LAYER* l, m_orderedLayers )
{ {
if( l->enabled && areRequiredLayersEnabled( l->id ) ) if( l->enabled && isTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) )
{ {
drawItem drawFunc( this, l ); drawItem drawFunc( this, l );
m_gal->SetTarget( l->target ); m_gal->SetTarget( l->target );
m_gal->SetLayerDepth( l->renderingOrder ); m_gal->SetLayerDepth( l->renderingOrder );
l->items->Query( aRect, drawFunc ); l->items->Query( aRect, drawFunc );
l->isDirty = false;
} }
l->isDirty = false;
} }
} }
...@@ -648,9 +666,27 @@ void VIEW::Redraw() ...@@ -648,9 +666,27 @@ void VIEW::Redraw()
VECTOR2D screenSize = m_gal->GetScreenPixelSize(); VECTOR2D screenSize = m_gal->GetScreenPixelSize();
BOX2I rect( ToWorld( VECTOR2D( 0, 0 ) ), BOX2I rect( ToWorld( VECTOR2D( 0, 0 ) ),
ToWorld( screenSize ) - ToWorld( VECTOR2D( 0, 0 ) ) ); ToWorld( screenSize ) - ToWorld( VECTOR2D( 0, 0 ) ) );
rect.Normalize(); rect.Normalize();
if( isTargetDirty( TARGET_CACHED ) || isTargetDirty( TARGET_NONCACHED ) )
{
// TARGET_CACHED and TARGET_NONCACHED have to be redrawn together, as they contain
// layers that rely on each other (eg. netnames are noncached, but tracks - are cached)
m_gal->ClearTarget( TARGET_NONCACHED );
m_gal->ClearTarget( TARGET_CACHED );
SetTargetDirty( TARGET_NONCACHED );
SetTargetDirty( TARGET_CACHED );
m_gal->DrawGrid();
}
m_gal->ClearTarget( TARGET_OVERLAY );
redrawRect( rect ); redrawRect( rect );
// All targets were redrawn, so nothing is dirty
SetTargetDirty( TARGET_CACHED, false );
SetTargetDirty( TARGET_NONCACHED, false );
} }
...@@ -801,3 +837,19 @@ void VIEW::RecacheAllItems( bool aImmediately ) ...@@ -801,3 +837,19 @@ void VIEW::RecacheAllItems( bool aImmediately )
wxLogDebug( wxT( "RecacheAllItems::%.1f ms" ), (double) totalRealTime.value / 1000.0 ); wxLogDebug( wxT( "RecacheAllItems::%.1f ms" ), (double) totalRealTime.value / 1000.0 );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
} }
bool VIEW::isTargetDirty( int aTarget ) const
{
wxASSERT( aTarget < TARGETS_NUMBER );
// Check if any of layers belonging to the target is dirty
BOOST_FOREACH( VIEW_LAYER* l, m_orderedLayers )
{
if( l->target == aTarget && l->isDirty )
return true;
}
// If no layer is dirty, just check the target status itself
return m_dirtyTargets[aTarget];
}
...@@ -50,8 +50,14 @@ public: ...@@ -50,8 +50,14 @@ public:
/// @copydoc COMPOSITOR::Resize() /// @copydoc COMPOSITOR::Resize()
virtual void Resize( unsigned int aWidth, unsigned int aHeight ); virtual void Resize( unsigned int aWidth, unsigned int aHeight );
/// @copydoc COMPOSITOR::CreateBuffer()
virtual unsigned int CreateBuffer();
/// @copydoc COMPOSITOR::GetBuffer() /// @copydoc COMPOSITOR::GetBuffer()
virtual unsigned int GetBuffer(); inline virtual unsigned int GetBuffer() const
{
return m_current + 1;
}
/// @copydoc COMPOSITOR::SetBuffer() /// @copydoc COMPOSITOR::SetBuffer()
virtual void SetBuffer( unsigned int aBufferHandle ); virtual void SetBuffer( unsigned int aBufferHandle );
...@@ -62,6 +68,21 @@ public: ...@@ -62,6 +68,21 @@ public:
/// @copydoc COMPOSITOR::DrawBuffer() /// @copydoc COMPOSITOR::DrawBuffer()
virtual void DrawBuffer( unsigned int aBufferHandle ); virtual void DrawBuffer( unsigned int aBufferHandle );
/**
* Function SetMainContext()
* Sets a context to be treated as the main context (ie. as a target of buffers rendering and
* as a source of settings for newly created buffers).
*
* @param aMainContext is the context that should be treated as the main one.
*/
inline virtual void SetMainContext( cairo_t* aMainContext )
{
m_mainContext = aMainContext;
// Use the context's transformation matrix
cairo_get_matrix( m_mainContext, &m_matrix );
}
protected: protected:
typedef boost::shared_array<unsigned int> BitmapPtr; typedef boost::shared_array<unsigned int> BitmapPtr;
typedef struct typedef struct
...@@ -71,7 +92,7 @@ protected: ...@@ -71,7 +92,7 @@ protected:
BitmapPtr bitmap; ///< Pixel storage BitmapPtr bitmap; ///< Pixel storage
} CAIRO_BUFFER; } CAIRO_BUFFER;
unsigned int m_current; ///< Currently used buffer handle unsigned int m_current; ///< Currently used buffer handle
typedef std::deque<CAIRO_BUFFER> CAIRO_BUFFERS; typedef std::deque<CAIRO_BUFFER> CAIRO_BUFFERS;
/// Pointer to the current context, so it can be changed /// Pointer to the current context, so it can be changed
......
...@@ -221,6 +221,9 @@ public: ...@@ -221,6 +221,9 @@ public:
/// @copydoc GAL::GetTarget() /// @copydoc GAL::GetTarget()
virtual RenderTarget GetTarget() const; virtual RenderTarget GetTarget() const;
/// @copydoc GAL::ClearTarget()
virtual void ClearTarget( RenderTarget aTarget );
// ------- // -------
// Cursor // Cursor
// ------- // -------
...@@ -267,6 +270,7 @@ private: ...@@ -267,6 +270,7 @@ private:
unsigned int mainBuffer; ///< Handle to the main buffer unsigned int mainBuffer; ///< Handle to the main buffer
unsigned int overlayBuffer; ///< Handle to the overlay buffer unsigned int overlayBuffer; ///< Handle to the overlay buffer
RenderTarget currentTarget; ///< Current rendering target RenderTarget currentTarget; ///< Current rendering target
bool validCompositor; ///< Compositor initialization flag
// Variables related to wxWidgets // Variables related to wxWidgets
wxWindow* parentWindow; ///< Parent window wxWindow* parentWindow; ///< Parent window
......
...@@ -57,12 +57,20 @@ public: ...@@ -57,12 +57,20 @@ public:
virtual void Resize( unsigned int aWidth, unsigned int aHeight ) = 0; virtual void Resize( unsigned int aWidth, unsigned int aHeight ) = 0;
/** /**
* Function GetBuffer() * Function CreateBuffer()
* prepares a new buffer that may be used as a rendering target. * prepares a new buffer that may be used as a rendering target.
* *
* @return is the handle of the buffer. In case of failure 0 (zero) is returned as the handle. * @return is the handle of the buffer. In case of failure 0 (zero) is returned as the handle.
*/ */
virtual unsigned int GetBuffer() = 0; virtual unsigned int CreateBuffer() = 0;
/**
* Function GetBuffer()
* returns currently used buffer handle.
*
* @return Currently used buffer handle.
*/
virtual unsigned int GetBuffer() const = 0;
/** /**
* Function SetBuffer() * Function SetBuffer()
......
...@@ -42,6 +42,9 @@ namespace KiGfx ...@@ -42,6 +42,9 @@ namespace KiGfx
TARGET_NONCACHED, ///< Auxiliary rendering target (noncached) TARGET_NONCACHED, ///< Auxiliary rendering target (noncached)
TARGET_OVERLAY ///< Items that may change while the view stays the same (noncached) TARGET_OVERLAY ///< Items that may change while the view stays the same (noncached)
}; };
/// Number of available rendering targets
static const int TARGETS_NUMBER = 3;
} }
#endif /* DEFINITIONS_H_ */ #endif /* DEFINITIONS_H_ */
...@@ -579,6 +579,13 @@ public: ...@@ -579,6 +579,13 @@ public:
*/ */
virtual RenderTarget GetTarget() const = 0; virtual RenderTarget GetTarget() const = 0;
/**
* @brief Clears the target for rendering.
*
* @param aTarget is the target to be cleared.
*/
virtual void ClearTarget( RenderTarget aTarget ) = 0;
// ------------- // -------------
// Grid methods // Grid methods
// ------------- // -------------
......
...@@ -49,18 +49,30 @@ public: ...@@ -49,18 +49,30 @@ public:
/// @copydoc COMPOSITOR::Resize() /// @copydoc COMPOSITOR::Resize()
virtual void Resize( unsigned int aWidth, unsigned int aHeight ); virtual void Resize( unsigned int aWidth, unsigned int aHeight );
/// @copydoc COMPOSITOR::GetBuffer() /// @copydoc COMPOSITOR::CreateBuffer()
virtual unsigned int GetBuffer(); virtual unsigned int CreateBuffer();
/// @copydoc COMPOSITOR::SetBuffer() /// @copydoc COMPOSITOR::SetBuffer()
virtual void SetBuffer( unsigned int aBufferHandle ); virtual void SetBuffer( unsigned int aBufferHandle );
/// @copydoc COMPOSITOR::GetBuffer()
inline virtual unsigned int GetBuffer() const
{
if( m_currentFbo == DIRECT_RENDERING )
return DIRECT_RENDERING;
return m_current + 1;
}
/// @copydoc COMPOSITOR::ClearBuffer() /// @copydoc COMPOSITOR::ClearBuffer()
virtual void ClearBuffer(); virtual void ClearBuffer();
/// @copydoc COMPOSITOR::DrawBuffer() /// @copydoc COMPOSITOR::DrawBuffer()
virtual void DrawBuffer( unsigned int aBufferHandle ); virtual void DrawBuffer( unsigned int aBufferHandle );
// Constant used by glBindFramebuffer to turn off rendering to framebuffers
static const unsigned int DIRECT_RENDERING = 0;
protected: protected:
typedef struct typedef struct
{ {
......
...@@ -214,6 +214,9 @@ public: ...@@ -214,6 +214,9 @@ public:
/// @copydoc GAL::GetTarget() /// @copydoc GAL::GetTarget()
virtual RenderTarget GetTarget() const; virtual RenderTarget GetTarget() const;
/// @copydoc GAL::ClearTarget()
virtual void ClearTarget( RenderTarget aTarget );
// ------- // -------
// Cursor // Cursor
// ------- // -------
......
...@@ -392,6 +392,20 @@ public: ...@@ -392,6 +392,20 @@ public:
*/ */
bool IsDirty() const; bool IsDirty() const;
/**
* Function SetTargetDirty()
* Sets or clears target 'dirty' flag.
* @param aTarget is the target to set.
* @param aState says if the flag should be set or cleared.
*/
inline void SetTargetDirty( int aTarget, bool aState = true )
{
wxASSERT( aTarget < TARGETS_NUMBER );
m_dirtyTargets[aTarget] = aState;
}
static const int VIEW_MAX_LAYERS = 128; ///* maximum number of layers that may be shown static const int VIEW_MAX_LAYERS = 128; ///* maximum number of layers that may be shown
private: private:
...@@ -462,6 +476,14 @@ private: ...@@ -462,6 +476,14 @@ private:
return ( m_layers.at( aLayer ).target == TARGET_CACHED ); return ( m_layers.at( aLayer ).target == TARGET_CACHED );
} }
/**
* Function isTargetDirty()
* Returns true if any of layers belonging to the target or the target itself should be
* redrawn.
* @return True if the above condition is fulfilled.
*/
bool isTargetDirty( int aTarget ) const;
/// Contains set of possible displayed layers and its properties /// Contains set of possible displayed layers and its properties
LayerMap m_layers; LayerMap m_layers;
...@@ -487,6 +509,9 @@ private: ...@@ -487,6 +509,9 @@ private:
/// static (eg. image/PDF) - does not. /// static (eg. image/PDF) - does not.
bool m_dynamic; bool m_dynamic;
/// Flags to mark targets as dirty, so they have to be redrawn on the next refresh event
bool m_dirtyTargets[TARGETS_NUMBER];
/// Rendering order modifier for layers that are marked as top layers /// Rendering order modifier for layers that are marked as top layers
static const int TOP_LAYER_MODIFIER = -VIEW_MAX_LAYERS; static const int TOP_LAYER_MODIFIER = -VIEW_MAX_LAYERS;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment