mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Specialize the pad wall drawing
Avoids slowdown when zoom/pan with many THTs as everything remains cached. Still slow in Cairo but this is expected Fixes https://gitlab.com/kicad/code/kicad/-/issues/20506
This commit is contained in:
parent
66c42f396c
commit
3ef862f7b6
@ -322,6 +322,12 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::DrawHoleWall( const VECTOR2D& aCenterPoint, double aRadius, double aWallWidth )
|
||||
{
|
||||
DrawCircle( aCenterPoint, aRadius + aWallWidth );
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||
{
|
||||
syncLineWidth();
|
||||
|
@ -67,6 +67,7 @@ GAL::GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
|
||||
SetLayerDepth( 0.0 );
|
||||
SetFlip( false, false );
|
||||
SetLineWidth( 1.0f );
|
||||
SetMinLineWidth( 1.0f );
|
||||
computeWorldScale();
|
||||
SetAxesEnabled( false );
|
||||
|
||||
|
@ -407,10 +407,13 @@ OPENGL_GAL::OPENGL_GAL( const KIGFX::VC_SETTINGS& aVcSettings, GAL_DISPLAY_OPTIO
|
||||
SetTarget( TARGET_NONCACHED );
|
||||
|
||||
// Avoid uninitialized variables:
|
||||
ufm_worldPixelSize = 1;
|
||||
ufm_screenPixelSize = 1;
|
||||
ufm_pixelSizeMultiplier = 1;
|
||||
ufm_antialiasingOffset = 1;
|
||||
ufm_worldPixelSize = -1;
|
||||
ufm_screenPixelSize = -1;
|
||||
ufm_pixelSizeMultiplier = -1;
|
||||
ufm_antialiasingOffset = -1;
|
||||
ufm_minLinePixelWidth = -1;
|
||||
ufm_fontTexture = -1;
|
||||
ufm_fontTextureWidth = -1;
|
||||
m_swapInterval = 0;
|
||||
}
|
||||
|
||||
@ -666,14 +669,6 @@ void OPENGL_GAL::BeginDrawing()
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
}
|
||||
|
||||
// Set shader parameter
|
||||
GLint ufm_fontTexture = m_shader->AddParameter( "u_fontTexture" );
|
||||
GLint ufm_fontTextureWidth = m_shader->AddParameter( "u_fontTextureWidth" );
|
||||
ufm_worldPixelSize = m_shader->AddParameter( "u_worldPixelSize" );
|
||||
ufm_screenPixelSize = m_shader->AddParameter( "u_screenPixelSize" );
|
||||
ufm_pixelSizeMultiplier = m_shader->AddParameter( "u_pixelSizeMultiplier" );
|
||||
ufm_antialiasingOffset = m_shader->AddParameter( "u_antialiasingOffset" );
|
||||
|
||||
m_shader->Use();
|
||||
m_shader->SetParameter( ufm_fontTexture, (int) FONT_TEXTURE_UNIT );
|
||||
m_shader->SetParameter( ufm_fontTextureWidth, (int) font_image.width );
|
||||
@ -694,6 +689,7 @@ void OPENGL_GAL::BeginDrawing()
|
||||
renderingOffset.x *= screenPixelSize.x;
|
||||
renderingOffset.y *= screenPixelSize.y;
|
||||
m_shader->SetParameter( ufm_antialiasingOffset, renderingOffset );
|
||||
m_shader->SetParameter( ufm_minLinePixelWidth, GetMinLineWidth() );
|
||||
m_shader->Deactivate();
|
||||
|
||||
// Something between BeginDrawing and EndDrawing seems to depend on
|
||||
@ -710,6 +706,18 @@ void OPENGL_GAL::BeginDrawing()
|
||||
#endif /* KICAD_GAL_PROFILE */
|
||||
}
|
||||
|
||||
void OPENGL_GAL::SetMinLineWidth( float aLineWidth )
|
||||
{
|
||||
GAL::SetMinLineWidth( aLineWidth );
|
||||
|
||||
if( m_shader && ufm_minLinePixelWidth != -1 )
|
||||
{
|
||||
m_shader->Use();
|
||||
m_shader->SetParameter( ufm_minLinePixelWidth, aLineWidth );
|
||||
m_shader->Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::EndDrawing()
|
||||
{
|
||||
@ -901,6 +909,25 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::DrawHoleWall( const VECTOR2D& aCenterPoint, double aHoleRadius,
|
||||
double aWallWidth )
|
||||
{
|
||||
if( m_isFillEnabled )
|
||||
{
|
||||
m_currentManager->Color( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
|
||||
|
||||
m_currentManager->Shader( SHADER_HOLE_WALL, 1.0, aHoleRadius, aWallWidth );
|
||||
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
|
||||
|
||||
m_currentManager->Shader( SHADER_HOLE_WALL, 2.0, aHoleRadius, aWallWidth );
|
||||
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
|
||||
|
||||
m_currentManager->Shader( SHADER_HOLE_WALL, 3.0, aHoleRadius, aWallWidth );
|
||||
m_currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::drawCircle( const VECTOR2D& aCenterPoint, double aRadius, bool aReserve )
|
||||
{
|
||||
if( m_isFillEnabled )
|
||||
@ -2802,6 +2829,9 @@ void OPENGL_GAL::init()
|
||||
if( !m_shader->IsLinked() && !m_shader->Link() )
|
||||
throw std::runtime_error( "Cannot link the shaders!" );
|
||||
|
||||
// Set up shader parameters after linking
|
||||
setupShaderParameters();
|
||||
|
||||
// Check if video card supports textures big enough to fit the font atlas
|
||||
int maxTextureSize;
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTextureSize );
|
||||
@ -2830,6 +2860,19 @@ void OPENGL_GAL::init()
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::setupShaderParameters()
|
||||
{
|
||||
// Initialize shader uniform parameter locations
|
||||
ufm_fontTexture = m_shader->AddParameter( "u_fontTexture" );
|
||||
ufm_fontTextureWidth = m_shader->AddParameter( "u_fontTextureWidth" );
|
||||
ufm_worldPixelSize = m_shader->AddParameter( "u_worldPixelSize" );
|
||||
ufm_screenPixelSize = m_shader->AddParameter( "u_screenPixelSize" );
|
||||
ufm_pixelSizeMultiplier = m_shader->AddParameter( "u_pixelSizeMultiplier" );
|
||||
ufm_antialiasingOffset = m_shader->AddParameter( "u_antialiasingOffset" );
|
||||
ufm_minLinePixelWidth = m_shader->AddParameter( "u_minLinePixelWidth" );
|
||||
}
|
||||
|
||||
|
||||
// Callback functions for the tesselator. Compare Redbook Chapter 11.
|
||||
void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
|
||||
{
|
||||
|
@ -35,6 +35,7 @@ const float SHADER_FILLED_CIRCLE = 2.0;
|
||||
const float SHADER_STROKED_CIRCLE = 3.0;
|
||||
const float SHADER_FONT = 4.0;
|
||||
const float SHADER_LINE_A = 5.0;
|
||||
const float SHADER_HOLE_WALL = 11.0;
|
||||
|
||||
varying vec4 v_shaderParams;
|
||||
varying vec2 v_circleCoords;
|
||||
@ -124,6 +125,10 @@ void main()
|
||||
{
|
||||
strokedCircle( v_circleCoords, v_shaderParams[2], v_shaderParams[3] );
|
||||
}
|
||||
else if( mode == SHADER_HOLE_WALL )
|
||||
{
|
||||
strokedCircle( v_circleCoords, v_shaderParams[2], v_shaderParams[3] );
|
||||
}
|
||||
else if( mode == SHADER_FONT )
|
||||
{
|
||||
vec2 tex = v_shaderParams.yz;
|
||||
|
@ -36,6 +36,7 @@ const float SHADER_LINE_C = 7.0;
|
||||
const float SHADER_LINE_D = 8.0;
|
||||
const float SHADER_LINE_E = 9.0;
|
||||
const float SHADER_LINE_F = 10.0;
|
||||
const float SHADER_HOLE_WALL = 11.0;
|
||||
|
||||
// Minimum line width
|
||||
const float MIN_WIDTH = 1.0;
|
||||
@ -72,8 +73,8 @@ void computeLineCoords( bool posture, vec2 vs, vec2 vp, vec2 texcoord, vec2 dir,
|
||||
vec2 s = sign( vec2( gl_ModelViewProjectionMatrix[0][0], gl_ModelViewProjectionMatrix[1][1] ) );
|
||||
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
if( pixelWidth < u_minLinePixelWidth )
|
||||
pixelWidth = u_minLinePixelWidth;
|
||||
|
||||
if ( pixelWidth > 1.0 || u_pixelSizeMultiplier > 1.0 )
|
||||
{
|
||||
@ -126,8 +127,59 @@ void computeCircleCoords( float mode, float vertexIndex, float radius, float lin
|
||||
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
if( pixelWidth < u_minLinePixelWidth )
|
||||
pixelWidth = u_minLinePixelWidth;
|
||||
|
||||
if( vertexIndex == 1.0 )
|
||||
{
|
||||
v_circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( -pixelR * sqrt(3.0), -pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 2.0 )
|
||||
{
|
||||
v_circleCoords = vec2( sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( pixelR * sqrt( 3.0 ), -pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 3.0 )
|
||||
{
|
||||
v_circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4( 0, 2 * pixelR, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 4.0 )
|
||||
{
|
||||
v_circleCoords = vec2( -sqrt( 3.0 ), 0.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 5.0 )
|
||||
{
|
||||
v_circleCoords = vec2( sqrt( 3.0 ), 0.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
else if( vertexIndex == 6.0 )
|
||||
{
|
||||
v_circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4( 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
v_shaderParams[2] = pixelR;
|
||||
v_shaderParams[3] = pixelWidth;
|
||||
|
||||
delta.x *= u_screenPixelSize.x;
|
||||
delta.y *= u_screenPixelSize.y;
|
||||
|
||||
gl_Position = center + delta + adjust;
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
void computeHoleWallCoords( float vertexIndex, float radius, float lineWidth )
|
||||
{
|
||||
vec4 delta;
|
||||
vec4 center = roundv( gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0), u_screenPixelSize );
|
||||
float pixelWidth = roundr( lineWidth / u_worldPixelSize, 1.0 );
|
||||
if( pixelWidth < u_minLinePixelWidth )
|
||||
pixelWidth = u_minLinePixelWidth;
|
||||
float pixelR = roundr( radius / u_worldPixelSize, 1.0 ) + pixelWidth;
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( vertexIndex == 1.0 )
|
||||
{
|
||||
@ -195,6 +247,8 @@ void main()
|
||||
computeLineCoords( posture, vs, vp, vec2( -1, 1 ), vec2( -1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_F )
|
||||
computeLineCoords( posture, -vs, vp, vec2( 1, 1 ), vec2( -1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_HOLE_WALL )
|
||||
computeHoleWallCoords( v_shaderParams.y, v_shaderParams.z, v_shaderParams.w );
|
||||
else if( mode == SHADER_FILLED_CIRCLE || mode == SHADER_STROKED_CIRCLE)
|
||||
computeCircleCoords( mode, v_shaderParams.y, v_shaderParams.z, v_shaderParams.w );
|
||||
else
|
||||
|
@ -78,6 +78,10 @@ public:
|
||||
/// @copydoc GAL::DrawCircle()
|
||||
void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) override;
|
||||
|
||||
/// @copydoc GAL::DrawHoleWall()
|
||||
void DrawHoleWall( const VECTOR2D& aCenterPoint, double aHoleRadius,
|
||||
double aWallWidth ) override;
|
||||
|
||||
/// @copydoc GAL::DrawArc()
|
||||
void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aAngle ) override;
|
||||
|
@ -142,6 +142,16 @@ public:
|
||||
*/
|
||||
virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) {};
|
||||
|
||||
/**
|
||||
* Draw a hole wall ring.
|
||||
*
|
||||
* @param aCenterPoint is the center point of the hole.
|
||||
* @param aHoleRadius is the radius of the hole.
|
||||
* @param aWallWidth is the wall thickness.
|
||||
*/
|
||||
virtual void DrawHoleWall( const VECTOR2D& aCenterPoint, double aHoleRadius,
|
||||
double aWallWidth ) {};
|
||||
|
||||
/**
|
||||
* Draw an arc.
|
||||
*
|
||||
@ -369,6 +379,16 @@ public:
|
||||
m_lineWidth = aLineWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum line width in pixels.
|
||||
*
|
||||
* @param aLineWidth is the minimum line width.
|
||||
*/
|
||||
virtual void SetMinLineWidth( float aLineWidth )
|
||||
{
|
||||
m_minLineWidth = aLineWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the line width.
|
||||
*
|
||||
@ -379,6 +399,16 @@ public:
|
||||
return m_lineWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum line width in pixels.
|
||||
*
|
||||
* @return the minimum line width.
|
||||
*/
|
||||
inline float GetMinLineWidth() const
|
||||
{
|
||||
return m_minLineWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the depth of the layer (position on the z-axis)
|
||||
*
|
||||
@ -1084,6 +1114,7 @@ protected:
|
||||
bool m_globalFlipY; ///< Flag for Y axis flipping
|
||||
|
||||
float m_lineWidth; ///< The line width
|
||||
float m_minLineWidth; ///< Minimum line width in pixels
|
||||
|
||||
bool m_isFillEnabled; ///< Is filling of graphic objects enabled ?
|
||||
bool m_isStrokeEnabled; ///< Are the outlines stroked ?
|
||||
|
@ -113,6 +113,8 @@ public:
|
||||
return IsShownOnScreen() && !GetClientRect().IsEmpty();
|
||||
}
|
||||
|
||||
void SetMinLineWidth( float aLineWidth ) override;
|
||||
|
||||
// ---------------
|
||||
// Drawing methods
|
||||
// ---------------
|
||||
@ -131,6 +133,10 @@ public:
|
||||
/// @copydoc GAL::DrawCircle()
|
||||
void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) override;
|
||||
|
||||
/// @copydoc GAL::DrawHoleWall()
|
||||
void DrawHoleWall( const VECTOR2D& aCenterPoint, double aHoleRadius,
|
||||
double aWallWidth ) override;
|
||||
|
||||
/// @copydoc GAL::DrawArc()
|
||||
void DrawArc( const VECTOR2D& aCenterPoint, double aRadius, const EDA_ANGLE& aStartAngle,
|
||||
const EDA_ANGLE& aAngle ) override;
|
||||
@ -377,6 +383,9 @@ private:
|
||||
GLint ufm_screenPixelSize;
|
||||
GLint ufm_pixelSizeMultiplier;
|
||||
GLint ufm_antialiasingOffset;
|
||||
GLint ufm_minLinePixelWidth;
|
||||
GLint ufm_fontTexture;
|
||||
GLint ufm_fontTextureWidth;
|
||||
|
||||
/// wx cursor showing the current native cursor.
|
||||
WX_CURSOR_TYPE m_currentwxCursor;
|
||||
@ -586,6 +595,13 @@ private:
|
||||
|
||||
VECTOR2D getScreenPixelSize() const;
|
||||
|
||||
/**
|
||||
* Set up the shader parameters for OpenGL rendering.
|
||||
* This method initializes all the uniform parameter locations
|
||||
* after the shader has been linked.
|
||||
*/
|
||||
void setupShaderParameters();
|
||||
|
||||
/**
|
||||
* Basic OpenGL initialization and feature checks.
|
||||
*
|
||||
|
@ -53,7 +53,8 @@ enum SHADER_MODE
|
||||
SHADER_LINE_C = 7,
|
||||
SHADER_LINE_D = 8,
|
||||
SHADER_LINE_E = 9,
|
||||
SHADER_LINE_F = 10
|
||||
SHADER_LINE_F = 10,
|
||||
SHADER_HOLE_WALL = 11
|
||||
};
|
||||
|
||||
///< Data structure for vertices {X,Y,Z,R,G,B,A,shader¶m}
|
||||
|
@ -1863,17 +1863,6 @@ double PAD::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
|
||||
return lodScaleForThreshold( aView, minSize, pcbIUScale.mmToIU( 0.5 ) );
|
||||
}
|
||||
|
||||
// Hole walls always need a repaint when zoom level changes after the last
|
||||
// LAYER_PAD_HOLEWALLS shape rebuild
|
||||
if( aLayer == LAYER_PAD_HOLEWALLS )
|
||||
{
|
||||
if( aView->GetGAL()->GetZoomFactor() != m_lastGalZoomLevel )
|
||||
{
|
||||
aView->Update( this, KIGFX::REPAINT );
|
||||
m_lastGalZoomLevel = aView->GetGAL()->GetZoomFactor();
|
||||
}
|
||||
}
|
||||
|
||||
VECTOR2L padSize = GetBoundingBox().GetSize();
|
||||
int64_t minSide = std::min( padSize.x, padSize.y );
|
||||
|
||||
|
@ -1448,22 +1448,26 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
|
||||
m_gal->SetIsStroke( false );
|
||||
double widthFactor = ADVANCED_CFG::GetCfg().m_HoleWallPaintingMultiplier;
|
||||
double lineWidth = widthFactor * m_holePlatingThickness;
|
||||
|
||||
// Prevent the hole wall from being drawn too thin (at least two pixels)
|
||||
// or too thick (cap at the size of the pad )
|
||||
lineWidth = std::max( lineWidth, 2.0 / m_gal->GetWorldScale() );
|
||||
lineWidth = std::min( lineWidth, aPad->GetSizeX() / 2.0 );
|
||||
lineWidth = std::min( lineWidth, aPad->GetSizeY() / 2.0 );
|
||||
|
||||
m_gal->SetFillColor( color );
|
||||
m_gal->SetMinLineWidth( lineWidth );
|
||||
|
||||
std::shared_ptr<SHAPE_SEGMENT> slot = aPad->GetEffectiveHoleShape();
|
||||
int holeSize = slot->GetWidth() + ( 2 * lineWidth );
|
||||
|
||||
if( slot->GetSeg().A == slot->GetSeg().B ) // Circular hole
|
||||
m_gal->DrawCircle( slot->GetSeg().A, KiROUND( holeSize / 2.0 ) );
|
||||
{
|
||||
double holeRadius = slot->GetWidth() / 2.0;
|
||||
m_gal->DrawHoleWall( slot->GetSeg().A, holeRadius, lineWidth );
|
||||
}
|
||||
else
|
||||
{
|
||||
int holeSize = slot->GetWidth() + ( 2 * lineWidth );
|
||||
m_gal->DrawSegment( slot->GetSeg().A, slot->GetSeg().B, holeSize );
|
||||
}
|
||||
|
||||
m_gal->SetMinLineWidth( 1.0 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user