Krita Source Code Documentation
Loading...
Searching...
No Matches
KisOpenGLUpdateInfoBuilder.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2018 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
7
8// TODO: conversion options into a separate file!
9#include "kis_update_info.h"
11
13
14#include <QReadWriteLock>
15#include <QReadLocker>
16#include <QWriteLocker>
17
18
19struct KRITAUI_NO_EXPORT KisOpenGLUpdateInfoBuilder::Private
20{
22
23 QBitArray channelFlags;
24 bool onlyOneChannelSelected = false;
25 int selectedChannelIndex = -1;
26
27 int textureBorder = 0;
29
31 QScopedPointer<KoColorConversionTransformation> proofingTransform;
32
34 QReadWriteLock lock;
35};
36
37
42
46
48{
49 return buildUpdateInfo(rect, srcImage->projection(), srcImage->bounds(), srcImage->currentLevelOfDetail(), convertColorSpace);
50}
51
52KisOpenGLUpdateInfoSP KisOpenGLUpdateInfoBuilder::buildUpdateInfo(const QRect &rect, KisPaintDeviceSP projection, const QRect &bounds, int levelOfDetail, bool convertColorSpace)
53{
55
56 QRect updateRect = rect & bounds;
57 if (updateRect.isEmpty()) return info;
58
60 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_d->conversionOptions.m_destinationColorSpace, info);
61
62 auto needCreateProofingTransform =
63 [this] () {
64 return !m_d->proofingTransform &&
65 m_d->proofingConfig &&
66 m_d->proofingConfig->displayFlags.testFlag(KoColorConversionTransformation::SoftProofing);
67 };
68
69 // lazily create transform
70 if (convertColorSpace && needCreateProofingTransform()) {
71
72 QWriteLocker locker(&m_d->lock);
73 if (needCreateProofingTransform()) {
74 const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(m_d->proofingConfig->proofingModel,
75 m_d->proofingConfig->proofingDepth,
76 m_d->proofingConfig->proofingProfile);
77 KoColorConversionTransformation::Intent displayIntent = m_d->proofingConfig->determineDisplayIntent(m_d->conversionOptions.m_renderingIntent);
78 KoColorConversionTransformation::ConversionFlags displayFlags = m_d->proofingConfig->determineDisplayFlags(m_d->conversionOptions.m_conversionFlags);
79
81 projection->colorSpace(),
82 m_d->conversionOptions.m_destinationColorSpace,
83 proofingSpace,
84 m_d->proofingConfig->conversionIntent,
85 displayIntent,
86 m_d->proofingConfig->useBlackPointCompensationFirstTransform,
87 m_d->proofingConfig->warningColor,
88 displayFlags));
89 }
90 }
91
92 QReadLocker locker(&m_d->lock);
93
103 QRect artificialRect = kisGrowRect(updateRect, m_d->textureBorder);
104 artificialRect &= bounds;
105
106 int firstColumn = xToCol(artificialRect.left());
107 int lastColumn = xToCol(artificialRect.right());
108 int firstRow = yToRow(artificialRect.top());
109 int lastRow = yToRow(artificialRect.bottom());
110
111 QBitArray channelFlags; // empty by default
112
113 if (!m_d->channelFlags.isEmpty() &&
114 m_d->channelFlags.size() == projection->colorSpace()->channelCount()) {
115
116 channelFlags = m_d->channelFlags;
117 }
118
119 qint32 numItems = (lastColumn - firstColumn + 1) * (lastRow - firstRow + 1);
120 info->tileList.reserve(numItems);
121
122 QRect alignedUpdateRect = updateRect;
123 QRect alignedBounds = bounds;
124
125 if (levelOfDetail) {
126 alignedUpdateRect = KisLodTransform::alignedRect(alignedUpdateRect, levelOfDetail);
127 alignedBounds = KisLodTransform::alignedRect(alignedBounds, levelOfDetail);
128 }
129
130 for (int col = firstColumn; col <= lastColumn; col++) {
131 for (int row = firstRow; row <= lastRow; row++) {
132
133 const QRect alignedTileTextureRect = calculatePhysicalTileRect(col, row, bounds, levelOfDetail);
134
136 new KisTextureTileUpdateInfo(col, row,
137 alignedTileTextureRect,
138 alignedUpdateRect,
139 alignedBounds,
140 levelOfDetail,
141 m_d->pool));
142 // Don't update empty tiles
143 if (tileInfo->valid()) {
144 tileInfo->retrieveData(projection, channelFlags, m_d->onlyOneChannelSelected, m_d->selectedChannelIndex);
145
146 if (convertColorSpace) {
147 if (m_d->proofingTransform) {
148 tileInfo->proofTo(m_d->conversionOptions.m_destinationColorSpace, m_d->proofingConfig->displayFlags, m_d->proofingTransform.data());
149 } else {
150 tileInfo->convertTo(m_d->conversionOptions.m_destinationColorSpace, m_d->conversionOptions.m_renderingIntent, m_d->conversionOptions.m_conversionFlags);
151 }
152 }
153
154 info->tileList.append(tileInfo);
155 }
156 else {
157 dbgUI << "Trying to create an empty tileinfo record" << col << row << alignedTileTextureRect << updateRect << bounds;
158 }
159 }
160 }
161
163 info->assignLevelOfDetail(levelOfDetail);
164 return info;
165}
166
167QRect KisOpenGLUpdateInfoBuilder::calculateEffectiveTileRect(int col, int row, const QRect &imageBounds) const
168{
169 return imageBounds &
170 QRect(col * m_d->effectiveTextureSize.width(),
171 row * m_d->effectiveTextureSize.height(),
172 m_d->effectiveTextureSize.width(),
173 m_d->effectiveTextureSize.height());
174}
175
176QRect KisOpenGLUpdateInfoBuilder::calculatePhysicalTileRect(int col, int row, const QRect &imageBounds, int levelOfDetail) const
177{
178 const QRect tileRect = calculateEffectiveTileRect(col, row, imageBounds);
179 const QRect tileTextureRect = kisGrowRect(tileRect, m_d->textureBorder);
180
181 const QRect alignedTileTextureRect = levelOfDetail ?
182 KisLodTransform::alignedRect(tileTextureRect, levelOfDetail) :
183 tileTextureRect;
184
185 return alignedTileTextureRect;
186}
187
188
190{
191 return x / m_d->effectiveTextureSize.width();
192}
193
195{
196 return y / m_d->effectiveTextureSize.height();
197}
198
200{
201 QReadLocker lock(&m_d->lock);
202
203 return m_d->conversionOptions.m_destinationColorSpace;
204}
205
207{
208 QWriteLocker lock(&m_d->lock);
209
210 m_d->conversionOptions = options;
211 // the proofing transform becomes invalid when the target colorspace changes
212 m_d->proofingTransform.reset();
213}
214
215void KisOpenGLUpdateInfoBuilder::setChannelFlags(const QBitArray &channelFrags, bool onlyOneChannelSelected, int selectedChannelIndex)
216{
217 QWriteLocker lock(&m_d->lock);
218
219 m_d->channelFlags = channelFrags;
220 m_d->onlyOneChannelSelected = onlyOneChannelSelected;
221 m_d->selectedChannelIndex = selectedChannelIndex;
222}
223
225{
226 QWriteLocker lock(&m_d->lock);
227
228 m_d->textureBorder = value;
229}
230
232{
233 QWriteLocker lock(&m_d->lock);
234
235 m_d->effectiveTextureSize = size;
236}
237
239{
240 QWriteLocker lock(&m_d->lock);
241
242 m_d->pool = pool;
243}
244
246{
247 QReadLocker lock(&m_d->lock);
248 return m_d->pool;
249}
250
252{
253 QWriteLocker lock(&m_d->lock);
254
255 m_d->proofingConfig = config;
256 m_d->proofingTransform.reset();
257}
258
260{
261 QReadLocker lock(&m_d->lock);
262
263 return m_d->proofingConfig;
264}
float value(const T *src, size_t ch)
KisPaintDeviceSP projection() const
int currentLevelOfDetail() const
QRect bounds() const override
static QRect alignedRect(const QRect &srcRect, int lod)
KisTextureTileUpdateInfoSPList tileList
void assignLevelOfDetail(int lod)
void assignDirtyImageRect(const QRect &rect)
const KoColorSpace * colorSpace() const
static KoColorConversionTransformation * generateProofingTransform(const KoColorSpace *srcCS, const KoColorSpace *dstCS, const KoColorSpace *proofingSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::Intent proofingIntent, bool bpcFirstTransform, KoColor gamutWarning, KoColorConversionTransformation::ConversionFlags displayConversionFlags)
virtual quint32 channelCount() const =0
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define bounds(x, a, b)
#define dbgUI
Definition kis_debug.h:52
T kisGrowRect(const T &rect, U offset)
Definition kis_global.h:186
const QScopedPointer< Private > m_d
void setChannelFlags(const QBitArray &channelFrags, bool onlyOneChannelSelected, int selectedChannelIndex)
QRect calculateEffectiveTileRect(int col, int row, const QRect &imageBounds) const
KisOpenGLUpdateInfoSP buildUpdateInfo(const QRect &rect, KisImageSP srcImage, bool convertColorSpace)
void setProofingConfig(KisProofingConfigurationSP config)
void setConversionOptions(const ConversionOptions &options)
const KoColorSpace * destinationColorSpace() const
void setEffectiveTextureSize(const QSize &size)
KisTextureTileInfoPoolSP textureInfoPool() const
QRect calculatePhysicalTileRect(int col, int row, const QRect &imageBounds, int levelOfDetail) const
QScopedPointer< KoColorConversionTransformation > proofingTransform
KisProofingConfigurationSP proofingConfig
void setTextureInfoPool(KisTextureTileInfoPoolSP pool)
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()