GAL code cleaning.

This commit is contained in:
Wayne Stambaugh 2021-02-16 17:25:27 -05:00
parent 0d2ee266a1
commit e7227a4f21
17 changed files with 938 additions and 826 deletions

View File

@ -2,7 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2013-2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2013-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -53,9 +54,8 @@
EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId, EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId,
const wxPoint& aPosition, const wxSize& aSize, const wxPoint& aPosition, const wxSize& aSize,
KIGFX::GAL_DISPLAY_OPTIONS& aOptions, KIGFX::GAL_DISPLAY_OPTIONS& aOptions, GAL_TYPE aGalType ) :
GAL_TYPE aGalType ) wxScrolledCanvas( aParentWindow, aWindowId, aPosition, aSize ),
: wxScrolledCanvas( aParentWindow, aWindowId, aPosition, aSize ),
m_edaFrame( nullptr ), m_edaFrame( nullptr ),
m_gal( nullptr ), m_gal( nullptr ),
m_view( nullptr ), m_view( nullptr ),
@ -96,18 +96,27 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this ); Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this );
Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this ); Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this );
Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( EDA_DRAW_PANEL_GAL::onLostFocus ), NULL, this ); Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( EDA_DRAW_PANEL_GAL::onLostFocus ), NULL, this );
Connect( wxEVT_SET_CURSOR, wxSetCursorEventHandler( EDA_DRAW_PANEL_GAL::onSetCursor ), NULL, this ); Connect( wxEVT_SET_CURSOR, wxSetCursorEventHandler( EDA_DRAW_PANEL_GAL::onSetCursor ), NULL,
this );
const wxEventType events[] = const wxEventType events[] = {
{
// Binding both EVT_CHAR and EVT_CHAR_HOOK ensures that all key events, // Binding both EVT_CHAR and EVT_CHAR_HOOK ensures that all key events,
// especially special key like arrow keys, are handled by the GAL event dispatcher, // especially special key like arrow keys, are handled by the GAL event dispatcher,
// and not sent to GUI without filtering, because they have a default action (scroll) // and not sent to GUI without filtering, because they have a default action (scroll)
// that must not be called. // that must not be called.
wxEVT_LEFT_UP, wxEVT_LEFT_DOWN, wxEVT_LEFT_DCLICK, wxEVT_LEFT_UP,
wxEVT_RIGHT_UP, wxEVT_RIGHT_DOWN, wxEVT_RIGHT_DCLICK, wxEVT_LEFT_DOWN,
wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DOWN, wxEVT_MIDDLE_DCLICK, wxEVT_LEFT_DCLICK,
wxEVT_MOTION, wxEVT_MOUSEWHEEL, wxEVT_CHAR, wxEVT_CHAR_HOOK, wxEVT_RIGHT_UP,
wxEVT_RIGHT_DOWN,
wxEVT_RIGHT_DCLICK,
wxEVT_MIDDLE_UP,
wxEVT_MIDDLE_DOWN,
wxEVT_MIDDLE_DCLICK,
wxEVT_MOTION,
wxEVT_MOUSEWHEEL,
wxEVT_CHAR,
wxEVT_CHAR_HOOK,
#if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT ) #if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
wxEVT_MAGNIFY, wxEVT_MAGNIFY,
#endif #endif
@ -115,7 +124,8 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
}; };
for( wxEventType eventType : events ) for( wxEventType eventType : events )
Connect( eventType, wxEventHandler( EDA_DRAW_PANEL_GAL::OnEvent ), NULL, m_eventDispatcher ); Connect( eventType, wxEventHandler( EDA_DRAW_PANEL_GAL::OnEvent ), NULL,
m_eventDispatcher );
m_pendingRefresh = false; m_pendingRefresh = false;
m_drawing = false; m_drawing = false;
@ -187,7 +197,8 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
wxASSERT( m_painter ); wxASSERT( m_painter );
m_drawing = true; m_drawing = true;
KIGFX::RENDER_SETTINGS* settings = static_cast<KIGFX::RENDER_SETTINGS*>( m_painter->GetSettings() ); KIGFX::RENDER_SETTINGS* settings =
static_cast<KIGFX::RENDER_SETTINGS*>( m_painter->GetSettings() );
try try
{ {
@ -206,7 +217,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
m_gal->SetCursorColor( settings->GetCursorColor() ); m_gal->SetCursorColor( settings->GetCursorColor() );
// TODO: find why ClearScreen() must be called here in opengl mode // TODO: find why ClearScreen() must be called here in opengl mode
// and only if m_view->IsDirty() in Cairo mode to avoid distaly artifacts // and only if m_view->IsDirty() in Cairo mode to avoid display artifacts
// when moving the mouse cursor // when moving the mouse cursor
if( m_backend == GAL_TYPE_OPENGL ) if( m_backend == GAL_TYPE_OPENGL )
m_gal->ClearScreen(); m_gal->ClearScreen();
@ -313,8 +324,6 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool aEraseBackground, const wxRect* aRect )
void EDA_DRAW_PANEL_GAL::ForceRefresh() void EDA_DRAW_PANEL_GAL::ForceRefresh()
{ {
//wxPaintEvent redrawEvent;
//wxPostEvent( this, redrawEvent );
m_pendingRefresh = true; m_pendingRefresh = true;
DoRePaint(); DoRePaint();
} }
@ -338,9 +347,10 @@ void EDA_DRAW_PANEL_GAL::SetEventDispatcher( TOOL_DISPATCHER* aEventDispatcher )
for( wxEventType type : eventTypes ) for( wxEventType type : eventTypes )
{ {
// While loop is used to be sure that all event handlers are removed. // While loop is used to be sure that all event handlers are removed.
while( m_parent->Disconnect( type, while( m_parent->Disconnect(
wxCommandEventHandler( TOOL_DISPATCHER::DispatchWxCommand ), type, wxCommandEventHandler( TOOL_DISPATCHER::DispatchWxCommand ), NULL,
NULL, m_eventDispatcher ) ); m_eventDispatcher ) )
;
} }
} }
} }
@ -416,7 +426,8 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType )
if( GAL_FALLBACK != aGalType ) if( GAL_FALLBACK != aGalType )
{ {
aGalType = GAL_FALLBACK; aGalType = GAL_FALLBACK;
DisplayInfoMessage( m_parent, DisplayInfoMessage(
m_parent,
_( "Could not use OpenGL, falling back to software rendering" ), _( "Could not use OpenGL, falling back to software rendering" ),
errormsg ); errormsg );
new_gal = new KIGFX::CAIRO_GAL( m_options, this, this, this ); new_gal = new KIGFX::CAIRO_GAL( m_options, this, this, this );
@ -430,9 +441,7 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType )
break; break;
} }
case GAL_TYPE_CAIRO: case GAL_TYPE_CAIRO: new_gal = new KIGFX::CAIRO_GAL( m_options, this, this, this ); break;
new_gal = new KIGFX::CAIRO_GAL( m_options, this, this, this );
break;
default: default:
wxASSERT( false ); wxASSERT( false );
@ -455,8 +464,7 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType )
result = false; result = false;
} }
// trigger update of the gal options in case they differ // trigger update of the gal options in case they differ from the defaults
// from the defaults
m_options.NotifyChanged(); m_options.NotifyChanged();
wxWindow* galWindow = dynamic_cast<wxWindow*>( new_gal ); wxWindow* galWindow = dynamic_cast<wxWindow*>( new_gal );
@ -499,8 +507,7 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType )
void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent ) void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent )
{ {
bool shouldSetFocus = m_lostFocus && m_stealsFocus bool shouldSetFocus = m_lostFocus && m_stealsFocus && !KIUI::IsInputControlFocused()
&& !KIUI::IsInputControlFocused()
&& !KIUI::IsModalDialogFocused(); && !KIUI::IsModalDialogFocused();
#if defined( _WIN32 ) #if defined( _WIN32 )
@ -523,9 +530,8 @@ void EDA_DRAW_PANEL_GAL::OnEvent( wxEvent& aEvent )
void EDA_DRAW_PANEL_GAL::onEnter( wxMouseEvent& aEvent ) void EDA_DRAW_PANEL_GAL::onEnter( wxMouseEvent& aEvent )
{ {
bool shouldSetFocus = m_stealsFocus bool shouldSetFocus =
&& !KIUI::IsInputControlFocused() m_stealsFocus && !KIUI::IsInputControlFocused() && !KIUI::IsModalDialogFocused();
&& !KIUI::IsModalDialogFocused();
#if defined( _WIN32 ) #if defined( _WIN32 )
// Ensure we are the active foreground window before we attempt to steal focus // Ensure we are the active foreground window before we attempt to steal focus
@ -570,8 +576,6 @@ void EDA_DRAW_PANEL_GAL::onRefreshTimer( wxTimerEvent& aEvent )
} }
} }
//wxPaintEvent redrawEvent;
//wxPostEvent( this, redrawEvent );
DoRePaint(); DoRePaint();
} }

View File

