Commit 9fa0c213 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix slowdown of animation playback in Krita

There were two reasons for it:

1) KisImageAnimationInterface::totalLength() used to recursively
   recalculate the length of the shot on every call to columnCount(),
   which is called from hasIndex() and as a consequence from everywhere.

2) Layer properties icons and i18n in KisBaseNode::sectionModelProperties()
   were loaded every time from the resource files.

Conflicts:
	krita/image/kis_base_node.cpp
	krita/image/kis_group_layer.cc
	krita/image/kis_layer.cc
	krita/image/kis_paint_layer.cc
	krita/image/kis_selection_mask.cpp
	krita/ui/canvas/kis_animation_player.cpp
parent 3278b0b2
......@@ -296,6 +296,7 @@ set(kritaimage_LIB_SRCS
kis_idle_watcher.cpp
kis_psd_layer_style.cpp
kis_layer_properties_icons.cpp
layerstyles/kis_multiple_projection.cpp
layerstyles/kis_layer_style_filter.cpp
......
......@@ -23,6 +23,9 @@
#include <KoProperties.h>
#include <KoColorSpace.h>
#include <KoCompositeOpRegistry.h>
#include "kis_paint_device.h"
#include "kis_layer_properties_icons.h"
struct Q_DECL_HIDDEN KisBaseNode::Private
{
......@@ -140,8 +143,8 @@ void KisBaseNode::setCompositeOpId(const QString& compositeOp)
KisNodeModel::PropertyList KisBaseNode::sectionModelProperties() const
{
KisNodeModel::PropertyList l;
l << KisNodeModel::Property(i18n("Visible"), KisIconUtils::loadIcon("visible"), KisIconUtils::loadIcon("novisible"), visible(), m_d->hack_visible.isInStasis, m_d->hack_visible.stateInStasis);
l << KisNodeModel::Property(i18n("Locked"), KisIconUtils::loadIcon("layer-locked"), KisIconUtils::loadIcon("layer-unlocked"), userLocked());
l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::visible, visible(), m_d->hack_visible.isInStasis, m_d->hack_visible.stateInStasis);
l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::locked, userLocked());
return l;
}
......
......@@ -36,6 +36,7 @@
#include "kis_clone_layer.h"
#include "kis_selection_mask.h"
#include "kis_psd_layer_style.h"
#include "kis_layer_properties_icons.h"
struct Q_DECL_HIDDEN KisGroupLayer::Private
......@@ -291,7 +292,9 @@ void KisGroupLayer::setPassThroughMode(bool value)
KisNodeModel::PropertyList KisGroupLayer::sectionModelProperties() const
{
KisNodeModel::PropertyList l = KisLayer::sectionModelProperties();
l << KisNodeModel::Property(i18n("Pass Through"), KisIconUtils::loadIcon("passthrough-enabled"), KisIconUtils::loadIcon("passthrough-disabled"), passThroughMode());
l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::passThrough, passThroughMode());
return l;
}
......
......@@ -36,7 +36,8 @@ struct KisImageAnimationInterface::Private
currentTime(0),
currentUITime(0),
externalFrameActive(false),
frameInvalidationBlocked(false)
frameInvalidationBlocked(false),
cachedLastFrameValue(-1)
{
}
......@@ -48,6 +49,7 @@ struct KisImageAnimationInterface::Private
KisTimeRange currentRange;
int framerate;
int cachedLastFrameValue;
};
......@@ -196,6 +198,7 @@ void KisImageAnimationInterface::notifyNodeChanged(const KisNode *node,
void KisImageAnimationInterface::invalidateFrames(const KisTimeRange &range, const QRect &rect)
{
m_d->cachedLastFrameValue = -1;
emit sigFramesChanged(range, rect);
}
......@@ -227,7 +230,11 @@ int findLastKeyframeTimeRecursive(KisNodeSP node)
int KisImageAnimationInterface::totalLength()
{
int lastKey = findLastKeyframeTimeRecursive(m_d->image->root());
if (m_d->cachedLastFrameValue < 0) {
m_d->cachedLastFrameValue = findLastKeyframeTimeRecursive(m_d->image->root());
}
int lastKey = m_d->cachedLastFrameValue;
lastKey = std::max(lastKey, m_d->currentRange.end());
lastKey = std::max(lastKey, m_d->currentUITime);
......
......@@ -52,6 +52,7 @@
#include "layerstyles/kis_layer_style_projection_plane.h"
#include "krita_utils.h"
#include "kis_layer_properties_icons.h"
class KisSafeProjection {
......@@ -219,10 +220,10 @@ KisNodeModel::PropertyList KisLayer::sectionModelProperties() const
}
if (m_d->layerStyle && !m_d->layerStyle->isEmpty()) {
l << KisNodeModel::Property(i18n("Layer Style"), KisIconUtils::loadIcon("layer-style-enabled"), KisIconUtils::loadIcon("layer-style-disabled"), m_d->layerStyle->isEnabled());
l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::layerStyle, m_d->layerStyle->isEnabled());
}
l << KisNodeModel::Property(i18n("Inherit Alpha"), KisIconUtils::loadIcon("transparency-disabled"), KisIconUtils::loadIcon("transparency-enabled"), alphaChannelDisabled());
l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::inheritAlpha, alphaChannelDisabled());
return l;
}
......
/*
* Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_layer_properties_icons.h"
#include <QMap>
#include <QGlobalStatic>
Q_GLOBAL_STATIC(KisLayerPropertiesIcons, s_instance)
#include <kis_icon_utils.h>
const KoID KisLayerPropertiesIcons::locked("locked", i18n("Locked"));
const KoID KisLayerPropertiesIcons::visible("visible", i18n("Visible"));
const KoID KisLayerPropertiesIcons::layerStyle("layer-style", i18n("Layer Style"));
const KoID KisLayerPropertiesIcons::inheritAlpha("inherit-alpha", i18n("Inherit Alpha"));
const KoID KisLayerPropertiesIcons::alphaLocked("alpha-locked", i18n("Alpha Locked"));
const KoID KisLayerPropertiesIcons::onionSkins("onion-skins", i18n("Onion Skins"));
const KoID KisLayerPropertiesIcons::passThrough("pass-through", i18n("Pass Through"));
const KoID KisLayerPropertiesIcons::selectionActive("selection-active", i18n("Active"));
struct IconsPair {
IconsPair() {}
IconsPair(const QIcon &_on, const QIcon &_off) : on(_on), off(_off) {}
QIcon on;
QIcon off;
const QIcon& getIcon(bool state) {
return state ? on : off;
}
};
struct KisLayerPropertiesIcons::Private
{
QMap<QString, IconsPair> icons;
};
KisLayerPropertiesIcons::KisLayerPropertiesIcons()
: m_d(new Private)
{
updateIcons();
}
KisLayerPropertiesIcons::~KisLayerPropertiesIcons()
{
}
KisLayerPropertiesIcons *KisLayerPropertiesIcons::instance()
{
return s_instance;
}
void KisLayerPropertiesIcons::updateIcons()
{
m_d->icons.clear();
m_d->icons.insert(locked.id(), IconsPair(KisIconUtils::loadIcon("visible"), KisIconUtils::loadIcon("novisible")));
m_d->icons.insert(visible.id(), IconsPair(KisIconUtils::loadIcon("layer-locked"), KisIconUtils::loadIcon("layer-unlocked")));
m_d->icons.insert(layerStyle.id(), IconsPair(KisIconUtils::loadIcon("layer-style-enabled"), KisIconUtils::loadIcon("layer-style-disabled")));
m_d->icons.insert(inheritAlpha.id(), IconsPair(KisIconUtils::loadIcon("transparency-disabled"), KisIconUtils::loadIcon("transparency-enabled")));
m_d->icons.insert(alphaLocked.id(), IconsPair(KisIconUtils::loadIcon("transparency-locked"), KisIconUtils::loadIcon("transparency-unlocked")));
m_d->icons.insert(onionSkins.id(), IconsPair(KisIconUtils::loadIcon("onionOn"), KisIconUtils::loadIcon("onionOff")));
m_d->icons.insert(passThrough.id(), IconsPair(KisIconUtils::loadIcon("passthrough-enabled"), KisIconUtils::loadIcon("passthrough-disabled")));
m_d->icons.insert(selectionActive.id(), IconsPair(KisIconUtils::loadIcon("local_selection_active"), KisIconUtils::loadIcon("local_selection_inactive")));
}
KisNodeModel::Property KisLayerPropertiesIcons::getProperty(const KoID &id, bool state)
{
const IconsPair &pair = instance()->m_d->icons[id.id()];
return KisNodeModel::Property(id.name(),
pair.on, pair.off, state);
}
KisNodeModel::Property KisLayerPropertiesIcons::getProperty(const KoID &id, bool state,
bool isInStasis, bool stateInStasis)
{
const IconsPair &pair = instance()->m_d->icons[id.id()];
return KisNodeModel::Property(id.name(),
pair.on, pair.off, state,
isInStasis, stateInStasis);
}
/*
* Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __KIS_LAYER_PROPERTIES_ICONS_H
#define __KIS_LAYER_PROPERTIES_ICONS_H
#include <QScopedPointer>
#include <KoID.h>
#include "kis_node_model.h"
class KisLayerPropertiesIcons
{
public:
KisLayerPropertiesIcons();
~KisLayerPropertiesIcons();
static const KoID locked;
static const KoID visible;
static const KoID layerStyle;
static const KoID inheritAlpha;
static const KoID alphaLocked;
static const KoID onionSkins;
static const KoID passThrough;
static const KoID selectionActive;
static KisLayerPropertiesIcons* instance();
static KisNodeModel::Property getProperty(const KoID &id, bool state);
static KisNodeModel::Property getProperty(const KoID &id, bool state,
bool isInStasis, bool stateInStasis);
private:
void updateIcons();
private:
struct Private;
const QScopedPointer<Private> m_d;
};
#endif /* __KIS_LAYER_PROPERTIES_ICONS_H */
......@@ -42,6 +42,7 @@
#include "kis_raster_keyframe_channel.h"
#include "kis_signal_auto_connection.h"
#include "kis_layer_properties_icons.h"
struct Q_DECL_HIDDEN KisPaintLayer::Private
{
......@@ -171,11 +172,10 @@ KisNodeModel::PropertyList KisPaintLayer::sectionModelProperties() const
{
KisNodeModel::PropertyList l = KisLayer::sectionModelProperties();
// XXX: get right icons
l << KisNodeModel::Property(i18n("Alpha Locked"), KisIconUtils::loadIcon("transparency-locked"), KisIconUtils::loadIcon("transparency-unlocked"), alphaLocked());
l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::alphaLocked, alphaLocked());
if (isAnimated()) {
l << KisNodeModel::Property(i18n("Onion skin"), koIcon("onionOn"), koIcon("onionOff"), onionSkinEnabled());
l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::onionSkins, onionSkinEnabled());
}
return l;
......
......@@ -34,6 +34,7 @@
#include <KoIcon.h>
#include <kis_icon.h>
#include "kis_thread_safe_signal_compressor.h"
#include "kis_layer_properties_icons.h"
struct Q_DECL_HIDDEN KisSelectionMask::Private
......@@ -115,7 +116,7 @@ void KisSelectionMask::accept(KisProcessingVisitor &visitor, KisUndoAdapter *und
KisNodeModel::PropertyList KisSelectionMask::sectionModelProperties() const
{
KisNodeModel::PropertyList l = KisBaseNode::sectionModelProperties();
l << KisNodeModel::Property(i18n("Active"), KisIconUtils::loadIcon("local_selection_active"), KisIconUtils::loadIcon("local_selection_inactive"), active());
l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::selectionActive, active());
return l;
}
......
......@@ -485,12 +485,7 @@ QVariant TimelineFramesModel::headerData(int section, Qt::Orientation orientatio
return m_d->layerName(section);
}
case TimelinePropertiesRole: {
KisNodeDummy *dummy = m_d->converter->dummyFromRow(section);
if (!dummy) return QVariant();
PropertyList props = dummy->node()->sectionModelProperties();
return QVariant::fromValue(props);
return QVariant::fromValue(m_d->layerProperties(section));
}
case OtherLayersRole: {
TimelineNodeListKeeper::OtherLayersList list =
......
......@@ -20,8 +20,15 @@
#include <QTimer>
//#define DEBUG_FRAMERATE
#ifdef DEBUG_FRAMERATE
#include <QTime>
#endif /* DEBUG_FRAMERATE */
#include "kis_global.h"
#include "kis_image.h"
#include "kis_canvas2.h"
#include "kis_animation_frame_cache.h"
......@@ -46,6 +53,10 @@ public:
KisCanvas2 *canvas;
KisSignalAutoConnectionsStore cancelStrokeConnections;
#ifdef DEBUG_FRAMERATE
QTime frameRateTimer;
#endif /* DEBUG_FRAMERATE */
};
KisAnimationPlayer::KisAnimationPlayer(KisCanvas2 *canvas)
......@@ -152,12 +163,28 @@ void KisAnimationPlayer::slotUpdate()
uploadFrame(m_d->currentFrame);
}
#ifdef DEBUG_FRAMERATE
#include "../../sdk/tests/testutil.h"
static TestUtil::MeasureAvgPortion C(25);
#endif /* DEBUG_FRAMERATE */
void KisAnimationPlayer::uploadFrame(int frame)
{
if (m_d->canvas->frameCache()->uploadFrame(frame)) {
m_d->canvas->updateCanvas();
emit sigFrameChanged();
}
//emit sigFrameChanged();
#ifdef DEBUG_FRAMERATE
if (!m_d->frameRateTimer.isValid()) {
m_d->frameRateTimer.start();
} else {
const int elapsed = m_d->frameRateTimer.restart();
C.addTotal(1000 / elapsed);
}
#endif /* DEBUG_FRAMERATE */
}
void KisAnimationPlayer::slotCancelPlayback()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment