perf: skip update from GIF timer if no animated elements are shown (#5042)

This commit is contained in:
nerix
2023-12-25 20:04:46 +01:00
committed by GitHub
parent 485fc5cdb4
commit 1006bf955a
9 changed files with 51 additions and 20 deletions
+1
View File
@@ -99,6 +99,7 @@
- Dev: BREAKING: Replace custom `import()` with normal Lua `require()`. (#5014) - Dev: BREAKING: Replace custom `import()` with normal Lua `require()`. (#5014)
- Dev: Fixed most compiler warnings. (#5028) - Dev: Fixed most compiler warnings. (#5028)
- Dev: Added the ability to show `ChannelView`s without a `Split`. (#4747) - Dev: Added the ability to show `ChannelView`s without a `Split`. (#4747)
- Dev: Channels without any animated elements on screen will skip updates from the GIF timer. (#5042)
## 2.4.6 ## 2.4.6
+7 -2
View File
@@ -196,8 +196,10 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
} }
// Painting // Painting
void MessageLayout::paint(const MessagePaintContext &ctx) MessagePaintResult MessageLayout::paint(const MessagePaintContext &ctx)
{ {
MessagePaintResult result;
QPixmap *pixmap = this->ensureBuffer(ctx.painter, ctx.canvasWidth); QPixmap *pixmap = this->ensureBuffer(ctx.painter, ctx.canvasWidth);
if (!this->bufferValid_) if (!this->bufferValid_)
@@ -209,7 +211,8 @@ void MessageLayout::paint(const MessagePaintContext &ctx)
ctx.painter.drawPixmap(0, ctx.y, *pixmap); ctx.painter.drawPixmap(0, ctx.y, *pixmap);
// draw gif emotes // draw gif emotes
this->container_.paintAnimatedElements(ctx.painter, ctx.y); result.hasAnimatedElements =
this->container_.paintAnimatedElements(ctx.painter, ctx.y);
// draw disabled // draw disabled
if (this->message_->flags.has(MessageFlag::Disabled)) if (this->message_->flags.has(MessageFlag::Disabled))
@@ -270,6 +273,8 @@ void MessageLayout::paint(const MessagePaintContext &ctx)
} }
this->bufferValid_ = true; this->bufferValid_ = true;
return result;
} }
QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width) QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width)
+5 -1
View File
@@ -32,6 +32,10 @@ enum class MessageLayoutFlag : uint8_t {
}; };
using MessageLayoutFlags = FlagsEnum<MessageLayoutFlag>; using MessageLayoutFlags = FlagsEnum<MessageLayoutFlag>;
struct MessagePaintResult {
bool hasAnimatedElements = false;
};
class MessageLayout class MessageLayout
{ {
public: public:
@@ -55,7 +59,7 @@ public:
bool layout(int width, float scale_, MessageElementFlags flags); bool layout(int width, float scale_, MessageElementFlags flags);
// Painting // Painting
void paint(const MessagePaintContext &ctx); MessagePaintResult paint(const MessagePaintContext &ctx);
void invalidateBuffer(); void invalidateBuffer();
void deleteBuffer(); void deleteBuffer();
void deleteCache(); void deleteCache();
@@ -235,13 +235,15 @@ void MessageLayoutContainer::paintElements(QPainter &painter,
} }
} }
void MessageLayoutContainer::paintAnimatedElements(QPainter &painter, bool MessageLayoutContainer::paintAnimatedElements(QPainter &painter,
int yOffset) const int yOffset) const
{ {
bool anyAnimatedElement = false;
for (const auto &element : this->elements_) for (const auto &element : this->elements_)
{ {
element->paintAnimated(painter, yOffset); anyAnimatedElement |= element->paintAnimated(painter, yOffset);
} }
return anyAnimatedElement;
} }
void MessageLayoutContainer::paintSelection(QPainter &painter, void MessageLayoutContainer::paintSelection(QPainter &painter,
@@ -64,8 +64,9 @@ struct MessageLayoutContainer {
/** /**
* Paint the animated elements in this message * Paint the animated elements in this message
* @returns true if this container contains at least one animated element
*/ */
void paintAnimatedElements(QPainter &painter, int yOffset) const; bool paintAnimatedElements(QPainter &painter, int yOffset) const;
/** /**
* Paint the selection for this container * Paint the selection for this container
+14 -6
View File
@@ -153,11 +153,11 @@ void ImageLayoutElement::paint(QPainter &painter,
} }
} }
void ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset) bool ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
{ {
if (this->image_ == nullptr) if (this->image_ == nullptr)
{ {
return; return false;
} }
if (this->image_->animated()) if (this->image_->animated())
@@ -167,8 +167,10 @@ void ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
auto rect = this->getRect(); auto rect = this->getRect();
rect.moveTop(rect.y() + yOffset); rect.moveTop(rect.y() + yOffset);
painter.drawPixmap(QRectF(rect), *pixmap, QRectF()); painter.drawPixmap(QRectF(rect), *pixmap, QRectF());
return true;
} }
} }
return false;
} }
int ImageLayoutElement::getMouseOverIndex(const QPoint &abs) const int ImageLayoutElement::getMouseOverIndex(const QPoint &abs) const
@@ -265,7 +267,7 @@ void LayeredImageLayoutElement::paint(QPainter &painter,
} }
} }
void LayeredImageLayoutElement::paintAnimated(QPainter &painter, int yOffset) bool LayeredImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
{ {
auto fullRect = QRectF(this->getRect()); auto fullRect = QRectF(this->getRect());
fullRect.moveTop(fullRect.y() + yOffset); fullRect.moveTop(fullRect.y() + yOffset);
@@ -297,6 +299,7 @@ void LayeredImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
} }
} }
} }
return animatedFlag;
} }
int LayeredImageLayoutElement::getMouseOverIndex(const QPoint &abs) const int LayeredImageLayoutElement::getMouseOverIndex(const QPoint &abs) const
@@ -446,8 +449,9 @@ void TextLayoutElement::paint(QPainter &painter,
QTextOption(Qt::AlignLeft | Qt::AlignTop)); QTextOption(Qt::AlignLeft | Qt::AlignTop));
} }
void TextLayoutElement::paintAnimated(QPainter &, int) bool TextLayoutElement::paintAnimated(QPainter & /*painter*/, int /*yOffset*/)
{ {
return false;
} }
int TextLayoutElement::getMouseOverIndex(const QPoint &abs) const int TextLayoutElement::getMouseOverIndex(const QPoint &abs) const
@@ -567,8 +571,10 @@ void TextIconLayoutElement::paint(QPainter &painter,
} }
} }
void TextIconLayoutElement::paintAnimated(QPainter &painter, int yOffset) bool TextIconLayoutElement::paintAnimated(QPainter & /*painter*/,
int /*yOffset*/)
{ {
return false;
} }
int TextIconLayoutElement::getMouseOverIndex(const QPoint &abs) const int TextIconLayoutElement::getMouseOverIndex(const QPoint &abs) const
@@ -640,8 +646,10 @@ void ReplyCurveLayoutElement::paint(QPainter &painter,
painter.drawPath(path); painter.drawPath(path);
} }
void ReplyCurveLayoutElement::paintAnimated(QPainter &painter, int yOffset) bool ReplyCurveLayoutElement::paintAnimated(QPainter & /*painter*/,
int /*yOffset*/)
{ {
return false;
} }
int ReplyCurveLayoutElement::getMouseOverIndex(const QPoint &abs) const int ReplyCurveLayoutElement::getMouseOverIndex(const QPoint &abs) const
@@ -52,7 +52,8 @@ public:
virtual size_t getSelectionIndexCount() const = 0; virtual size_t getSelectionIndexCount() const = 0;
virtual void paint(QPainter &painter, virtual void paint(QPainter &painter,
const MessageColors &messageColors) = 0; const MessageColors &messageColors) = 0;
virtual void paintAnimated(QPainter &painter, int yOffset) = 0; /// @returns true if anything was painted
virtual bool paintAnimated(QPainter &painter, int yOffset) = 0;
virtual int getMouseOverIndex(const QPoint &abs) const = 0; virtual int getMouseOverIndex(const QPoint &abs) const = 0;
virtual int getXFromIndex(size_t index) = 0; virtual int getXFromIndex(size_t index) = 0;
@@ -86,7 +87,7 @@ protected:
uint32_t to = UINT32_MAX) const override; uint32_t to = UINT32_MAX) const override;
size_t getSelectionIndexCount() const override; size_t getSelectionIndexCount() const override;
void paint(QPainter &painter, const MessageColors &messageColors) override; void paint(QPainter &painter, const MessageColors &messageColors) override;
void paintAnimated(QPainter &painter, int yOffset) override; bool paintAnimated(QPainter &painter, int yOffset) override;
int getMouseOverIndex(const QPoint &abs) const override; int getMouseOverIndex(const QPoint &abs) const override;
int getXFromIndex(size_t index) override; int getXFromIndex(size_t index) override;
@@ -105,7 +106,7 @@ protected:
uint32_t to = UINT32_MAX) const override; uint32_t to = UINT32_MAX) const override;
size_t getSelectionIndexCount() const override; size_t getSelectionIndexCount() const override;
void paint(QPainter &painter, const MessageColors &messageColors) override; void paint(QPainter &painter, const MessageColors &messageColors) override;
void paintAnimated(QPainter &painter, int yOffset) override; bool paintAnimated(QPainter &painter, int yOffset) override;
int getMouseOverIndex(const QPoint &abs) const override; int getMouseOverIndex(const QPoint &abs) const override;
int getXFromIndex(size_t index) override; int getXFromIndex(size_t index) override;
@@ -158,7 +159,7 @@ protected:
uint32_t to = UINT32_MAX) const override; uint32_t to = UINT32_MAX) const override;
size_t getSelectionIndexCount() const override; size_t getSelectionIndexCount() const override;
void paint(QPainter &painter, const MessageColors &messageColors) override; void paint(QPainter &painter, const MessageColors &messageColors) override;
void paintAnimated(QPainter &painter, int yOffset) override; bool paintAnimated(QPainter &painter, int yOffset) override;
int getMouseOverIndex(const QPoint &abs) const override; int getMouseOverIndex(const QPoint &abs) const override;
int getXFromIndex(size_t index) override; int getXFromIndex(size_t index) override;
@@ -182,7 +183,7 @@ protected:
uint32_t to = UINT32_MAX) const override; uint32_t to = UINT32_MAX) const override;
size_t getSelectionIndexCount() const override; size_t getSelectionIndexCount() const override;
void paint(QPainter &painter, const MessageColors &messageColors) override; void paint(QPainter &painter, const MessageColors &messageColors) override;
void paintAnimated(QPainter &painter, int yOffset) override; bool paintAnimated(QPainter &painter, int yOffset) override;
int getMouseOverIndex(const QPoint &abs) const override; int getMouseOverIndex(const QPoint &abs) const override;
int getXFromIndex(size_t index) override; int getXFromIndex(size_t index) override;
@@ -200,7 +201,7 @@ public:
protected: protected:
void paint(QPainter &painter, const MessageColors &messageColors) override; void paint(QPainter &painter, const MessageColors &messageColors) override;
void paintAnimated(QPainter &painter, int yOffset) override; bool paintAnimated(QPainter &painter, int yOffset) override;
int getMouseOverIndex(const QPoint &abs) const override; int getMouseOverIndex(const QPoint &abs) const override;
int getXFromIndex(size_t index) override; int getXFromIndex(size_t index) override;
void addCopyTextToString(QString &str, uint32_t from = 0, void addCopyTextToString(QString &str, uint32_t from = 0,
+8 -2
View File
@@ -406,7 +406,10 @@ void ChannelView::initializeSignals()
this->signalHolder_.managedConnect(getApp()->windows->gifRepaintRequested, this->signalHolder_.managedConnect(getApp()->windows->gifRepaintRequested,
[&] { [&] {
this->queueUpdate(); if (this->anyAnimationShown_)
{
this->queueUpdate();
}
}); });
this->signalHolder_.managedConnect( this->signalHolder_.managedConnect(
@@ -1470,6 +1473,8 @@ void ChannelView::drawMessages(QPainter &painter)
}; };
bool showLastMessageIndicator = getSettings()->showLastMessageIndicator; bool showLastMessageIndicator = getSettings()->showLastMessageIndicator;
bool anyAnimation = false;
for (; ctx.messageIndex < messagesSnapshot.size(); ++ctx.messageIndex) for (; ctx.messageIndex < messagesSnapshot.size(); ++ctx.messageIndex)
{ {
MessageLayout *layout = messagesSnapshot[ctx.messageIndex].get(); MessageLayout *layout = messagesSnapshot[ctx.messageIndex].get();
@@ -1483,7 +1488,7 @@ void ChannelView::drawMessages(QPainter &painter)
ctx.isLastReadMessage = false; ctx.isLastReadMessage = false;
} }
layout->paint(ctx); anyAnimation |= layout->paint(ctx).hasAnimatedElements;
if (this->highlightedMessage_ == layout) if (this->highlightedMessage_ == layout)
{ {
@@ -1504,6 +1509,7 @@ void ChannelView::drawMessages(QPainter &painter)
break; break;
} }
} }
this->anyAnimationShown_ = anyAnimation;
if (end == nullptr) if (end == nullptr)
{ {
+3
View File
@@ -273,6 +273,9 @@ private:
bool lastMessageHasAlternateBackground_ = false; bool lastMessageHasAlternateBackground_ = false;
bool lastMessageHasAlternateBackgroundReverse_ = true; bool lastMessageHasAlternateBackgroundReverse_ = true;
/// Tracks if this view has painted any animated element in the last #paintEvent().
bool anyAnimationShown_ = false;
bool pausable_ = false; bool pausable_ = false;
QTimer pauseTimer_; QTimer pauseTimer_;
std::unordered_map<PauseReason, std::optional<SteadyClock::time_point>> std::unordered_map<PauseReason, std::optional<SteadyClock::time_point>>