@ -2,7 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -35,7 +36,9 @@
using namespace KIGFX; 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 ),
m_currentAntialiasingMode( CAIRO_ANTIALIAS_DEFAULT ) m_currentAntialiasingMode( CAIRO_ANTIALIAS_DEFAULT )
{ {
// Do not have uninitialized members: // Do not have uninitialized members:
@ -59,20 +62,12 @@ void CAIRO_COMPOSITOR::Initialize()
void CAIRO_COMPOSITOR::SetAntialiasingMode( CAIRO_ANTIALIASING_MODE aMode ) void CAIRO_COMPOSITOR::SetAntialiasingMode( CAIRO_ANTIALIASING_MODE aMode )
{ {
switch( aMode ) switch( aMode )
{ {
case CAIRO_ANTIALIASING_MODE::FAST: case CAIRO_ANTIALIASING_MODE::FAST: m_currentAntialiasingMode = CAIRO_ANTIALIAS_FAST; break;
m_currentAntialiasingMode = CAIRO_ANTIALIAS_FAST; case CAIRO_ANTIALIASING_MODE::GOOD: m_currentAntialiasingMode = CAIRO_ANTIALIAS_GOOD; break;
break; case CAIRO_ANTIALIASING_MODE::BEST: m_currentAntialiasingMode = CAIRO_ANTIALIAS_BEST; break;
case CAIRO_ANTIALIASING_MODE::GOOD: default: m_currentAntialiasingMode = CAIRO_ANTIALIAS_NONE;
m_currentAntialiasingMode = CAIRO_ANTIALIAS_GOOD;
break;
case CAIRO_ANTIALIASING_MODE::BEST:
m_currentAntialiasingMode = CAIRO_ANTIALIAS_BEST;
break;
default:
m_currentAntialiasingMode = CAIRO_ANTIALIAS_NONE;
} }
clean(); clean();
@ -98,10 +93,9 @@ unsigned int CAIRO_COMPOSITOR::CreateBuffer()
// Create the Cairo surface // Create the Cairo surface
cairo_surface_t* surface = cairo_image_surface_create_for_data( cairo_surface_t* surface = cairo_image_surface_create_for_data(
(unsigned char*) bitmap, (unsigned char*) bitmap, CAIRO_FORMAT_ARGB32, m_width, m_height, m_stride );
CAIRO_FORMAT_ARGB32, m_width,
m_height, m_stride );
cairo_t* context = cairo_create( surface ); cairo_t* context = cairo_create( surface );
#ifdef DEBUG #ifdef DEBUG
cairo_status_t status = cairo_status( context ); cairo_status_t status = cairo_status( context );
wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, wxT( "Cairo context creation error" ) ); wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, wxT( "Cairo context creation error" ) );
@ -136,10 +130,12 @@ void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
cairo_set_matrix( *m_currentContext, &m_matrix ); cairo_set_matrix( *m_currentContext, &m_matrix );
} }
void CAIRO_COMPOSITOR::Begin() void CAIRO_COMPOSITOR::Begin()
{ {
} }
void CAIRO_COMPOSITOR::ClearBuffer( const COLOR4D& aColor ) void CAIRO_COMPOSITOR::ClearBuffer( const COLOR4D& aColor )
{ {
// Clear the pixel storage // Clear the pixel storage
@ -164,10 +160,12 @@ void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
cairo_set_matrix( m_mainContext, &m_matrix ); cairo_set_matrix( m_mainContext, &m_matrix );
} }
void CAIRO_COMPOSITOR::Present() void CAIRO_COMPOSITOR::Present()
{ {
} }
void CAIRO_COMPOSITOR::clean() void CAIRO_COMPOSITOR::clean()
{ {
CAIRO_BUFFERS::const_iterator it; CAIRO_BUFFERS::const_iterator it;

View File

@ -2,8 +2,9 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012-2020 Kicad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2012-2021 Kicad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017-2018 CERN * Copyright (C) 2017-2018 CERN
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* CairoGal - Graphics Abstraction Layer for Cairo * CairoGal - Graphics Abstraction Layer for Cairo
@ -45,9 +46,7 @@
using namespace KIGFX; using namespace KIGFX;
CAIRO_GAL_BASE::CAIRO_GAL_BASE( GAL_DISPLAY_OPTIONS& aDisplayOptions ) : GAL( aDisplayOptions )
CAIRO_GAL_BASE::CAIRO_GAL_BASE( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
GAL( aDisplayOptions )
{ {
// Initialise grouping // Initialise grouping
isGrouping = false; isGrouping = false;
@ -103,6 +102,7 @@ void CAIRO_GAL_BASE::endDrawing()
Flush(); Flush();
} }
void CAIRO_GAL_BASE::updateWorldScreenMatrix() void CAIRO_GAL_BASE::updateWorldScreenMatrix()
{ {
cairo_matrix_multiply( &currentWorld2Screen, &currentXform, &cairoWorldScreenMatrix ); cairo_matrix_multiply( &currentWorld2Screen, &currentXform, &cairoWorldScreenMatrix );
@ -268,7 +268,8 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
auto pb = xform( aEndPoint ); auto pb = xform( aEndPoint );
auto rb = ( pa0 - pa ).EuclideanNorm(); auto rb = ( pa0 - pa ).EuclideanNorm();
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b,
strokeColor.a );
cairo_move_to( currentContext, pa0.x, pa0.y ); cairo_move_to( currentContext, pa0.x, pa0.y );
cairo_line_to( currentContext, pb0.x, pb0.y ); cairo_line_to( currentContext, pb0.x, pb0.y );
@ -277,7 +278,8 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
cairo_line_to( currentContext, pb1.x, pb1.y ); cairo_line_to( currentContext, pb1.x, pb1.y );
cairo_arc( currentContext, pb.x, pb.y, rb, lineAngle - M_PI / 2.0, lineAngle + M_PI / 2.0 ); cairo_arc( currentContext, pb.x, pb.y, rb, lineAngle - M_PI / 2.0, lineAngle + M_PI / 2.0 );
cairo_arc( currentContext, pa.x, pa.y, rb, lineAngle + M_PI / 2.0, lineAngle + 3.0 * M_PI / 2.0 ); cairo_arc( currentContext, pa.x, pa.y, rb, lineAngle + M_PI / 2.0,
lineAngle + 3.0 * M_PI / 2.0 );
flushPath(); flushPath();
} }
@ -338,8 +340,8 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, doub
} }
void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
double aEndAngle, double aWidth ) double aStartAngle, double aEndAngle, double aWidth )
{ {
if( isFillEnabled ) if( isFillEnabled )
{ {
@ -375,7 +377,8 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
cairo_save( currentContext ); cairo_save( currentContext );
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b,
strokeColor.a );
cairo_translate( currentContext, mid.x, mid.y ); cairo_translate( currentContext, mid.x, mid.y );
@ -386,7 +389,8 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
cairo_arc( currentContext, 0, 0, r + width, startAngleS, endAngleS ); cairo_arc( currentContext, 0, 0, r + width, startAngleS, endAngleS );
cairo_new_sub_path( currentContext ); cairo_new_sub_path( currentContext );
cairo_arc_negative( currentContext, startPointS.x, startPointS.y, width, startAngleS, startAngleS + M_PI ); cairo_arc_negative( currentContext, startPointS.x, startPointS.y, width, startAngleS,
startAngleS + M_PI );
cairo_new_sub_path( currentContext ); cairo_new_sub_path( currentContext );
cairo_arc( currentContext, endPointS.x, endPointS.y, width, endAngleS, endAngleS + M_PI ); cairo_arc( currentContext, endPointS.x, endPointS.y, width, endAngleS, endAngleS + M_PI );
@ -477,12 +481,12 @@ void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap )
cairo_surface_flush( image ); cairo_surface_flush( image );
unsigned char* pix_buffer = cairo_image_surface_get_data( image ); unsigned char* pix_buffer = cairo_image_surface_get_data( image );
// The pixel buffer of the initial bitmap: // The pixel buffer of the initial bitmap:
const wxImage& bm_pix_buffer = *aBitmap.GetImageData(); const wxImage& bm_pix_buffer = *aBitmap.GetImageData();
uint32_t mask_color = ( bm_pix_buffer.GetMaskRed() << 16 ) + uint32_t mask_color = ( bm_pix_buffer.GetMaskRed() << 16 )
( bm_pix_buffer.GetMaskGreen() << 8 ) + + ( bm_pix_buffer.GetMaskGreen() << 8 ) + ( bm_pix_buffer.GetMaskBlue() );
( bm_pix_buffer.GetMaskBlue() );
// Copy the source bitmap to the cairo bitmap buffer. // Copy the source bitmap to the cairo bitmap buffer.
// In cairo bitmap buffer, a ARGB32 bitmap is an ARGB pixel packed into a uint_32 // In cairo bitmap buffer, a ARGB32 bitmap is an ARGB pixel packed into a uint_32
@ -639,12 +643,9 @@ void CAIRO_GAL_BASE::Transform( const MATRIX3x3D& aTransformation )
{ {
cairo_matrix_t cairoTransformation, newXform; cairo_matrix_t cairoTransformation, newXform;
cairo_matrix_init( &cairoTransformation, cairo_matrix_init( &cairoTransformation, aTransformation.m_data[0][0],
aTransformation.m_data[0][0], aTransformation.m_data[1][0], aTransformation.m_data[0][1],
aTransformation.m_data[1][0], aTransformation.m_data[1][1], aTransformation.m_data[0][2],
aTransformation.m_data[0][1],
aTransformation.m_data[1][1],
aTransformation.m_data[0][2],
aTransformation.m_data[1][2] ); aTransformation.m_data[1][2] );
cairo_matrix_multiply( &newXform, &currentXform, &cairoTransformation ); cairo_matrix_multiply( &newXform, &currentXform, &cairoTransformation );
@ -782,8 +783,7 @@ void CAIRO_GAL_BASE::DrawGroup( int aGroupNumber )
storePath(); storePath();
for( GROUP::iterator it = groups[aGroupNumber].begin(); for( GROUP::iterator it = groups[aGroupNumber].begin(); it != groups[aGroupNumber].end(); ++it )
it != groups[aGroupNumber].end(); ++it )
{ {
switch( it->command ) switch( it->command )
{ {
@ -796,13 +796,13 @@ void CAIRO_GAL_BASE::DrawGroup( int aGroupNumber )
break; break;
case CMD_SET_FILLCOLOR: case CMD_SET_FILLCOLOR:
fillColor = COLOR4D( it->argument.dblArg[0], it->argument.dblArg[1], it->argument.dblArg[2], fillColor = COLOR4D( it->argument.dblArg[0], it->argument.dblArg[1],
it->argument.dblArg[3] ); it->argument.dblArg[2], it->argument.dblArg[3] );
break; break;
case CMD_SET_STROKECOLOR: case CMD_SET_STROKECOLOR:
strokeColor = COLOR4D( it->argument.dblArg[0], it->argument.dblArg[1], it->argument.dblArg[2], strokeColor = COLOR4D( it->argument.dblArg[0], it->argument.dblArg[1],
it->argument.dblArg[3] ); it->argument.dblArg[2], it->argument.dblArg[3] );
break; break;
case CMD_SET_LINE_WIDTH: case CMD_SET_LINE_WIDTH:
@ -812,18 +812,20 @@ void CAIRO_GAL_BASE::DrawGroup( int aGroupNumber )
cairo_device_to_user_distance( currentContext, &x, &y ); cairo_device_to_user_distance( currentContext, &x, &y );
double minWidth = std::min( fabs( x ), fabs( y ) ); double minWidth = std::min( fabs( x ), fabs( y ) );
cairo_set_line_width( currentContext, std::max( it->argument.dblArg[0], minWidth ) ); cairo_set_line_width( currentContext, std::max( it->argument.dblArg[0], minWidth ) );
}
break; break;
}
case CMD_STROKE_PATH: case CMD_STROKE_PATH:
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b,
strokeColor.a );
cairo_append_path( currentContext, it->cairoPath ); cairo_append_path( currentContext, it->cairoPath );
cairo_stroke( currentContext ); cairo_stroke( currentContext );
break; break;
case CMD_FILL_PATH: case CMD_FILL_PATH:
cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, strokeColor.a ); cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b,
strokeColor.a );
cairo_append_path( currentContext, it->cairoPath ); cairo_append_path( currentContext, it->cairoPath );
cairo_fill( currentContext ); cairo_fill( currentContext );
break; break;
@ -869,8 +871,7 @@ void CAIRO_GAL_BASE::ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColo
{ {
storePath(); storePath();
for( GROUP::iterator it = groups[aGroupNumber].begin(); for( GROUP::iterator it = groups[aGroupNumber].begin(); it != groups[aGroupNumber].end(); ++it )
it != groups[aGroupNumber].end(); ++it )
{ {
if( it->command == CMD_SET_FILLCOLOR || it->command == CMD_SET_STROKECOLOR ) if( it->command == CMD_SET_FILLCOLOR || it->command == CMD_SET_STROKECOLOR )
{ {
@ -1030,12 +1031,12 @@ void CAIRO_GAL_BASE::drawGridPoint( const VECTOR2D& aPoint, double aWidth, doubl
cairo_fill( currentContext ); cairo_fill( currentContext );
} }
void CAIRO_GAL_BASE::flushPath() void CAIRO_GAL_BASE::flushPath()
{ {
if( isFillEnabled ) if( isFillEnabled )
{ {
cairo_set_source_rgba( currentContext, cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
fillColor.r, fillColor.g, fillColor.b, fillColor.a );
if( isStrokeEnabled ) if( isStrokeEnabled )
cairo_fill_preserve( currentContext ); cairo_fill_preserve( currentContext );
@ -1045,8 +1046,8 @@ void CAIRO_GAL_BASE::flushPath()
if( isStrokeEnabled ) if( isStrokeEnabled )
{ {
cairo_set_source_rgba( currentContext, cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b,
strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); strokeColor.a );
cairo_stroke( currentContext ); cairo_stroke( currentContext );
} }
} }
@ -1062,14 +1063,15 @@ void CAIRO_GAL_BASE::storePath()
{ {
if( isFillEnabled ) if( isFillEnabled )
{ {
cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a ); cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b,
fillColor.a );
cairo_fill_preserve( currentContext ); cairo_fill_preserve( currentContext );
} }
if( isStrokeEnabled ) if( isStrokeEnabled )
{ {
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b,
strokeColor.b, strokeColor.a ); strokeColor.a );
cairo_stroke_preserve( currentContext ); cairo_stroke_preserve( currentContext );
} }
} }
@ -1110,8 +1112,8 @@ void CAIRO_GAL_BASE::blitCursor( wxMemoryDC& clientDC )
const auto cColor = getCursorColor(); const auto cColor = getCursorColor();
const int cursorSize = fullscreenCursor ? 8000 : 80; const int cursorSize = fullscreenCursor ? 8000 : 80;
wxColour color( cColor.r * cColor.a * 255, cColor.g * cColor.a * 255, wxColour color( cColor.r * cColor.a * 255, cColor.g * cColor.a * 255, cColor.b * cColor.a * 255,
cColor.b * cColor.a * 255, 255 ); 255 );
clientDC.SetPen( wxPen( color ) ); clientDC.SetPen( wxPen( color ) );
clientDC.DrawLine( p.x - cursorSize / 2, p.y, p.x + cursorSize / 2, p.y ); clientDC.DrawLine( p.x - cursorSize / 2, p.y, p.x + cursorSize / 2, p.y );
clientDC.DrawLine( p.x, p.y - cursorSize / 2, p.x, p.y + cursorSize / 2 ); clientDC.DrawLine( p.x, p.y - cursorSize / 2, p.x, p.y + cursorSize / 2 );
@ -1206,9 +1208,9 @@ unsigned int CAIRO_GAL_BASE::getNewGroupNumber()
} }
CAIRO_GAL::CAIRO_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, CAIRO_GAL::CAIRO_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent,
wxWindow* aParent, wxEvtHandler* aMouseListener, wxEvtHandler* aMouseListener, wxEvtHandler* aPaintListener,
wxEvtHandler* aPaintListener, const wxString& aName ) : const wxString& aName ) :
CAIRO_GAL_BASE( aDisplayOptions ), CAIRO_GAL_BASE( aDisplayOptions ),
wxWindow( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxEXPAND, aName ) wxWindow( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxEXPAND, aName )
{ {
@ -1286,14 +1288,15 @@ void CAIRO_GAL::endDrawing()
// by cairo into a format understood by wxImage. // by cairo into a format understood by wxImage.
pixman_image_t* dstImg = pixman_image_create_bits( pixman_image_t* dstImg = pixman_image_create_bits(
wxPlatformInfo::Get().GetEndianness() == wxENDIAN_LITTLE ? PIXMAN_b8g8r8 : wxPlatformInfo::Get().GetEndianness() == wxENDIAN_LITTLE ? PIXMAN_b8g8r8
PIXMAN_r8g8b8, : PIXMAN_r8g8b8,
screenSize.x, screenSize.y, (uint32_t*) wxOutput, wxBufferWidth * 3 ); screenSize.x, screenSize.y, (uint32_t*) wxOutput, wxBufferWidth * 3 );
pixman_image_t* srcImg = pixman_image_create_bits( PIXMAN_a8r8g8b8, screenSize.x, screenSize.y, pixman_image_t* srcImg =
pixman_image_create_bits( PIXMAN_a8r8g8b8, screenSize.x, screenSize.y,
(uint32_t*) bitmapBuffer, wxBufferWidth * 4 ); (uint32_t*) bitmapBuffer, wxBufferWidth * 4 );
pixman_image_composite( PIXMAN_OP_SRC, srcImg, NULL, dstImg, pixman_image_composite( PIXMAN_OP_SRC, srcImg, NULL, dstImg, 0, 0, 0, 0, 0, 0, screenSize.x,
0, 0, 0, 0, 0, 0, screenSize.x, screenSize.y ); screenSize.y );
// Free allocated memory // Free allocated memory
pixman_image_unref( srcImg ); pixman_image_unref( srcImg );
@ -1379,13 +1382,9 @@ void CAIRO_GAL::SetTarget( RENDER_TARGET aTarget )
{ {
default: default:
case TARGET_CACHED: case TARGET_CACHED:
case TARGET_NONCACHED: case TARGET_NONCACHED: compositor->SetBuffer( mainBuffer ); break;
compositor->SetBuffer( mainBuffer );
break;
case TARGET_OVERLAY: case TARGET_OVERLAY: compositor->SetBuffer( overlayBuffer ); break;
compositor->SetBuffer( overlayBuffer );
break;
} }
currentTarget = aTarget; currentTarget = aTarget;
@ -1408,13 +1407,8 @@ void CAIRO_GAL::ClearTarget( RENDER_TARGET aTarget )
// Cached and noncached items are rendered to the same buffer // Cached and noncached items are rendered to the same buffer
default: default:
case TARGET_CACHED: case TARGET_CACHED:
case TARGET_NONCACHED: case TARGET_NONCACHED: compositor->SetBuffer( mainBuffer ); break;
compositor->SetBuffer( mainBuffer ); case TARGET_OVERLAY: compositor->SetBuffer( overlayBuffer ); break;
break;
case TARGET_OVERLAY:
compositor->SetBuffer( overlayBuffer );
break;
} }
compositor->ClearBuffer( COLOR4D::BLACK ); compositor->ClearBuffer( COLOR4D::BLACK );
@ -1429,8 +1423,8 @@ void CAIRO_GAL::initSurface()
if( isInitialized ) if( isInitialized )
return; return;
surface = cairo_image_surface_create_for_data( bitmapBuffer, GAL_FORMAT, surface = cairo_image_surface_create_for_data( bitmapBuffer, GAL_FORMAT, wxBufferWidth,
wxBufferWidth, screenSize.y, stride ); screenSize.y, stride );
context = cairo_create( surface ); context = cairo_create( surface );
@ -1438,6 +1432,7 @@ void CAIRO_GAL::initSurface()
cairo_status_t status = cairo_status( context ); cairo_status_t status = cairo_status( context );
wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, wxT( "Cairo context creation error" ) ); wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, wxT( "Cairo context creation error" ) );
#endif /* DEBUG */ #endif /* DEBUG */
currentContext = context; currentContext = context;
isInitialized = true; isInitialized = true;
@ -1461,7 +1456,9 @@ void CAIRO_GAL::deinitSurface()
void CAIRO_GAL::allocateBitmaps() void CAIRO_GAL::allocateBitmaps()
{ {
wxBufferWidth = screenSize.x; wxBufferWidth = screenSize.x;
while( ( ( wxBufferWidth * 3 ) % 4 ) != 0 ) wxBufferWidth++;
while( ( ( wxBufferWidth * 3 ) % 4 ) != 0 )
wxBufferWidth++;
// Create buffer, use the system independent Cairo context backend // Create buffer, use the system independent Cairo context backend
stride = cairo_format_stride_for_width( GAL_FORMAT, wxBufferWidth ); stride = cairo_format_stride_for_width( GAL_FORMAT, wxBufferWidth );
@ -1520,7 +1517,6 @@ bool CAIRO_GAL::updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions )
if( validCompositor && aOptions.cairo_antialiasing_mode != compositor->GetAntialiasingMode() ) if( validCompositor && aOptions.cairo_antialiasing_mode != compositor->GetAntialiasingMode() )
{ {
compositor->SetAntialiasingMode( options.cairo_antialiasing_mode ); compositor->SetAntialiasingMode( options.cairo_antialiasing_mode );
validCompositor = false; validCompositor = false;
deinitSurface(); deinitSurface();
@ -1593,8 +1589,10 @@ void CAIRO_GAL_BASE::DrawGrid()
SWAP( gridStartY, >, gridEndY ); SWAP( gridStartY, >, gridEndY );
// Ensure the grid fills the screen // Ensure the grid fills the screen
--gridStartX; ++gridEndX; --gridStartX;
--gridStartY; ++gridEndY; ++gridEndX;
--gridStartY;
++gridEndY;
// Draw the grid behind all other layers // Draw the grid behind all other layers
SetLayerDepth( depthRange.y * 0.75 ); SetLayerDepth( depthRange.y * 0.75 );
@ -1627,7 +1625,6 @@ void CAIRO_GAL_BASE::DrawGrid()
SetLineWidth( ( i % gridTick ) ? marker : doubleMarker ); SetLineWidth( ( i % gridTick ) ? marker : doubleMarker );
drawGridLine( VECTOR2D( x, gridStartY * gridScreenSize.y + gridOrigin.y ), drawGridLine( VECTOR2D( x, gridStartY * gridScreenSize.y + gridOrigin.y ),
VECTOR2D( x, gridEndY * gridScreenSize.y + gridOrigin.y ) ); VECTOR2D( x, gridEndY * gridScreenSize.y + gridOrigin.y ) );
} }
} }
else // Dots or Crosses grid else // Dots or Crosses grid
@ -1659,4 +1656,3 @@ void CAIRO_GAL_BASE::DrawGrid()
} }
} }
} }

