Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_memory_window.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2010 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_debug.h"
8#include "kis_memory_window.h"
9
10#include <QDir>
11
12#define SWP_PREFIX "KRITA_SWAP_FILE_XXXXXX"
13
14KisMemoryWindow::KisMemoryWindow(const QString &swapDir, quint64 writeWindowSize)
15 : m_readWindowEx(writeWindowSize / 4),
16 m_writeWindowEx(writeWindowSize)
17{
18 m_valid = true;
19
20 // swapDir will never be empty, as KisImageConfig::swapDir() always provides
21 // us with a (platform specific) default directory, even if none is explicitly
22 // configured by the user; also we do not want any logic that determines the
23 // default swap dir here.
24 KIS_SAFE_ASSERT_RECOVER_NOOP(!swapDir.isEmpty());
25
26 QDir d(swapDir);
27 if (!d.exists()) {
28 m_valid = d.mkpath(swapDir);
29 }
30
31 const QString swapFileTemplate = swapDir + '/' + SWP_PREFIX;
32
33 if (m_valid) {
34 m_file.setFileTemplate(swapFileTemplate);
35 bool res = m_file.open();
36 if (!res || m_file.fileName().isEmpty()) {
37 m_valid = false;
38 }
39 }
40
41 if (!m_valid) {
42 qWarning() << "Could not create or open swapfile; disabling swapfile" << swapFileTemplate;
43 }
44}
45
49
51{
52 if (!adjustWindow(readChunk, &m_readWindowEx, &m_writeWindowEx)) {
53 return nullptr;
54 }
55
56 return m_readWindowEx.calculatePointer(readChunk);
57}
58
60{
61 if (!adjustWindow(writeChunk, &m_writeWindowEx, &m_readWindowEx)) {
62 return nullptr;
63 }
64
65 return m_writeWindowEx.calculatePointer(writeChunk);
66}
67
69 MappingWindow *adjustingWindow,
70 MappingWindow *otherWindow)
71{
72 if(!(adjustingWindow->window) ||
73 !(requestedChunk.m_begin >= adjustingWindow->chunk.m_begin &&
74 requestedChunk.m_end <= adjustingWindow->chunk.m_end))
75 {
76 m_file.unmap(adjustingWindow->window);
77
78 quint64 windowSize = adjustingWindow->defaultSize;
79 if(requestedChunk.size() > windowSize) {
80 warnKrita <<
81 "KisMemoryWindow: the requested chunk is too "
82 "big to fit into the mapping! "
83 "Adjusting mapping to avoid SIGSEGV...";
84
85 windowSize = requestedChunk.size();
86 }
87
88 adjustingWindow->chunk.setChunk(requestedChunk.m_begin, windowSize);
89
90 if(adjustingWindow->chunk.m_end >= (quint64)m_file.size()) {
91 // Align by 32 bytes
92 quint64 newSize = (adjustingWindow->chunk.m_end + 1 + 32) & (~31ULL);
93
94#ifdef Q_OS_WIN32
105 if (otherWindow->chunk.size()) {
106 m_file.unmap(otherWindow->window);
107 }
108#else
109 Q_UNUSED(otherWindow);
110#endif
111
112 if (!m_file.resize(newSize)) {
113 return false;
114 }
115
116#ifdef Q_OS_WIN32
117 if (otherWindow->chunk.size()) {
118 otherWindow->window = m_file.map(otherWindow->chunk.m_begin,
119 otherWindow->chunk.size());
120 }
121#endif
122 }
123
124#ifdef Q_OS_UNIX
125 // A workaround for https://bugreports.qt-project.org/browse/QTBUG-6330
126 m_file.exists();
127#endif
128
129 adjustingWindow->window = m_file.map(adjustingWindow->chunk.m_begin,
130 adjustingWindow->chunk.size());
131
132 if (!adjustingWindow->window) {
133 return false;
134 }
135 }
136
137 return true;
138}
void setChunk(quint64 begin, quint64 size)
quint64 size() const
quint8 * getWriteChunkPtr(KisChunk writeChunk)
MappingWindow m_readWindowEx
quint8 * getReadChunkPtr(KisChunk readChunk)
bool adjustWindow(const KisChunkData &requestedChunk, MappingWindow *adjustingWindow, MappingWindow *otherWindow)
KisMemoryWindow(const QString &swapDir, quint64 writeWindowSize=DEFAULT_WINDOW_SIZE)
QTemporaryFile m_file
MappingWindow m_writeWindowEx
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
#define warnKrita
Definition kis_debug.h:87
#define SWP_PREFIX
quint8 * calculatePointer(const KisChunkData &other) const