2
* Copyright (c) 2010 Dmitry Kazakov <dimula73@gmail.com>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include "kis_texture_tile.h"
26
inline QRectF relativeRect(const QRect &br /* baseRect */,
27
const QRect &cr /* childRect */,
28
const KisGLTexturesInfo *texturesInfo)
30
const qreal x = qreal(cr.x() - br.x()) / texturesInfo->width;
31
const qreal y = qreal(cr.y() - br.y()) / texturesInfo->height;
32
const qreal w = qreal(cr.width()) / texturesInfo->width;
33
const qreal h = qreal(cr.height()) / texturesInfo->height;
35
return QRectF(x, y, w, h);
39
KisTextureTile::KisTextureTile(QRect imageRect, const KisGLTexturesInfo *texturesInfo,
40
const GLvoid *fillData)
42
: m_tileRectInImagePixels(imageRect), m_texturesInfo(texturesInfo)
44
m_textureRectInImagePixels =
45
stretchRect(m_tileRectInImagePixels, texturesInfo->border);
47
m_tileRectInTexturePixels = relativeRect(m_textureRectInImagePixels,
48
m_tileRectInImagePixels,
51
glGenTextures(1, &m_textureId);
52
glBindTexture(GL_TEXTURE_2D, m_textureId);
53
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
54
glTexImage2D(GL_TEXTURE_2D, 0,
55
m_texturesInfo->format,
56
m_texturesInfo->width,
57
m_texturesInfo->height, 0,
58
GL_BGRA, GL_UNSIGNED_BYTE, fillData);
61
KisTextureTile::~KisTextureTile() {
62
glDeleteTextures(1, &m_textureId);
65
void KisTextureTile::update(const KisTextureTileUpdateInfo &updateInfo) {
66
glBindTexture(GL_TEXTURE_2D, m_textureId);
67
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
69
if (updateInfo.isEntireTileUpdated()) {
71
glTexImage2D(GL_TEXTURE_2D, 0,
72
m_texturesInfo->format,
73
m_texturesInfo->width,
74
m_texturesInfo->height, 0,
75
GL_BGRA, m_texturesInfo->type,
78
QPoint patchOffset = updateInfo.patchOffset();
79
QSize patchSize = updateInfo.patchSize();
81
glTexSubImage2D(GL_TEXTURE_2D, 0,
82
patchOffset.x(), patchOffset.y(),
83
patchSize.width(), patchSize.height(),
84
GL_BGRA, m_texturesInfo->type,
89
* On the boundaries of KisImage, there is a border-effect as well.
90
* So we just repeat the bounding pixels of the image to make
91
* bilinear interpolator happy.
93
repeatStripes(updateInfo);
96
inline void KisTextureTile::repeatStripes(const KisTextureTileUpdateInfo &updateInfo) {
98
* WARN: This function can repeat stripes of 1px width only!
101
const int pixelSize = updateInfo.pixelSize();
102
const QRect imageRect = m_texturesInfo->imageRect;
103
const QPoint patchOffset = updateInfo.patchOffset();
104
const QSize patchSize = updateInfo.patchSize();
105
const QRect patchRect = QRect(m_textureRectInImagePixels.topLeft() +
109
if(imageRect.top() == patchRect.top()) {
110
glTexSubImage2D(GL_TEXTURE_2D, 0,
111
patchOffset.x(), patchOffset.y() - 1,
112
patchSize.width(), 1,
113
GL_BGRA, m_texturesInfo->type,
118
if(imageRect.bottom() == patchRect.bottom()) {
119
int shift = patchSize.width() * (patchSize.height() - 1) *
122
glTexSubImage2D(GL_TEXTURE_2D, 0,
123
patchOffset.x(), patchOffset.y() + patchSize.height(),
124
patchSize.width(), 1,
125
GL_BGRA, m_texturesInfo->type,
126
updateInfo.data() + shift);
130
if(imageRect.left() == patchRect.left()) {
131
QByteArray columnBuffer(patchSize.height() * pixelSize, 0);
133
quint8 *srcPtr = updateInfo.data();
134
quint8 *dstPtr = (quint8*) columnBuffer.data();
135
for(int i = 0; i < patchSize.height(); i++) {
136
memcpy(dstPtr, srcPtr, pixelSize);
138
srcPtr += patchSize.width() * pixelSize;
142
glTexSubImage2D(GL_TEXTURE_2D, 0,
143
patchOffset.x() - 1, patchOffset.y(),
144
1, patchSize.height(),
145
GL_BGRA, m_texturesInfo->type,
146
columnBuffer.constData());
149
if(imageRect.right() == patchRect.right()) {
150
QByteArray columnBuffer(patchSize.height() * pixelSize, 0);
152
quint8 *srcPtr = updateInfo.data() + (patchSize.width() - 1) * pixelSize;
153
quint8 *dstPtr = (quint8*) columnBuffer.data();
154
for(int i = 0; i < patchSize.height(); i++) {
155
memcpy(dstPtr, srcPtr, pixelSize);
157
srcPtr += patchSize.width() * pixelSize;
161
glTexSubImage2D(GL_TEXTURE_2D, 0,
162
patchOffset.x() + patchSize.width(), patchOffset.y(),
163
1, patchSize.height(),
164
GL_BGRA, m_texturesInfo->type,
165
columnBuffer.constData());
170
void KisTextureTile::drawPoints() {
172
* We create a float rect here to workaround Qt's
173
* "history reasons" in calculation of right()
174
* and bottom() coordinates of integer rects.
176
QRectF imageRect(m_tileRectInImagePixels);
182
ipt = imageRect.topLeft();
183
tpt = m_tileRectInTexturePixels.topLeft();
184
glTexCoord2f(tpt.x(), tpt.y());
185
glVertex2f(ipt.x(), ipt.y());
187
ipt = imageRect.topRight();
188
tpt = m_tileRectInTexturePixels.topRight();
189
glTexCoord2f(tpt.x(), tpt.y());
190
glVertex2f(ipt.x(), ipt.y());
192
ipt = imageRect.bottomRight();
193
tpt = m_tileRectInTexturePixels.bottomRight();
194
glTexCoord2f(tpt.x(), tpt.y());
195
glVertex2f(ipt.x(), ipt.y());
197
ipt = imageRect.bottomLeft();
198
tpt = m_tileRectInTexturePixels.bottomLeft();
199
glTexCoord2f(tpt.x(), tpt.y());
200
glVertex2f(ipt.x(), ipt.y());
206
#endif /* HAVE_OPENGL */