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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 51 additions and 20 deletions

View file

@ -99,6 +99,7 @@
- Dev: BREAKING: Replace custom `import()` with normal Lua `require()`. (#5014)
- Dev: Fixed most compiler warnings. (#5028)
- 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

View file

@ -196,8 +196,10 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
}
// Painting
void MessageLayout::paint(const MessagePaintContext &ctx)
MessagePaintResult MessageLayout::paint(const MessagePaintContext &ctx)
{
MessagePaintResult result;
QPixmap *pixmap = this->ensureBuffer(ctx.painter, ctx.canvasWidth);
if (!this->bufferValid_)
@ -209,7 +211,8 @@ void MessageLayout::paint(const MessagePaintContext &ctx)
ctx.painter.drawPixmap(0, ctx.y, *pixmap);
// draw gif emotes
this->container_.paintAnimatedElements(ctx.painter, ctx.y);
result.hasAnimatedElements =
this->container_.paintAnimatedElements(ctx.painter, ctx.y);
// draw disabled
if (this->message_->flags.has(MessageFlag::Disabled))
@ -270,6 +273,8 @@ void MessageLayout::paint(const MessagePaintContext &ctx)
}
this->bufferValid_ = true;
return result;
}
QPixmap *MessageLayout::ensureBuffer(QPainter &painter, int width)

View file

@ -32,6 +32,10 @@ enum class MessageLayoutFlag : uint8_t {
};
using MessageLayoutFlags = FlagsEnum<MessageLayoutFlag>;
struct MessagePaintResult {
bool hasAnimatedElements = false;
};
class MessageLayout
{
public:
@ -55,7 +59,7 @@ public:
bool layout(int width, float scale_, MessageElementFlags flags);
// Painting
void paint(const MessagePaintContext &ctx);
MessagePaintResult paint(const MessagePaintContext &ctx);
void invalidateBuffer();
void deleteBuffer();
void deleteCache();

View file

@ -235,13 +235,15 @@ void MessageLayoutContainer::paintElements(QPainter &painter,
}
}
void MessageLayoutContainer::paintAnimatedElements(QPainter &painter,
bool MessageLayoutContainer::paintAnimatedElements(QPainter &painter,
int yOffset) const
{
bool anyAnimatedElement = false;
for (const auto &element : this->elements_)
{
element->paintAnimated(painter, yOffset);
anyAnimatedElement |= element->paintAnimated(painter, yOffset);
}
return anyAnimatedElement;
}
void MessageLayoutContainer::paintSelection(QPainter &painter,

View file

@ -64,8 +64,9 @@ struct MessageLayoutContainer {
/**
* 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

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)
{
return;
return false;
}
if (this->image_->animated())
@ -167,8 +167,10 @@ void ImageLayoutElement::paintAnimated(QPainter &painter, int yOffset)
auto rect = this->getRect();
rect.moveTop(rect.y() + yOffset);
painter.drawPixmap(QRectF(rect), *pixmap, QRectF());
return true;
}
}
return false;
}
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());
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
@ -446,8 +449,9 @@ void TextLayoutElement::paint(QPainter &painter,
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
@ -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
@ -640,8 +646,10 @@ void ReplyCurveLayoutElement::paint(QPainter &painter,
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

View file

@ -52,7 +52,8 @@ public:
virtual size_t getSelectionIndexCount() const = 0;
virtual void paint(QPainter &painter,
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 getXFromIndex(size_t index) = 0;
@ -86,7 +87,7 @@ protected:
uint32_t to = UINT32_MAX) const override;
size_t getSelectionIndexCount() const 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 getXFromIndex(size_t index) override;
@ -105,7 +106,7 @@ protected:
uint32_t to = UINT32_MAX) const override;
size_t getSelectionIndexCount() const 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 getXFromIndex(size_t index) override;
@ -158,7 +159,7 @@ protected:
uint32_t to = UINT32_MAX) const override;
size_t getSelectionIndexCount() const 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 getXFromIndex(size_t index) override;
@ -182,7 +183,7 @@ protected:
uint32_t to = UINT32_MAX) const override;
size_t getSelectionIndexCount() const 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 getXFromIndex(size_t index) override;
@ -200,7 +201,7 @@ public:
protected:
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 getXFromIndex(size_t index) override;
void addCopyTextToString(QString &str, uint32_t from = 0,

View file

@ -406,7 +406,10 @@ void ChannelView::initializeSignals()
this->signalHolder_.managedConnect(getApp()->windows->gifRepaintRequested,
[&] {
this->queueUpdate();
if (this->anyAnimationShown_)
{
this->queueUpdate();
}
});
this->signalHolder_.managedConnect(
@ -1470,6 +1473,8 @@ void ChannelView::drawMessages(QPainter &painter)
};
bool showLastMessageIndicator = getSettings()->showLastMessageIndicator;
bool anyAnimation = false;
for (; ctx.messageIndex < messagesSnapshot.size(); ++ctx.messageIndex)
{
MessageLayout *layout = messagesSnapshot[ctx.messageIndex].get();
@ -1483,7 +1488,7 @@ void ChannelView::drawMessages(QPainter &painter)
ctx.isLastReadMessage = false;
}
layout->paint(ctx);
anyAnimation |= layout->paint(ctx).hasAnimatedElements;
if (this->highlightedMessage_ == layout)
{
@ -1504,6 +1509,7 @@ void ChannelView::drawMessages(QPainter &painter)
break;
}
}
this->anyAnimationShown_ = anyAnimation;
if (end == nullptr)
{

View file

@ -273,6 +273,9 @@ private:
bool lastMessageHasAlternateBackground_ = false;
bool lastMessageHasAlternateBackgroundReverse_ = true;
/// Tracks if this view has painted any animated element in the last #paintEvent().
bool anyAnimationShown_ = false;
bool pausable_ = false;
QTimer pauseTimer_;
std::unordered_map<PauseReason, std::optional<SteadyClock::time_point>>