smarter matrial updates
This commit is contained in:
parent
b138d04053
commit
634ca3bed3
@ -229,9 +229,8 @@ namespace
|
||||
class GradientMaterial : public QskGradientMaterial
|
||||
{
|
||||
public:
|
||||
GradientMaterial( QGradient::Type type,
|
||||
const QGradientStops& stops, QGradient::Spread spread )
|
||||
: QskGradientMaterial( type, stops, spread )
|
||||
GradientMaterial( QGradient::Type type )
|
||||
: QskGradientMaterial( type )
|
||||
{
|
||||
setFlag( Blending | RequiresFullMatrix );
|
||||
|
||||
@ -355,16 +354,39 @@ namespace
|
||||
class LinearMaterial final : public GradientMaterial
|
||||
{
|
||||
public:
|
||||
LinearMaterial(
|
||||
const QGradientStops& stops, QGradient::Spread spread,
|
||||
const QPointF& start, const QPointF& stop )
|
||||
: GradientMaterial( QGradient::LinearGradient, stops, spread )
|
||||
, m_start( start )
|
||||
, m_stop( stop )
|
||||
LinearMaterial()
|
||||
: GradientMaterial( QGradient::LinearGradient )
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
@ -382,8 +404,10 @@ namespace
|
||||
return GradientMaterial::compare( other );
|
||||
}
|
||||
|
||||
const QVector2D m_start;
|
||||
const QVector2D m_stop;
|
||||
QSGMaterialShader* createShader() const override;
|
||||
|
||||
QVector2D m_start;
|
||||
QVector2D m_stop;
|
||||
};
|
||||
|
||||
#ifdef SHADER_GL
|
||||
@ -485,26 +509,58 @@ namespace
|
||||
class RadialMaterial final : public GradientMaterial
|
||||
{
|
||||
public:
|
||||
RadialMaterial(
|
||||
const QGradientStops& stops, QGradient::Spread spread,
|
||||
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 )
|
||||
RadialMaterial()
|
||||
: GradientMaterial( QGradient::RadialGradient )
|
||||
{
|
||||
}
|
||||
|
||||
QSGMaterialShader* createShader() const override;
|
||||
|
||||
QSGMaterialType* type() const override
|
||||
{
|
||||
static QSGMaterialType 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
|
||||
{
|
||||
const auto mat = static_cast< const RadialMaterial* >( other );
|
||||
@ -522,10 +578,12 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
const QVector2D m_center;
|
||||
const QVector2D m_focalPoint;
|
||||
const float m_centerRadius;
|
||||
const float m_focalRadius;
|
||||
QSGMaterialShader* createShader() const override;
|
||||
|
||||
QVector2D m_center;
|
||||
QVector2D m_focalPoint;
|
||||
float m_centerRadius = 0.0;
|
||||
float m_focalRadius = 0.0;
|
||||
};
|
||||
|
||||
#ifdef SHADER_GL
|
||||
@ -650,22 +708,41 @@ namespace
|
||||
class ConicalMaterial final : public GradientMaterial
|
||||
{
|
||||
public:
|
||||
ConicalMaterial( const QGradientStops& stops,
|
||||
const QPointF& center, qreal angle )
|
||||
: GradientMaterial( QGradient::ConicalGradient, stops, QGradient::PadSpread )
|
||||
, m_center( center )
|
||||
, m_radians( -qDegreesToRadians( angle ) )
|
||||
ConicalMaterial()
|
||||
: GradientMaterial( QGradient::ConicalGradient )
|
||||
{
|
||||
}
|
||||
|
||||
QSGMaterialShader* createShader() const override;
|
||||
|
||||
QSGMaterialType* type() const override
|
||||
{
|
||||
static QSGMaterialType 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
|
||||
{
|
||||
const auto mat = static_cast< const ConicalMaterial* >( other );
|
||||
@ -676,8 +753,10 @@ namespace
|
||||
return GradientMaterial::compare( other );
|
||||
}
|
||||
|
||||
const QVector2D m_center;
|
||||
const float m_radians;
|
||||
QSGMaterialShader* createShader() const override;
|
||||
|
||||
QVector2D m_center;
|
||||
float m_radians = 0.0;
|
||||
};
|
||||
|
||||
#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() ) )
|
||||
{
|
||||
case QGradient::LinearGradient:
|
||||
{
|
||||
auto linearGradient = static_cast< const QLinearGradient* >( gradient );
|
||||
|
||||
return new LinearMaterial(
|
||||
linearGradient->stops(), linearGradient->spread(),
|
||||
linearGradient->start(), linearGradient->finalStop() );
|
||||
auto material = static_cast< LinearMaterial* >( this );
|
||||
return material->setGradient( static_cast< const QLinearGradient* >( gradient ) );
|
||||
}
|
||||
|
||||
case QGradient::RadialGradient:
|
||||
{
|
||||
auto radialGradient = static_cast< const QRadialGradient* >( gradient );
|
||||
|
||||
return new RadialMaterial(
|
||||
radialGradient->stops(), radialGradient->spread(),
|
||||
radialGradient->center(), radialGradient->centerRadius(),
|
||||
radialGradient->focalPoint(), radialGradient->focalRadius() );
|
||||
auto material = static_cast< RadialMaterial* >( this );
|
||||
return material->setGradient( static_cast< const QRadialGradient* >( gradient ) );
|
||||
}
|
||||
|
||||
case QGradient::ConicalGradient:
|
||||
{
|
||||
auto conicalGradient = static_cast< const QConicalGradient* >( gradient );
|
||||
|
||||
return new ConicalMaterial( conicalGradient->stops(),
|
||||
conicalGradient->center(), conicalGradient->angle() );
|
||||
auto material = static_cast< ConicalMaterial* >( this );
|
||||
return material->setGradient( static_cast< const QConicalGradient* >( gradient ) );
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
static QskGradientMaterial* create( const QGradient* );
|
||||
static QskGradientMaterial* createMaterial( QGradient::Type );
|
||||
|
||||
bool updateGradient( const QGradient* );
|
||||
QGradient::Type gradientType() const;
|
||||
|
||||
const QGradientStops& stops() const;
|
||||
QGradient::Spread spread() const;
|
||||
|
||||
protected:
|
||||
QskGradientMaterial( QGradient::Type,
|
||||
const QGradientStops&, QGradient::Spread );
|
||||
QskGradientMaterial( QGradient::Type );
|
||||
|
||||
void setStops( const QGradientStops& );
|
||||
void setSpread( QGradient::Spread );
|
||||
|
||||
private:
|
||||
const QGradient::Type m_gradientType;
|
||||
const QGradientStops m_stops;
|
||||
const QGradient::Spread m_spread;
|
||||
};
|
||||
|
||||
inline QskGradientMaterial::QskGradientMaterial( QGradient::Type type,
|
||||
const QGradientStops& stops, QGradient::Spread spread )
|
||||
: m_gradientType( type )
|
||||
, m_stops( stops )
|
||||
, m_spread( spread )
|
||||
{
|
||||
}
|
||||
QGradientStops m_stops;
|
||||
QGradient::Spread m_spread = QGradient::PadSpread;
|
||||
};
|
||||
|
||||
inline QGradient::Type QskGradientMaterial::gradientType() const
|
||||
{
|
||||
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
|
||||
{
|
||||
return m_stops;
|
||||
|
@ -56,6 +56,46 @@ static void qskUpdateGeometry( const QPainterPath& path, QSGGeometry& geometry )
|
||||
#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
|
||||
{
|
||||
public:
|
||||
@ -66,7 +106,7 @@ class QskShapeNodePrivate final : public QSGGeometryNodePrivate
|
||||
}
|
||||
|
||||
QSGGeometry geometry;
|
||||
QSGMaterial* material = nullptr;
|
||||
QGradient::Type gradientType = QGradient::NoGradient;
|
||||
};
|
||||
|
||||
QskShapeNode::QskShapeNode()
|
||||
@ -80,33 +120,65 @@ QskShapeNode::QskShapeNode()
|
||||
|
||||
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 ...
|
||||
{
|
||||
qskUpdateGeometry( path, *geometry() );
|
||||
qskUpdateGeometry( path, d->geometry );
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
||||
if ( true ) // For the moment we always update the material
|
||||
if ( material() == nullptr || d->gradientType != QGradient::NoGradient )
|
||||
{
|
||||
auto material = new QSGFlatColorMaterial();
|
||||
material->setColor( color );
|
||||
setMaterial( new QSGFlatColorMaterial() );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
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 ...
|
||||
{
|
||||
qskUpdateGeometry( path, *geometry() );
|
||||
qskUpdateGeometry( path, d->geometry );
|
||||
markDirty( QSGNode::DirtyGeometry );
|
||||
}
|
||||
|
||||
if ( true ) // For the moment we always update the material
|
||||
if ( ( material() == nullptr ) || gradient->type() != d->gradientType )
|
||||
{
|
||||
setMaterial( QskGradientMaterial::create( gradient ) );
|
||||
markDirty( QSGNode::DirtyMaterial );
|
||||
setMaterial( QskGradientMaterial::createMaterial( gradient->type() ) );
|
||||
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