File indexing completed on 2024-05-26 04:28:06

0001 /*
0002  *  SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
0003  *  SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 #ifndef KIS_TILEDDATAMANAGER_H_
0008 #define KIS_TILEDDATAMANAGER_H_
0009 
0010 #include <QtGlobal>
0011 #include <QVector>
0012 #include <KisRegion.h>
0013 
0014 #include <kis_shared.h>
0015 #include <kis_shared_ptr.h>
0016 #include "config-hash-table-implementation.h"
0017 
0018 //#include "kis_debug.h"
0019 #include "kritaimage_export.h"
0020 
0021 #ifdef USE_LOCK_FREE_HASH_TABLE
0022 #include "kis_tile_hash_table2.h"
0023 #else
0024 #include "kis_tile_hash_table.h"
0025 #endif // USE_LOCK_FREE_HASH_TABLE
0026 
0027 #include "kis_memento_manager.h"
0028 #include "kis_memento.h"
0029 #include "KisTiledExtentManager.h"
0030 
0031 class KisTiledDataManager;
0032 typedef KisSharedPtr<KisTiledDataManager> KisTiledDataManagerSP;
0033 
0034 class KisTiledIterator;
0035 class KisTiledRandomAccessor;
0036 class KisPaintDeviceWriter;
0037 class QIODevice;
0038 
0039 /**
0040  * KisTiledDataManager implements the interface that KisDataManager defines
0041  *
0042  * The interface definition is enforced by KisDataManager calling all the methods
0043  * which must also be defined in KisTiledDataManager. It is not allowed to change the interface
0044  * as other datamanagers may also rely on the same interface.
0045  *
0046  * * Storing undo/redo data
0047  * * Offering ordered and unordered iterators over rects of pixels
0048  * * (eventually) efficiently loading and saving data in a format
0049  * that may allow deferred loading.
0050  *
0051  * A datamanager knows nothing about the type of pixel data except
0052  * how many quint8's a single pixel takes.
0053  */
0054 
0055 class KRITAIMAGE_EXPORT KisTiledDataManager : public KisShared
0056 {
0057 private:
0058     static const qint32 LEGACY_VERSION = 1;
0059     static const qint32 CURRENT_VERSION = 2;
0060 
0061 protected:
0062     /*FIXME:*/
0063 public:
0064     KisTiledDataManager(quint32 pixelSize, const quint8 *defPixel);
0065     virtual ~KisTiledDataManager();
0066     KisTiledDataManager(const KisTiledDataManager &dm);
0067     KisTiledDataManager & operator=(const KisTiledDataManager &dm);
0068 
0069 
0070 protected:
0071     // Allow the baseclass of iterators access to the interior
0072     // derived iterator classes must go through KisTiledIterator
0073     friend class KisTiledIterator;
0074     friend class KisBaseIterator;
0075     friend class KisTiledRandomAccessor;
0076     friend class KisRandomAccessor2;
0077     friend class KisStressJob;
0078 
0079 public:
0080     void setDefaultPixel(const quint8 *defPixel);
0081     const quint8 *defaultPixel() const {
0082         return m_defaultPixel;
0083     }
0084 
0085     /**
0086      * Every iterator fetches both types of tiles all the time: old and new.
0087      * For projection devices these tiles are **always** the same, but doing
0088      * two distinct calls makes double pressure on the read-write lock in the
0089      * hash table.
0090      *
0091      * Merging two calls into one allows us to avoid additional tile fetch from
0092      * the hash table and therefore reduce waiting time.
0093      */
0094     inline void getTilesPair(qint32 col, qint32 row, bool writable, KisTileSP *tile, KisTileSP *oldTile) {
0095         *tile = getTile(col, row, writable);
0096 
0097         bool unused;
0098         *oldTile = m_mementoManager->getCommittedTile(col, row, unused);
0099 
0100         if (!*oldTile) {
0101             *oldTile = *tile;
0102         }
0103     }
0104 
0105     inline KisTileSP getTile(qint32 col, qint32 row, bool writable) {
0106         if (writable) {
0107             bool newTile;
0108             KisTileSP tile = m_hashTable->getTileLazy(col, row, newTile);
0109             if (newTile) {
0110                 m_extentManager.notifyTileAdded(col, row);
0111             }
0112             return tile;
0113 
0114         } else {
0115             bool unused;
0116             return m_hashTable->getReadOnlyTileLazy(col, row, unused);
0117         }
0118     }
0119 
0120     inline KisTileSP getReadOnlyTileLazy(qint32 col, qint32 row, bool &existingTile) {
0121         return m_hashTable->getReadOnlyTileLazy(col, row, existingTile);
0122     }
0123 
0124     inline KisTileSP getOldTile(qint32 col, qint32 row, bool &existingTile) {
0125         KisTileSP tile = m_mementoManager->getCommittedTile(col, row, existingTile);
0126         return tile ? tile : getReadOnlyTileLazy(col, row, existingTile);
0127     }
0128 
0129     inline KisTileSP getOldTile(qint32 col, qint32 row) {
0130         bool unused;
0131         return getOldTile(col, row, unused);
0132     }
0133 
0134     KisMementoSP getMemento() {
0135         QWriteLocker locker(&m_lock);
0136         KisMementoSP memento = m_mementoManager->getMemento();
0137         memento->saveOldDefaultPixel(m_defaultPixel, m_pixelSize);
0138         return memento;
0139     }
0140 
0141     /**
0142      * Finishes having already started transaction
0143      */
0144     void commit() {
0145         QWriteLocker locker(&m_lock);
0146 
0147         KisMementoSP memento = m_mementoManager->currentMemento();
0148         if(memento) {
0149             memento->saveNewDefaultPixel(m_defaultPixel, m_pixelSize);
0150         }
0151 
0152         m_mementoManager->commit();
0153     }
0154 
0155     void rollback(KisMementoSP memento) {
0156         commit();
0157 
0158         QWriteLocker locker(&m_lock);
0159         m_mementoManager->rollback(m_hashTable, memento);
0160         const quint8 *defaultPixel = memento->oldDefaultPixel();
0161         if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) {
0162             setDefaultPixelImpl(defaultPixel);
0163         }
0164         recalculateExtent();
0165     }
0166     void rollforward(KisMementoSP memento) {
0167         commit();
0168 
0169         QWriteLocker locker(&m_lock);
0170         m_mementoManager->rollforward(m_hashTable, memento);
0171         const quint8 *defaultPixel = memento->newDefaultPixel();
0172         if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) {
0173             setDefaultPixelImpl(defaultPixel);
0174         }
0175         recalculateExtent();
0176     }
0177     bool hasCurrentMemento() const {
0178         return m_mementoManager->hasCurrentMemento();
0179         //return true;
0180     }
0181 
0182     /**
0183      * Removes all the history that precedes the revision
0184      * pointed by oldestMemento. That is after calling to
0185      * purgeHistory(someMemento) you won't be able to do
0186      * rollback(someMemento) anymore.
0187      */
0188     void purgeHistory(KisMementoSP oldestMemento) {
0189         QWriteLocker locker(&m_lock);
0190         m_mementoManager->purgeHistory(oldestMemento);
0191     }
0192 
0193     static void releaseInternalPools();
0194 
0195 protected:
0196     /**
0197      * Reads and writes the tiles
0198      */
0199     bool write(KisPaintDeviceWriter &store);
0200     bool read(QIODevice *stream);
0201 
0202     void purge(const QRect& area);
0203 
0204     inline quint32 pixelSize() const {
0205         return m_pixelSize;
0206     }
0207 
0208     /* FIXME:*/
0209 public:
0210 
0211 
0212     void  extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) const;
0213     void  setExtent(qint32 x, qint32 y, qint32 w, qint32 h);
0214     QRect extent() const;
0215     void  setExtent(QRect newRect);
0216 
0217     KisRegion region() const;
0218 
0219     void clear(QRect clearRect, quint8 clearValue);
0220     void clear(QRect clearRect, const quint8 *clearPixel);
0221     void clear(qint32 x, qint32 y, qint32 w, qint32 h, quint8 clearValue);
0222     void clear(qint32 x, qint32 y,  qint32 w, qint32 h, const quint8 *clearPixel);
0223     void clear();
0224 
0225     /**
0226      * Clones rect from another datamanager. The cloned area will be
0227      * shared between both datamanagers as much as possible using
0228      * copy-on-write. Parts of the rect that cannot be shared
0229      * (cross tiles) are deep-copied,
0230      */
0231     void bitBlt(KisTiledDataManager *srcDM, const QRect &rect);
0232 
0233     /**
0234      * The same as \ref bitBlt(), but reads old data
0235      */
0236     void bitBltOldData(KisTiledDataManager *srcDM, const QRect &rect);
0237 
0238     /**
0239      * Clones rect from another datamanager in a rough and fast way.
0240      * All the tiles touched by rect will be shared, between both
0241      * managers, that means it will copy a bigger area than was
0242      * requested. This method is supposed to be used for bitBlt'ing
0243      * into temporary paint devices.
0244      */
0245     void bitBltRough(KisTiledDataManager *srcDM, const QRect &rect);
0246 
0247     /**
0248      * The same as \ref bitBltRough(), but reads old data
0249      */
0250     void bitBltRoughOldData(KisTiledDataManager *srcDM, const QRect &rect);
0251 
0252     /**
0253      * write the specified data to x, y. There is no checking on pixelSize!
0254      */
0255     void setPixel(qint32 x, qint32 y, const quint8 * data);
0256 
0257 
0258     /**
0259      * Copy the bytes in the specified rect to a vector. The caller is responsible
0260      * for managing the vector.
0261      *
0262      * \param bytes the bytes
0263      * \param x x of top left corner
0264      * \param y y of top left corner
0265      * \param w width
0266      * \param h height
0267      * \param dataRowStride is the step (in bytes) which should be
0268      *                      added to \p bytes pointer to get to the
0269      *                      next row
0270      */
0271     void readBytes(quint8 * bytes,
0272                    qint32 x, qint32 y,
0273                    qint32 w, qint32 h,
0274                    qint32 dataRowStride = -1) const;
0275     /**
0276      * Copy the bytes in the vector to the specified rect. If there are bytes left
0277      * in the vector after filling the rect, they will be ignored. If there are
0278      * not enough bytes, the rest of the rect will be filled with the default value
0279      * given (by default, 0);
0280      *
0281      * \param bytes the bytes
0282      * \param x x of top left corner
0283      * \param y y of top left corner
0284      * \param w width
0285      * \param h height
0286      * \param dataRowStride is the step (in bytes) which should be
0287      *                      added to \p bytes pointer to get to the
0288      *                      next row
0289      */
0290     void writeBytes(const quint8 * bytes,
0291                     qint32 x, qint32 y,
0292                     qint32 w, qint32 h,
0293                     qint32 dataRowStride = -1);
0294 
0295     /**
0296      * Copy the bytes in the paint device into a vector of arrays of bytes,
0297      * where the number of arrays is the number of channels in the
0298      * paint device. If the specified area is larger than the paint
0299      * device's extent, the default pixel will be read.
0300      */
0301     QVector<quint8*> readPlanarBytes(QVector<qint32> channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const;
0302 
0303     /**
0304      * Write the data in the separate arrays to the channels. If there
0305      * are less vectors than channels, the remaining channels will not
0306      * be copied. If any of the arrays points to 0, the channel in
0307      * that location will not be touched. If the specified area is
0308      * larger than the paint device, the paint device will be
0309      * extended. There are no guards: if the area covers more pixels
0310      * than there are bytes in the arrays, krita will happily fill
0311      * your paint device with areas of memory you never wanted to be
0312      * read. Krita may also crash.
0313      */
0314     void writePlanarBytes(QVector<quint8*> planes, QVector<qint32> channelsizes, qint32 x, qint32 y, qint32 w, qint32 h);
0315 
0316     /**
0317      * Get the number of contiguous columns starting at x, valid for all values
0318      * of y between minY and maxY.
0319      */
0320     qint32 numContiguousColumns(qint32 x, qint32 minY, qint32 maxY) const;
0321 
0322     /**
0323      * Get the number of contiguous rows starting at y, valid for all values
0324      * of x between minX and maxX.
0325      */
0326     qint32 numContiguousRows(qint32 y, qint32 minX, qint32 maxX) const;
0327 
0328     /**
0329      * Get the row stride at pixel (x, y). This is the number of bytes to add to a
0330      * pointer to pixel (x, y) to access (x, y + 1).
0331      */
0332     qint32 rowStride(qint32 x, qint32 y) const;
0333 
0334 private:
0335     KisTileHashTable *m_hashTable;
0336     KisMementoManager *m_mementoManager;
0337     quint8* m_defaultPixel;
0338     qint32 m_pixelSize;
0339     KisTiledExtentManager m_extentManager;
0340 
0341     mutable QReadWriteLock m_lock;
0342 
0343 private:
0344     // Allow compression routines to calculate (col,row) coordinates
0345     // and pixel size
0346     friend class KisAbstractTileCompressor;
0347     friend class KisTileDataWrapper;
0348     inline qint32 xToCol(qint32 x) const
0349     {
0350         return divideRoundDown(x, KisTileData::WIDTH);
0351     }
0352     inline qint32 yToRow(qint32 y) const
0353     {
0354         return divideRoundDown(y, KisTileData::HEIGHT);
0355     }
0356 
0357 private:
0358     void setDefaultPixelImpl(const quint8 *defPixel);
0359 
0360     bool writeTilesHeader(KisPaintDeviceWriter &store, quint32 numTiles);
0361     bool processTilesHeader(QIODevice *stream, quint32 &numTiles);
0362 
0363     inline qint32 divideRoundDown(qint32 x, const qint32 y) const
0364     {
0365         /**
0366          * Equivalent to the following:
0367          * -(( -x + (y-1) ) / y)
0368          */
0369 
0370         return x >= 0 ? x / y : -(((-x - 1) / y) + 1);
0371     }
0372 
0373     void recalculateExtent();
0374 
0375     quint8* duplicatePixel(qint32 num, const quint8 *pixel);
0376 
0377     template<bool useOldSrcData>
0378         void bitBltImpl(KisTiledDataManager *srcDM, const QRect &rect);
0379     template<bool useOldSrcData>
0380         void bitBltRoughImpl(KisTiledDataManager *srcDM, const QRect &rect);
0381 
0382     void writeBytesBody(const quint8 *data,
0383                         qint32 x, qint32 y,
0384                         qint32 width, qint32 height,
0385                         qint32 dataRowStride = -1);
0386     void readBytesBody(quint8 *data,
0387                        qint32 x, qint32 y,
0388                        qint32 width, qint32 height,
0389                        qint32 dataRowStride = -1) const;
0390 
0391     template <bool allChannelsPresent>
0392     void writePlanarBytesBody(QVector<quint8*> planes,
0393                               QVector<qint32> channelsizes,
0394                               qint32 x, qint32 y, qint32 w, qint32 h);
0395     QVector<quint8*> readPlanarBytesBody(QVector<qint32> channelsizes,
0396                                          qint32 x, qint32 y,
0397                                          qint32 w, qint32 h) const;
0398 public:
0399     void debugPrintInfo() {
0400         m_mementoManager->debugPrintInfo();
0401     }
0402 
0403 };
0404 
0405 // during development the following line helps to check the interface is correct
0406 // it should be safe to keep it here even during normal compilation
0407 //#include "kis_datamanager.h"
0408 
0409 #endif // KIS_TILEDDATAMANAGER_H_
0410