Commit 292c6ff5 authored by Bart Coppens's avatar Bart Coppens

Port the newer tiles swap code from 1.6 to trunk (the one without madvise and...

Port the newer tiles swap code from 1.6 to trunk (the one without madvise and lesser crashing on huge images), and fixed a crash (should look into why that works on 1.6).
On another happy note: this is my first KDE4-Krita2 commit \o/ :-)

svn path=/trunk/koffice/; revision=544688
parent b546b0cf
......@@ -153,13 +153,13 @@ public:
/**
* Get a read-only pointer to the specified pixel.
*/
inline const quint8* pixel(qint32 x, qint32 y)
inline const quint8* pixel(qint32 x, qint32 y) KDE_DEPRECATED
{ return ACTUAL_DATAMGR::pixel(x, y); }
/**
* Get a read-write pointer to the specified pixel.
*/
inline quint8* writablePixel(qint32 x, qint32 y)
inline quint8* writablePixel(qint32 x, qint32 y) KDE_DEPRECATED
{ return ACTUAL_DATAMGR::writablePixel(x, y); }
/**
......
......@@ -646,8 +646,11 @@ void KisPaintDevice::convertTo(KisColorSpace * dstColorSpace, qint32 renderingIn
qint32 columns = qMin(numContiguousDstColumns, numContiguousSrcColumns);
columns = qMin(columns, columnsRemaining);
const quint8 *srcData = pixel(column, row);
quint8 *dstData = dst.writablePixel(column, row);
KisHLineIteratorPixel srcIt = createHLineIterator(column, row, columns, false);
KisHLineIteratorPixel dstIt = dst.createHLineIterator(column, row, columns, true);
const quint8 *srcData = srcIt.rawData();
quint8 *dstData = dstIt.rawData();
m_colorSpace->convertPixelsTo(srcData, dstData, dstColorSpace, columns, renderingIntent);
......@@ -1049,7 +1052,8 @@ bool KisPaintDevice::pixel(qint32 x, qint32 y, KisColor * kc)
KisColor KisPaintDevice::colorAt(qint32 x, qint32 y)
{
return KisColor(m_datamanager->pixel(x - m_x, y - m_y), m_colorSpace);
KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
return KisColor(iter.rawData(), m_colorSpace);
}
bool KisPaintDevice::setPixel(qint32 x, qint32 y, const QColor& c, quint8 opacity)
......
......@@ -234,12 +234,12 @@ public:
/**
* Get a read-only pointer to pixel (x, y).
*/
const quint8* pixel(qint32 x, qint32 y);
const quint8* pixel(qint32 x, qint32 y) KDE_DEPRECATED;
/**
* Get a read-write pointer to pixel (x, y).
*/
quint8* writablePixel(qint32 x, qint32 y);
quint8* writablePixel(qint32 x, qint32 y) KDE_DEPRECATED;
/**
* Converts the paint device to a different colorspace
......
......@@ -202,12 +202,13 @@ void KisPainter::bitBlt(qint32 dx, qint32 dy,
qint32 columns = qMin(numContiguousDstColumns, numContiguousSrcColumns);
columns = qMin(columns, columnsRemaining);
const quint8 *srcData = srcdev->pixel(srcX, srcY);
qint32 srcRowStride = srcdev->rowStride(srcX, srcY);
KisHLineIteratorPixel srcIt = srcdev->createHLineIterator(srcX, srcY, columns, false);
const quint8 *srcData = srcIt.rawData();
quint8 *dstData = m_device->writablePixel(dstX, dstY);
qint32 dstRowStride = m_device->rowStride(dstX, dstY);
KisHLineIteratorPixel dstIt = m_device->createHLineIterator(dstX, dstY, columns, true);
quint8 *dstData = dstIt.rawData();
m_colorSpace->bitBlt(dstData,
dstRowStride,
......@@ -307,14 +308,17 @@ void KisPainter::bltSelection(qint32 dx, qint32 dy,
columns = qMin(numContiguousSelColumns, columns);
columns = qMin(columns, columnsRemaining);
quint8 *dstData = m_device->writablePixel(dstX, dstY);
qint32 dstRowStride = m_device->rowStride(dstX, dstY);
KisHLineIteratorPixel dstIt = m_device->createHLineIterator(dstX, dstY, columns, true);
quint8 *dstData = dstIt.rawData();
const quint8 *srcData = srcdev->pixel(srcX, srcY);
qint32 srcRowStride = srcdev->rowStride(srcX, srcY);
KisHLineIteratorPixel srcIt = srcdev->createHLineIterator(srcX, srcY, columns, false);
const quint8 *srcData = srcIt.rawData();
const quint8 *selData = seldev->pixel(dstX, dstY);
qint32 selRowStride = seldev->rowStride(dstX, dstY);
KisHLineIteratorPixel selIt = seldev->createHLineIterator(dstX, dstY, columns, false);
const quint8 *selData = selIt.rawData();
m_colorSpace->bitBlt(dstData,
dstRowStride,
......
......@@ -53,6 +53,11 @@ KisTile::KisTile(const KisTile& rhs, qint32 col, qint32 row)
allocate();
// If we ensure it's loaded, we won't need to modify the tiles with addReader and so,
// which modify the constness much more explicitly than this one, that only does it
// implicitly (that is, it has a non-const copy of the pointer tile somewhere)
KisTileManager::instance()->ensureTileLoaded(&rhs);
assert(rhs.m_data);
if (rhs.m_data) {
memcpy(m_data, rhs.m_data, WIDTH * HEIGHT * m_pixelSize * sizeof(quint8));
}
......@@ -76,6 +81,9 @@ KisTile::KisTile(const KisTile& rhs)
allocate();
// Ditto as above
KisTileManager::instance()->ensureTileLoaded(&rhs);
assert(rhs.m_data);
if (rhs.m_data) {
memcpy(m_data, rhs.m_data, WIDTH * HEIGHT * m_pixelSize * sizeof(quint8));
}
......@@ -112,17 +120,18 @@ void KisTile::setNext(KisTile *n)
quint8 *KisTile::data(qint32 x, qint32 y ) const
{
//Q_ASSERT(m_data != 0);
Q_ASSERT(m_data != 0);
//addReader(); [!] const!
if (m_data == 0) return 0;
//removeReader(); [!]
return m_data + m_pixelSize * ( y * WIDTH + x );
}
void KisTile::setData(const quint8 *pixel)
{
quint8 *dst = m_data;
addReader();
quint8 *dst = m_data;
for(int i=0; i <WIDTH * HEIGHT;i++)
{
memcpy(dst, pixel, m_pixelSize);
......@@ -139,6 +148,7 @@ void KisTile::addReader()
kDebug(41000) << m_nReadlock << endl;
assert(0);
}
assert(m_data);
}
void KisTile::removeReader()
......
......@@ -55,7 +55,7 @@ public:
void setNext(KisTile *);
KisTile *getNext() const { return m_nextTile; }
/// Functions that are needed for locking the tiles into memory for caching
void addReader();
void removeReader();
......
......@@ -350,11 +350,12 @@ void KisTiledDataManager::clear(qint32 x, qint32 y, qint32 w, qint32 h, quint8 c
QRect clearTileRect = clearRect & tileRect;
tile->addReader();
if (clearTileRect == tileRect) {
// Clear whole tile
tile->addReader();
memset(tile->data(), clearValue, KisTile::WIDTH * KisTile::HEIGHT * m_pixelSize);
tile->removeReader();
} else {
quint32 rowsRemaining = clearTileRect.height();
......@@ -366,6 +367,7 @@ void KisTiledDataManager::clear(qint32 x, qint32 y, qint32 w, qint32 h, quint8 c
--rowsRemaining;
}
}
tile->removeReader();
}
}
}
......@@ -455,11 +457,13 @@ void KisTiledDataManager::clear(qint32 x, qint32 y, qint32 w, qint32 h, const qu
if (clearTileRect == tileRect) {
// Clear whole tile
tile->addReader();
memcpy(tile->data(), clearPixelData, KisTile::WIDTH * KisTile::HEIGHT * m_pixelSize);
tile->removeReader();
} else {
quint32 rowsRemaining = clearTileRect.height();
tile->addReader();
quint8 *dst = tile->data(clearTileRect.x() - tileRect.x(), clearTileRect.y() - tileRect.y());
while (rowsRemaining > 0) {
......@@ -467,6 +471,7 @@ void KisTiledDataManager::clear(qint32 x, qint32 y, qint32 w, qint32 h, const qu
dst += rowStride;
--rowsRemaining;
}
tile->removeReader();
}
}
}
......@@ -826,6 +831,13 @@ KisTile *KisTiledDataManager::getOldTile(qint32 col, qint32 row, KisTile *def)
quint8* KisTiledDataManager::pixelPtr(qint32 x, qint32 y, bool writable)
{
// Ahem, this is a bit not as good. The point is, this function needs the tile data,
// but it might be swapped out. This code swaps it in, but at function exit it might
// be swapped out again! THIS MAKES THE RETURNED POINTER QUITE VOLATILE
return pixelPtrSafe(x, y, writable) -> data();
}
KisTileDataWrapperSP KisTiledDataManager::pixelPtrSafe(qint32 x, qint32 y, bool writable) {
qint32 row = yToRow(y);
qint32 col = xToCol(x);
......@@ -836,7 +848,7 @@ quint8* KisTiledDataManager::pixelPtr(qint32 x, qint32 y, bool writable)
KisTile *tile = getTile(col, row, writable);
return tile->data() + offset;
return KisTileDataWrapperSP(new KisTileDataWrapper(tile, offset));
}
const quint8* KisTiledDataManager::pixel(qint32 x, qint32 y)
......@@ -887,7 +899,8 @@ void KisTiledDataManager::readBytes(quint8 * data,
qint32 columns = qMin(numContiguousSrcColumns, columnsRemaining);
const quint8 *srcData = pixel(srcX, srcY);
KisTileDataWrapperSP tileData = pixelPtrSafe(srcX, srcY, false);
const quint8 *srcData = tileData -> data();
qint32 srcRowStride = rowStride(srcX, srcY);
quint8 *dstData = data + ((dstX + (dstY * w)) * m_pixelSize);
......@@ -945,7 +958,9 @@ void KisTiledDataManager::writeBytes(const quint8 * bytes,
qint32 columns = qMin(numContiguousdstColumns, columnsRemaining);
quint8 *dstData = writablePixel(dstX, dstY);
//quint8 *dstData = writablePixel(dstX, dstY);
KisTileDataWrapperSP tileData = pixelPtrSafe(dstX, dstY, true);
quint8 *dstData = tileData->data();
qint32 dstRowStride = rowStride(dstX, dstY);
const quint8 *srcData = bytes + ((srcX + (srcY * w)) * m_pixelSize);
......@@ -1013,3 +1028,13 @@ qint32 KisTiledDataManager::numTiles(void) const
return m_numTiles;
}
KisTileDataWrapper::KisTileDataWrapper(KisTile* tile, qint32 offset)
: m_tile(tile), m_offset(offset)
{
m_tile->addReader();
}
KisTileDataWrapper::~KisTileDataWrapper()
{
m_tile->removeReader();
}
......@@ -37,6 +37,17 @@ typedef KSharedPtr<KisDataManager> KisDataManagerSP;
class KisTiledIterator;
class KoStore;
class KisTileDataWrapper : public KShared {
KisTile* m_tile;
qint32 m_offset;
public:
KisTileDataWrapper(KisTile* tile, qint32 offset);
virtual ~KisTileDataWrapper();
quint8* data() const { return m_tile->data() + m_offset; }
};
typedef KSharedPtr<KisTileDataWrapper> KisTileDataWrapperSP;
/**
* KisTiledDataManager implements the interface that KisDataManager defines
*
......@@ -186,6 +197,7 @@ private:
qint32 yToRow(qint32 y) const;
void getContiguousColumnsAndRows(qint32 x, qint32 y, qint32 *columns, qint32 *rows);
quint8* pixelPtr(qint32 x, qint32 y, bool writable);
KisTileDataWrapperSP pixelPtrSafe(qint32 x, qint32 y, bool writable);
};
......
This diff is collapsed.
......@@ -18,6 +18,8 @@
#ifndef KIS_TILEMANAGER_H_
#define KIS_TILEMANAGER_H_
#include <sys/types.h>
#include <qglobal.h>
#include <QMap>
#include <q3valuelist.h>
......@@ -48,8 +50,9 @@ public:
public: // Tile management
void registerTile(KisTile* tile);
void deregisterTile(KisTile* tile);
void ensureTileLoaded(KisTile* tile);
void maySwapTile(KisTile* tile);
// these can change the tile indirectly, though, through the actual swapping!
void ensureTileLoaded(const KisTile* tile);
void maySwapTile(const KisTile* tile);
public: // Pool management
quint8* requestTileData(qint32 pixelSize);
......@@ -66,15 +69,21 @@ private:
private:
static KisTileManager *m_singleton;
KTempFile m_tempFile;
int m_fileSize;
off_t m_fileSize;
// For use when any swap-allocating function failed; the risk of swap allocating failing
// again is too big, and we'd clutter the logs with kWarnings otherwise
bool m_swapForbidden;
struct TileInfo { KisTile *tile; bool inMem; int filePos; int size; int fsize;
bool validNode; Q3ValueList<TileInfo*>::iterator node; };
typedef struct { quint8 *pointer; int filePos; int size; } FreeInfo;
typedef QMap<KisTile*, TileInfo*> TileMap;
// validNode says if you can swap it (true) or not (false) mmapped, if this tile
// currently is memory mapped. If it is false, but onFile, it is on disk,
// but not mmapped, and should be mapped!
// filePos is the position inside the file; size is the actual size, fsize is the size
// being used in the swap for this tile (may be larger!)
struct TileInfo { KisTile *tile; off_t filePos; int size; int fsize;
Q3ValueList<TileInfo*>::iterator node;
bool inMem; bool onFile; bool mmapped; bool validNode; };
typedef struct { off_t filePos; int size; } FreeInfo;
typedef QMap<const KisTile*, TileInfo*> TileMap;
typedef Q3ValueList<TileInfo*> TileList;
typedef Q3ValueList<FreeInfo*> FreeList;
typedef Q3ValueVector<FreeList> FreeListList;
......@@ -109,6 +118,10 @@ private:
bool isPoolTile(quint8* data, qint32 pixelSize);
void reclaimTileToPool(quint8* data, qint32 pixelSize);
// Mmap wrapper that prints warnings on error. The result is stored in the *& result
// the return value is true on succes, false on failure. Other args as in man mmap
bool kritaMmap(quint8*& result, void *start, size_t length,
int prot, int flags, int fd, off_t offset);
};
#endif // KIS_TILEMANAGER_H_
......@@ -193,13 +193,14 @@ void KisAutoContrast::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFil
quint8 *firstPixel = iter.rawData();
while(iter.selectedness()==MAX_SELECTED && maxpix)
{
--maxpix;
++iter;
if (maxpix != 0)
++iter;
++npix;
}
// adjust
src->colorSpace()->applyAdjustment(firstPixel, firstPixel, adj, npix);
pixelsProcessed += npix;
++iter;
break;
}
......@@ -286,12 +287,14 @@ void KisDesaturateFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, Ki
while(iter.selectedness()==MAX_SELECTED && maxpix)
{
--maxpix;
++iter;
if (maxpix != 0)
++iter;
++npix;
}
// adjust
src->colorSpace()->applyAdjustment(firstPixel, firstPixel, m_adj, npix);
pixelsProcessed += npix;
++iter;
break;
}
......
......@@ -274,7 +274,8 @@ void KisRainDropsFilter::rainDrops(KisPaintDeviceSP src, KisPaintDeviceSP dst, c
QColor newColor;
newColor.setRgb(newRed, newGreen, newBlue);
cs->fromQColor(newColor, dst->writablePixel(rect.x() + n, rect.y() + m));
KisHLineIterator dstIt = dst->createHLineIterator(rect.x() + n, rect.y() + m, 1, true);
cs->fromQColor(newColor, dstIt.rawData());
}
}
}
......@@ -303,8 +304,9 @@ void KisRainDropsFilter::rainDrops(KisPaintDeviceSP src, KisPaintDeviceSP dst, c
if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width))
{
QColor color;
cs->toQColor(dst->pixel(rect.x() + n, rect.y() + m),
&color);
KisHLineIterator dstIt = dst->createHLineIterator(rect.x() + n, rect.y() + m, 1, false);
&color);
cs->toQColor(dstIt.rawData(), &color);
R += color.red();
G += color.green();
......@@ -321,7 +323,8 @@ void KisRainDropsFilter::rainDrops(KisPaintDeviceSP src, KisPaintDeviceSP dst, c
QColor color;
color.setRgb((int)(R / BlurPixels), (int)(G / BlurPixels), (int)(B / BlurPixels));
cs->fromQColor(color, dst->writablePixel(rect.x() + n, rect.y() + m));
KisHLineIterator dstIt = dst->createHLineIterator(rect.x() + n, rect.y() + m, 1, true);
cs->fromQColor(color, dstIt.rawData());
}
}
}
......
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