diff --git a/libs/ui/canvas/kis_canvas_updates_compressor.cpp b/libs/ui/canvas/kis_canvas_updates_compressor.cpp index e5e2769a49..8d6b5d3c97 100644 --- a/libs/ui/canvas/kis_canvas_updates_compressor.cpp +++ b/libs/ui/canvas/kis_canvas_updates_compressor.cpp @@ -1,56 +1,59 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * 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_canvas_updates_compressor.h" bool KisCanvasUpdatesCompressor::putUpdateInfo(KisUpdateInfoSP info) { const int levelOfDetail = info->levelOfDetail(); const QRect newUpdateRect = info->dirtyImageRect(); if (newUpdateRect.isEmpty()) return false; QMutexLocker l(&m_mutex); - KisUpdateInfoList::iterator it = m_updatesList.begin(); - - while (it != m_updatesList.end()) { - if (levelOfDetail == (*it)->levelOfDetail() && - newUpdateRect.contains((*it)->dirtyImageRect())) { - - /** - * We should always remove the overridden update and put 'info' to the end - * of the queue. Otherwise, the updates will become reordered and the canvas - * may have tiles artifacts with "outdated" data - */ - it = m_updatesList.erase(it); - } else { - ++it; + + if (info->canBeCompressed()) { + KisUpdateInfoList::iterator it = m_updatesList.begin(); + while (it != m_updatesList.end()) { + if ((*it)->canBeCompressed() && + levelOfDetail == (*it)->levelOfDetail() && + newUpdateRect.contains((*it)->dirtyImageRect())) { + + /** + * We should always remove the overridden update and put 'info' to the end + * of the queue. Otherwise, the updates will become reordered and the canvas + * may have tiles artifacts with "outdated" data + */ + it = m_updatesList.erase(it); + } else { + ++it; + } } } m_updatesList.append(info); return m_updatesList.size() <= 1; } void KisCanvasUpdatesCompressor::takeUpdateInfo(KisUpdateInfoList &list) { KIS_SAFE_ASSERT_RECOVER(list.isEmpty()) { list.clear(); } QMutexLocker l(&m_mutex); m_updatesList.swap(list); } diff --git a/libs/ui/canvas/kis_update_info.cpp b/libs/ui/canvas/kis_update_info.cpp index 11a23b0669..af5b3797d2 100644 --- a/libs/ui/canvas/kis_update_info.cpp +++ b/libs/ui/canvas/kis_update_info.cpp @@ -1,121 +1,131 @@ /* * Copyright (c) 2010, Dmitry Kazakov * * 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_update_info.h" /** * The connection in KisCanvas2 uses queued signals * with an argument of KisNodeSP type, so we should * register it beforehand */ struct KisUpdateInfoSPStaticRegistrar { KisUpdateInfoSPStaticRegistrar() { qRegisterMetaType("KisUpdateInfoSP"); } }; static KisUpdateInfoSPStaticRegistrar __registrar; KisUpdateInfo::KisUpdateInfo() { } KisUpdateInfo::~KisUpdateInfo() { } QRect KisUpdateInfo::dirtyViewportRect() { return QRect(); } +bool KisUpdateInfo::canBeCompressed() const +{ + return true; +} + QRect KisPPUpdateInfo::dirtyViewportRect() { return viewportRect.toAlignedRect(); } QRect KisPPUpdateInfo::dirtyImageRect() const { return dirtyImageRectVar; } int KisPPUpdateInfo::levelOfDetail() const { return 0; } KisOpenGLUpdateInfo::KisOpenGLUpdateInfo() : m_levelOfDetail(0) { } QRect KisOpenGLUpdateInfo::dirtyViewportRect() { qFatal("Not implemented yet!"); return QRect(); } void KisOpenGLUpdateInfo::assignDirtyImageRect(const QRect &rect) { m_dirtyImageRect = rect; } void KisOpenGLUpdateInfo::assignLevelOfDetail(int lod) { m_levelOfDetail = lod; } QRect KisOpenGLUpdateInfo::dirtyImageRect() const { return m_dirtyImageRect; } int KisOpenGLUpdateInfo::levelOfDetail() const { return m_levelOfDetail; } bool KisOpenGLUpdateInfo::tryMergeWith(const KisOpenGLUpdateInfo &rhs) { if (m_levelOfDetail != rhs.m_levelOfDetail) return false; // TODO: that makes the algorithm of updates compressor incorrect! m_dirtyImageRect |= rhs.m_dirtyImageRect; tileList.append(rhs.tileList); return true; } KisMarkerUpdateInfo::KisMarkerUpdateInfo(KisMarkerUpdateInfo::Type type, const QRect &dirtyImageRect) : m_type(type), m_dirtyImageRect(dirtyImageRect) { } KisMarkerUpdateInfo::Type KisMarkerUpdateInfo::type() const { return m_type; } QRect KisMarkerUpdateInfo::dirtyImageRect() const { return m_dirtyImageRect; } int KisMarkerUpdateInfo::levelOfDetail() const { // return invalid level of detail to avoid merging the update info // with other updates return -1 - (int)m_type; } + +bool KisMarkerUpdateInfo::canBeCompressed() const +{ + return false; +} diff --git a/libs/ui/canvas/kis_update_info.h b/libs/ui/canvas/kis_update_info.h index 62d29966b5..2b76e1d34b 100644 --- a/libs/ui/canvas/kis_update_info.h +++ b/libs/ui/canvas/kis_update_info.h @@ -1,168 +1,170 @@ /* * Copyright (c) 2010, Dmitry Kazakov * * 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_UPDATE_INFO_H_ #define KIS_UPDATE_INFO_H_ #include #include "kis_image_patch.h" #include "kis_shared.h" #include "kritaui_export.h" #include "opengl/kis_texture_tile_update_info.h" #include "kis_ui_types.h" class KRITAUI_EXPORT KisUpdateInfo : public KisShared { public: KisUpdateInfo(); virtual ~KisUpdateInfo(); virtual QRect dirtyViewportRect(); virtual QRect dirtyImageRect() const = 0; virtual int levelOfDetail() const = 0; + virtual bool canBeCompressed() const; }; Q_DECLARE_METATYPE(KisUpdateInfoSP) struct ConversionOptions { ConversionOptions() : m_needsConversion(false) {} ConversionOptions(const KoColorSpace *destinationColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) : m_needsConversion(true), m_destinationColorSpace(destinationColorSpace), m_renderingIntent(renderingIntent), m_conversionFlags(conversionFlags) { } bool m_needsConversion; const KoColorSpace *m_destinationColorSpace = 0; KoColorConversionTransformation::Intent m_renderingIntent; KoColorConversionTransformation::ConversionFlags m_conversionFlags; }; class KisOpenGLUpdateInfo; typedef KisSharedPtr KisOpenGLUpdateInfoSP; class KisOpenGLUpdateInfo : public KisUpdateInfo { public: KisOpenGLUpdateInfo(); KisTextureTileUpdateInfoSPList tileList; QRect dirtyViewportRect() override; QRect dirtyImageRect() const override; void assignDirtyImageRect(const QRect &rect); void assignLevelOfDetail(int lod); int levelOfDetail() const override; bool tryMergeWith(const KisOpenGLUpdateInfo& rhs); private: QRect m_dirtyImageRect; int m_levelOfDetail; }; class KisPPUpdateInfo : public KisUpdateInfo { public: enum TransferType { DIRECT, PATCH }; QRect dirtyViewportRect() override; QRect dirtyImageRect() const override; int levelOfDetail() const override; /** * The rect that was reported by KisImage as dirty */ QRect dirtyImageRectVar; /** * Rect of KisImage corresponding to @ref viewportRect . * It is cropped and aligned corresponding to the canvas. */ QRect imageRect; /** * Rect of canvas widget corresponding to @ref imageRect */ QRectF viewportRect; qreal scaleX; qreal scaleY; /** * Defines the way the source image is painted onto * prescaled QImage */ TransferType transfer; /** * Render hints for painting the direct painting/patch painting */ QPainter::RenderHints renderHints; /** * The number of additional pixels those should be added * to the patch */ qint32 borderWidth; /** * Used for temporary storage of KisImage's data * by KisProjectionCache */ KisImagePatch patch; }; class KisMarkerUpdateInfo : public KisUpdateInfo { public: enum Type { StartBatch = 0, EndBatch, BlockLodUpdates, UnblockLodUpdates, }; public: KisMarkerUpdateInfo(Type type, const QRect &dirtyImageRect); Type type() const; QRect dirtyImageRect() const override; int levelOfDetail() const override; + bool canBeCompressed() const override; private: Type m_type; QRect m_dirtyImageRect; }; #endif /* KIS_UPDATE_INFO_H_ */