smarter matrial updates
This commit is contained in:
parent
b138d04053
commit
634ca3bed3
@ -229,9 +229,8 @@ namespace
|
|||||||
class GradientMaterial : public QskGradientMaterial
|
class GradientMaterial : public QskGradientMaterial
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GradientMaterial( QGradient::Type type,
|
GradientMaterial( QGradient::Type type )
|
||||||
const QGradientStops& stops, QGradient::Spread spread )
|
: QskGradientMaterial( type )
|
||||||
: QskGradientMaterial( type, stops, spread )
|
|
||||||
{
|
{
|
||||||
setFlag( Blending | RequiresFullMatrix );
|
setFlag( Blending | RequiresFullMatrix );
|
||||||
|
|
||||||
@ -355,16 +354,39 @@ namespace
|
|||||||
class LinearMaterial final : public GradientMaterial
|
class LinearMaterial final : public GradientMaterial
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LinearMaterial(
|
LinearMaterial()
|
||||||
const QGradientStops& stops, QGradient::Spread spread,
|
: GradientMaterial( QGradient::LinearGradient )
|
||||||
const QPointF& start, const QPointF& stop )
|
|
||||||
: GradientMaterial( QGradient::LinearGradient, stops, spread )
|
|
||||||
, m_start( start )
|
|
||||||
, m_stop( stop )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGMaterialShader* createShader() const override;
|
bool setGradient( const QLinearGradient* gradient )
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if ( gradient->stops() != stops() )
|
||||||
|
{
|
||||||
|
setStops( gradient->stops() );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( gradient->spread() != spread() )
|
||||||
|
{
|
||||||
|
setSpread( gradient->spread() );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector2D start( gradient->start() );
|
||||||
|
const QVector2D stop( gradient->finalStop() );
|
||||||
|
|
||||||
|
if ( m_start != start || m_stop != stop )
|
||||||
|
{
|
||||||
|
m_start = start;
|
||||||
|
m_stop = stop;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
QSGMaterialType* type() const override
|
QSGMaterialType* type() const override
|
||||||
{
|
{
|
||||||
@ -382,8 +404,10 @@ namespace
|
|||||||
return GradientMaterial::compare( other );
|
return GradientMaterial::compare( other );
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector2D m_start;
|
QSGMaterialShader* createShader() const override;
|
||||||
const QVector2D m_stop;
|
|
||||||
|
QVector2D m_start;
|
||||||
|
QVector2D m_stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SHADER_GL
|
#ifdef SHADER_GL
|
||||||
@ -485,26 +509,58 @@ namespace
|
|||||||
class RadialMaterial final : public GradientMaterial
|
class RadialMaterial final : public GradientMaterial
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RadialMaterial(
|
RadialMaterial()
|
||||||
const QGradientStops& stops, QGradient::Spread spread,
|
: GradientMaterial( QGradient::RadialGradient )
|
||||||
const QPointF& center, qreal centerRadius,
|
|
||||||
const QPointF& focalPoint, qreal focalRadius )
|
|
||||||
: GradientMaterial( QGradient::RadialGradient, stops, spread )
|
|
||||||
, m_center( center )
|
|
||||||
, m_focalPoint( focalPoint )
|
|
||||||
, m_centerRadius( centerRadius )
|
|
||||||
, m_focalRadius( focalRadius )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGMaterialShader* createShader() const override;
|
|
||||||
|
|
||||||
QSGMaterialType* type() const override
|
QSGMaterialType* type() const override
|
||||||
{
|
{
|
||||||
static QSGMaterialType type;
|
static QSGMaterialType type;
|
||||||
return &type;
|
return &type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool setGradient( const QRadialGradient* gradient )
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if ( gradient->stops() != stops() )
|
||||||
|
{
|
||||||
|
setStops( gradient->stops() );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( gradient->spread() != spread() )
|
||||||
|
{
|
||||||
|
setSpread( gradient->spread() );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector2D center( gradient->center() );
|
||||||
|
const float centerRadius = gradient->centerRadius();
|
||||||
|
|
||||||
|
if ( ( center != m_center ) || ( m_centerRadius != centerRadius ) )
|
||||||
|
{
|
||||||
|
m_center = center;
|
||||||
|
m_centerRadius = centerRadius;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector2D focalPoint( gradient->focalPoint() );
|
||||||
|
const float focalRadius = gradient->focalRadius();
|
||||||
|
|
||||||
|
if ( ( focalPoint != m_focalPoint ) || ( focalRadius != m_focalRadius ) )
|
||||||
|
{
|
||||||
|
m_focalPoint = focalPoint;
|
||||||
|
m_focalRadius = focalRadius;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
int compare( const QSGMaterial* other ) const override
|
int compare( const QSGMaterial* other ) const override
|
||||||
{
|
{
|
||||||
const auto mat = static_cast< const RadialMaterial* >( other );
|
const auto mat = static_cast< const RadialMaterial* >( other );
|
||||||
@ -522,10 +578,12 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector2D m_center;
|
QSGMaterialShader* createShader() const override;
|
||||||
const QVector2D m_focalPoint;
|
|
||||||
const float m_centerRadius;
|
QVector2D m_center;
|
||||||
const float m_focalRadius;
|
QVector2D m_focalPoint;
|
||||||
|
float m_centerRadius = 0.0;
|
||||||
|
float m_focalRadius = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SHADER_GL
|
#ifdef SHADER_GL
|
||||||
@ -650,22 +708,41 @@ namespace
|
|||||||
class ConicalMaterial final : public GradientMaterial
|
class ConicalMaterial final : public GradientMaterial
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConicalMaterial( const QGradientStops& stops,
|
ConicalMaterial()
|
||||||
const QPointF& center, qreal angle )
|
: GradientMaterial( QGradient::ConicalGradient )
|
||||||
: GradientMaterial( QGradient::ConicalGradient, stops, QGradient::PadSpread )
|
|
||||||
, m_center( center )
|
|
||||||
, m_radians( -qDegreesToRadians( angle ) )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGMaterialShader* createShader() const override;
|
|
||||||
|
|
||||||
QSGMaterialType* type() const override
|
QSGMaterialType* type() const override
|
||||||
{
|
{
|
||||||
static QSGMaterialType type;
|
static QSGMaterialType type;
|
||||||
return &type;
|
return &type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool setGradient( const QConicalGradient* gradient )
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if ( gradient->stops() != stops() )
|
||||||
|
{
|
||||||
|
setStops( gradient->stops() );
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector2D center( gradient->center() );
|
||||||
|
const float radians = -qDegreesToRadians( gradient->angle() );
|
||||||
|
|
||||||
|
if ( center != m_center || radians != m_radians )
|
||||||
|
{
|
||||||
|
m_center = center;
|
||||||
|
m_radians = radians;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
int compare( const QSGMaterial* other ) const override
|
int compare( const QSGMaterial* other ) const override
|
||||||
{
|
{
|
||||||
const auto mat = static_cast< const ConicalMaterial* >( other );
|
const auto mat = static_cast< const ConicalMaterial* >( other );
|
||||||
@ -676,8 +753,10 @@ namespace
|
|||||||
return GradientMaterial::compare( other );
|
return GradientMaterial::compare( other );
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector2D m_center;
|
QSGMaterialShader* createShader() const override;
|
||||||
const float m_radians;
|
|
||||||
|
QVector2D m_center;
|
||||||
|
float m_radians = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SHADER_GL
|
#ifdef SHADER_GL
|
||||||
@ -774,39 +853,65 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QskGradientMaterial* QskGradientMaterial::create( const QGradient* gradient )
|
QskGradientMaterial::QskGradientMaterial( QGradient::Type type )
|
||||||
|
: m_gradientType( type )
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename Material >
|
||||||
|
inline Material* qskEnsureMaterial( QskGradientMaterial* material )
|
||||||
|
{
|
||||||
|
if ( material == nullptr )
|
||||||
|
material = new Material();
|
||||||
|
|
||||||
|
return static_cast< Material* >( material );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskGradientMaterial::updateGradient( const QGradient* gradient )
|
||||||
|
{
|
||||||
|
Q_ASSERT( gradient && gradient->type() == m_gradientType );
|
||||||
|
|
||||||
|
if ( gradient == nullptr || gradient->type() != m_gradientType )
|
||||||
|
return false;
|
||||||
|
|
||||||
switch ( static_cast< int >( gradient->type() ) )
|
switch ( static_cast< int >( gradient->type() ) )
|
||||||
{
|
{
|
||||||
case QGradient::LinearGradient:
|
case QGradient::LinearGradient:
|
||||||
{
|
{
|
||||||
auto linearGradient = static_cast< const QLinearGradient* >( gradient );
|
auto material = static_cast< LinearMaterial* >( this );
|
||||||
|
return material->setGradient( static_cast< const QLinearGradient* >( gradient ) );
|
||||||
return new LinearMaterial(
|
|
||||||
linearGradient->stops(), linearGradient->spread(),
|
|
||||||
linearGradient->start(), linearGradient->finalStop() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case QGradient::RadialGradient:
|
case QGradient::RadialGradient:
|
||||||
{
|
{
|
||||||
auto radialGradient = static_cast< const QRadialGradient* >( gradient );
|
auto material = static_cast< RadialMaterial* >( this );
|
||||||
|
return material->setGradient( static_cast< const QRadialGradient* >( gradient ) );
|
||||||
return new RadialMaterial(
|
|
||||||
radialGradient->stops(), radialGradient->spread(),
|
|
||||||
radialGradient->center(), radialGradient->centerRadius(),
|
|
||||||
radialGradient->focalPoint(), radialGradient->focalRadius() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case QGradient::ConicalGradient:
|
case QGradient::ConicalGradient:
|
||||||
{
|
{
|
||||||
auto conicalGradient = static_cast< const QConicalGradient* >( gradient );
|
auto material = static_cast< ConicalMaterial* >( this );
|
||||||
|
return material->setGradient( static_cast< const QConicalGradient* >( gradient ) );
|
||||||
return new ConicalMaterial( conicalGradient->stops(),
|
|
||||||
conicalGradient->center(), conicalGradient->angle() );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QskGradientMaterial* QskGradientMaterial::createMaterial( QGradient::Type gradientType )
|
||||||
|
{
|
||||||
|
switch ( gradientType )
|
||||||
|
{
|
||||||
|
case QGradient::LinearGradient:
|
||||||
|
return new LinearMaterial();
|
||||||
|
|
||||||
|
case QGradient::RadialGradient:
|
||||||
|
return new RadialMaterial();
|
||||||
|
|
||||||
|
case QGradient::ConicalGradient:
|
||||||
|
return new ConicalMaterial();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,36 +13,42 @@
|
|||||||
class QSK_EXPORT QskGradientMaterial : public QSGMaterial
|
class QSK_EXPORT QskGradientMaterial : public QSGMaterial
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static QskGradientMaterial* create( const QGradient* );
|
static QskGradientMaterial* createMaterial( QGradient::Type );
|
||||||
|
|
||||||
|
bool updateGradient( const QGradient* );
|
||||||
QGradient::Type gradientType() const;
|
QGradient::Type gradientType() const;
|
||||||
|
|
||||||
const QGradientStops& stops() const;
|
const QGradientStops& stops() const;
|
||||||
QGradient::Spread spread() const;
|
QGradient::Spread spread() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QskGradientMaterial( QGradient::Type,
|
QskGradientMaterial( QGradient::Type );
|
||||||
const QGradientStops&, QGradient::Spread );
|
|
||||||
|
void setStops( const QGradientStops& );
|
||||||
|
void setSpread( QGradient::Spread );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QGradient::Type m_gradientType;
|
const QGradient::Type m_gradientType;
|
||||||
const QGradientStops m_stops;
|
|
||||||
const QGradient::Spread m_spread;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline QskGradientMaterial::QskGradientMaterial( QGradient::Type type,
|
QGradientStops m_stops;
|
||||||
const QGradientStops& stops, QGradient::Spread spread )
|
QGradient::Spread m_spread = QGradient::PadSpread;
|
||||||
: m_gradientType( type )
|
};
|
||||||
, m_stops( stops )
|
|
||||||
, m_spread( spread )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QGradient::Type QskGradientMaterial::gradientType() const
|
inline QGradient::Type QskGradientMaterial::gradientType() const
|
||||||
{
|
{
|
||||||
return m_gradientType;
|
return m_gradientType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void QskGradientMaterial::setStops( const QGradientStops& stops )
|
||||||
|
{
|
||||||
|
m_stops = stops;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void QskGradientMaterial::setSpread( QGradient::Spread spread )
|
||||||
|
{
|
||||||
|
m_spread = spread;
|
||||||
|
}
|
||||||
|
|
||||||
inline const QGradientStops& QskGradientMaterial::stops() const
|
inline const QGradientStops& QskGradientMaterial::stops() const
|
||||||
{
|
{
|
||||||
return m_stops;
|
return m_stops;
|
||||||
|
@ -56,6 +56,46 @@ static void qskUpdateGeometry( const QPainterPath& path, QSGGeometry& geometry )
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void qskResetGeometry( QskShapeNode* node )
|
||||||
|
{
|
||||||
|
auto g = node->geometry();
|
||||||
|
if ( g->vertexCount() > 0 )
|
||||||
|
{
|
||||||
|
g->allocate( 0 );
|
||||||
|
node->markDirty( QSGNode::DirtyGeometry );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool qskIsGradientVisible( const QGradient* gradient )
|
||||||
|
{
|
||||||
|
if ( gradient && gradient->type() != QGradient::NoGradient )
|
||||||
|
{
|
||||||
|
for ( const auto stop : gradient->stops() )
|
||||||
|
{
|
||||||
|
if ( stop.second.alpha() > 0 )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool qskIsGradientMonochrome( const QGradient* gradient )
|
||||||
|
{
|
||||||
|
if ( gradient && gradient->type() != QGradient::NoGradient )
|
||||||
|
{
|
||||||
|
const auto stops = gradient->stops();
|
||||||
|
|
||||||
|
for ( int i = 1; i < stops.count(); i++ )
|
||||||
|
{
|
||||||
|
if ( stops[i].second != stops[i - 1].second )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
class QskShapeNodePrivate final : public QSGGeometryNodePrivate
|
class QskShapeNodePrivate final : public QSGGeometryNodePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -66,7 +106,7 @@ class QskShapeNodePrivate final : public QSGGeometryNodePrivate
|
|||||||
}
|
}
|
||||||
|
|
||||||
QSGGeometry geometry;
|
QSGGeometry geometry;
|
||||||
QSGMaterial* material = nullptr;
|
QGradient::Type gradientType = QGradient::NoGradient;
|
||||||
};
|
};
|
||||||
|
|
||||||
QskShapeNode::QskShapeNode()
|
QskShapeNode::QskShapeNode()
|
||||||
@ -80,33 +120,65 @@ QskShapeNode::QskShapeNode()
|
|||||||
|
|
||||||
void QskShapeNode::updateNode( const QPainterPath& path, const QColor& color )
|
void QskShapeNode::updateNode( const QPainterPath& path, const QColor& color )
|
||||||
{
|
{
|
||||||
|
Q_D( QskShapeNode );
|
||||||
|
|
||||||
|
if ( path.isEmpty() || !color.isValid() || color.alpha() == 0 )
|
||||||
|
{
|
||||||
|
qskResetGeometry( this );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( true ) // For the moment we always update the geometry. TODO ...
|
if ( true ) // For the moment we always update the geometry. TODO ...
|
||||||
{
|
{
|
||||||
qskUpdateGeometry( path, *geometry() );
|
qskUpdateGeometry( path, d->geometry );
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( true ) // For the moment we always update the material
|
if ( material() == nullptr || d->gradientType != QGradient::NoGradient )
|
||||||
{
|
{
|
||||||
auto material = new QSGFlatColorMaterial();
|
setMaterial( new QSGFlatColorMaterial() );
|
||||||
material->setColor( color );
|
d->gradientType = QGradient::NoGradient;
|
||||||
|
}
|
||||||
|
|
||||||
setMaterial( material );
|
const auto c = color.toRgb();
|
||||||
|
|
||||||
|
auto colorMaterial = static_cast< QSGFlatColorMaterial* >( material() );
|
||||||
|
if ( colorMaterial->color() != c )
|
||||||
|
{
|
||||||
|
colorMaterial->setColor( c );
|
||||||
markDirty( QSGNode::DirtyMaterial );
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskShapeNode::updateNode( const QPainterPath& path, const QGradient* gradient )
|
void QskShapeNode::updateNode( const QPainterPath& path, const QGradient* gradient )
|
||||||
{
|
{
|
||||||
|
if ( path.isEmpty() || !qskIsGradientVisible( gradient ) )
|
||||||
|
{
|
||||||
|
qskResetGeometry( this );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( qskIsGradientMonochrome( gradient ) )
|
||||||
|
{
|
||||||
|
updateNode( path, gradient->stops().first().first );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_D( QskShapeNode );
|
||||||
|
|
||||||
if ( true ) // For the moment we always update the geometry. TODO ...
|
if ( true ) // For the moment we always update the geometry. TODO ...
|
||||||
{
|
{
|
||||||
qskUpdateGeometry( path, *geometry() );
|
qskUpdateGeometry( path, d->geometry );
|
||||||
markDirty( QSGNode::DirtyGeometry );
|
markDirty( QSGNode::DirtyGeometry );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( true ) // For the moment we always update the material
|
if ( ( material() == nullptr ) || gradient->type() != d->gradientType )
|
||||||
{
|
{
|
||||||
setMaterial( QskGradientMaterial::create( gradient ) );
|
setMaterial( QskGradientMaterial::createMaterial( gradient->type() ) );
|
||||||
markDirty( QSGNode::DirtyMaterial );
|
d->gradientType = gradient->type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto gradientMaterial = static_cast< QskGradientMaterial* >( material() );
|
||||||
|
if ( gradientMaterial->updateGradient( gradient ) )
|
||||||
|
markDirty( QSGNode::DirtyMaterial );
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user