60using namespace std::placeholders;
68#include <glsl_kicad_frag.h>
69#include <glsl_kicad_vert.h>
81constexpr GLuint STENCIL_DOTS_MARKER = 0x01;
83constexpr GLuint STENCIL_GRID_COVERAGE = 0x80;
90 wxGLAttributes attribs;
94 attribs.RGBA().MinRGBA( 8, 8, 8, 0 ).DoubleBuffer().Depth( 8 ).EndList();
154 glDeleteTextures( 1, &bitmap.second.id );
160#ifndef DISABLE_BITMAP_CACHE
166 if( glIsTexture( it->second.id ) )
168 it->second.accessTime = wxGetUTCTimeMillis().GetValue();
169 return it->second.id;
174 glDeleteTextures( 1, &it->second.id );
202 return std::numeric_limits< GLuint >::max();
204 GLint maxTextureSize;
205 glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTextureSize );
209 if( !imgData.IsOk() )
210 return std::numeric_limits< GLuint >::max();
212 bmp.
w = imgData.GetSize().x;
213 bmp.
h = imgData.GetSize().y;
219 glGenTextures( 1, &textureID );
227 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
229 if( imgData.HasAlpha() || imgData.HasMask() )
231 bmp.
size =
static_cast<size_t>( bmp.
w ) * bmp.
h * 4;
233 const std::vector<uint8_t> rgba =
ImageToRgba( imgData );
235 glBindTexture( GL_TEXTURE_2D, textureID );
236 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.
w, bmp.
h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
241 bmp.
size =
static_cast<size_t>( bmp.
w ) * bmp.
h * 3;
243 uint8_t* srcP = imgData.GetData();
245 glBindTexture( GL_TEXTURE_2D, textureID );
246 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, bmp.
w, bmp.
h, 0, GL_RGB, GL_UNSIGNED_BYTE, srcP );
249 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
250 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
252 long long currentTime = wxGetUTCTimeMillis().GetValue();
257#ifndef DISABLE_BITMAP_CACHE
267 for(
const auto& [kiid, cachedBmp] :
m_bitmaps )
269 const int cacheTimeoutMillis = 1000L;
271 if( currentTime - cachedBmp.accessTime > cacheTimeoutMillis )
285 toRemove = *toRemoveLru;
291 glDeleteTextures( 1, &cachedBitmap.
id );
309 wxEvtHandler* aMouseListener, wxEvtHandler* aPaintListener,
310 const wxString& aName ) :
311 GAL( aDisplayOptions ),
335 throw std::runtime_error(
"Could not create the main OpenGL context" );
344 throw std::runtime_error(
"Could not create a private OpenGL context" );
390#if defined _WIN32 || defined _WIN64
397 SetSize( aParent->GetClientSize() );
400 SetPosition( wxPoint( 0, 0 ) );
412 gluTessProperty(
m_tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
515 static std::optional<wxString> cached;
517 if( cached.has_value() )
520 wxString retVal = wxEmptyString;
522 wxFrame* testFrame =
new wxFrame(
nullptr, wxID_ANY, wxT(
"" ), wxDefaultPosition,
523 wxSize( 1, 1 ), wxFRAME_TOOL_WINDOW | wxNO_BORDER );
545 catch( std::runtime_error& err )
548 retVal = wxString( err.what() );
609#ifdef KICAD_GAL_PROFILE
610 PROF_TIMER totalRealTime(
"OPENGL_GAL::beginDrawing()",
true );
613 wxASSERT_MSG(
m_isContextLocked,
"GAL_DRAWING_CONTEXT RAII object should have locked context. "
614 "Calling GAL::beginDrawing() directly is not allowed." );
616 wxASSERT_MSG(
IsVisible(),
"GAL::beginDrawing() must not be entered when GAL is not visible. "
617 "Other drawing routines will expect everything to be initialized "
618 "which will not be the case." );
624 glMatrixMode( GL_PROJECTION );
647 catch(
const std::runtime_error& )
649 wxLogVerbose(
"Could not create a framebuffer for diff mode blending.\n" );
656 catch(
const std::runtime_error& )
658 wxLogVerbose(
"Could not create a framebuffer for overlays.\n" );
668 glDisable( GL_TEXTURE_2D );
670 glShadeModel( GL_FLAT );
673 glEnable( GL_DEPTH_TEST );
674 glDepthFunc( GL_LESS );
677 glEnable( GL_BLEND );
678 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
680 glMatrixMode( GL_MODELVIEW );
684 GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
694 glLoadMatrixd( matrixData );
713 const GLint FONT_TEXTURE_UNIT = 2;
718 glActiveTexture( GL_TEXTURE0 + FONT_TEXTURE_UNIT );
723 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
724 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
725 checkGlError(
"loading bitmap font", __FILE__, __LINE__ );
727 glActiveTexture( GL_TEXTURE0 );
733 glActiveTexture( GL_TEXTURE0 + FONT_TEXTURE_UNIT );
735 glActiveTexture( GL_TEXTURE0 );
742 checkGlError(
"setting bitmap font sampler as shader parameter", __FILE__, __LINE__ );
752 double pixelSizeMultiplier =
m_compositor->GetAntialiasSupersamplingFactor();
755 renderingOffset.
x *= screenPixelSize.
x;
756 renderingOffset.
y *= screenPixelSize.
y;
763 glActiveTexture( GL_TEXTURE0 );
768#ifdef KICAD_GAL_PROFILE
769 totalRealTime.
Stop();
770 wxLogTrace(
traceGalProfile, wxT(
"OPENGL_GAL::beginDrawing(): %.1f ms" ),
771 totalRealTime.
msecs() );
794 PROF_TIMER cntEndNoncached(
"gl-end-noncached" );
804 cntEndNoncached.
Start();
806 cntEndNoncached.
Stop();
808 cntEndCached.
Start();
812 cntEndOverlay.
Start();
818 cntEndOverlay.
Stop();
820 cntComposite.
Start();
823 glColor4d( 1.0, 1.0, 1.0, 1.0 );
842#ifdef KICAD_GAL_PROFILE
864 glGetIntegerv( GL_VIEWPORT, viewport );
866 const int w = viewport[2];
867 const int h = viewport[3];
869 GLint readBuffer = GL_COLOR_ATTACHMENT0;
870 glGetIntegerv( GL_DRAW_BUFFER, &readBuffer );
876 std::vector<unsigned char> rgba( (
size_t) w * h * 4 );
879 glPixelStorei( GL_PACK_ALIGNMENT, 1 );
880 glReadBuffer( (
GLenum) readBuffer );
881 glReadPixels( 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgba.data() );
884 unsigned char* rgb = (
unsigned char*) malloc( (
size_t) w * h * 3 );
885 unsigned char* alpha = (
unsigned char*) malloc( (
size_t) w * h );
887 for(
int i = 0; i < w * h; ++i )
889 rgb[i * 3 + 0] = rgba[i * 4 + 0];
890 rgb[i * 3 + 1] = rgba[i * 4 + 1];
891 rgb[i * 3 + 2] = rgba[i * 4 + 2];
892 alpha[i] = rgba[i * 4 + 3];
895 aDstImage.SetData( rgb, w, h,
false );
896 aDstImage.SetAlpha( alpha,
false );
898 aDstImage = aDstImage.Mirror(
false );
944 if( glGetGraphicsResetStatus )
945 return glGetGraphicsResetStatus();
947 if( glGetGraphicsResetStatusARB )
948 return glGetGraphicsResetStatusARB();
959 if( status != GL_NO_ERROR )
962 return status != GL_NO_ERROR;
976 bool mainOwned =
false;
1005 if( GL_RESET_BUDGET::CLOCK::now() -
m_resetDetectedAt >= std::chrono::seconds( 2 ) )
1007 wxLogTrace(
traceGalContext, wxS(
"GL reset did not report completion, rebuilding anyway" ) );
1026 wxASSERT_MSG(
m_isContextLocked,
"Context not locked. A GAL_CONTEXT_LOCKER RAII object must "
1027 "be stacked rather than making separate lock/unlock calls." );
1030 "Context was locked by a different client. "
1031 "Should not be possible with RAII objects." );
1046 wxASSERT_MSG(
m_isContextLocked,
"GAL_UPDATE_CONTEXT RAII object should have locked context. "
1047 "Calling this from anywhere else is not allowed." );
1049 wxASSERT_MSG(
IsVisible(),
"GAL::beginUpdate() must not be entered when GAL is not visible. "
1050 "Other update routines will expect everything to be initialized "
1051 "which will not be the case." );
1087 VECTOR2D startEndVector = aEndPoint - aStartPoint;
1094 float startX =
static_cast<float>( aStartPoint.
x );
1095 float startY =
static_cast<float>( aStartPoint.
y );
1096 float endX =
static_cast<float>( aEndPoint.
x );
1097 float endY =
static_cast<float>( aEndPoint.
y );
1099 if( startX == endX && startY == endY )
1101 drawCircle( aStartPoint, aWidth / 2, aReserve );
1236 double startAngle = aStartAngle.
AsRadians();
1237 double endAngle = startAngle + aAngle.
AsRadians();
1254 for( alpha = startAngle; ( alpha + alphaIncrement ) < endAngle; )
1260 alpha += alphaIncrement;
1266 const VECTOR2D endPoint( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
1279 VECTOR2D p( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
1281 unsigned int lineCount = 0;
1283 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1286 if( alpha != endAngle )
1291 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1293 VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
1300 if( alpha != endAngle )
1302 VECTOR2D p_last( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
1313 double aWidth,
double aMaxError )
1324 double startAngle = aStartAngle.
AsRadians();
1325 double endAngle = startAngle + aAngle.
AsRadians();
1333 double alphaIncrement = 2.0 *
M_PI / segCount360;
1338 int seg_count =
KiROUND( ( endAngle - startAngle ) / alphaIncrement );
1340 if( seg_count % 2 != 0 )
1344 if( seg_count == 0 )
1346 VECTOR2D p_start( aCenterPoint.
x + cos( startAngle ) * aRadius,
1347 aCenterPoint.
y + sin( startAngle ) * aRadius );
1349 VECTOR2D p_end( aCenterPoint.
x + cos( endAngle ) * aRadius,
1350 aCenterPoint.
y + sin( endAngle ) * aRadius );
1357 alphaIncrement = ( endAngle - startAngle ) / seg_count;
1367 double width = aWidth / 2.0;
1368 VECTOR2D startPoint( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
1369 VECTOR2D endPoint( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
1374 VECTOR2D pOuter( cos( startAngle ) * ( aRadius + width ),
1375 sin( startAngle ) * ( aRadius + width ) );
1377 VECTOR2D pInner( cos( startAngle ) * ( aRadius - width ),
1378 sin( startAngle ) * ( aRadius - width ) );
1382 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1384 VECTOR2D pNextOuter( cos( alpha ) * ( aRadius + width ),
1385 sin( alpha ) * ( aRadius + width ) );
1386 VECTOR2D pNextInner( cos( alpha ) * ( aRadius - width ),
1387 sin( alpha ) * ( aRadius - width ) );
1392 pOuter = pNextOuter;
1393 pInner = pNextInner;
1397 if( alpha != endAngle )
1399 VECTOR2D pLastOuter( cos( endAngle ) * ( aRadius + width ),
1400 sin( endAngle ) * ( aRadius + width ) );
1401 VECTOR2D pLastInner( cos( endAngle ) * ( aRadius - width ),
1402 sin( endAngle ) * ( aRadius - width ) );
1414 VECTOR2D p( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
1419 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1425 if( alpha != endAngle )
1432 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1434 VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
1441 if( alpha != endAngle )
1443 VECTOR2D p_last( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
1455 if( aMajorRadius <= 0 || aMinorRadius <= 0 )
1458 const double alphaIncrement =
calcAngleStep( aMajorRadius );
1459 const double cosPhi = std::cos( aRotation.
AsRadians() );
1460 const double sinPhi = std::sin( aRotation.
AsRadians() );
1462 auto eval = [&](
double theta ) ->
VECTOR2D
1464 const double lx = aMajorRadius * std::cos( theta );
1465 const double ly = aMinorRadius * std::sin( theta );
1466 return VECTOR2D( lx * cosPhi - ly * sinPhi, lx * sinPhi + ly * cosPhi );
1479 for( alpha = 0.0; ( alpha + alphaIncrement ) < 2.0 *
M_PI; )
1482 alpha += alphaIncrement;
1506 unsigned int lineCount = 0;
1509 for( countAlpha = alphaIncrement; countAlpha < 2.0 *
M_PI; countAlpha += alphaIncrement )
1519 for( alpha = alphaIncrement; alpha < 2.0 *
M_PI; alpha += alphaIncrement )
1521 const VECTOR2D p_next = eval( alpha );
1537 if( aMajorRadius <= 0 || aMinorRadius <= 0 )
1540 double startAngle = aStartAngle.
AsRadians();
1541 double endAngle = aEndAngle.
AsRadians();
1544 const double alphaIncrement =
calcAngleStep( aMajorRadius );
1545 const double cosPhi = std::cos( aRotation.
AsRadians() );
1546 const double sinPhi = std::sin( aRotation.
AsRadians() );
1548 auto eval = [&](
double theta ) ->
VECTOR2D
1550 const double lx = aMajorRadius * std::cos( theta );
1551 const double ly = aMinorRadius * std::sin( theta );
1552 return VECTOR2D( lx * cosPhi - ly * sinPhi, lx * sinPhi + ly * cosPhi );
1566 for( alpha = startAngle; ( alpha + alphaIncrement ) < endAngle; )
1569 alpha += alphaIncrement;
1580 const VECTOR2D p2 = eval( endAngle );
1592 unsigned int lineCount = 0;
1595 for( countAlpha = startAngle + alphaIncrement; countAlpha <= endAngle; countAlpha += alphaIncrement )
1598 if( countAlpha != endAngle )
1606 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1608 const VECTOR2D p_next = eval( alpha );
1614 if( alpha != endAngle )
1616 const VECTOR2D p_last = eval( endAngle );
1628 VECTOR2D diagonalPointA( aEndPoint.
x, aStartPoint.
y );
1629 VECTOR2D diagonalPointB( aStartPoint.
x, aEndPoint.
y );
1655 if( aStartPoint == aEndPoint )
1661 std::deque<VECTOR2D> pointList;
1663 pointList.push_back( aStartPoint );
1664 pointList.push_back( diagonalPointA );
1665 pointList.push_back( aEndPoint );
1666 pointList.push_back( diagonalPointB );
1667 pointList.push_back( aStartPoint );
1679 return aPointList[idx];
1681 aPointList.size(), aWidth );
1695 return aLineChain.
CPoint( idx );
1697 numPoints, aWidth );
1706 return aPointList[idx];
1708 aPointList.size() );
1717 return aPointList[idx];
1719 aPointList.size() );
1728 return aPointList[idx];
1744 return aLineChain.
CPoint( idx );
1752 int lineQuadCount = 0;
1754 for(
const std::vector<VECTOR2D>& points : aPointList )
1755 lineQuadCount += points.size() - 1;
1759 for(
const std::vector<VECTOR2D>& points : aPointList )
1766 points.size(),
false );
1773 wxCHECK( aPointList.size() >= 2, );
1774 auto points = std::unique_ptr<GLdouble[]>(
new GLdouble[3 * aPointList.size()] );
1775 GLdouble* ptr = points.get();
1777 for(
const VECTOR2D& p : aPointList )
1790 wxCHECK( aListSize >= 2, );
1791 auto points = std::unique_ptr<GLdouble[]>(
new GLdouble[3 * aListSize] );
1792 GLdouble* target = points.get();
1795 for(
int i = 0; i < aListSize; ++i )
1808 bool aStrokeTriangulation )
1815 int totalTriangleCount = 0;
1830 for(
size_t i = 0; i < triPoly->GetTriangleCount(); i++ )
1833 triPoly->GetTriangle( i, a, b, c );
1845 const auto& poly = aPolySet.
Polygon( j );
1847 for(
const auto& lc : poly )
1856 aStrokeTriangulation =
true;
1860 if( aStrokeTriangulation )
1869 for(
size_t i = 0; i < triPoly->GetTriangleCount(); i++ )
1872 triPoly->GetTriangle( i, a, b, c );
1904 std::unique_ptr<GLdouble[]> points(
new GLdouble[3 * pointCount] );
1905 GLdouble* ptr = points.get();
1907 for(
int i = 0; i < pointCount; ++i )
1921 double aFilterValue )
1923 std::vector<VECTOR2D> output;
1924 std::vector<VECTOR2D> pointCtrl;
1926 pointCtrl.push_back( aStartPoint );
1927 pointCtrl.push_back( aControlPointA );
1928 pointCtrl.push_back( aControlPointB );
1929 pointCtrl.push_back( aEndPoint );
1932 converter.
GetPoly( output, aFilterValue );
1934 if( output.size() == 1 )
1935 output.push_back( output.front() );
1943 GLfloat alpha = std::clamp( alphaBlend, 0.0, 1.0 );
1953 glm::vec4 v0 = xform * glm::vec4( -w / 2, -h / 2, 0.0, 0.0 );
1954 glm::vec4
v1 = xform * glm::vec4( w / 2, -h / 2, 0.0, 0.0 );
1955 glm::vec4
v2 = xform * glm::vec4( w / 2, h / 2, 0.0, 0.0 );
1956 glm::vec4
v3 = xform * glm::vec4( -w / 2, h / 2, 0.0, 0.0 );
1957 glm::vec4 trans = xform[3];
1961 if( !glIsTexture( texture_id ) )
1964 GLboolean depthMask = GL_TRUE;
1965 glGetBooleanv( GL_DEPTH_WRITEMASK, &depthMask );
1968 glDepthMask( GL_FALSE );
1970 glDepthFunc( GL_ALWAYS );
1972 glAlphaFunc( GL_GREATER, 0.01f );
1973 glEnable( GL_ALPHA_TEST );
1975 glMatrixMode( GL_TEXTURE );
1977 glTranslated( 0.5, 0.5, 0.5 );
1979 glTranslated( -0.5, -0.5, -0.5 );
1981 glMatrixMode( GL_MODELVIEW );
1983 glTranslated( trans.x, trans.y, trans.z );
1985 glEnable( GL_TEXTURE_2D );
1986 glActiveTexture( GL_TEXTURE0 );
1987 glBindTexture( GL_TEXTURE_2D, texture_id );
1989 float texStartX = aBitmap.
IsMirroredX() ? 1.0 : 0.0;
1990 float texEndX = aBitmap.
IsMirroredX() ? 0.0 : 1.0;
1991 float texStartY = aBitmap.
IsMirroredY() ? 1.0 : 0.0;
1992 float texEndY = aBitmap.
IsMirroredY() ? 0.0 : 1.0;
1994 glBegin( GL_QUADS );
1995 glColor4f( 1.0, 1.0, 1.0, alpha );
1996 glTexCoord2f( texStartX, texStartY );
1998 glColor4f( 1.0, 1.0, 1.0, alpha );
1999 glTexCoord2f( texEndX, texStartY);
2001 glColor4f( 1.0, 1.0, 1.0, alpha );
2002 glTexCoord2f( texEndX, texEndY);
2004 glColor4f( 1.0, 1.0, 1.0, alpha );
2005 glTexCoord2f( texStartX, texEndY);
2009 glBindTexture( GL_TEXTURE_2D, 0 );
2011#ifdef DISABLE_BITMAP_CACHE
2012 glDeleteTextures( 1, &texture_id );
2017 glMatrixMode( GL_TEXTURE );
2019 glMatrixMode( GL_MODELVIEW );
2021 glDisable( GL_ALPHA_TEST );
2023 glDepthMask( depthMask );
2025 glDepthFunc( GL_LESS );
2034 || aText.Contains( wxT(
"^{" ) )
2035 || aText.Contains( wxT(
"_{" ) )
2036 || aText.Contains( wxT(
"\n" ) ) )
2047 double overbarHeight = textSize.
y;
2078 wxFAIL_MSG( wxT(
"Indeterminate state legal only in dialogs." ) );
2094 overbarHeight = -textSize.
y / 2.0;
2098 wxFAIL_MSG( wxT(
"Indeterminate state legal only in dialogs." ) );
2102 int overbarLength = 0;
2103 int overbarDepth = -1;
2104 int braceNesting = 0;
2106 auto iterateString =
2107 [&](
const std::function<void(
int aOverbarLength,
int aOverbarHeight )>& overbarFn,
2108 const std::function<int(
unsigned long aChar )>& bitmapCharFn )
2112 wxASSERT_MSG( *chIt !=
'\n' && *chIt !=
'\r',
2113 "No support for multiline bitmap text yet" );
2115 if( *chIt ==
'~' && overbarDepth == -1 )
2119 if( ++lookahead !=
end && *lookahead ==
'{' )
2122 overbarDepth = braceNesting;
2127 else if( *chIt ==
'{' )
2131 else if( *chIt ==
'}' )
2133 if( braceNesting > 0 )
2136 if( braceNesting == overbarDepth )
2138 overbarFn( overbarLength, overbarHeight );
2146 if( overbarDepth != -1 )
2147 overbarLength += bitmapCharFn( *chIt );
2149 bitmapCharFn( *chIt );
2156 int overbarsCount = 0;
2159 [&overbarsCount](
int aOverbarLength,
int aOverbarHeight )
2163 [&charsCount](
unsigned long aChar ) ->
int
2179 [&](
int aOverbarLength,
int aOverbarHeight )
2183 [&](
unsigned long aChar ) ->
int
2191 if( overbarDepth != -1 && overbarLength > 0 )
2221 if( renderGlobalGrid )
2243 if( renderGlobalGrid )
2255 std::vector<const GRID_SOURCE*> ordered;
2260 if( !src.highlighted )
2261 ordered.push_back( &src );
2266 if( src.highlighted )
2267 ordered.push_back( &src );
2271 const float majorLineWidth = minorLineWidth * 2.0f;
2274 glDisable( GL_DEPTH_TEST );
2275 glDisable( GL_TEXTURE_2D );
2278 glEnable( GL_STENCIL_TEST );
2279 glStencilMask( 0xFF );
2280 glClear( GL_STENCIL_BUFFER_BIT );
2287 const GLuint coverageMask = src.
highlighted ? 0 : STENCIL_GRID_COVERAGE;
2289 glStencilMask( 0x00 );
2290 glStencilFunc( GL_EQUAL, 0, coverageMask );
2291 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2308 glColor4d( color.
r, color.
g, color.
b, color.
a );
2317 auto drawCrossAt = [&](
const VECTOR2D& pos,
bool aMajor,
double aArmAngle )
2319 const float w = aMajor ? majorLineWidth : minorLineWidth;
2320 const double len = 2.0 * w;
2321 const double c = std::cos( aArmAngle );
2322 const double s = std::sin( aArmAngle );
2323 const VECTOR2D arm1( c * len, s * len );
2324 const VECTOR2D arm2( -s * len, c * len );
2329 DrawLine( pos - arm1, pos + arm1 );
2330 DrawLine( pos - arm2, pos + arm2 );
2334 auto beginLines = [&]()
2341 auto drawDotsViaStencil = [&](
auto&& aMarkAxis,
auto&& aRenderAxis )
2344 glStencilMask( STENCIL_DOTS_MARKER );
2345 glClear( GL_STENCIL_BUFFER_BIT );
2348 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
2349 glStencilFunc( GL_EQUAL, STENCIL_DOTS_MARKER, coverageMask );
2350 glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
2357 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
2358 glStencilMask( 0x00 );
2359 glStencilFunc( GL_EQUAL, STENCIL_DOTS_MARKER, STENCIL_DOTS_MARKER | coverageMask );
2360 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2369 const double rMax = lattice.
extent.
x;
2370 const double phiMax = lattice.
extent.
y;
2371 const double dr = lattice.
pitch.
x;
2372 const double dPhi = lattice.
pitch.
y;
2374 wxASSERT( dr > 0.0 && dPhi > 0.0 );
2376 auto drawArcs = [&]()
2379 for(
double r = 0; r <= rMax + 1e-6; r += dr, ++rIdx )
2389 auto drawSpokes = [&]()
2392 for(
double phi = 0; phi <= phiMax + 1e-6; phi += dPhi, ++pIdx )
2395 const double cx = std::cos( phi );
2396 const double cy = std::sin( phi );
2409 drawDotsViaStencil( drawArcs, drawSpokes );
2414 for(
double r = 0; r <= rMax + 1e-6; r += dr, ++rIdx )
2417 for(
double phi = 0; phi <= phiMax + 1e-6; phi += dPhi, ++pIdx )
2419 const bool major = lattice.
IsMajor( rIdx ) && lattice.
IsMajor( pIdx );
2420 const VECTOR2D pos( r * std::cos( phi ), r * std::sin( phi ) );
2421 drawCrossAt( pos, major, phi );
2430 const double dx = lattice.
pitch.
x;
2431 const double dy = lattice.
pitch.
y;
2433 wxASSERT( dx > 0.0 && dy > 0.0 );
2435 double xMin, xMax, yMin, yMax;
2436 int ixMin, ixMax, iyMin, iyMax;
2447 yMin = localBBox.
GetTop();
2450 ixMin = (int) std::floor( xMin / dx );
2451 ixMax = (int) std::ceil( xMax / dx );
2452 iyMin = (int) std::floor( yMin / dy );
2453 iyMax = (int) std::ceil( yMax / dy );
2461 ixMin = (int) -( src.
extent.
x / dx );
2462 ixMax = (int) ( src.
extent.
x / dx );
2463 iyMin = (int) -( src.
extent.
y / dy );
2464 iyMax = (int) ( src.
extent.
y / dy );
2467 auto drawVerticals = [&]()
2469 for(
int ix = ixMin; ix <= ixMax; ++ix )
2471 const double x = ix * dx;
2482 auto drawHorizontals = [&]()
2484 for(
int iy = iyMin; iy <= iyMax; ++iy )
2486 const double y = iy * dy;
2504 drawDotsViaStencil( drawVerticals, drawHorizontals );
2508 for(
int ix = ixMin; ix <= ixMax; ++ix )
2510 for(
int iy = iyMin; iy <= iyMax; ++iy )
2512 const bool major = lattice.
IsMajor( ix ) && lattice.
IsMajor( iy );
2513 drawCrossAt(
VECTOR2D( ix * dx, iy * dy ), major, 0.0 );
2520 default: wxFAIL_MSG( wxT(
"drawGridSources: unhandled GRID_SOURCE::KIND" ) );
break;
2529 glStencilMask( 0x00 );
2530 glStencilFunc( GL_EQUAL, 0, coverageMask );
2531 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2544 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
2545 glStencilMask( STENCIL_GRID_COVERAGE );
2546 glStencilFunc( GL_ALWAYS, STENCIL_GRID_COVERAGE, STENCIL_GRID_COVERAGE );
2547 glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
2554 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
2558 glDisable( GL_STENCIL_TEST );
2560 glEnable( GL_DEPTH_TEST );
2561 glEnable( GL_TEXTURE_2D );
2571 m_compositor->Resize( aWidth * scaleFactor, aHeight * scaleFactor );
2574 wxGLCanvas::SetSize( aWidth, aHeight );
2580 bool s = wxGLCanvas::Show( aShow );
2583 wxGLCanvas::Raise();
2601 glClearColor( 0, 0, 0, 1 );
2602 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
2608 GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
2610 matrixData[0] = aTransformation.
m_data[0][0];
2611 matrixData[1] = aTransformation.
m_data[1][0];
2612 matrixData[2] = aTransformation.
m_data[2][0];
2613 matrixData[4] = aTransformation.
m_data[0][1];
2614 matrixData[5] = aTransformation.
m_data[1][1];
2615 matrixData[6] = aTransformation.
m_data[2][1];
2616 matrixData[12] = aTransformation.
m_data[0][2];
2617 matrixData[13] = aTransformation.
m_data[1][2];
2618 matrixData[14] = aTransformation.
m_data[2][2];
2620 glMultMatrixd( matrixData );
2658 std::shared_ptr<VERTEX_ITEM> newItem = std::make_shared<VERTEX_ITEM>( *
m_cachedManager );
2660 m_groups.insert( std::make_pair( groupNumber, newItem ) );
2793 wxLogTrace(
traceGalXorMode, wxT(
"OPENGL_GAL::StartDiffLayer() called" ) );
2800 wxLogTrace(
traceGalXorMode, wxT(
"StartDiffLayer(): setting target to TARGET_TEMP" ) );
2807 wxLogTrace(
traceGalXorMode, wxT(
"StartDiffLayer(): TARGET_TEMP set and cleared, compositor buffer=%u" ),
2812 wxLogTrace(
traceGalXorMode, wxT(
"StartDiffLayer(): WARNING - no temp buffer!" ) );
2819 wxLogTrace(
traceGalXorMode, wxT(
"OPENGL_GAL::EndDiffLayer() called" ) );
2820 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): m_tempBuffer=%u, m_mainBuffer=%u" ),
2825 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): using temp buffer path" ) );
2830 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): calling DrawBufferDifference" ) );
2838 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): DrawBufferDifference returned" ) );
2842 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): NO temp buffer, using fallback path" ) );
2845 glBlendFunc( GL_SRC_ALPHA, GL_ONE );
2847 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2850 wxLogTrace(
traceGalXorMode, wxT(
"OPENGL_GAL::EndDiffLayer() complete" ) );
2862#if wxCHECK_VERSION( 3, 3, 0 )
2874#if wxCHECK_VERSION( 3, 3, 0 )
2893 const bool aReserve )
2911 * glm::vec4( aStartPoint.
x, aStartPoint.
y, 0.0, 0.0 );
2913 * glm::vec4( aEndPoint.
x, aEndPoint.
y, 0.0, 0.0 );
2997 double outerRadius = aRadius + (
m_lineWidth / 2 );
3043 GLdouble* point = aPoints;
3045 for(
int i = 0; i < aPointCount; ++i )
3063 return VECTOR2D( aPoints[idx * 3], aPoints[idx * 3 + 1] );
3073 wxCHECK( aPointCount > 0, );
3077 if( aPointCount == 1 )
3079 drawLineQuad( aPointGetter( 0 ), aPointGetter( 0 ), aReserve );
3088 for(
int i = 1; i < aPointCount; ++i )
3090 auto start = aPointGetter( i - 1 );
3091 auto end = aPointGetter( i );
3099 int aPointCount,
double aWidth,
bool aReserve )
3101 wxCHECK( aPointCount >= 2, );
3107 for(
int i = 1; i < aPointCount; ++i )
3109 auto start = aPointGetter( i - 1 );
3110 auto end = aPointGetter( i );
3112 float startx = start.x;
3113 float starty = start.y;
3122 if( startx == endx && starty == endy )
3134 vertices += 6 + 6 + 3 + 3;
3140 for(
int i = 1; i < aPointCount; ++i )
3142 auto start = aPointGetter( i - 1 );
3143 auto end = aPointGetter( i );
3176 const float Y = box.
atlasY;
3177 const float XOFF = box.
x;
3178 const float YOFF = box.
y;
3179 const float W = box.
w;
3180 const float H = box.
h;
3227 const float H = glyph->
maxy - glyph->
miny;
3298 const int cursorSize = 80;
3305 GLboolean depthTestEnabled = glIsEnabled( GL_DEPTH_TEST );
3306 glDisable( GL_DEPTH_TEST );
3308 glActiveTexture( GL_TEXTURE0 );
3309 glDisable( GL_TEXTURE_2D );
3310 glEnable( GL_BLEND );
3311 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
3314 glColor4d( color.
r, color.
g, color.
b, color.
a );
3316 glMatrixMode( GL_PROJECTION );
3318 glTranslated( 0, 0, -0.5 );
3320 glBegin( GL_LINES );
3335 double offset1 = cy - cx;
3336 VECTOR2D pos_start( screenTopLeft.
x, screenTopLeft.
x + offset1 );
3337 VECTOR2D pos_end( screenBottomRight.
x, screenBottomRight.
x + offset1 );
3340 glVertex2d( pos_start.
x, pos_start.
y );
3341 glVertex2d( pos_end.
x, pos_end.
y );
3344 double offset2 = cy + cx;
3345 VECTOR2D neg_start( screenTopLeft.
x, offset2 - screenTopLeft.
x );
3346 VECTOR2D neg_end( screenBottomRight.
x, offset2 - screenBottomRight.
x );
3349 glVertex2d( neg_start.
x, neg_start.
y );
3350 glVertex2d( neg_end.
x, neg_end.
y );
3354 glVertex2d( cursorCenter.
x, cursorBegin.
y );
3355 glVertex2d( cursorCenter.
x, cursorEnd.
y );
3357 glVertex2d( cursorBegin.
x, cursorCenter.
y );
3358 glVertex2d( cursorEnd.
x, cursorCenter.
y );
3365 if( depthTestEnabled )
3366 glEnable( GL_DEPTH_TEST );
3372 wxASSERT_MSG(
m_groups.size() < std::numeric_limits<unsigned int>::max(),
3373 wxT(
"There are no free slots to store a group" ) );
3384 wxASSERT_MSG(
m_isContextLocked,
"This should only be called from within a locked context." );
3388 throw std::runtime_error(
"Could not create the tesselator" );
3392 int glVersion = gladLoaderLoadGL();
3394 if( glVersion == 0 )
3395 throw std::runtime_error(
"Failed to load OpenGL via loader" );
3399 const char* vendor = (
const char*) glGetString( GL_VENDOR );
3400 const char* renderer = (
const char*) glGetString( GL_RENDERER );
3401 const char* version = (
const char*) glGetString( GL_VERSION );
3404 throw std::runtime_error(
"No GL context is current (glGetString returned NULL)" );
3408 wxLogTrace(
traceGalContext, wxS(
"GL context %p ready on canvas %p: %s | %s | %s" ),
3410 wxString::FromUTF8( renderer ), wxString::FromUTF8( version ) );
3412 GLint resetStrategy = 0;
3414 if( GLAD_GL_VERSION_4_5 || GLAD_GL_ARB_robustness || GLAD_GL_KHR_robustness )
3415 glGetIntegerv( GL_RESET_NOTIFICATION_STRATEGY, &resetStrategy );
3420 if( !GLAD_GL_VERSION_2_1 )
3421 throw std::runtime_error(
"OpenGL 2.1 or higher is required!" );
3423#if defined( __LINUX__ )
3425 if( glDebugMessageCallback )
3431 if( !GLAD_GL_ARB_framebuffer_object )
3432 throw std::runtime_error(
"Framebuffer objects are not supported!" );
3435 if( !GLAD_GL_ARB_vertex_buffer_object )
3436 throw std::runtime_error(
"Vertex buffer objects are not supported!" );
3441 BUILTIN_SHADERS::glsl_kicad_vert ) )
3443 throw std::runtime_error(
"Cannot compile vertex shader!" );
3448 BUILTIN_SHADERS::glsl_kicad_frag ) )
3450 throw std::runtime_error(
"Cannot compile fragment shader!" );
3454 throw std::runtime_error(
"Cannot link the shaders!" );
3461 glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTextureSize );
3467 throw std::runtime_error(
"Requested texture size is not supported" );
3470#if wxCHECK_VERSION( 3, 3, 3 )
3471 wxGLCanvas::SetSwapInterval( -1 );
3508 GLdouble* vertex =
static_cast<GLdouble*
>( aVertexPtr );
3512 assert( vboManager );
3513 vboManager->
Vertex( vertex[0], vertex[1], vertex[2] );
3518 GLdouble** dataOut,
void* aData )
3520 GLdouble* vertex =
new GLdouble[3];
3526 param->
intersectPoints.emplace_back( vertex, std::default_delete<GLdouble[]>() );
3528 memcpy( vertex, coords, 3 *
sizeof( GLdouble ) );
3549#if defined( _MSC_VER )
3550#pragma warning( push )
3551#pragma warning( disable : 4191 )
3557#if defined( _MSC_VER )
3558#pragma warning( pop )
3573 return ( ceil( f / r ) - 0.5 ) * r;
3606 outlineGlyph.Triangulate(
3621 if( aGlyphs.empty() )
3624 bool allGlyphsAreStroke =
true;
3625 bool allGlyphsAreOutline =
true;
3627 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3629 if( !glyph->IsStroke() )
3631 allGlyphsAreStroke =
false;
3636 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3638 if( !glyph->IsOutline() )
3640 allGlyphsAreOutline =
false;
3645 if( allGlyphsAreStroke )
3648 int lineQuadCount = 0;
3650 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3654 for(
const std::vector<VECTOR2D>& points : strokeGlyph )
3655 lineQuadCount += points.size() - 1;
3660 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3664 for(
const std::vector<VECTOR2D>& points : strokeGlyph )
3671 points.size(),
false );
3677 else if( allGlyphsAreOutline )
3680 int triangleCount = 0;
3682 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3686 for(
unsigned int i = 0; i < outlineGlyph.TriangulatedPolyCount(); i++ )
3689 outlineGlyph.TriangulatedPolygon( i );
3700 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3704 for(
unsigned int i = 0; i < outlineGlyph.TriangulatedPolyCount(); i++ )
3707 outlineGlyph.TriangulatedPolygon( i );
3724 for(
size_t i = 0; i < aGlyphs.size(); i++ )
3725 DrawGlyph( *aGlyphs[i], i, aGlyphs.size() );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetOpenGLInfo(const char *aVendor, const char *aRenderer, const char *aVersion)
A setter for OpenGL info when it's initialized.
void SetOpenGLBackendInfo(wxString aBackend)
A setter for OpenGL backend info after the canvas is created.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Bezier curves to polygon converter.
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
This class handle bitmap images in KiCad.
const wxImage * GetOriginalImageData() const
VECTOR2I GetSizePixels() const
EDA_ANGLE Rotation() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
static const WX_CURSOR_TYPE GetCursor(KICURSOR aCursorType, bool aHiDPI=false)
Get a cursor bundle (wx 3.3+) or appropriate cursor (older versions)
void UnlockCtx(wxGLContext *aContext)
Allow other canvases to bind an OpenGL context.
void DestroyCtx(wxGLContext *aContext)
Destroy a managed OpenGL context.
bool LockCtx(wxGLContext *aContext, wxGLCanvas *aCanvas)
Set a context as current and prevents other canvases from switching it.
wxGLContext * CreateCtx(wxGLCanvas *aCanvas, const wxGLContext *aOther=nullptr)
Create a managed OpenGL context.
static int SetSwapInterval(wxGLCanvas *aCanvas, int aVal)
Attempt to set the OpenGL swap interval.
static wxString DetectGLBackend(wxGLCanvas *aCanvas)
HIDPI_GL_CANVAS(const KIGFX::VC_SETTINGS &aSettings, wxWindow *aParent, const wxGLAttributes &aGLAttribs, wxWindowID aId=wxID_ANY, const wxPoint &aPos=wxDefaultPosition, const wxSize &aSize=wxDefaultSize, long aStyle=0, const wxString &aName=wxGLCanvasName, const wxPalette &aPalette=wxNullPalette)
virtual wxSize GetNativePixelSize() const
double GetScaleFactor() const
Get the current scale factor.
virtual bool IsStroke() const
virtual bool IsOutline() const
A color representation with 4 components: red, green, blue, alpha.
COLOR4D Darkened(double aFactor) const
Return a color that is darker by a given factor, without modifying object.
static const COLOR4D BLACK
bool IsTextMirrored() const
void SetGridColor(const COLOR4D &aGridColor)
Set the grid color.
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
bool IsCursorEnabled() const
Return information about cursor visibility.
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
friend class GAL_CONTEXT_LOCKER
MATRIX3x3D m_worldScreenMatrix
World transformation.
VECTOR2D GetVisibleGridSize() const
Return the visible grid size in x and y directions.
double m_layerDepth
The actual layer depth.
COLOR4D gridSourceColor(const GRID_SOURCE &aSrc) const
The colour a grid source is drawn in, brightened while it is being edited.
MATRIX3x3D m_screenWorldMatrix
Screen transformation.
friend class GAL_SCOPED_ATTRS
bool m_axesEnabled
Should the axes be drawn.
VECTOR2I m_screenSize
Screen size in screen (wx logical) coordinates.
GR_TEXT_H_ALIGN_T GetHorizontalJustify() const
void normalize(T &a, T &b)
Ensure that the first element is smaller than the second.
VECTOR2D m_depthRange
Range of the depth.
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual bool SetNativeCursorStyle(KICURSOR aCursor, bool aHiDPI)
Set the cursor in the native panel.
GRID_STYLE m_gridStyle
Grid display style.
COLOR4D m_axesColor
Color of the axes.
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
float m_lineWidth
The line width.
void computeWorldScale()
Compute the scaling factor for the world->screen matrix.
GRID_LATTICE gridLattice(const GRID_SOURCE &aSrc) const
Thin a grid source's pitch out until its lines are far enough apart on screen.
void drawGridCoverageShape(const GRID_SOURCE &aSrc)
Draw the area a grid source covers in its own frame with the current fill and stroke.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
VECTOR2D m_gridSize
The grid size.
COLOR4D getCursorColor() const
Get the actual cursor color to draw.
COLOR4D m_fillColor
The fill color.
double m_worldUnitLength
The unit length of the world coordinates [inch].
virtual bool updatedGalDisplayOptions(const GAL_DISPLAY_OPTIONS &aOptions)
Handle updating display options.
void SetAxesColor(const COLOR4D &aAxesColor)
Set the axes color.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
BOX2D gridScreenBBox(const GRID_SOURCE &aSrc) const
VECTOR2D m_cursorPosition
Current cursor position (world coordinates)
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
const VECTOR2I & GetGlyphSize() const
int m_gridTick
Every tick line gets the double width.
double m_worldScale
The scale factor world->screen.
VECTOR2D m_gridOrigin
The grid origin.
virtual void SetMinLineWidth(float aLineWidth)
Set the minimum line width in pixels.
KICURSOR m_currentNativeCursor
Current cursor.
bool m_globalFlipY
Flag for Y axis flipping.
float GetMinLineWidth() const
Get the minimum line width in pixels.
bool m_isFillEnabled
Is filling of graphic objects enabled ?
virtual void ComputeWorldScreenMatrix()
Compute the world <-> screen transformation matrix.
float gridMinorLineWidth(double aWorldPixelSize, double aScaleFactor) const
Compute the world width of a minor grid line.
COLOR4D m_gridColor
Color of the grid.
COLOR4D m_strokeColor
The color of the outlines.
bool m_isStrokeEnabled
Are the outlines stroked ?
std::vector< GRID_SOURCE > m_gridSources
Sources overlayed on the display grid.
GAL_DISPLAY_OPTIONS & m_options
bool m_gridVisibility
Should the grid be shown.
static constexpr int SEG_PER_CIRCLE_COUNT
The default number of segments approximating a full circle.
virtual void BitmapText(const wxString &aText, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle)
Draw a text using a bitmap font.
bool m_globalFlipX
Flag for X axis flipping.
GR_TEXT_V_ALIGN_T GetVerticalJustify() const
KIGFX::CROSS_HAIR_MODE m_crossHairMode
Crosshair drawing mode.
VECTOR2D m_lookAtPoint
Point to be looked at in world space.
GAL(GAL_DISPLAY_OPTIONS &aOptions)
static double calcAngleStep(double aRadius)
Compute the angle step when drawing arcs/circles approximated with lines.
GLuint cacheBitmap(const BITMAP_BASE *aBitmap)
const size_t m_cacheMaxElements
GLuint RequestBitmap(const BITMAP_BASE *aBitmap)
void Abandon()
Drop the cached texture names without deleting them.
std::list< GLuint > m_freedTextureIds
std::map< const KIID, CACHED_BITMAP > m_bitmaps
std::list< KIID > m_cacheLru
Limit how often the OpenGL canvases are rebuilt after GPU resets.
static const unsigned int DIRECT_RENDERING
OpenGL implementation of the Graphics Abstraction Layer.
void Transform(const MATRIX3x3D &aTransformation) override
Transform the context.
void drawPolygon(GLdouble *aPoints, int aPointCount)
Draw a filled polygon.
void ChangeGroupDepth(int aGroupNumber, int aDepth) override
Change the depth (Z-axis position) of the group.
void skipMouseEvent(wxMouseEvent &aEvent)
Skip the mouse event to the parent.
void drawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth, bool aReserve=true)
Internal method for segment drawing.
unsigned int m_groupCounter
Counter used for generating keys for groups.
void EndDiffLayer() override
Ends rendering of a differential layer.
VERTEX_MANAGER * m_overlayManager
Container for storing overlaid VERTEX_ITEMs.
void Scale(const VECTOR2D &aScale) override
Scale the context.
bool m_isInitialized
Basic initialization flag, has to be done when the window is visible.
VERTEX_MANAGER * m_currentManager
Currently used VERTEX_MANAGER (for storing VERTEX_ITEMs).
void drawCircle(const VECTOR2D &aCenterPoint, double aRadius, bool aReserve=true)
Internal method for circle drawing.
std::deque< std::shared_ptr< GLdouble > > m_tessIntersects
void DrawEllipseArc(const VECTOR2D &aCenterPoint, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle) override
Draw an elliptical arc in world coordinates.
void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius) override
Draw a circle using world coordinates.
bool IsInitialized() const override
Return the initialization status for the canvas.
void LockContext(int aClientCookie) override
Use GAL_CONTEXT_LOCKER RAII object unless you know what you're doing.
WX_CURSOR_TYPE m_currentwxCursor
wx cursor showing the current native cursor.
unsigned int m_mainBuffer
Main rendering target.
static std::set< OPENGL_GAL * > m_instances
Canvases to repaint after a reset.
std::unique_ptr< GL_BITMAP_CACHE > m_bitmapCache
std::pair< VECTOR2D, float > computeBitmapTextSize(const UTF8 &aText) const
Compute a size of text drawn using bitmap font with current text setting applied.
void SetTarget(RENDER_TARGET aTarget) override
Set the target for rendering.
void blitCursor()
Blit cursor into the current screen.
static wxString CheckFeatures(GAL_DISPLAY_OPTIONS &aOptions)
Check OpenGL features.
void ClearTarget(RENDER_TARGET aTarget) override
Clear the target for rendering.
void drawBitmapOverbar(double aLength, double aHeight, bool aReserve=true)
Draw an overbar over the currently drawn text.
void EndGroup() override
End the group.
bool m_isBitmapFontInitialized
Is the shader set to use bitmap fonts?
static GL_RESET_BUDGET m_resetBudget
Rate of resets tolerated before falling back.
void drawSegmentChain(const std::function< VECTOR2D(int)> &aPointGetter, int aPointCount, double aWidth, bool aReserve=true)
Generic way of drawing a chain of segments stored in different containers.
void DrawArcSegment(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle, double aWidth, double aMaxError) override
Draw an arc segment.
void BitmapText(const wxString &aText, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle) override
Draw a text using a bitmap font.
bool updatedGalDisplayOptions(const GAL_DISPLAY_OPTIONS &aOptions) override
Update handler for OpenGL settings.
unsigned int m_overlayBuffer
Auxiliary rendering target (for menus etc.)
void PostPaint(wxPaintEvent &aEvent)
Post an event to m_paintListener.
OPENGL_COMPOSITOR * m_compositor
Handles multiple rendering targets.
VERTEX_MANAGER * m_cachedManager
Container for storing cached VERTEX_ITEMs.
void Translate(const VECTOR2D &aTranslation) override
Translate the context.
static bool m_glLoaded
GL entry points are loaded, so resets can be queried.
void DrawPolyline(const std::deque< VECTOR2D > &aPointList) override
Draw a polyline.
bool SetNativeCursorStyle(KICURSOR aCursor, bool aHiDPI) override
Set the cursor in the native panel.
void DrawCurve(const VECTOR2D &startPoint, const VECTOR2D &controlPointA, const VECTOR2D &controlPointB, const VECTOR2D &endPoint, double aFilterValue=0.0) override
Draw a cubic bezier spline.
void drawFilledSemiCircle(const VECTOR2D &aCenterPoint, double aRadius, double aAngle)
Draw a filled semicircle.
void onPaint(wxPaintEvent &aEvent)
This is the OnPaint event handler.
void DrawGroup(int aGroupNumber) override
Draw the stored group.
GLint ufm_minLinePixelWidth
void Restore() override
Restore the context.
int m_ownContextGroupId
Group this canvas' contexts were created in.
bool IsResetSettled() override
Check whether the driver has finished the reset that destroyed this canvas' context.
void DrawGrid() override
Draw the grid.
void DrawSegmentChain(const std::vector< VECTOR2D > &aPointList, double aWidth) override
Draw a chain of rounded segments.
static GL_RESET_BUDGET::CLOCK::time_point m_resetDetectedAt
When the last reset was detected, to stop waiting on a driver that never reports completion.
void drawStrokedSemiCircle(const VECTOR2D &aCenterPoint, double aRadius, double aAngle, bool aReserve=true)
Draw a stroked semicircle.
unsigned int getNewGroupNumber()
Return a valid key that can be used as a new group number.
void Flush() override
Force all remaining objects to be drawn.
GLint ufm_antialiasingOffset
void DeleteGroup(int aGroupNumber) override
Delete the group from the memory.
bool IsVisible() const override
Return true if the GAL canvas is visible on the screen.
wxEvtHandler * m_mouseListener
int m_swapInterval
Used to store swap interval information.
void ClearCache() override
Delete all data created during caching of graphic items.
double getWorldPixelSize() const
void DrawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth) override
Draw a rounded segment.
GROUPS_MAP m_groups
Stores information about VBO objects (groups)
void endUpdate() override
Disable item update mode.
void ClearScreen() override
Clear the screen.
void ResizeScreen(int aWidth, int aHeight) override
Resizes the canvas.
GLint ufm_fontTextureWidth
void DrawPolygon(const std::deque< VECTOR2D > &aPointList) override
Draw a polygon.
void drawTriangulatedPolyset(const SHAPE_POLY_SET &aPoly, bool aStrokeTriangulation)
Draw a set of polygons with a cached triangulation.
void DrawCursor(const VECTOR2D &aCursorPosition) override
Draw the cursor.
void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a rectangle.
VERTEX_MANAGER * m_nonCachedManager
Container for storing non-cached VERTEX_ITEMs.
int drawBitmapChar(unsigned long aChar, bool aReserve=true)
Draw a single character using bitmap font.
GLUtesselator * m_tesselator
wxEvtHandler * m_paintListener
void StartDiffLayer() override
Begins rendering of a differential layer.
static bool m_resetSettled
Driver finished the last reset.
bool m_isContextLocked
Used for assertion checking.
void Save() override
Save the context.
void DrawHoleWall(const VECTOR2D &aCenterPoint, double aHoleRadius, double aWallWidth) override
Draw a hole wall ring.
bool m_isFramebufferInitialized
Are the framebuffers initialized?
void ComputeWorldScreenMatrix() override
Compute the world <-> screen transformation matrix.
void orphanContextGroup()
Abandon the shared context group so the next canvas created starts a fresh one.
bool Show(bool aShow) override
Shows/hides the GAL canvas.
void SetMinLineWidth(float aLineWidth) override
Set the minimum line width in pixels.
static GLuint g_fontTexture
Bitmap font texture handle (shared)
virtual bool HasTarget(RENDER_TARGET aTarget) override
Return true if the target exists.
GAL_CONTEXT_LOSS GetContextLoss() const override
Check whether a GPU reset destroyed this canvas' rendering context.
bool GetScreenshot(wxImage &aDstImage)
void reserveLineQuads(const int aLineCount)
Reserve specified number of line quads.
void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a line.
OPENGL_GAL(const KIGFX::VC_SETTINGS &aVcSettings, GAL_DISPLAY_OPTIONS &aDisplayOptions, wxWindow *aParent, wxEvtHandler *aMouseListener=nullptr, wxEvtHandler *aPaintListener=nullptr, const wxString &aName=wxT("GLCanvas"))
void beginUpdate() override
Enable item update mode.
void DrawEllipse(const VECTOR2D &aCenterPoint, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation) override
Draw a closed ellipse.
virtual void DrawGlyph(const KIFONT::GLYPH &aGlyph, int aNth, int aTotal) override
Draw a polygon representing a font glyph.
bool m_isGrouping
Was a group started?
void BeginDrawing() override
Start/end drawing functions, draw calls can be only made in between the calls to BeginDrawing()/EndDr...
GLint ufm_screenPixelSize
void Rotate(double aAngle) override
Rotate the context.
int BeginGroup() override
Begin a group.
GLint ufm_pixelSizeMultiplier
VECTOR2D getScreenPixelSize() const
void drawGridSources()
Render m_gridSources priority-descending; each writes its coverage into the stencil so lower-priority...
static int m_contextGroupId
Changes each time a reset kills the shared group.
void DrawBitmap(const BITMAP_BASE &aBitmap, double alphaBlend=1.0) override
Draw a bitmap image.
void drawPolyline(const std::function< VECTOR2D(int)> &aPointGetter, int aPointCount, bool aReserve=true)
Generic way of drawing a polyline stored in different containers.
bool detectContextReset()
RENDER_TARGET GetTarget() const override
Get the currently used target for rendering.
void skipGestureEvent(wxGestureEvent &aEvent)
Skip the gesture event to the parent.
void UnlockContext(int aClientCookie) override
void drawSemiCircle(const VECTOR2D &aCenterPoint, double aRadius, double aAngle)
Draw a semicircle.
void drawLineQuad(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, bool aReserve=true)
Draw a quad for the line.
VERTEX_MANAGER * m_tempManager
Container for storing temp (diff mode) VERTEX_ITEMs.
virtual void DrawGlyphs(const std::vector< std::unique_ptr< KIFONT::GLYPH > > &aGlyphs) override
Draw polygons representing font glyphs.
void onSetNativeCursor(wxSetCursorEvent &aEvent)
Give the correct cursor image when the native widget asks for it.
void EnableDepthTest(bool aEnabled=false) override
void EndDrawing() override
End the drawing, needs to be called for every new frame.
SHADER * m_shader
There is only one shader used for different objects.
void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle) override
Draw an arc.
bool m_isContextValid
Did the last lock make us current?
void DrawPolylines(const std::vector< std::vector< VECTOR2D > > &aPointLists) override
Draw multiple polylines.
RENDER_TARGET m_currentTarget
Current rendering target.
wxGLContext * m_glPrivContext
Canvas-specific OpenGL context.
void ChangeGroupColor(int aGroupNumber, const COLOR4D &aNewColor) override
Change the color used to draw the group.
static bool m_isBitmapFontLoaded
Is the bitmap font texture loaded?
static bool m_resetBudgetExhausted
Resets came too often to keep using OpenGL.
static wxGLContext * m_glMainContext
Parent OpenGL context.
void setupShaderParameters()
Set up the shader parameters for OpenGL rendering.
unsigned int m_tempBuffer
Temporary rendering target (for diffing etc.)
void init()
Basic OpenGL initialization and feature checks.
static int m_instanceCounter
GL GAL instance counter.
Class to control vertex container and GPU with possibility of emulating old-style OpenGL 1....
bool Vertex(const VERTEX &aVertex)
Add a vertex with the given coordinates to the currently set item.
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
GL_CONTEXT_MANAGER * GetGLContextManager()
A small class to help profiling.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
void Start()
Start or restart the counter.
double msecs(bool aSinceLast=false)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
size_t GetTriangleCount() const
void GetTriangle(int index, VECTOR2I &a, VECTOR2I &b, VECTOR2I &c) const
Represent a set of closed polygons.
bool IsTriangulationUpToDate() const
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
const TRIANGULATED_POLYGON * TriangulatedPolygon(int aIndex) const
unsigned int TriangulatedPolyCount() const
Return the number of triangulated polygons.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
uni_iter is a non-mutating iterator that walks through unicode code points in the UTF8 encoded string...
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
static constexpr EDA_ANGLE FULL_CIRCLE
a few functions useful in geometry calculations.
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
const wxChar *const traceGalContext
Flag to enable debug output of GAL context binding.
const wxChar *const traceGalProfile
Flag to enable debug output of GAL performance profiling.
This file contains miscellaneous commonly used macros and functions.
MATRIX3x3< double > MATRIX3x3D
std::pair< VECTOR2D, float > ComputeBitmapTextSize(const UTF8 &aText)
Size of a line of text in atlas units, and how far its glyphs sit above their lowest point.
double SpaceAdvance()
How far a space moves the pen.
const FONT_GLYPH_TYPE * LookupGlyph(unsigned int aCodepoint)
GAL_API FONT_IMAGE_TYPE font_image
GLYPH_BOX ComputeGlyphBox(const FONT_GLYPH_TYPE &aGlyph)
The Cairo implementation of the graphics abstraction layer.
std::vector< uint8_t > ImageToRgba(const wxImage &aImage)
The pixels of aImage as tightly packed RGBA, transparent where it has alpha or a mask.
constexpr double GRID_DIM_ALPHA
Opacity of the background wash laid over a selected grid item's area, to fade the grids showing throu...
GAL_CONTEXT_LOSS
State of a canvas' rendering context after a GPU reset.
@ REPEATED
Contexts keep being lost; stop using this backend.
@ RECOVERABLE
Context was lost; rebuild the canvas.
@ DOTS
Use dots for the grid.
@ LINES
Use lines for the grid.
@ SHADER_TYPE_VERTEX
Vertex shader.
@ SHADER_TYPE_FRAGMENT
Fragment shader.
RENDER_TARGET
RENDER_TARGET: Possible rendering targets.
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
@ TARGET_TEMP
Temporary target for drawing in separate layer.
@ TARGET_CACHED
Main rendering target (cached)
@ TARGET_OVERLAY
Items that may change while the view stays the same (noncached)
constexpr size_t BITMAP_CACHE_MAX_BYTES
Texture memory the GPU canvases may hold for placed bitmaps before they evict the oldest.
wxImage FitImageToTexture(const wxImage &aImage, int aMaxTextureSize)
Fit an image into the largest texture a GPU can hold.
constexpr double GRID_EDGE_DARKEN
How far the hairline round a grid's coverage sits below its own colour.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
static const wxChar *const traceGalXorMode
static void InitTesselatorCallbacks(GLUtesselator *aTesselator)
void CALLBACK CombineCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut, void *aData)
static GLenum queryResetStatus()
void CALLBACK VertexCallback(GLvoid *aVertexPtr, void *aData)
void CALLBACK EdgeCallback(GLboolean aEdgeFlag)
static wxGLAttributes getGLAttribs()
void CALLBACK ErrorCallback(GLenum aErrorCode)
double round_to_half_pixel(double f, double r)
PGM_BASE & Pgm()
The global program "get" accessor.
std::vector< FAB_LAYER_COLOR > dummy
unsigned priority
Higher wins where grids overlap.
double orientation
Rotation about origin, radians CCW.
VECTOR2D extent
Cartesian: (dx, dy) = size/2 from origin.
VECTOR2D pitch
Cartesian: (dx, dy); polar: (dr, dPhi rad).
Where a glyph's quad sits and what it samples, in font units, which are also atlas texels.
float h
size of the quad and of its cell in the atlas
float atlasY
corner of the cell in the atlas, inside its smoothing border
float y
corner of the quad from the pen position
The spacing of a grid source's lattice as it is drawn at the current zoom.
bool IsMajor(int aIndex) const
VECTOR2D extent
as GRID_SOURCE::extent, with an unbounded polar grid reaching past the screen
VECTOR2D pitch
along x and y, or of radius and angle for a polar grid
Render-time projection of a grid: GRID_GEOMETRY (kind/origin/pitch/orientation/extent) plus rendering...
unsigned tick
Major-tick interval (0 = inherit default).
bool axesEnabled
Skip grid lines coincident with the world axes (only meaningful for unbounded cartesian).
bool highlighted
Render with edit-mode emphasis (selected grid).
bool unbounded
No extent; visible range derived from screen corners.
Parameters passed to the GLU tesselator.
VERTEX_MANAGER * vboManager
Manager used for storing new vertices.
std::deque< std::shared_ptr< GLdouble > > & intersectPoints
Intersect points, that have to be freed after tessellation.
Structure to keep VIEW_CONTROLS settings for easy store/restore operations.
@ GR_TEXT_H_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_INDETERMINATE
wxLogTrace helper definitions.
void enableGlDebug(bool aEnable)
Enable or disable OpenGL driver messages output.
int checkGlError(const std::string &aInfo, const char *aFile, int aLine, bool aThrow)
Check if a recent OpenGL operation has failed.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
VECTOR2I ToVECTOR2I(const wxSize &aSize)