View File

@ -1,5 +1,7 @@
/* /*
* Copyright (C) 2019 CERN * Copyright (C) 2019 CERN
* Copyright (C) 2021 Kicad Developers, see AUTHORS.txt for contributors.
*
* Author: Maciej Suminski <maciej.suminski@cern.ch> * Author: Maciej Suminski <maciej.suminski@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
@ -27,8 +29,8 @@
#ifdef NOMINMAX /* workaround for gdiplus.h */ #ifdef NOMINMAX /* workaround for gdiplus.h */
#include <algorithm> #include <algorithm>
using std::min;
using std::max; using std::max;
using std::min;
#endif #endif
#ifdef __WXMSW__ #ifdef __WXMSW__
@ -45,8 +47,10 @@ using std::max;
using namespace KIGFX; using namespace KIGFX;
CAIRO_PRINT_CTX::CAIRO_PRINT_CTX( wxDC* aDC ) CAIRO_PRINT_CTX::CAIRO_PRINT_CTX( wxDC* aDC ) :
: m_gcdc( nullptr ), m_ctx( nullptr ), m_surface( nullptr ) m_gcdc( nullptr ),
m_ctx( nullptr ),
m_surface( nullptr )
{ {
if( wxPrinterDC* printerDC = dynamic_cast<wxPrinterDC*>( aDC ) ) if( wxPrinterDC* printerDC = dynamic_cast<wxPrinterDC*>( aDC ) )
m_gcdc = new wxGCDC( *printerDC ); m_gcdc = new wxGCDC( *printerDC );
@ -69,6 +73,7 @@ CAIRO_PRINT_CTX::CAIRO_PRINT_CTX( wxDC* aDC )
#ifdef __WXGTK__ #ifdef __WXGTK__
m_ctx = static_cast<cairo_t*>( gctx->GetNativeContext() ); m_ctx = static_cast<cairo_t*>( gctx->GetNativeContext() );
m_surface = cairo_get_target( m_ctx ); m_surface = cairo_get_target( m_ctx );
// On linux, cairo printers have 72 DPI by default. // On linux, cairo printers have 72 DPI by default.
// This is an unusable resolution for us. // This is an unusable resolution for us.
// A better resolution could be 4800 DPI (at 600 DPI, we still have minor // A better resolution could be 4800 DPI (at 600 DPI, we still have minor
@ -76,8 +81,10 @@ CAIRO_PRINT_CTX::CAIRO_PRINT_CTX( wxDC* aDC )
// so modify the default: // so modify the default:
#define DEFAULT_DPI 72.0 #define DEFAULT_DPI 72.0
#define KICAD_PRINTER_DPI 4800.0 #define KICAD_PRINTER_DPI 4800.0
// our device scale is DEFAULT_DPI / KICAD_PRINTER_DPI // our device scale is DEFAULT_DPI / KICAD_PRINTER_DPI
cairo_surface_set_device_scale( m_surface, DEFAULT_DPI/KICAD_PRINTER_DPI, DEFAULT_DPI/KICAD_PRINTER_DPI ); cairo_surface_set_device_scale( m_surface, DEFAULT_DPI / KICAD_PRINTER_DPI,
DEFAULT_DPI / KICAD_PRINTER_DPI );
m_dpi = KICAD_PRINTER_DPI; m_dpi = KICAD_PRINTER_DPI;
#endif /* __WXGTK__ */ #endif /* __WXGTK__ */
@ -125,8 +132,8 @@ CAIRO_PRINT_CTX::~CAIRO_PRINT_CTX()
CAIRO_PRINT_GAL::CAIRO_PRINT_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, CAIRO_PRINT_GAL::CAIRO_PRINT_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions,
std::unique_ptr<CAIRO_PRINT_CTX> aContext ) std::unique_ptr<CAIRO_PRINT_CTX> aContext ) :
: CAIRO_GAL_BASE( aDisplayOptions ) CAIRO_GAL_BASE( aDisplayOptions )
{ {
m_printCtx = std::move( aContext ); m_printCtx = std::move( aContext );
context = currentContext = m_printCtx->GetContext(); context = currentContext = m_printCtx->GetContext();
@ -144,7 +151,8 @@ CAIRO_PRINT_GAL::CAIRO_PRINT_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions,
void CAIRO_PRINT_GAL::ComputeWorldScreenMatrix() void CAIRO_PRINT_GAL::ComputeWorldScreenMatrix()
{ {
worldScale = screenDPI * worldUnitLength * zoomFactor; worldScale = screenDPI * worldUnitLength * zoomFactor;
const auto paperSizeIU = VECTOR2D( m_nativePaperSize.y, m_nativePaperSize.x ) /* inches */ / worldUnitLength; /* 1 inch in IU */ const auto paperSizeIU = VECTOR2D( m_nativePaperSize.y, m_nativePaperSize.x ) /* inches */
/ worldUnitLength; /* 1 inch in IU */
const auto paperSizeIUTransposed = VECTOR2D( paperSizeIU.y, paperSizeIU.x ); const auto paperSizeIUTransposed = VECTOR2D( paperSizeIU.y, paperSizeIU.x );
MATRIX3x3D scale, translation, flip, rotate, lookat; MATRIX3x3D scale, translation, flip, rotate, lookat;

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2016 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 2016-2021 Kicad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -39,8 +39,8 @@ using namespace KIGFX;
// ANTIALIASING_NONE // ANTIALIASING_NONE
// ========================= // =========================
ANTIALIASING_NONE::ANTIALIASING_NONE( OPENGL_COMPOSITOR* aCompositor ) ANTIALIASING_NONE::ANTIALIASING_NONE( OPENGL_COMPOSITOR* aCompositor ) :
: compositor( aCompositor ) compositor( aCompositor )
{ {
} }
@ -88,8 +88,8 @@ unsigned int ANTIALIASING_NONE::CreateBuffer()
} }
namespace { namespace
{
void draw_fullscreen_primitive() void draw_fullscreen_primitive()
{ {
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
@ -121,16 +121,16 @@ namespace {
glPopMatrix(); glPopMatrix();
} }
} } // namespace
// ========================= // =========================
// ANTIALIASING_SUPERSAMPLING // ANTIALIASING_SUPERSAMPLING
// ========================= // =========================
ANTIALIASING_SUPERSAMPLING::ANTIALIASING_SUPERSAMPLING( OPENGL_COMPOSITOR* aCompositor, ANTIALIASING_SUPERSAMPLING::ANTIALIASING_SUPERSAMPLING( OPENGL_COMPOSITOR* aCompositor,
SUPERSAMPLING_MODE aMode ) SUPERSAMPLING_MODE aMode ) :
: compositor( aCompositor ), mode( aMode ), ssaaMainBuffer( 0 ), compositor( aCompositor ),
areBuffersCreated( false ), areShadersCreated( false ) mode( aMode ), ssaaMainBuffer( 0 ), areBuffersCreated( false ), areShadersCreated( false )
{ {
} }
@ -140,16 +140,22 @@ bool ANTIALIASING_SUPERSAMPLING::Init()
if( mode == SUPERSAMPLING_MODE::X4 && !areShadersCreated ) if( mode == SUPERSAMPLING_MODE::X4 && !areShadersCreated )
{ {
x4_shader = std::make_unique<SHADER>(); x4_shader = std::make_unique<SHADER>();
x4_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, BUILTIN_SHADERS::ssaa_x4_vertex_shader ); x4_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX,
x4_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, BUILTIN_SHADERS::ssaa_x4_fragment_shader ); BUILTIN_SHADERS::ssaa_x4_vertex_shader );
x4_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT,
BUILTIN_SHADERS::ssaa_x4_fragment_shader );
x4_shader->Link(); x4_shader->Link();
checkGlError( "linking supersampling x4 shader" ); checkGlError( "linking supersampling x4 shader" );
GLint source_parameter = x4_shader->AddParameter( "source" ); checkGlError( "getting pass 1 colorTex" ); GLint source_parameter = x4_shader->AddParameter( "source" );
checkGlError( "getting pass 1 colorTex" );
x4_shader->Use(); checkGlError( "using pass 1 shader" ); x4_shader->Use();
x4_shader->SetParameter( source_parameter, 0 ); checkGlError( "setting colorTex uniform" ); checkGlError( "using pass 1 shader" );
x4_shader->Deactivate(); checkGlError( "deactivating pass 2 shader" ); x4_shader->SetParameter( source_parameter, 0 );
checkGlError( "setting colorTex uniform" );
x4_shader->Deactivate();
checkGlError( "deactivating pass 2 shader" );
areShadersCreated = true; areShadersCreated = true;
} }
@ -232,9 +238,11 @@ unsigned int ANTIALIASING_SUPERSAMPLING::CreateBuffer()
// ANTIALIASING_SMAA // ANTIALIASING_SMAA
// =============================== // ===============================
ANTIALIASING_SMAA::ANTIALIASING_SMAA( OPENGL_COMPOSITOR* aCompositor, SMAA_QUALITY aQuality ) ANTIALIASING_SMAA::ANTIALIASING_SMAA( OPENGL_COMPOSITOR* aCompositor, SMAA_QUALITY aQuality ) :
: areBuffersInitialized( false ), shadersLoaded( false ), areBuffersInitialized( false ),
quality( aQuality ), compositor( aCompositor ) shadersLoaded( false ),
quality( aQuality ),
compositor( aCompositor )
{ {
smaaBaseBuffer = 0; smaaBaseBuffer = 0;
smaaEdgesBuffer = 0; smaaEdgesBuffer = 0;
@ -266,7 +274,8 @@ void ANTIALIASING_SMAA::loadShaders()
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT, 0, GL_RG, GL_UNSIGNED_BYTE, areaTexBytes ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT, 0, GL_RG,
GL_UNSIGNED_BYTE, areaTexBytes );
checkGlError( "loading smaa area tex" ); checkGlError( "loading smaa area tex" );
glGenTextures( 1, &smaaSearchTex ); glGenTextures( 1, &smaaSearchTex );
@ -275,7 +284,8 @@ void ANTIALIASING_SMAA::loadShaders()
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 0, GL_RED, GL_UNSIGNED_BYTE, searchTexBytes ); glTexImage2D( GL_TEXTURE_2D, 0, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 0, GL_RED,
GL_UNSIGNED_BYTE, searchTexBytes );
checkGlError( "loading smaa search tex" ); checkGlError( "loading smaa search tex" );
std::string quality_string; std::string quality_string;
@ -307,8 +317,7 @@ uniform vec4 SMAA_RT_METRICS;
uniform vec4 SMAA_RT_METRICS; uniform vec4 SMAA_RT_METRICS;
)SHADER" ); )SHADER" );
std::string smaa_source = std::string smaa_source = std::string( BUILTIN_SHADERS::smaa_base_shader_p1 )
std::string( BUILTIN_SHADERS::smaa_base_shader_p1 )
+ std::string( BUILTIN_SHADERS::smaa_base_shader_p2 ) + std::string( BUILTIN_SHADERS::smaa_base_shader_p2 )
+ std::string( BUILTIN_SHADERS::smaa_base_shader_p3 ) + std::string( BUILTIN_SHADERS::smaa_base_shader_p3 )
+ std::string( BUILTIN_SHADERS::smaa_base_shader_p4 ); + std::string( BUILTIN_SHADERS::smaa_base_shader_p4 );
@ -317,60 +326,84 @@ uniform vec4 SMAA_RT_METRICS;
// Set up pass 1 Shader // Set up pass 1 Shader
// //
pass_1_shader = std::make_unique<SHADER>(); pass_1_shader = std::make_unique<SHADER>();
pass_1_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, pass_1_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, quality_string,
quality_string, smaa_source, BUILTIN_SHADERS::smaa_pass_1_vertex_shader ); smaa_source, BUILTIN_SHADERS::smaa_pass_1_vertex_shader );
pass_1_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble, pass_1_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble,
quality_string, smaa_source, BUILTIN_SHADERS::smaa_pass_1_fragment_shader ); quality_string, smaa_source,
BUILTIN_SHADERS::smaa_pass_1_fragment_shader );
pass_1_shader->Link(); pass_1_shader->Link();
checkGlError( "linking pass 1 shader" ); checkGlError( "linking pass 1 shader" );
GLint smaaColorTexParameter = pass_1_shader->AddParameter( "colorTex" ); checkGlError( "pass1: getting colorTex uniform" ); GLint smaaColorTexParameter = pass_1_shader->AddParameter( "colorTex" );
pass_1_metrics = pass_1_shader->AddParameter( "SMAA_RT_METRICS" ); checkGlError( "pass1: getting metrics uniform" ); checkGlError( "pass1: getting colorTex uniform" );
pass_1_metrics = pass_1_shader->AddParameter( "SMAA_RT_METRICS" );
checkGlError( "pass1: getting metrics uniform" );
pass_1_shader->Use(); checkGlError( "pass1: using shader" ); pass_1_shader->Use();
pass_1_shader->SetParameter( smaaColorTexParameter, 0 ); checkGlError( "pass1: setting colorTex uniform" ); checkGlError( "pass1: using shader" );
pass_1_shader->Deactivate(); checkGlError( "pass1: deactivating shader" ); pass_1_shader->SetParameter( smaaColorTexParameter, 0 );
checkGlError( "pass1: setting colorTex uniform" );
pass_1_shader->Deactivate();
checkGlError( "pass1: deactivating shader" );
// //
// set up pass 2 shader // set up pass 2 shader
// //
pass_2_shader = std::make_unique<SHADER>(); pass_2_shader = std::make_unique<SHADER>();
pass_2_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, pass_2_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, quality_string,
quality_string, smaa_source, BUILTIN_SHADERS::smaa_pass_2_vertex_shader ); smaa_source, BUILTIN_SHADERS::smaa_pass_2_vertex_shader );
pass_2_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble, pass_2_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble,
quality_string, smaa_source, BUILTIN_SHADERS::smaa_pass_2_fragment_shader ); quality_string, smaa_source,
BUILTIN_SHADERS::smaa_pass_2_fragment_shader );
pass_2_shader->Link(); pass_2_shader->Link();
checkGlError( "linking pass 2 shader" ); checkGlError( "linking pass 2 shader" );
GLint smaaEdgesTexParameter = pass_2_shader->AddParameter( "edgesTex" ); checkGlError( "pass2: getting colorTex uniform" ); GLint smaaEdgesTexParameter = pass_2_shader->AddParameter( "edgesTex" );
GLint smaaAreaTexParameter = pass_2_shader->AddParameter( "areaTex" ); checkGlError( "pass2: getting areaTex uniform" ); checkGlError( "pass2: getting colorTex uniform" );
GLint smaaSearchTexParameter = pass_2_shader->AddParameter( "searchTex" ); checkGlError( "pass2: getting searchTex uniform" ); GLint smaaAreaTexParameter = pass_2_shader->AddParameter( "areaTex" );
pass_2_metrics = pass_2_shader->AddParameter( "SMAA_RT_METRICS" ); checkGlError( "pass2: getting metrics uniform" ); checkGlError( "pass2: getting areaTex uniform" );
GLint smaaSearchTexParameter = pass_2_shader->AddParameter( "searchTex" );
checkGlError( "pass2: getting searchTex uniform" );
pass_2_metrics = pass_2_shader->AddParameter( "SMAA_RT_METRICS" );
checkGlError( "pass2: getting metrics uniform" );
pass_2_shader->Use(); checkGlError( "pass2: using shader" ); pass_2_shader->Use();
pass_2_shader->SetParameter( smaaEdgesTexParameter, 0 ); checkGlError( "pass2: setting colorTex uniform" ); checkGlError( "pass2: using shader" );
pass_2_shader->SetParameter( smaaAreaTexParameter, 1 ); checkGlError( "pass2: setting areaTex uniform" ); pass_2_shader->SetParameter( smaaEdgesTexParameter, 0 );
pass_2_shader->SetParameter( smaaSearchTexParameter, 3 ); checkGlError( "pass2: setting searchTex uniform" ); checkGlError( "pass2: setting colorTex uniform" );
pass_2_shader->Deactivate(); checkGlError( "pass2: deactivating shader" ); pass_2_shader->SetParameter( smaaAreaTexParameter, 1 );
checkGlError( "pass2: setting areaTex uniform" );
pass_2_shader->SetParameter( smaaSearchTexParameter, 3 );
checkGlError( "pass2: setting searchTex uniform" );
pass_2_shader->Deactivate();
checkGlError( "pass2: deactivating shader" );
// //
// set up pass 3 shader // set up pass 3 shader
// //
pass_3_shader = std::make_unique<SHADER>(); pass_3_shader = std::make_unique<SHADER>();
pass_3_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, pass_3_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_VERTEX, vert_preamble, quality_string,
quality_string, smaa_source, BUILTIN_SHADERS::smaa_pass_3_vertex_shader ); smaa_source, BUILTIN_SHADERS::smaa_pass_3_vertex_shader );
pass_3_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble, pass_3_shader->LoadShaderFromStrings( KIGFX::SHADER_TYPE_FRAGMENT, frag_preamble,
quality_string, smaa_source, BUILTIN_SHADERS::smaa_pass_3_fragment_shader ); quality_string, smaa_source,
BUILTIN_SHADERS::smaa_pass_3_fragment_shader );
pass_3_shader->Link(); pass_3_shader->Link();
GLint smaaP3ColorTexParameter = pass_3_shader->AddParameter( "colorTex" ); checkGlError( "pass3: getting colorTex uniform" ); GLint smaaP3ColorTexParameter = pass_3_shader->AddParameter( "colorTex" );
GLint smaaBlendTexParameter = pass_3_shader->AddParameter( "blendTex" ); checkGlError( "pass3: getting blendTex uniform" ); checkGlError( "pass3: getting colorTex uniform" );
pass_3_metrics = pass_3_shader->AddParameter( "SMAA_RT_METRICS" ); checkGlError( "pass3: getting metrics uniform" ); GLint smaaBlendTexParameter = pass_3_shader->AddParameter( "blendTex" );
checkGlError( "pass3: getting blendTex uniform" );
pass_3_metrics = pass_3_shader->AddParameter( "SMAA_RT_METRICS" );
checkGlError( "pass3: getting metrics uniform" );
pass_3_shader->Use(); checkGlError( "pass3: using shader" ); pass_3_shader->Use();
pass_3_shader->SetParameter( smaaP3ColorTexParameter, 0 ); checkGlError( "pass3: setting colorTex uniform" ); checkGlError( "pass3: using shader" );
pass_3_shader->SetParameter( smaaBlendTexParameter, 1 ); checkGlError( "pass3: setting blendTex uniform" ); pass_3_shader->SetParameter( smaaP3ColorTexParameter, 0 );
pass_3_shader->Deactivate(); checkGlError( "pass3: deactivating shader" ); checkGlError( "pass3: setting colorTex uniform" );
pass_3_shader->SetParameter( smaaBlendTexParameter, 1 );
checkGlError( "pass3: setting blendTex uniform" );
pass_3_shader->Deactivate();
checkGlError( "pass3: deactivating shader" );
shadersLoaded = true; shadersLoaded = true;
} }
@ -380,20 +413,29 @@ void ANTIALIASING_SMAA::updateUniforms()
{ {
auto dims = compositor->GetScreenSize(); auto dims = compositor->GetScreenSize();
pass_1_shader->Use(); checkGlError( "pass1: using shader" ); pass_1_shader->Use();
pass_1_shader->SetParameter( pass_1_metrics, checkGlError( "pass1: using shader" );
1.f / float( dims.x ), 1.f / float( dims.y ), float( dims.x ), float( dims.y ) ); checkGlError( "pass1: setting metrics uniform" ); pass_1_shader->SetParameter( pass_1_metrics, 1.f / float( dims.x ), 1.f / float( dims.y ),
pass_1_shader->Deactivate(); checkGlError( "pass1: deactivating shader" ); float( dims.x ), float( dims.y ) );
checkGlError( "pass1: setting metrics uniform" );
pass_1_shader->Deactivate();
checkGlError( "pass1: deactivating shader" );
pass_2_shader->Use(); checkGlError( "pass2: using shader" ); pass_2_shader->Use();
pass_2_shader->SetParameter( pass_2_metrics, checkGlError( "pass2: using shader" );
1.f / float( dims.x ), 1.f / float( dims.y ), float( dims.x ), float( dims.y ) ); checkGlError( "pass2: setting metrics uniform" ); pass_2_shader->SetParameter( pass_2_metrics, 1.f / float( dims.x ), 1.f / float( dims.y ),
pass_2_shader->Deactivate(); checkGlError( "pass2: deactivating shader" ); float( dims.x ), float( dims.y ) );
checkGlError( "pass2: setting metrics uniform" );
pass_2_shader->Deactivate();
checkGlError( "pass2: deactivating shader" );
pass_3_shader->Use(); checkGlError( "pass3: using shader" ); pass_3_shader->Use();
pass_3_shader->SetParameter( pass_3_metrics, checkGlError( "pass3: using shader" );
1.f / float( dims.x ), 1.f / float( dims.y ), float( dims.x ), float( dims.y ) ); checkGlError( "pass3: setting metrics uniform" ); pass_3_shader->SetParameter( pass_3_metrics, 1.f / float( dims.x ), 1.f / float( dims.y ),
pass_3_shader->Deactivate(); checkGlError( "pass3: deactivating shader" ); float( dims.x ), float( dims.y ) );
checkGlError( "pass3: setting metrics uniform" );
pass_3_shader->Deactivate();
checkGlError( "pass3: deactivating shader" );
} }
@ -451,7 +493,8 @@ void ANTIALIASING_SMAA::Begin()
} }
namespace { namespace
{
void draw_fullscreen_triangle() void draw_fullscreen_triangle()
{ {
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
@ -474,7 +517,7 @@ namespace {
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glPopMatrix(); glPopMatrix();
} }
} } // namespace
void ANTIALIASING_SMAA::Present() void ANTIALIASING_SMAA::Present()
@ -492,8 +535,10 @@ void ANTIALIASING_SMAA::Present()
compositor->ClearBuffer( COLOR4D::BLACK ); compositor->ClearBuffer( COLOR4D::BLACK );
glActiveTexture( GL_TEXTURE0 ); glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, sourceTexture ); checkGlError( "binding colorTex" ); glBindTexture( GL_TEXTURE_2D, sourceTexture );
pass_1_shader->Use(); checkGlError( "using smaa pass 1 shader" ); checkGlError( "binding colorTex" );
pass_1_shader->Use();
checkGlError( "using smaa pass 1 shader" );
draw_fullscreen_triangle(); draw_fullscreen_triangle();
pass_1_shader->Deactivate(); pass_1_shader->Deactivate();

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright 2013-2017 CERN * Copyright 2013-2017 CERN
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -48,7 +48,11 @@
using namespace KIGFX; using namespace KIGFX;
CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) : CACHED_CONTAINER::CACHED_CONTAINER( unsigned int aSize ) :
VERTEX_CONTAINER( aSize ), m_item( NULL ), m_chunkSize( 0 ), m_chunkOffset( 0 ), m_maxIndex( 0 ) VERTEX_CONTAINER( aSize ),
m_item( NULL ),
m_chunkSize( 0 ),
m_chunkOffset( 0 ),
m_maxIndex( 0 )
{ {
// In the beginning there is only free space // In the beginning there is only free space
m_freeChunks.insert( std::make_pair( aSize, 0 ) ); m_freeChunks.insert( std::make_pair( aSize, 0 ) );
@ -341,7 +345,6 @@ void CACHED_CONTAINER::mergeFreeChunks()
// and let's check the next chunk // and let's check the next chunk
offset = itf->first; offset = itf->first;
size = itf->second; size = itf->second;
} }
} }
@ -389,6 +392,7 @@ void CACHED_CONTAINER::test()
// Used space check // Used space check
unsigned int used_space = 0; unsigned int used_space = 0;
ITEMS::iterator itr; ITEMS::iterator itr;
for( itr = m_items.begin(); itr != m_items.end(); ++itr ) for( itr = m_items.begin(); itr != m_items.end(); ++itr )
used_space += ( *itr )->GetSize(); used_space += ( *itr )->GetSize();

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright 2013-2017 CERN * Copyright 2013-2017 CERN
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -30,10 +30,11 @@
#include <gal/opengl/shader.h> #include <gal/opengl/shader.h>
#include <gal/opengl/utils.h> #include <gal/opengl/utils.h>
#include <wx/log.h>
#include <list> #include <list>
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
#include <wx/log.h>
#include <profile.h> #include <profile.h>
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
@ -92,6 +93,8 @@ void CACHED_CONTAINER_GPU::Unmap()
{ {
wxCHECK( IsMapped(), /*void*/ ); wxCHECK( IsMapped(), /*void*/ );
// This gets called from ~CACHED_CONTAINER_GPU. To avoid throwing an exception from
// the dtor, catch it here instead.
glUnmapBuffer( GL_ARRAY_BUFFER ); glUnmapBuffer( GL_ARRAY_BUFFER );
checkGlError( "unmapping vertices buffer" ); checkGlError( "unmapping vertices buffer" );
glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ARRAY_BUFFER, 0 );
@ -110,7 +113,8 @@ bool CACHED_CONTAINER_GPU::defragmentResize( unsigned int aNewSize )
wxCHECK( IsMapped(), false ); wxCHECK( IsMapped(), false );
wxLogTrace( "GAL_CACHED_CONTAINER_GPU", wxLogTrace( "GAL_CACHED_CONTAINER_GPU",
wxT( "Resizing & defragmenting container from %d to %d" ), m_currentSize, aNewSize ); wxT( "Resizing & defragmenting container from %d to %d" ), m_currentSize,
aNewSize );
// No shrinking if we cannot fit all the data // No shrinking if we cannot fit all the data
if( usedSpace() > aNewSize ) if( usedSpace() > aNewSize )
@ -150,8 +154,8 @@ bool CACHED_CONTAINER_GPU::defragmentResize( unsigned int aNewSize )
int itemSize = item->GetSize(); int itemSize = item->GetSize();
// Move an item to the new container // Move an item to the new container
glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, itemOffset * VERTEX_SIZE,
itemOffset * VERTEX_SIZE, newOffset * VERTEX_SIZE, itemSize * VERTEX_SIZE ); newOffset * VERTEX_SIZE, itemSize * VERTEX_SIZE );
// Update new offset // Update new offset
item->setOffset( newOffset ); item->setOffset( newOffset );
@ -188,8 +192,7 @@ bool CACHED_CONTAINER_GPU::defragmentResize( unsigned int aNewSize )
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
totalTime.Stop(); totalTime.Stop();
wxLogTrace( "GAL_CACHED_CONTAINER_GPU", wxLogTrace( "GAL_CACHED_CONTAINER_GPU", "Defragmented container storing %d vertices / %.1f ms",
"Defragmented container storing %d vertices / %.1f ms",
m_currentSize - m_freeSpace, totalTime.msecs() ); m_currentSize - m_freeSpace, totalTime.msecs() );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
@ -209,8 +212,8 @@ bool CACHED_CONTAINER_GPU::defragmentResizeMemcpy( unsigned int aNewSize )
wxCHECK( IsMapped(), false ); wxCHECK( IsMapped(), false );
wxLogTrace( "GAL_CACHED_CONTAINER_GPU", wxLogTrace( "GAL_CACHED_CONTAINER_GPU",
wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ), wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ), m_currentSize,
m_currentSize, aNewSize ); aNewSize );
// No shrinking if we cannot fit all the data // No shrinking if we cannot fit all the data
if( usedSpace() > aNewSize ) if( usedSpace() > aNewSize )
@ -254,8 +257,7 @@ bool CACHED_CONTAINER_GPU::defragmentResizeMemcpy( unsigned int aNewSize )
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
totalTime.Stop(); totalTime.Stop();
wxLogTrace( "GAL_CACHED_CONTAINER_GPU", wxLogTrace( "GAL_CACHED_CONTAINER_GPU", "Defragmented container storing %d vertices / %.1f ms",
"Defragmented container storing %d vertices / %.1f ms",
m_currentSize - m_freeSpace, totalTime.msecs() ); m_currentSize - m_freeSpace, totalTime.msecs() );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright 2013-2017 CERN * Copyright 2013-2017 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -40,7 +42,8 @@
using namespace KIGFX; using namespace KIGFX;
CACHED_CONTAINER_RAM::CACHED_CONTAINER_RAM( unsigned int aSize ) : CACHED_CONTAINER_RAM::CACHED_CONTAINER_RAM( unsigned int aSize ) :
CACHED_CONTAINER( aSize ), m_verticesBuffer( 0 ) CACHED_CONTAINER( aSize ),
m_verticesBuffer( 0 )
{ {
glGenBuffers( 1, &m_verticesBuffer ); glGenBuffers( 1, &m_verticesBuffer );
checkGlError( "generating vertices buffer" ); checkGlError( "generating vertices buffer" );
@ -76,8 +79,8 @@ void CACHED_CONTAINER_RAM::Unmap()
bool CACHED_CONTAINER_RAM::defragmentResize( unsigned int aNewSize ) bool CACHED_CONTAINER_RAM::defragmentResize( unsigned int aNewSize )
{ {
wxLogTrace( "GAL_CACHED_CONTAINER", wxLogTrace( "GAL_CACHED_CONTAINER",
wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ), wxT( "Resizing & defragmenting container (memcpy) from %d to %d" ), m_currentSize,
m_currentSize, aNewSize ); aNewSize );
// No shrinking if we cannot fit all the data // No shrinking if we cannot fit all the data
if( usedSpace() > aNewSize ) if( usedSpace() > aNewSize )
@ -101,8 +104,7 @@ bool CACHED_CONTAINER_RAM::defragmentResize( unsigned int aNewSize )
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
totalTime.Stop(); totalTime.Stop();
wxLogTrace( "GAL_CACHED_CONTAINER", wxLogTrace( "GAL_CACHED_CONTAINER", "Defragmented container storing %d vertices / %.1f ms",
"Defragmented container storing %d vertices / %.1f ms",
m_currentSize - m_freeSpace, totalTime.msecs() ); m_currentSize - m_freeSpace, totalTime.msecs() );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright 2013-2017 CERN * Copyright 2013-2017 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -49,7 +51,11 @@ GPU_MANAGER* GPU_MANAGER::MakeManager( VERTEX_CONTAINER* aContainer )
GPU_MANAGER::GPU_MANAGER( VERTEX_CONTAINER* aContainer ) : GPU_MANAGER::GPU_MANAGER( VERTEX_CONTAINER* aContainer ) :
m_isDrawing( false ), m_container( aContainer ), m_shader( NULL ), m_shaderAttrib( 0 ), m_enableDepthTest( true ) m_isDrawing( false ),
m_container( aContainer ),
m_shader( NULL ),
m_shaderAttrib( 0 ),
m_enableDepthTest( true )
{ {
} }
@ -73,8 +79,12 @@ void GPU_MANAGER::SetShader( SHADER& aShader )
// Cached manager // Cached manager
GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) : GPU_CACHED_MANAGER::GPU_CACHED_MANAGER( VERTEX_CONTAINER* aContainer ) :
GPU_MANAGER( aContainer ), m_buffersInitialized( false ), m_indicesPtr( NULL ), GPU_MANAGER( aContainer ),
m_indicesBuffer( 0 ), m_indicesSize( 0 ), m_indicesCapacity( 0 ) m_buffersInitialized( false ),
m_indicesPtr( NULL ),
m_indicesBuffer( 0 ),
m_indicesSize( 0 ),
m_indicesCapacity( 0 )
{ {
// Allocate the biggest possible buffer for indices // Allocate the biggest possible buffer for indices
resizeIndices( aContainer->GetSize() ); resizeIndices( aContainer->GetSize() );
@ -122,7 +132,8 @@ void GPU_CACHED_MANAGER::DrawIndices( unsigned int aOffset, unsigned int aSize )
wxASSERT( m_isDrawing ); wxASSERT( m_isDrawing );
// Copy indices of items that should be drawn to GPU memory // Copy indices of items that should be drawn to GPU memory
for( unsigned int i = aOffset; i < aOffset + aSize; *m_indicesPtr++ = i++ ); for( unsigned int i = aOffset; i < aOffset + aSize; *m_indicesPtr++ = i++ )
;
m_indicesSize += aSize; m_indicesSize += aSize;
} }
@ -132,7 +143,8 @@ void GPU_CACHED_MANAGER::DrawAll()
{ {
wxASSERT( m_isDrawing ); wxASSERT( m_isDrawing );
for( unsigned int i = 0; i < m_indicesSize; *m_indicesPtr++ = i++ ); for( unsigned int i = 0; i < m_indicesSize; *m_indicesPtr++ = i++ )
;
m_indicesSize = m_container->GetSize(); m_indicesSize = m_container->GetSize();
} }
@ -175,13 +187,13 @@ void GPU_CACHED_MANAGER::EndDrawing()
{ {
m_shader->Use(); m_shader->Use();
glEnableVertexAttribArray( m_shaderAttrib ); glEnableVertexAttribArray( m_shaderAttrib );
glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
VERTEX_SIZE, (GLvoid*) SHADER_OFFSET ); (GLvoid*) SHADER_OFFSET );
} }
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indicesBuffer ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_indicesBuffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_indicesSize * sizeof(int), glBufferData( GL_ELEMENT_ARRAY_BUFFER, m_indicesSize * sizeof( int ), (GLvoid*) m_indices.get(),
(GLvoid*) m_indices.get(), GL_DYNAMIC_DRAW ); GL_DYNAMIC_DRAW );
glDrawElements( GL_TRIANGLES, m_indicesSize, GL_UNSIGNED_INT, 0 ); glDrawElements( GL_TRIANGLES, m_indicesSize, GL_UNSIGNED_INT, 0 );
@ -207,8 +219,8 @@ void GPU_CACHED_MANAGER::EndDrawing()
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
totalRealTime.Stop(); totalRealTime.Stop();
wxLogTrace( "GAL_PROFILE", wxLogTrace( "GAL_PROFILE", wxT( "GPU_CACHED_MANAGER::EndDrawing(): %.1f ms" ),
wxT( "GPU_CACHED_MANAGER::EndDrawing(): %.1f ms" ), totalRealTime.msecs() ); totalRealTime.msecs() );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
} }
@ -280,8 +292,8 @@ void GPU_NONCACHED_MANAGER::EndDrawing()
m_shader->Use(); m_shader->Use();
glEnableVertexAttribArray( m_shaderAttrib ); glEnableVertexAttribArray( m_shaderAttrib );
glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
VERTEX_SIZE, shaders ); shaders );
} }
glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() ); glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
@ -304,8 +316,8 @@ void GPU_NONCACHED_MANAGER::EndDrawing()
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
totalRealTime.Stop(); totalRealTime.Stop();
wxLogTrace( "GAL_PROFILE", wxLogTrace( "GAL_PROFILE", wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ),
wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ), totalRealTime.msecs() ); totalRealTime.msecs() );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
} }

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -35,7 +37,8 @@
using namespace KIGFX; using namespace KIGFX;
NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) : NONCACHED_CONTAINER::NONCACHED_CONTAINER( unsigned int aSize ) :
VERTEX_CONTAINER( aSize ), m_freePtr( 0 ) VERTEX_CONTAINER( aSize ),
m_freePtr( 0 )
{ {
m_vertices = static_cast<VERTEX*>( malloc( aSize * sizeof( VERTEX ) ) ); m_vertices = static_cast<VERTEX*>( malloc( aSize * sizeof( VERTEX ) ) );
memset( m_vertices, 0x00, aSize * sizeof( VERTEX ) ); memset( m_vertices, 0x00, aSize * sizeof( VERTEX ) );
@ -60,9 +63,8 @@ VERTEX* NONCACHED_CONTAINER::Allocate( unsigned int aSize )
if( m_freeSpace < aSize ) if( m_freeSpace < aSize )
{ {
// Double the space // Double the space
VERTEX* newVertices = static_cast<VERTEX*>( realloc( m_vertices, VERTEX* newVertices =
m_currentSize * 2 * static_cast<VERTEX*>( realloc( m_vertices, m_currentSize * 2 * sizeof( VERTEX ) ) );
sizeof(VERTEX) ) );
if( newVertices != NULL ) if( newVertices != NULL )
{ {

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -40,8 +42,11 @@
using namespace KIGFX; using namespace KIGFX;
OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() : OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() :
m_initialized( false ), m_curBuffer( 0 ), m_initialized( false ),
m_mainFbo( 0 ), m_depthBuffer( 0 ), m_curFbo( DIRECT_RENDERING ), m_curBuffer( 0 ),
m_mainFbo( 0 ),
m_depthBuffer( 0 ),
m_curFbo( DIRECT_RENDERING ),
m_currentAntialiasingMode( OPENGL_ANTIALIASING_MODE::NONE ) m_currentAntialiasingMode( OPENGL_ANTIALIASING_MODE::NONE )
{ {
m_antialiasing = std::make_unique<ANTIALIASING_NONE>( this ); m_antialiasing = std::make_unique<ANTIALIASING_NONE>( this );
@ -87,10 +92,12 @@ void OPENGL_COMPOSITOR::Initialize()
m_antialiasing = std::make_unique<ANTIALIASING_SMAA>( this, SMAA_QUALITY::ULTRA ); m_antialiasing = std::make_unique<ANTIALIASING_SMAA>( this, SMAA_QUALITY::ULTRA );
break; break;
case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X2: case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X2:
m_antialiasing = std::make_unique<ANTIALIASING_SUPERSAMPLING>( this, SUPERSAMPLING_MODE::X2 ); m_antialiasing =
std::make_unique<ANTIALIASING_SUPERSAMPLING>( this, SUPERSAMPLING_MODE::X2 );
break; break;
case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X4: case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X4:
m_antialiasing = std::make_unique<ANTIALIASING_SUPERSAMPLING>( this, SUPERSAMPLING_MODE::X4 ); m_antialiasing =
std::make_unique<ANTIALIASING_SUPERSAMPLING>( this, SUPERSAMPLING_MODE::X4 );
break; break;
} }
@ -161,7 +168,8 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer( VECTOR2U aDimensions )
if( (int) usedBuffers() >= maxBuffers ) if( (int) usedBuffers() >= maxBuffers )
{ {
throw std::runtime_error( "Cannot create more framebuffers. OpenGL rendering " throw std::runtime_error(
"Cannot create more framebuffers. OpenGL rendering "
"backend requires at least 3 framebuffers. You may try to update/change " "backend requires at least 3 framebuffers. You may try to update/change "
"your graphic drivers." ); "your graphic drivers." );
} }
@ -195,8 +203,8 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer( VECTOR2U aDimensions )
// Bind the texture to the specific attachment point, clear and rebind the screen // Bind the texture to the specific attachment point, clear and rebind the screen
bindFb( m_mainFbo ); bindFb( m_mainFbo );
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, GL_TEXTURE_2D, textureTarget,
GL_TEXTURE_2D, textureTarget, 0 ); 0 );
// Check the status, exit if the framebuffer can't be created // Check the status, exit if the framebuffer can't be created
GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
@ -223,7 +231,8 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer( VECTOR2U aDimensions )
break; break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT: case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
throw std::runtime_error( "The combination of internal formats of the attached " throw std::runtime_error(
"The combination of internal formats of the attached "
"images violates an implementation-dependent set of restrictions." ); "images violates an implementation-dependent set of restrictions." );
break; break;
@ -283,8 +292,8 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
glDrawBuffer( m_buffers[m_curBuffer].attachmentPoint ); glDrawBuffer( m_buffers[m_curBuffer].attachmentPoint );
checkGlError( "setting draw buffer" ); checkGlError( "setting draw buffer" );
glViewport( 0, 0, glViewport( 0, 0, m_buffers[m_curBuffer].dimensions.x,
m_buffers[m_curBuffer].dimensions.x, m_buffers[m_curBuffer].dimensions.y ); m_buffers[m_curBuffer].dimensions.y );
} }
else else
{ {
@ -414,11 +423,8 @@ int OPENGL_COMPOSITOR::GetAntialiasSupersamplingFactor() const
{ {
switch( m_currentAntialiasingMode ) switch( m_currentAntialiasingMode )
{ {
case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X2: case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X2: return 2;
return 2; case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X4: return 4;
case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X4: default: return 1;
return 4;
default:
return 1;
} }
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012-2020 Kicad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2012-2021 Kicad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
@ -83,20 +83,18 @@ int OPENGL_GAL::instanceCounter = 0;
GLuint OPENGL_GAL::fontTexture = 0; GLuint OPENGL_GAL::fontTexture = 0;
bool OPENGL_GAL::isBitmapFontLoaded = false; bool OPENGL_GAL::isBitmapFontLoaded = false;
namespace KIGFX { namespace KIGFX
{
class GL_BITMAP_CACHE class GL_BITMAP_CACHE
{ {
public: public:
GL_BITMAP_CACHE() GL_BITMAP_CACHE() {}
{
}
~GL_BITMAP_CACHE(); ~GL_BITMAP_CACHE();
GLuint RequestBitmap( const BITMAP_BASE* aBitmap ); GLuint RequestBitmap( const BITMAP_BASE* aBitmap );
private: private:
struct CACHED_BITMAP struct CACHED_BITMAP
{ {
GLuint id; GLuint id;
@ -108,7 +106,7 @@ private:
std::map<const BITMAP_BASE*, CACHED_BITMAP> m_bitmaps; std::map<const BITMAP_BASE*, CACHED_BITMAP> m_bitmaps;
}; };
}; }; // namespace KIGFX
GL_BITMAP_CACHE::~GL_BITMAP_CACHE() GL_BITMAP_CACHE::~GL_BITMAP_CACHE()
@ -170,8 +168,8 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
if( imgData.HasAlpha() ) if( imgData.HasAlpha() )
p[3] = imgData.GetAlpha( x, y ); p[3] = imgData.GetAlpha( x, y );
else if( imgData.HasMask() && p[0] == imgData.GetMaskRed() && else if( imgData.HasMask() && p[0] == imgData.GetMaskRed()
p[1] == imgData.GetMaskGreen() && p[2] == imgData.GetMaskBlue() ) && p[1] == imgData.GetMaskGreen() && p[2] == imgData.GetMaskBlue() )
p[3] = wxALPHA_TRANSPARENT; p[3] = wxALPHA_TRANSPARENT;
else else
p[3] = wxALPHA_OPAQUE; p[3] = wxALPHA_OPAQUE;
@ -179,7 +177,8 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
} }
glBindTexture( GL_TEXTURE_2D, textureID ); glBindTexture( GL_TEXTURE_2D, textureID );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w + extra_w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf.get() ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w + extra_w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
buf.get() );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
@ -502,8 +501,8 @@ void OPENGL_GAL::beginDrawing()
glActiveTexture( GL_TEXTURE0 + FONT_TEXTURE_UNIT ); glActiveTexture( GL_TEXTURE0 + FONT_TEXTURE_UNIT );
glGenTextures( 1, &fontTexture ); glGenTextures( 1, &fontTexture );
glBindTexture( GL_TEXTURE_2D, fontTexture ); glBindTexture( GL_TEXTURE_2D, fontTexture );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, font_image.width, font_image.height, glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, font_image.width, font_image.height, 0, GL_RGB,
0, GL_RGB, GL_UNSIGNED_BYTE, font_image.pixels ); GL_UNSIGNED_BYTE, font_image.pixels );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
checkGlError( "loading bitmap font" ); checkGlError( "loading bitmap font" );
@ -551,7 +550,8 @@ void OPENGL_GAL::beginDrawing()
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
totalRealTime.Stop(); totalRealTime.Stop();
wxLogTrace( "GAL_PROFILE", wxT( "OPENGL_GAL::beginDrawing(): %.1f ms" ), totalRealTime.msecs() ); wxLogTrace( "GAL_PROFILE", wxT( "OPENGL_GAL::beginDrawing(): %.1f ms" ),
totalRealTime.msecs() );
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
} }
@ -663,9 +663,9 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
float endx = aStartPoint.x + lineLength; float endx = aStartPoint.x + lineLength;
float endy = aStartPoint.y + lineLength; float endy = aStartPoint.y + lineLength;
// Be careful about floating point rounding. As we draw segments in larger and larger coordinates, // Be careful about floating point rounding. As we draw segments in larger and larger
// the shader (which uses floats) will lose precision and stop drawing small segments. // coordinates, the shader (which uses floats) will lose precision and stop drawing small
// In this case, we need to draw a circle for the minimal segment // segments. In this case, we need to draw a circle for the minimal segment.
if( startx == endx || starty == endy ) if( startx == endx || starty == endy )
{ {
DrawCircle( aStartPoint, aWidth / 2 ); DrawCircle( aStartPoint, aWidth / 2 );
@ -692,11 +692,9 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
currentManager->Translate( aStartPoint.x, aStartPoint.y, 0.0 ); currentManager->Translate( aStartPoint.x, aStartPoint.y, 0.0 );
currentManager->Rotate( lineAngle, 0.0f, 0.0f, 1.0f ); currentManager->Rotate( lineAngle, 0.0f, 0.0f, 1.0f );
drawLineQuad( VECTOR2D( 0.0, aWidth / 2.0 ), drawLineQuad( VECTOR2D( 0.0, aWidth / 2.0 ), VECTOR2D( lineLength, aWidth / 2.0 ) );
VECTOR2D( lineLength, aWidth / 2.0 ) );
drawLineQuad( VECTOR2D( 0.0, -aWidth / 2.0 ), drawLineQuad( VECTOR2D( 0.0, -aWidth / 2.0 ), VECTOR2D( lineLength, -aWidth / 2.0 ) );
VECTOR2D( lineLength, -aWidth / 2.0 ) );
// Draw line caps // Draw line caps
drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2 ); drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2 );
@ -866,10 +864,8 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, d
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
double width = aWidth / 2.0; double width = aWidth / 2.0;
VECTOR2D startPoint( cos( aStartAngle ) * aRadius, VECTOR2D startPoint( cos( aStartAngle ) * aRadius, sin( aStartAngle ) * aRadius );
sin( aStartAngle ) * aRadius ); VECTOR2D endPoint( cos( aEndAngle ) * aRadius, sin( aEndAngle ) * aRadius );
VECTOR2D endPoint( cos( aEndAngle ) * aRadius,
sin( aEndAngle ) * aRadius );
drawStrokedSemiCircle( startPoint, width, aStartAngle + M_PI ); drawStrokedSemiCircle( startPoint, width, aStartAngle + M_PI );
drawStrokedSemiCircle( endPoint, width, aEndAngle ); drawStrokedSemiCircle( endPoint, width, aEndAngle );
@ -977,13 +973,23 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
void OPENGL_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList ) void OPENGL_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList )
{ {
drawPolyline( [&](int idx) { return aPointList[idx]; }, aPointList.size() ); drawPolyline(
[&]( int idx )
{
return aPointList[idx];
},
aPointList.size() );
} }
void OPENGL_GAL::DrawPolyline( const VECTOR2D aPointList[], int aListSize ) void OPENGL_GAL::DrawPolyline( const VECTOR2D aPointList[], int aListSize )
{ {
drawPolyline( [&](int idx) { return aPointList[idx]; }, aListSize ); drawPolyline(
[&]( int idx )
{
return aPointList[idx];
},
aListSize );
} }
@ -994,7 +1000,12 @@ void OPENGL_GAL::DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain )
if( aLineChain.IsClosed() ) if( aLineChain.IsClosed() )
numPoints += 1; numPoints += 1;
drawPolyline( [&](int idx) { return aLineChain.CPoint(idx); }, numPoints ); drawPolyline(
[&]( int idx )
{
return aLineChain.CPoint( idx );
},
numPoints );
} }
@ -1113,7 +1124,6 @@ void OPENGL_GAL::DrawPolygon( const SHAPE_POLY_SET& aPolySet )
} }
void OPENGL_GAL::DrawPolygon( const SHAPE_LINE_CHAIN& aPolygon ) void OPENGL_GAL::DrawPolygon( const SHAPE_LINE_CHAIN& aPolygon )
{ {
wxCHECK( aPolygon.PointCount() >= 2, /* void */ ); wxCHECK( aPolygon.PointCount() >= 2, /* void */ );
@ -1241,9 +1251,7 @@ void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2D& aPosition,
switch( GetHorizontalJustify() ) switch( GetHorizontalJustify() )
{ {
case GR_TEXT_HJUSTIFY_CENTER: case GR_TEXT_HJUSTIFY_CENTER: Translate( VECTOR2D( -textSize.x / 2.0, 0 ) ); break;
Translate( VECTOR2D( -textSize.x / 2.0, 0 ) );
break;
case GR_TEXT_HJUSTIFY_RIGHT: case GR_TEXT_HJUSTIFY_RIGHT:
//if( !IsTextMirrored() ) //if( !IsTextMirrored() )
@ -1268,8 +1276,7 @@ void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2D& aPosition,
overbarHeight = 0; overbarHeight = 0;
break; break;
case GR_TEXT_VJUSTIFY_BOTTOM: case GR_TEXT_VJUSTIFY_BOTTOM: break;
break;
} }
int i = 0; int i = 0;
@ -1391,8 +1398,10 @@ void OPENGL_GAL::DrawGrid()
SWAP( gridStartY, >, gridEndY ); SWAP( gridStartY, >, gridEndY );
// Ensure the grid fills the screen // Ensure the grid fills the screen
--gridStartX; ++gridEndX; --gridStartX;
--gridStartY; ++gridEndY; ++gridEndX;
--gridStartY;
++gridEndY;
glDisable( GL_DEPTH_TEST ); glDisable( GL_DEPTH_TEST );
glDisable( GL_TEXTURE_2D ); glDisable( GL_TEXTURE_2D );
@ -1413,7 +1422,6 @@ void OPENGL_GAL::DrawGrid()
if( gridStyle == GRID_STYLE::SMALL_CROSS ) if( gridStyle == GRID_STYLE::SMALL_CROSS )
{ {
// Vertical positions // Vertical positions
for( int j = gridStartY; j <= gridEndY; j++ ) for( int j = gridStartY; j <= gridEndY; j++ )
{ {
@ -1522,6 +1530,7 @@ void OPENGL_GAL::ClearScreen( )
{ {
// Clear screen // Clear screen
compositor->SetBuffer( OPENGL_COMPOSITOR::DIRECT_RENDERING ); compositor->SetBuffer( OPENGL_COMPOSITOR::DIRECT_RENDERING );
// NOTE: Black used here instead of m_clearColor; it will be composited later // NOTE: Black used here instead of m_clearColor; it will be composited later
glClearColor( 0, 0, 0, 1 ); glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
@ -1639,17 +1648,9 @@ void OPENGL_GAL::SetTarget( RENDER_TARGET aTarget )
switch( aTarget ) switch( aTarget )
{ {
default: default:
case TARGET_CACHED: case TARGET_CACHED: currentManager = cachedManager; break;
currentManager = cachedManager; case TARGET_NONCACHED: currentManager = nonCachedManager; break;
break; case TARGET_OVERLAY: currentManager = overlayManager; break;
case TARGET_NONCACHED:
currentManager = nonCachedManager;
break;
case TARGET_OVERLAY:
currentManager = overlayManager;
break;
} }
currentTarget = aTarget; currentTarget = aTarget;
@ -1699,11 +1700,9 @@ bool OPENGL_GAL::HasTarget( RENDER_TARGET aTarget )
{ {
default: default:
case TARGET_CACHED: case TARGET_CACHED:
case TARGET_NONCACHED: case TARGET_NONCACHED: return true;
return true;
case TARGET_OVERLAY: case TARGET_OVERLAY: return ( overlayBuffer != 0 );
return ( overlayBuffer != 0 );
} }
} }
@ -1735,7 +1734,8 @@ void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
* dots mark triangles' hypotenuses * dots mark triangles' hypotenuses
*/ */
auto v1 = currentManager->GetTransformation() * glm::vec4( aStartPoint.x, aStartPoint.y, 0.0, 0.0 ); auto v1 = currentManager->GetTransformation()
* glm::vec4( aStartPoint.x, aStartPoint.y, 0.0, 0.0 );
auto v2 = currentManager->GetTransformation() * glm::vec4( aEndPoint.x, aEndPoint.y, 0.0, 0.0 ); auto v2 = currentManager->GetTransformation() * glm::vec4( aEndPoint.x, aEndPoint.y, 0.0, 0.0 );
VECTOR2D vs( v2.x - v1.x, v2.y - v1.y ); VECTOR2D vs( v2.x - v1.x, v2.y - v1.y );
@ -1779,8 +1779,7 @@ void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, d
} }
void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle )
double aAngle )
{ {
Save(); Save();
@ -1874,7 +1873,11 @@ void OPENGL_GAL::drawPolygon( GLdouble* aPoints, int aPointCount )
if( isStrokeEnabled ) if( isStrokeEnabled )
{ {
drawPolyline( [&](int idx) { return VECTOR2D( aPoints[idx * 3], aPoints[idx * 3 + 1] ); }, drawPolyline(
[&]( int idx )
{
return VECTOR2D( aPoints[idx * 3], aPoints[idx * 3 + 1] );
},
aPointCount ); aPointCount );
} }
} }
@ -1940,6 +1943,7 @@ int OPENGL_GAL::drawBitmapChar( unsigned long aChar )
currentManager->Reserve( 6 ); currentManager->Reserve( 6 );
Translate( VECTOR2D( XOFF, YOFF ) ); Translate( VECTOR2D( XOFF, YOFF ) );
/* Glyph: /* Glyph:
* v0 v1 * v0 v1
* +--+ * +--+
@ -2094,8 +2098,7 @@ void OPENGL_GAL::blitCursor()
VECTOR2D cursorCenter = ( cursorBegin + cursorEnd ) / 2; VECTOR2D cursorCenter = ( cursorBegin + cursorEnd ) / 2;
const COLOR4D cColor = getCursorColor(); const COLOR4D cColor = getCursorColor();
const COLOR4D color( cColor.r * cColor.a, cColor.g * cColor.a, const COLOR4D color( cColor.r * cColor.a, cColor.g * cColor.a, cColor.b * cColor.a, 1.0 );
cColor.b * cColor.a, 1.0 );
glActiveTexture( GL_TEXTURE0 ); glActiveTexture( GL_TEXTURE0 );
glDisable( GL_TEXTURE_2D ); glDisable( GL_TEXTURE_2D );
@ -2128,7 +2131,6 @@ unsigned int OPENGL_GAL::getNewGroupNumber()
void OPENGL_GAL::init() void OPENGL_GAL::init()
{ {
wxASSERT( IsShownOnScreen() ); wxASSERT( IsShownOnScreen() );
wxASSERT_MSG( m_isContextLocked, "This should only be called from within a locked context." ); wxASSERT_MSG( m_isContextLocked, "This should only be called from within a locked context." );
@ -2178,10 +2180,14 @@ void OPENGL_GAL::init()
throw std::runtime_error( "Vertex buffer objects are not supported!" ); throw std::runtime_error( "Vertex buffer objects are not supported!" );
// Prepare shaders // Prepare shaders
if( !shader->IsLinked() && !shader->LoadShaderFromStrings( SHADER_TYPE_VERTEX, BUILTIN_SHADERS::kicad_vertex_shader ) ) if( !shader->IsLinked()
&& !shader->LoadShaderFromStrings( SHADER_TYPE_VERTEX,
BUILTIN_SHADERS::kicad_vertex_shader ) )
throw std::runtime_error( "Cannot compile vertex shader!" ); throw std::runtime_error( "Cannot compile vertex shader!" );
if( !shader->IsLinked() && !shader->LoadShaderFromStrings( SHADER_TYPE_FRAGMENT, BUILTIN_SHADERS::kicad_fragment_shader ) ) if( !shader->IsLinked()
&& !shader->LoadShaderFromStrings( SHADER_TYPE_FRAGMENT,
BUILTIN_SHADERS::kicad_fragment_shader ) )
throw std::runtime_error( "Cannot compile fragment shader!" ); throw std::runtime_error( "Cannot compile fragment shader!" );
if( !shader->IsLinked() && !shader->Link() ) if( !shader->IsLinked() && !shader->Link() )
@ -2213,7 +2219,7 @@ void OPENGL_GAL::init()
} }
// ------------------------------------- // Callback functions for the tesselator // ------------------------------------- // Compare Redbook Chapter 11 // Callback functions for the tesselator. Compare Redbook Chapter 11.
void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData ) void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
{ {
GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr ); GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr );
@ -2225,9 +2231,8 @@ void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
} }
void CALLBACK CombineCallback( GLdouble coords[3], void CALLBACK CombineCallback( GLdouble coords[3], GLdouble* vertex_data[4], GLfloat weight[4],
GLdouble* vertex_data[4], GLdouble** dataOut, void* aData )
GLfloat weight[4], GLdouble** dataOut, void* aData )
{ {
GLdouble* vertex = new GLdouble[3]; GLdouble* vertex = new GLdouble[3];
OPENGL_GAL::TessParams* param = static_cast<OPENGL_GAL::TessParams*>( aData ); OPENGL_GAL::TessParams* param = static_cast<OPENGL_GAL::TessParams*>( aData );
@ -2285,4 +2290,3 @@ void OPENGL_GAL::ComputeWorldScreenMatrix()
GAL::ComputeWorldScreenMatrix(); GAL::ComputeWorldScreenMatrix();
} }

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012-2020 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 2012-2021 Kicad Developers, see AUTHORS.txt for contributors.
* *
* Graphics Abstraction Layer (GAL) for OpenGL * Graphics Abstraction Layer (GAL) for OpenGL
* *
@ -234,8 +234,7 @@ std::string SHADER::ReadSource( const std::string& aShaderSourceName )
} }
bool SHADER::loadShaderFromStringArray( SHADER_TYPE aShaderType, const char** aArray, bool SHADER::loadShaderFromStringArray( SHADER_TYPE aShaderType, const char** aArray, size_t aSize )
size_t aSize )
{ {
assert( !isShaderLinked ); assert( !isShaderLinked );

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2016-2017 CERN * Copyright (C) 2016-2017 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -64,34 +66,46 @@ int checkGlError( const std::string& aInfo, bool aThrow )
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
errorMsg = "The framebuffer attachment points are incomplete."; errorMsg = "The framebuffer attachment points are incomplete.";
break; break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
errorMsg = "No images attached to the framebuffer."; errorMsg = "No images attached to the framebuffer.";
break; break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
errorMsg = "The framebuffer does not have at least one image attached to it."; errorMsg = "The framebuffer does not have at least one image attached to it.";
break; break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
errorMsg = "The framebuffer read buffer is incomplete."; errorMsg = "The framebuffer read buffer is incomplete.";
break; break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT: case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
errorMsg = "The combination of internal formats of the attached images violates an implementation-dependent set of restrictions."; errorMsg = "The combination of internal formats of the attached images violates an "
"implementation dependent set of restrictions.";
break; break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
errorMsg = "GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers."; errorMsg =
"GL_RENDERBUFFER_SAMPLES is not the same for all attached render buffers.";
break; break;
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT: case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT:
errorMsg = "Framebuffer incomplete layer targets errors."; errorMsg = "Framebuffer incomplete layer targets errors.";
break; break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
errorMsg = "Framebuffer attachments have different dimensions"; errorMsg = "Framebuffer attachments have different dimensions";
break; break;
default: default:
errorMsg.Printf( "Unknown incomplete framebuffer error id %X", status ); errorMsg.Printf( "Unknown incomplete framebuffer error id %X", status );
} }
} }
else else
{
errorMsg = wxString::Format( "Error: %s: invalid framebuffer operation", aInfo ); errorMsg = wxString::Format( "Error: %s: invalid framebuffer operation", aInfo );
} }
}
break; break;
case GL_OUT_OF_MEMORY: case GL_OUT_OF_MEMORY:
@ -125,8 +139,9 @@ int checkGlError( const std::string& aInfo, bool aThrow )
// debugMsgCallback is a callback function for glDebugMessageCallback. // debugMsgCallback is a callback function for glDebugMessageCallback.
// It must have the right type ( GLAPIENTRY ) // It must have the right type ( GLAPIENTRY )
static void GLAPIENTRY debugMsgCallback( GLenum aSource, GLenum aType, GLuint aId, static void GLAPIENTRY debugMsgCallback( GLenum aSource, GLenum aType, GLuint aId, GLenum aSeverity,
GLenum aSeverity, GLsizei aLength, const GLchar* aMessage, const void* aUserParam ) GLsizei aLength, const GLchar* aMessage,
const void* aUserParam )
{ {
switch( aSeverity ) switch( aSeverity )
{ {

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -56,8 +58,12 @@ VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached )
VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) : VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) :
m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), m_freeSpace( aSize ),
m_vertices( NULL ), m_failed( false ), m_dirty( true ) m_currentSize( aSize ),
m_initialSize( aSize ),
m_vertices( NULL ),
m_failed( false ),
m_dirty( true )
{ {
} }

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -34,7 +36,9 @@
using namespace KIGFX; using namespace KIGFX;
VERTEX_ITEM::VERTEX_ITEM( const VERTEX_MANAGER& aManager ) : VERTEX_ITEM::VERTEX_ITEM( const VERTEX_MANAGER& aManager ) :
m_manager( aManager ), m_offset( 0 ), m_size( 0 ) 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 // As the item is created, we are going to modify it, so call to SetItem() is needed
m_manager.SetItem( *this ); m_manager.SetItem( *this );

View File

@ -2,6 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013-2016 CERN * Copyright (C) 2013-2016 CERN
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -38,7 +40,10 @@
using namespace KIGFX; using namespace KIGFX;
VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) : VERTEX_MANAGER::VERTEX_MANAGER( bool aCached ) :
m_noTransform( true ), m_transform( 1.0f ), m_reserved( NULL ), m_reservedSpace( 0 ) m_noTransform( true ),
m_transform( 1.0f ),
m_reserved( NULL ),
m_reservedSpace( 0 )
{ {
m_container.reset( VERTEX_CONTAINER::MakeContainer( aCached ) ); m_container.reset( VERTEX_CONTAINER::MakeContainer( aCached ) );
m_gpu.reset( GPU_MANAGER::MakeManager( m_container.get() ) ); m_gpu.reset( GPU_MANAGER::MakeManager( m_container.get() ) );