Commit ed26d212 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Added a sliding memory window for an upcoming swapper

It just provides random access to the file through memory mapping.

svn path=/trunk/koffice/; revision=1152107
parent bf8359c2
...@@ -48,6 +48,7 @@ set(libkritatile_SRCS ...@@ -48,6 +48,7 @@ set(libkritatile_SRCS
${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_legacy_tile_compressor.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_legacy_tile_compressor.cpp
${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_tile_compressor_2.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_tile_compressor_2.cpp
${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_chunk_allocator.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_chunk_allocator.cpp
${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_memory_window.cpp
) )
add_subdirectory( tiles3 ) add_subdirectory( tiles3 )
endif(USE_TILESYSTEM EQUAL 1) endif(USE_TILESYSTEM EQUAL 1)
......
...@@ -61,8 +61,17 @@ class KisChunkData ...@@ -61,8 +61,17 @@ class KisChunkData
{ {
public: public:
KisChunkData(quint64 begin, quint64 size) KisChunkData(quint64 begin, quint64 size)
: m_begin(begin), m_end(begin + size - 1)
{ {
setChunk(begin, size);
}
inline void setChunk(quint64 begin, quint64 size) {
m_begin = begin;
m_end = begin + size - 1;
}
inline quint64 size() const {
return m_end - m_begin +1;
} }
bool operator== (const KisChunkData& other) const bool operator== (const KisChunkData& other) const
...@@ -88,14 +97,18 @@ public: ...@@ -88,14 +97,18 @@ public:
{ {
} }
inline quint64 begin() { inline quint64 begin() const {
return m_iterator->m_begin; return m_iterator->m_begin;
} }
inline quint64 end() { inline quint64 end() const {
return m_iterator->m_end; return m_iterator->m_end;
} }
inline quint64 size() const {
return m_iterator->size();
}
inline KisChunkDataListIterator position() { inline KisChunkDataListIterator position() {
return m_iterator; return m_iterator;
} }
......
/*
* Copyright (c) 2010 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_debug.h"
#include "kis_memory_window.h"
KisMemoryWindow::KisMemoryWindow(quint64 writeWindowSize)
: m_readWindowChunk(0,0), m_writeWindowChunk(0,0)
{
m_writeWindowSize = writeWindowSize;
m_readWindowSize = writeWindowSize / 4;
m_file.open();
m_readWindow = 0;
m_writeWindow = 0;
}
KisMemoryWindow::~KisMemoryWindow()
{
}
quint8* KisMemoryWindow::getReadChunkPtr(const KisChunkData &readChunk)
{
adjustWindow(readChunk, &m_readWindow, &m_readWindowChunk, m_readWindowSize);
return m_readWindow + (readChunk.m_begin - m_readWindowChunk.m_begin);
}
quint8* KisMemoryWindow::getWriteChunkPtr(const KisChunkData &writeChunk)
{
adjustWindow(writeChunk, &m_writeWindow, &m_writeWindowChunk, m_writeWindowSize);
return m_writeWindow + (writeChunk.m_begin - m_writeWindowChunk.m_begin);
}
void KisMemoryWindow::adjustWindow(const KisChunkData &requestedChunk,
quint8 **window,
KisChunkData *windowChunk,
quint64 windowSize)
{
if(!(*window) ||
!(requestedChunk.m_begin >= windowChunk->m_begin &&
requestedChunk.m_end <= windowChunk->m_end))
{
m_file.unmap(*window);
if(requestedChunk.size() > windowSize) {
qWarning() <<
"KisMemoryWindow: the requested chunk is too "
"big to fit into the mapping! "
"Adjusting mapping to avoid SIGSEGV...";
windowSize = requestedChunk.size();
}
windowChunk->setChunk(requestedChunk.m_begin, windowSize);
if(windowChunk->m_end >= (quint64)m_file.size()) {
// Align by 32 bytes
quint64 newSize = (windowChunk->m_end + 1 + 32) & (~31ULL);
m_file.resize(newSize);
}
#warning "A workaround for http://bugreports.qt.nokia.com/browse/QTBUG-6330"
m_file.exists();
*window = m_file.map(windowChunk->m_begin, windowChunk->size());
}
}
/*
* Copyright (c) 2010 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_MEMORY_WINDOW_H
#define __KIS_MEMORY_WINDOW_H
#include "krita_export.h"
#include <QTemporaryFile>
#include "kis_chunk_allocator.h"
#define MiB (1ULL << 20)
#define DEFAULT_WINDOW_SIZE 16*MiB
class KRITAIMAGE_EXPORT KisMemoryWindow
{
public:
KisMemoryWindow(quint64 writeWindowSize = DEFAULT_WINDOW_SIZE);
~KisMemoryWindow();
quint8* getReadChunkPtr(const KisChunkData &readChunk);
quint8* getWriteChunkPtr(const KisChunkData &writeChunk);
private:
void adjustWindow(const KisChunkData &requestedChunk, quint8 **window,
KisChunkData *windowChunk, quint64 windowSize);
private:
QTemporaryFile m_file;
KisChunkData m_readWindowChunk;
KisChunkData m_writeWindowChunk;
quint8 *m_readWindow;
quint8 *m_writeWindow;
quint64 m_readWindowSize;
quint64 m_writeWindowSize;
};
#endif /* __KIS_CHUNK_ALLOCATOR_H */
...@@ -31,3 +31,8 @@ target_link_libraries(KisMemoryPoolTest ${KDE4_KDEUI_LIBS} ${QT_QTTEST_LIBRARY} ...@@ -31,3 +31,8 @@ target_link_libraries(KisMemoryPoolTest ${KDE4_KDEUI_LIBS} ${QT_QTTEST_LIBRARY}
set(kis_chunk_allocator_test_SRCS kis_chunk_allocator_test.cpp ../swap/kis_chunk_allocator.cpp) set(kis_chunk_allocator_test_SRCS kis_chunk_allocator_test.cpp ../swap/kis_chunk_allocator.cpp)
kde4_add_unit_test(KisChunkAllocatorTest TESTNAME krita-image-KisChunkAllocatorTest ${kis_chunk_allocator_test_SRCS}) kde4_add_unit_test(KisChunkAllocatorTest TESTNAME krita-image-KisChunkAllocatorTest ${kis_chunk_allocator_test_SRCS})
target_link_libraries(KisChunkAllocatorTest ${KDE4_KDEUI_LIBS} ${QT_QTTEST_LIBRARY}) target_link_libraries(KisChunkAllocatorTest ${KDE4_KDEUI_LIBS} ${QT_QTTEST_LIBRARY})
########### next target ###############
set(kis_memory_window_test_SRCS kis_memory_window_test.cpp ../swap/kis_memory_window.cpp)
kde4_add_unit_test(KisMemoryWindowTest TESTNAME krita-image-KisMemoryWindowTest ${kis_memory_window_test_SRCS})
target_link_libraries(KisMemoryWindowTest ${KDE4_KDEUI_LIBS} ${QT_QTTEST_LIBRARY})
/*
* Copyright (c) 2010 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_memory_window_test.h"
#include <qtest_kde.h>
#include "kis_debug.h"
#include "tiles3/swap/kis_memory_window.h"
void KisMemoryWindowTest::testWindow()
{
KisMemoryWindow memory(1024);
quint8 oddValue = 0xee;
const quint8 chunkLength = 10;
quint8 oddBuf[chunkLength];
memset(oddBuf, oddValue, chunkLength);
KisChunkData chunk1(0, chunkLength);
KisChunkData chunk2(1025, chunkLength);
quint8 *ptr;
ptr = memory.getWriteChunkPtr(chunk1);
memcpy(ptr, oddBuf, chunkLength);
ptr = memory.getWriteChunkPtr(chunk2);
memcpy(ptr, oddBuf, chunkLength);
ptr = memory.getReadChunkPtr(chunk2);
QVERIFY(!memcmp(ptr, oddBuf, chunkLength));
ptr = memory.getWriteChunkPtr(chunk1);
QVERIFY(!memcmp(ptr, oddBuf, chunkLength));
}
QTEST_KDEMAIN(KisMemoryWindowTest, NoGUI)
#include "kis_memory_window_test.moc"
/*
* Copyright (c) 2010 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_MEMORY_WINDOW_TEST_H
#define KIS_MEMORY_WINDOW_TEST_H
#include <QtTest/QtTest>
class KisMemoryWindowTest : public QObject
{
Q_OBJECT
private slots:
void testWindow();
};
#endif /* KIS_MEMORY_WINDOW_TEST_H */
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