Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_texture_tile.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#define GL_GLEXT_PROTOTYPES
8#include "kis_texture_tile.h"
11
12#include <kis_debug.h>
13#if !defined(QT_OPENGL_ES)
14#include <QOpenGLBuffer>
15#endif
16
17#ifndef GL_BGRA
18#define GL_BGRA 0x814F
19#endif
20
21#ifndef GL_RGBA16_EXT
22#define GL_RGBA16_EXT 0x805B
23#endif
24
25
27{
28
29 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
30 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
31 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
32 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, m_numMipmapLevels);
33 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
34 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_numMipmapLevels);
35
36 if ((m_texturesInfo->internalFormat == GL_RGBA8 && m_texturesInfo->format == GL_RGBA)
37#ifndef QT_OPENGL_ES_2
38 || (m_texturesInfo->internalFormat == GL_RGBA16 && m_texturesInfo->format == GL_RGBA)
39#endif
41 ) {
42 // If image format is RGBA8, swap the red and blue channels for the proper color
43 // This is for OpenGL ES support and only used if lacking GL_EXT_texture_format_BGRA8888
44 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
45 f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
46 }
47
48 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
49}
50
52{
53 // QPainter::drawText relies on this.
54 // Ref: https://bugreports.qt.io/browse/QTBUG-65496
55 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
56}
57
58inline QRectF relativeRect(const QRect &br /* baseRect */,
59 const QRect &cr /* childRect */,
60 const KisGLTexturesInfo *texturesInfo)
61{
62 const qreal x = qreal(cr.x() - br.x()) / texturesInfo->width;
63 const qreal y = qreal(cr.y() - br.y()) / texturesInfo->height;
64 const qreal w = qreal(cr.width()) / texturesInfo->width;
65 const qreal h = qreal(cr.height()) / texturesInfo->height;
66
67 return QRectF(x, y, w, h);
68}
69
70#include "kis_debug.h"
71
72KisTextureTile::KisTextureTile(const QRect &imageRect, const KisGLTexturesInfo *texturesInfo,
73 const QByteArray &fillData, KisOpenGL::FilterMode filter,
74 KisOpenGLBufferCircularStorage *bufferStorage, int numMipmapLevels, QOpenGLFunctions *fcn)
75
76 : m_textureId(0)
77 , m_tileRectInImagePixels(imageRect)
78 , m_filter(filter)
79 , m_texturesInfo(texturesInfo)
80 , m_needsMipmapRegeneration(false)
81 , m_preparedLodPlane(0)
82 , m_numMipmapLevels(numMipmapLevels)
83 , f(fcn)
84 , m_bufferStorage(bufferStorage)
85{
86 const GLvoid *fd = fillData.constData();
87
90
94
95 f->glGenTextures(1, &m_textureId);
96 f->glBindTexture(GL_TEXTURE_2D, m_textureId);
97
99
102
103 f->glTexImage2D(GL_TEXTURE_2D, 0,
108 m_texturesInfo->type, fd);
109
111
113}
114
116{
117 f->glDeleteTextures(1, &m_textureId);
118}
119
120int KisTextureTile::bindToActiveTexture(bool blockMipmapRegeneration)
121{
122 f->glBindTexture(GL_TEXTURE_2D, m_textureId);
123
124 if (m_needsMipmapRegeneration && !blockMipmapRegeneration) {
127 }
128
129 return m_preparedLodPlane;
130}
131
140
146
148{
149 f->glGenerateMipmap(GL_TEXTURE_2D);
152}
153
154void KisTextureTile::update(const KisTextureTileUpdateInfo &updateInfo, bool blockMipmapRegeneration)
155{
156 f->initializeOpenGLFunctions();
157 f->glBindTexture(GL_TEXTURE_2D, m_textureId);
158
160
161 const int patchLevelOfDetail = updateInfo.patchLevelOfDetail();
162 const QSize patchSize = updateInfo.realPatchSize();
163 const QPoint patchOffset = updateInfo.realPatchOffset();
164
165 const GLvoid *fd = updateInfo.data();
166
195 if (!blockMipmapRegeneration &&
196 patchLevelOfDetail > 0 &&
198 !updateInfo.isEntireTileUpdated())
200
202 }
203
204
205 if (updateInfo.isEntireTileUpdated()) {
207 m_bufferStorage, &fd, updateInfo.patchPixelsLength());
208
209 f->glTexImage2D(GL_TEXTURE_2D, patchLevelOfDetail,
211 patchSize.width(),
212 patchSize.height(), 0,
215 fd);
216 }
217 else {
218 const int size = patchSize.width() * patchSize.height() * updateInfo.pixelSize();
220 m_bufferStorage, &fd, size);
221
222 f->glTexSubImage2D(GL_TEXTURE_2D, patchLevelOfDetail,
223 patchOffset.x(), patchOffset.y(),
224 patchSize.width(), patchSize.height(),
227 fd);
228
229 }
230
242 const int pixelSize = updateInfo.pixelSize();
243 const QSize tileSize = updateInfo.realTileSize();
244
245 if(updateInfo.isTopmost()) {
246 int start = 0;
247 int end = patchOffset.y() - 1;
248
249 const GLvoid *fd = updateInfo.data();
250 const int size = patchSize.width() * pixelSize;
252 m_bufferStorage, &fd, size);
253
254 for (int i = start; i <= end; i++) {
255 f->glTexSubImage2D(GL_TEXTURE_2D, patchLevelOfDetail,
256 patchOffset.x(), i,
257 patchSize.width(), 1,
260 fd);
261 }
262 }
263
264 if (updateInfo.isBottommost()) {
265 int shift = patchSize.width() * (patchSize.height() - 1) *
266 pixelSize;
267
268 int start = patchOffset.y() + patchSize.height();
269 int end = tileSize.height() - 1;
270
271 const GLvoid *fd = updateInfo.data() + shift;
272 const int size = patchSize.width() * pixelSize;
274 m_bufferStorage, &fd, size);
275
276 for (int i = start; i < end; i++) {
277 f->glTexSubImage2D(GL_TEXTURE_2D, patchLevelOfDetail,
278 patchOffset.x(), i,
279 patchSize.width(), 1,
282 fd);
283 }
284 }
285
286 if (updateInfo.isLeftmost()) {
287
288 QByteArray columnBuffer(patchSize.height() * pixelSize, 0);
289
290 quint8 *srcPtr = updateInfo.data();
291 quint8 *dstPtr = (quint8*) columnBuffer.data();
292 for(int i = 0; i < patchSize.height(); i++) {
293 memcpy(dstPtr, srcPtr, pixelSize);
294
295 srcPtr += patchSize.width() * pixelSize;
296 dstPtr += pixelSize;
297 }
298
299 int start = 0;
300 int end = patchOffset.x() - 1;
301
302 const GLvoid *fd = columnBuffer.constData();
303 const int size = columnBuffer.size();
305 m_bufferStorage, &fd, size);
306
307 for (int i = start; i <= end; i++) {
308 f->glTexSubImage2D(GL_TEXTURE_2D, patchLevelOfDetail,
309 i, patchOffset.y(),
310 1, patchSize.height(),
313 fd);
314 }
315 }
316
317 if (updateInfo.isRightmost()) {
318
319 QByteArray columnBuffer(patchSize.height() * pixelSize, 0);
320
321 quint8 *srcPtr = updateInfo.data() + (patchSize.width() - 1) * pixelSize;
322 quint8 *dstPtr = (quint8*) columnBuffer.data();
323 for(int i = 0; i < patchSize.height(); i++) {
324 memcpy(dstPtr, srcPtr, pixelSize);
325
326 srcPtr += patchSize.width() * pixelSize;
327 dstPtr += pixelSize;
328 }
329
330 int start = patchOffset.x() + patchSize.width();
331 int end = tileSize.width() - 1;
332
333 const GLvoid *fd = columnBuffer.constData();
334 const int size = columnBuffer.size();
336 m_bufferStorage, &fd, size);
337
338 for (int i = start; i <= end; i++) {
339 f->glTexSubImage2D(GL_TEXTURE_2D, patchLevelOfDetail,
340 i, patchOffset.y(),
341 1, patchSize.height(),
344 fd);
345 }
346 }
347
350 // if (!updateInfo.isEntireTileUpdated() &&
351 // !(!patchLevelOfDetail || !m_preparedLodPlane || patchLevelOfDetail == m_preparedLodPlane)) {
352 // qDebug() << "WARNING: LodN switch is requested for the partial tile update!. Flickering is possible..." << ppVar(patchSize);
353 // qDebug() << " " << ppVar(m_preparedLodPlane);
354 // qDebug() << " " << ppVar(patchLevelOfDetail);
355 // }
356
358
359 if (!patchLevelOfDetail) {
370 } else {
372 }
373 } else {
374 setPreparedLodPlane(patchLevelOfDetail);
375 }
376}
377
378QRectF KisTextureTile::imageRectInTexturePixels(const QRect &imageRect) const
379{
381 imageRect,
383
384}
@ NearestFilterMode
Definition kis_opengl.h:34
@ HighQualityFiltering
Definition kis_opengl.h:37
@ BilinearFilterMode
Definition kis_opengl.h:35
@ TrilinearFilterMode
Definition kis_opengl.h:36
QRect m_textureRectInImagePixels
const KisGLTexturesInfo * m_texturesInfo
QOpenGLFunctions * f
void restoreTextureParameters()
QRectF m_tileRectInTexturePixels
void setPreparedLodPlane(int lod)
KisOpenGL::FilterMode m_filter
KisTextureTile(const QRect &imageRect, const KisGLTexturesInfo *texturesInfo, const QByteArray &fillData, KisOpenGL::FilterMode mode, KisOpenGLBufferCircularStorage *bufferStorage, int numMipmapLevels, QOpenGLFunctions *f)
void update(const KisTextureTileUpdateInfo &updateInfo, bool blockMipmapRegeneration)
void setNeedsMipmapRegeneration()
int bindToActiveTexture(bool blockMipmapRegeneration)
QRect m_tileRectInImagePixels
KisOpenGLBufferCircularStorage * m_bufferStorage
QRectF imageRectInTexturePixels(const QRect &imageRect) const
T kisGrowRect(const T &rect, U offset)
Definition kis_global.h:186
void fillData(KisPaintDeviceSP pd, int w, int h, QDataStream &stream)
#define GL_RGBA16_EXT
#define GL_CLAMP_TO_EDGE
QRectF relativeRect(const QRect &br, const QRect &cr, const KisGLTexturesInfo *texturesInfo)