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