Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/gui/opengl/qopengltextureglyphcache.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||||||||
2 | ** | - | ||||||||||||
3 | ** Copyright (C) 2015 The Qt Company Ltd. | - | ||||||||||||
4 | ** Contact: http://www.qt.io/licensing/ | - | ||||||||||||
5 | ** | - | ||||||||||||
6 | ** This file is part of the QtGui module of the Qt Toolkit. | - | ||||||||||||
7 | ** | - | ||||||||||||
8 | ** $QT_BEGIN_LICENSE:LGPL21$ | - | ||||||||||||
9 | ** Commercial License Usage | - | ||||||||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||
14 | ** and conditions see http://www.qt.io/terms-conditions. For further | - | ||||||||||||
15 | ** information use the contact form at http://www.qt.io/contact-us. | - | ||||||||||||
16 | ** | - | ||||||||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||
19 | ** General Public License version 2.1 or version 3 as published by the Free | - | ||||||||||||
20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and | - | ||||||||||||
21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the | - | ||||||||||||
22 | ** following information to ensure the GNU Lesser General Public License | - | ||||||||||||
23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and | - | ||||||||||||
24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - | ||||||||||||
25 | ** | - | ||||||||||||
26 | ** As a special exception, The Qt Company gives you certain additional | - | ||||||||||||
27 | ** rights. These rights are described in The Qt Company LGPL Exception | - | ||||||||||||
28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - | ||||||||||||
29 | ** | - | ||||||||||||
30 | ** $QT_END_LICENSE$ | - | ||||||||||||
31 | ** | - | ||||||||||||
32 | ****************************************************************************/ | - | ||||||||||||
33 | - | |||||||||||||
34 | #include "qopengltextureglyphcache_p.h" | - | ||||||||||||
35 | #include "qopenglpaintengine_p.h" | - | ||||||||||||
36 | #include "private/qopenglengineshadersource_p.h" | - | ||||||||||||
37 | #include "qopenglextensions_p.h" | - | ||||||||||||
38 | #include <qrgb.h> | - | ||||||||||||
39 | #include <private/qdrawhelper_p.h> | - | ||||||||||||
40 | - | |||||||||||||
41 | QT_BEGIN_NAMESPACE | - | ||||||||||||
42 | - | |||||||||||||
43 | - | |||||||||||||
44 | QBasicAtomicInt qopengltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); | - | ||||||||||||
45 | - | |||||||||||||
46 | QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) | - | ||||||||||||
47 | : QImageTextureGlyphCache(format, matrix) | - | ||||||||||||
48 | , m_textureResource(0) | - | ||||||||||||
49 | , pex(0) | - | ||||||||||||
50 | , m_blitProgram(0) | - | ||||||||||||
51 | , m_filterMode(Nearest) | - | ||||||||||||
52 | , m_serialNumber(qopengltextureglyphcache_serial_number.fetchAndAddRelaxed(1)) | - | ||||||||||||
53 | , m_buffer(QOpenGLBuffer::VertexBuffer) | - | ||||||||||||
54 | { | - | ||||||||||||
55 | #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG | - | ||||||||||||
56 | qDebug(" -> QOpenGLTextureGlyphCache() %p for context %p.", this, QOpenGLContext::currentContext()); | - | ||||||||||||
57 | #endif | - | ||||||||||||
58 | m_vertexCoordinateArray[0] = -1.0f; | - | ||||||||||||
59 | m_vertexCoordinateArray[1] = -1.0f; | - | ||||||||||||
60 | m_vertexCoordinateArray[2] = 1.0f; | - | ||||||||||||
61 | m_vertexCoordinateArray[3] = -1.0f; | - | ||||||||||||
62 | m_vertexCoordinateArray[4] = 1.0f; | - | ||||||||||||
63 | m_vertexCoordinateArray[5] = 1.0f; | - | ||||||||||||
64 | m_vertexCoordinateArray[6] = -1.0f; | - | ||||||||||||
65 | m_vertexCoordinateArray[7] = 1.0f; | - | ||||||||||||
66 | - | |||||||||||||
67 | m_textureCoordinateArray[0] = 0.0f; | - | ||||||||||||
68 | m_textureCoordinateArray[1] = 0.0f; | - | ||||||||||||
69 | m_textureCoordinateArray[2] = 1.0f; | - | ||||||||||||
70 | m_textureCoordinateArray[3] = 0.0f; | - | ||||||||||||
71 | m_textureCoordinateArray[4] = 1.0f; | - | ||||||||||||
72 | m_textureCoordinateArray[5] = 1.0f; | - | ||||||||||||
73 | m_textureCoordinateArray[6] = 0.0f; | - | ||||||||||||
74 | m_textureCoordinateArray[7] = 1.0f; | - | ||||||||||||
75 | } never executed: end of block | 0 | ||||||||||||
76 | - | |||||||||||||
77 | QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache() | - | ||||||||||||
78 | { | - | ||||||||||||
79 | #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG | - | ||||||||||||
80 | qDebug(" -> ~QOpenGLTextureGlyphCache() %p.", this); | - | ||||||||||||
81 | #endif | - | ||||||||||||
82 | clear(); | - | ||||||||||||
83 | } never executed: end of block | 0 | ||||||||||||
84 | - | |||||||||||||
85 | #if !defined(QT_OPENGL_ES_2) | - | ||||||||||||
86 | static inline bool isCoreProfile() | - | ||||||||||||
87 | { | - | ||||||||||||
88 | return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile; never executed: return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile; | 0 | ||||||||||||
89 | } | - | ||||||||||||
90 | #endif | - | ||||||||||||
91 | - | |||||||||||||
92 | void QOpenGLTextureGlyphCache::createTextureData(int width, int height) | - | ||||||||||||
93 | { | - | ||||||||||||
94 | QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); | - | ||||||||||||
95 | if (ctx == 0) {
| 0 | ||||||||||||
96 | qWarning("QOpenGLTextureGlyphCache::createTextureData: Called with no context"); | - | ||||||||||||
97 | return; never executed: return; | 0 | ||||||||||||
98 | } | - | ||||||||||||
99 | - | |||||||||||||
100 | // create in QImageTextureGlyphCache baseclass is meant to be called | - | ||||||||||||
101 | // only to create the initial image and does not preserve the content, | - | ||||||||||||
102 | // so we don't call when this function is called from resize. | - | ||||||||||||
103 | if (ctx->d_func()->workaround_brokenFBOReadBack && image().isNull())
| 0 | ||||||||||||
104 | QImageTextureGlyphCache::createTextureData(width, height); never executed: QImageTextureGlyphCache::createTextureData(width, height); | 0 | ||||||||||||
105 | - | |||||||||||||
106 | // Make the lower glyph texture size 16 x 16. | - | ||||||||||||
107 | if (width < 16)
| 0 | ||||||||||||
108 | width = 16; never executed: width = 16; | 0 | ||||||||||||
109 | if (height < 16)
| 0 | ||||||||||||
110 | height = 16; never executed: height = 16; | 0 | ||||||||||||
111 | - | |||||||||||||
112 | if (m_textureResource && !m_textureResource->m_texture) {
| 0 | ||||||||||||
113 | delete m_textureResource; | - | ||||||||||||
114 | m_textureResource = 0; | - | ||||||||||||
115 | } never executed: end of block | 0 | ||||||||||||
116 | - | |||||||||||||
117 | if (!m_textureResource)
| 0 | ||||||||||||
118 | m_textureResource = new QOpenGLGlyphTexture(ctx); never executed: m_textureResource = new QOpenGLGlyphTexture(ctx); | 0 | ||||||||||||
119 | - | |||||||||||||
120 | QOpenGLFunctions *funcs = ctx->functions(); | - | ||||||||||||
121 | funcs->glGenTextures(1, &m_textureResource->m_texture); | - | ||||||||||||
122 | funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); | - | ||||||||||||
123 | - | |||||||||||||
124 | m_textureResource->m_width = width; | - | ||||||||||||
125 | m_textureResource->m_height = height; | - | ||||||||||||
126 | - | |||||||||||||
127 | if (m_format == QFontEngine::Format_A32 || m_format == QFontEngine::Format_ARGB) {
| 0 | ||||||||||||
128 | QVarLengthArray<uchar> data(width * height * 4); | - | ||||||||||||
129 | for (int i = 0; i < data.size(); ++i)
| 0 | ||||||||||||
130 | data[i] = 0; never executed: data[i] = 0; | 0 | ||||||||||||
131 | funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); | - | ||||||||||||
132 | } else { never executed: end of block | 0 | ||||||||||||
133 | QVarLengthArray<uchar> data(width * height); | - | ||||||||||||
134 | for (int i = 0; i < data.size(); ++i)
| 0 | ||||||||||||
135 | data[i] = 0; never executed: data[i] = 0; | 0 | ||||||||||||
136 | #if !defined(QT_OPENGL_ES_2) | - | ||||||||||||
137 | const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA;
| 0 | ||||||||||||
138 | const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
| 0 | ||||||||||||
139 | #else | - | ||||||||||||
140 | const GLint internalFormat = GL_ALPHA; | - | ||||||||||||
141 | const GLenum format = GL_ALPHA; | - | ||||||||||||
142 | #endif | - | ||||||||||||
143 | funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, &data[0]); | - | ||||||||||||
144 | } never executed: end of block | 0 | ||||||||||||
145 | - | |||||||||||||
146 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | - | ||||||||||||
147 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | - | ||||||||||||
148 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | - | ||||||||||||
149 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | - | ||||||||||||
150 | m_filterMode = Nearest; | - | ||||||||||||
151 | - | |||||||||||||
152 | if (!m_buffer.isCreated()) {
| 0 | ||||||||||||
153 | m_buffer.create(); | - | ||||||||||||
154 | m_buffer.bind(); | - | ||||||||||||
155 | static GLfloat buf[sizeof(m_vertexCoordinateArray) + sizeof(m_textureCoordinateArray)]; | - | ||||||||||||
156 | memcpy(buf, m_vertexCoordinateArray, sizeof(m_vertexCoordinateArray)); | - | ||||||||||||
157 | memcpy(buf + (sizeof(m_vertexCoordinateArray) / sizeof(GLfloat)), | - | ||||||||||||
158 | m_textureCoordinateArray, | - | ||||||||||||
159 | sizeof(m_textureCoordinateArray)); | - | ||||||||||||
160 | m_buffer.allocate(buf, sizeof(buf)); | - | ||||||||||||
161 | m_buffer.release(); | - | ||||||||||||
162 | } never executed: end of block | 0 | ||||||||||||
163 | - | |||||||||||||
164 | if (!m_vao.isCreated())
| 0 | ||||||||||||
165 | m_vao.create(); never executed: m_vao.create(); | 0 | ||||||||||||
166 | } never executed: end of block | 0 | ||||||||||||
167 | - | |||||||||||||
168 | void QOpenGLTextureGlyphCache::setupVertexAttribs() | - | ||||||||||||
169 | { | - | ||||||||||||
170 | m_buffer.bind(); | - | ||||||||||||
171 | m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), GL_FLOAT, 0, 2); | - | ||||||||||||
172 | m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), GL_FLOAT, sizeof(m_vertexCoordinateArray), 2); | - | ||||||||||||
173 | m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); | - | ||||||||||||
174 | m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); | - | ||||||||||||
175 | m_buffer.release(); | - | ||||||||||||
176 | } never executed: end of block | 0 | ||||||||||||
177 | - | |||||||||||||
178 | void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) | - | ||||||||||||
179 | { | - | ||||||||||||
180 | QOpenGLContext *ctx = QOpenGLContext::currentContext(); | - | ||||||||||||
181 | if (ctx == 0) {
| 0 | ||||||||||||
182 | qWarning("QOpenGLTextureGlyphCache::resizeTextureData: Called with no context"); | - | ||||||||||||
183 | return; never executed: return; | 0 | ||||||||||||
184 | } | - | ||||||||||||
185 | - | |||||||||||||
186 | QOpenGLFunctions *funcs = ctx->functions(); | - | ||||||||||||
187 | GLint oldFbo; | - | ||||||||||||
188 | funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFbo); | - | ||||||||||||
189 | - | |||||||||||||
190 | int oldWidth = m_textureResource->m_width; | - | ||||||||||||
191 | int oldHeight = m_textureResource->m_height; | - | ||||||||||||
192 | - | |||||||||||||
193 | // Make the lower glyph texture size 16 x 16. | - | ||||||||||||
194 | if (width < 16)
| 0 | ||||||||||||
195 | width = 16; never executed: width = 16; | 0 | ||||||||||||
196 | if (height < 16)
| 0 | ||||||||||||
197 | height = 16; never executed: height = 16; | 0 | ||||||||||||
198 | - | |||||||||||||
199 | GLuint oldTexture = m_textureResource->m_texture; | - | ||||||||||||
200 | createTextureData(width, height); | - | ||||||||||||
201 | - | |||||||||||||
202 | if (ctx->d_func()->workaround_brokenFBOReadBack) {
| 0 | ||||||||||||
203 | QImageTextureGlyphCache::resizeTextureData(width, height); | - | ||||||||||||
204 | Q_ASSERT(image().depth() == 8); | - | ||||||||||||
205 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); | - | ||||||||||||
206 | funcs->glDeleteTextures(1, &oldTexture); | - | ||||||||||||
207 | return; never executed: return; | 0 | ||||||||||||
208 | } | - | ||||||||||||
209 | - | |||||||||||||
210 | // ### the QTextureGlyphCache API needs to be reworked to allow | - | ||||||||||||
211 | // ### resizeTextureData to fail | - | ||||||||||||
212 | - | |||||||||||||
213 | funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo); | - | ||||||||||||
214 | - | |||||||||||||
215 | GLuint tmp_texture; | - | ||||||||||||
216 | funcs->glGenTextures(1, &tmp_texture); | - | ||||||||||||
217 | funcs->glBindTexture(GL_TEXTURE_2D, tmp_texture); | - | ||||||||||||
218 | funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, | - | ||||||||||||
219 | GL_RGBA, GL_UNSIGNED_BYTE, NULL); | - | ||||||||||||
220 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | - | ||||||||||||
221 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | - | ||||||||||||
222 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | - | ||||||||||||
223 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | - | ||||||||||||
224 | m_filterMode = Nearest; | - | ||||||||||||
225 | funcs->glBindTexture(GL_TEXTURE_2D, 0); | - | ||||||||||||
226 | funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | - | ||||||||||||
227 | GL_TEXTURE_2D, tmp_texture, 0); | - | ||||||||||||
228 | - | |||||||||||||
229 | funcs->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); | - | ||||||||||||
230 | funcs->glBindTexture(GL_TEXTURE_2D, oldTexture); | - | ||||||||||||
231 | - | |||||||||||||
232 | if (pex != 0)
| 0 | ||||||||||||
233 | pex->transferMode(BrushDrawingMode); never executed: pex->transferMode(BrushDrawingMode); | 0 | ||||||||||||
234 | - | |||||||||||||
235 | funcs->glDisable(GL_STENCIL_TEST); | - | ||||||||||||
236 | funcs->glDisable(GL_DEPTH_TEST); | - | ||||||||||||
237 | funcs->glDisable(GL_SCISSOR_TEST); | - | ||||||||||||
238 | funcs->glDisable(GL_BLEND); | - | ||||||||||||
239 | - | |||||||||||||
240 | funcs->glViewport(0, 0, oldWidth, oldHeight); | - | ||||||||||||
241 | - | |||||||||||||
242 | QOpenGLShaderProgram *blitProgram = 0; | - | ||||||||||||
243 | if (pex == 0) {
| 0 | ||||||||||||
244 | if (m_blitProgram == 0) {
| 0 | ||||||||||||
245 | m_blitProgram = new QOpenGLShaderProgram; | - | ||||||||||||
246 | const bool isCoreProfile = ctx->format().profile() == QSurfaceFormat::CoreProfile; | - | ||||||||||||
247 | - | |||||||||||||
248 | { | - | ||||||||||||
249 | QString source; | - | ||||||||||||
250 | source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader)); | - | ||||||||||||
251 | source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader)); | - | ||||||||||||
252 | - | |||||||||||||
253 | QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram); | - | ||||||||||||
254 | vertexShader->compileSourceCode(source); | - | ||||||||||||
255 | - | |||||||||||||
256 | m_blitProgram->addShader(vertexShader); | - | ||||||||||||
257 | } | - | ||||||||||||
258 | - | |||||||||||||
259 | { | - | ||||||||||||
260 | QString source; | - | ||||||||||||
261 | source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader)); | - | ||||||||||||
262 | source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader)); | - | ||||||||||||
263 | - | |||||||||||||
264 | QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram); | - | ||||||||||||
265 | fragmentShader->compileSourceCode(source); | - | ||||||||||||
266 | - | |||||||||||||
267 | m_blitProgram->addShader(fragmentShader); | - | ||||||||||||
268 | } | - | ||||||||||||
269 | - | |||||||||||||
270 | m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); | - | ||||||||||||
271 | m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); | - | ||||||||||||
272 | - | |||||||||||||
273 | m_blitProgram->link(); | - | ||||||||||||
274 | - | |||||||||||||
275 | if (m_vao.isCreated()) {
| 0 | ||||||||||||
276 | m_vao.bind(); | - | ||||||||||||
277 | setupVertexAttribs(); | - | ||||||||||||
278 | } never executed: end of block | 0 | ||||||||||||
279 | } never executed: end of block | 0 | ||||||||||||
280 | - | |||||||||||||
281 | if (m_vao.isCreated())
| 0 | ||||||||||||
282 | m_vao.bind(); never executed: m_vao.bind(); | 0 | ||||||||||||
283 | else | - | ||||||||||||
284 | setupVertexAttribs(); never executed: setupVertexAttribs(); | 0 | ||||||||||||
285 | - | |||||||||||||
286 | m_blitProgram->bind(); | - | ||||||||||||
287 | blitProgram = m_blitProgram; | - | ||||||||||||
288 | - | |||||||||||||
289 | } else { never executed: end of block | 0 | ||||||||||||
290 | pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, m_vertexCoordinateArray); | - | ||||||||||||
291 | pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, m_textureCoordinateArray); | - | ||||||||||||
292 | - | |||||||||||||
293 | pex->shaderManager->useBlitProgram(); | - | ||||||||||||
294 | blitProgram = pex->shaderManager->blitProgram(); | - | ||||||||||||
295 | } never executed: end of block | 0 | ||||||||||||
296 | - | |||||||||||||
297 | blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); | - | ||||||||||||
298 | - | |||||||||||||
299 | funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); | - | ||||||||||||
300 | - | |||||||||||||
301 | funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); | - | ||||||||||||
302 | - | |||||||||||||
303 | funcs->glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); | - | ||||||||||||
304 | - | |||||||||||||
305 | funcs->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | - | ||||||||||||
306 | GL_RENDERBUFFER, 0); | - | ||||||||||||
307 | funcs->glDeleteTextures(1, &tmp_texture); | - | ||||||||||||
308 | funcs->glDeleteTextures(1, &oldTexture); | - | ||||||||||||
309 | - | |||||||||||||
310 | funcs->glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)oldFbo); | - | ||||||||||||
311 | - | |||||||||||||
312 | if (pex != 0) {
| 0 | ||||||||||||
313 | funcs->glViewport(0, 0, pex->width, pex->height); | - | ||||||||||||
314 | pex->updateClipScissorTest(); | - | ||||||||||||
315 | } else { never executed: end of block | 0 | ||||||||||||
316 | if (m_vao.isCreated()) {
| 0 | ||||||||||||
317 | m_vao.release(); | - | ||||||||||||
318 | } else { never executed: end of block | 0 | ||||||||||||
319 | m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); | - | ||||||||||||
320 | m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); | - | ||||||||||||
321 | } never executed: end of block | 0 | ||||||||||||
322 | } | - | ||||||||||||
323 | } | - | ||||||||||||
324 | - | |||||||||||||
325 | void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) | - | ||||||||||||
326 | { | - | ||||||||||||
327 | QOpenGLContext *ctx = QOpenGLContext::currentContext(); | - | ||||||||||||
328 | if (ctx == 0) {
| 0 | ||||||||||||
329 | qWarning("QOpenGLTextureGlyphCache::fillTexture: Called with no context"); | - | ||||||||||||
330 | return; never executed: return; | 0 | ||||||||||||
331 | } | - | ||||||||||||
332 | - | |||||||||||||
333 | QOpenGLFunctions *funcs = ctx->functions(); | - | ||||||||||||
334 | if (ctx->d_func()->workaround_brokenFBOReadBack) {
| 0 | ||||||||||||
335 | QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition); | - | ||||||||||||
336 | - | |||||||||||||
337 | funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); | - | ||||||||||||
338 | const QImage &texture = image(); | - | ||||||||||||
339 | const uchar *bits = texture.constBits(); | - | ||||||||||||
340 | bits += c.y * texture.bytesPerLine() + c.x; | - | ||||||||||||
341 | for (int i=0; i<c.h; ++i) {
| 0 | ||||||||||||
342 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits); | - | ||||||||||||
343 | bits += texture.bytesPerLine(); | - | ||||||||||||
344 | } never executed: end of block | 0 | ||||||||||||
345 | return; never executed: return; | 0 | ||||||||||||
346 | } | - | ||||||||||||
347 | - | |||||||||||||
348 | QImage mask = textureMapForGlyph(glyph, subPixelPosition); | - | ||||||||||||
349 | const int maskWidth = mask.width(); | - | ||||||||||||
350 | const int maskHeight = mask.height(); | - | ||||||||||||
351 | - | |||||||||||||
352 | if (mask.format() == QImage::Format_Mono) {
| 0 | ||||||||||||
353 | mask = mask.convertToFormat(QImage::Format_Indexed8); | - | ||||||||||||
354 | for (int y = 0; y < maskHeight; ++y) {
| 0 | ||||||||||||
355 | uchar *src = (uchar *) mask.scanLine(y); | - | ||||||||||||
356 | for (int x = 0; x < maskWidth; ++x)
| 0 | ||||||||||||
357 | src[x] = -src[x]; // convert 0 and 1 into 0 and 255 never executed: src[x] = -src[x]; | 0 | ||||||||||||
358 | } never executed: end of block | 0 | ||||||||||||
359 | } else if (mask.depth() == 32) { never executed: end of block
| 0 | ||||||||||||
360 | if (mask.format() == QImage::Format_RGB32
| 0 | ||||||||||||
361 | // We need to make the alpha component equal to the average of the RGB values. | - | ||||||||||||
362 | // This is needed when drawing sub-pixel antialiased text on translucent targets. | - | ||||||||||||
363 | #if Q_BYTE_ORDER == Q_BIG_ENDIAN | - | ||||||||||||
364 | || mask.format() == QImage::Format_ARGB32_Premultiplied | - | ||||||||||||
365 | #else | - | ||||||||||||
366 | || (mask.format() == QImage::Format_ARGB32_Premultiplied
| 0 | ||||||||||||
367 | && ctx->isOpenGLES())
| 0 | ||||||||||||
368 | #endif | - | ||||||||||||
369 | ) { | - | ||||||||||||
370 | for (int y = 0; y < maskHeight; ++y) {
| 0 | ||||||||||||
371 | QRgb *src = (QRgb *) mask.scanLine(y); | - | ||||||||||||
372 | for (int x = 0; x < maskWidth; ++x) {
| 0 | ||||||||||||
373 | int r = qRed(src[x]); | - | ||||||||||||
374 | int g = qGreen(src[x]); | - | ||||||||||||
375 | int b = qBlue(src[x]); | - | ||||||||||||
376 | int avg; | - | ||||||||||||
377 | if (mask.format() == QImage::Format_RGB32)
| 0 | ||||||||||||
378 | avg = (r + g + b + 1) / 3; // "+1" for rounding. never executed: avg = (r + g + b + 1) / 3; | 0 | ||||||||||||
379 | else // Format_ARGB_Premultiplied | - | ||||||||||||
380 | avg = qAlpha(src[x]); never executed: avg = qAlpha(src[x]); | 0 | ||||||||||||
381 | - | |||||||||||||
382 | src[x] = qRgba(r, g, b, avg); | - | ||||||||||||
383 | // swizzle the bits to accommodate for the GL_RGBA upload. | - | ||||||||||||
384 | #if Q_BYTE_ORDER != Q_BIG_ENDIAN | - | ||||||||||||
385 | if (ctx->isOpenGLES())
| 0 | ||||||||||||
386 | #endif | - | ||||||||||||
387 | src[x] = ARGB2RGBA(src[x]); never executed: src[x] = ARGB2RGBA(src[x]); | 0 | ||||||||||||
388 | } never executed: end of block | 0 | ||||||||||||
389 | } never executed: end of block | 0 | ||||||||||||
390 | } never executed: end of block | 0 | ||||||||||||
391 | } never executed: end of block | 0 | ||||||||||||
392 | - | |||||||||||||
393 | funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); | - | ||||||||||||
394 | if (mask.depth() == 32) {
| 0 | ||||||||||||
395 | #ifdef QT_OPENGL_ES_2 | - | ||||||||||||
396 | GLenum fmt = GL_RGBA; | - | ||||||||||||
397 | #else | - | ||||||||||||
398 | GLenum fmt = ctx->isOpenGLES() ? GL_RGBA : GL_BGRA;
| 0 | ||||||||||||
399 | #endif // QT_OPENGL_ES_2 | - | ||||||||||||
400 | - | |||||||||||||
401 | #if Q_BYTE_ORDER == Q_BIG_ENDIAN | - | ||||||||||||
402 | fmt = GL_RGBA; | - | ||||||||||||
403 | #endif | - | ||||||||||||
404 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, fmt, GL_UNSIGNED_BYTE, mask.bits()); | - | ||||||||||||
405 | } else { never executed: end of block | 0 | ||||||||||||
406 | // The scanlines in mask are 32-bit aligned, even for mono or 8-bit formats. This | - | ||||||||||||
407 | // is good because it matches the default of 4 bytes for GL_UNPACK_ALIGNMENT. | - | ||||||||||||
408 | #if !defined(QT_OPENGL_ES_2) | - | ||||||||||||
409 | const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
| 0 | ||||||||||||
410 | #else | - | ||||||||||||
411 | const GLenum format = GL_ALPHA; | - | ||||||||||||
412 | #endif | - | ||||||||||||
413 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits()); | - | ||||||||||||
414 | } never executed: end of block | 0 | ||||||||||||
415 | } | - | ||||||||||||
416 | - | |||||||||||||
417 | int QOpenGLTextureGlyphCache::glyphPadding() const | - | ||||||||||||
418 | { | - | ||||||||||||
419 | return 1; never executed: return 1; | 0 | ||||||||||||
420 | } | - | ||||||||||||
421 | - | |||||||||||||
422 | int QOpenGLTextureGlyphCache::maxTextureWidth() const | - | ||||||||||||
423 | { | - | ||||||||||||
424 | QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); | - | ||||||||||||
425 | if (ctx == 0)
| 0 | ||||||||||||
426 | return QImageTextureGlyphCache::maxTextureWidth(); never executed: return QImageTextureGlyphCache::maxTextureWidth(); | 0 | ||||||||||||
427 | else | - | ||||||||||||
428 | return ctx->d_func()->maxTextureSize(); never executed: return ctx->d_func()->maxTextureSize(); | 0 | ||||||||||||
429 | } | - | ||||||||||||
430 | - | |||||||||||||
431 | int QOpenGLTextureGlyphCache::maxTextureHeight() const | - | ||||||||||||
432 | { | - | ||||||||||||
433 | QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); | - | ||||||||||||
434 | if (ctx == 0)
| 0 | ||||||||||||
435 | return QImageTextureGlyphCache::maxTextureHeight(); never executed: return QImageTextureGlyphCache::maxTextureHeight(); | 0 | ||||||||||||
436 | - | |||||||||||||
437 | if (ctx->d_func()->workaround_brokenTexSubImage)
| 0 | ||||||||||||
438 | return qMin(1024, ctx->d_func()->maxTextureSize()); never executed: return qMin(1024, ctx->d_func()->maxTextureSize()); | 0 | ||||||||||||
439 | else | - | ||||||||||||
440 | return ctx->d_func()->maxTextureSize(); never executed: return ctx->d_func()->maxTextureSize(); | 0 | ||||||||||||
441 | } | - | ||||||||||||
442 | - | |||||||||||||
443 | void QOpenGLTextureGlyphCache::clear() | - | ||||||||||||
444 | { | - | ||||||||||||
445 | if (m_textureResource)
| 0 | ||||||||||||
446 | m_textureResource->free(); never executed: m_textureResource->free(); | 0 | ||||||||||||
447 | m_textureResource = 0; | - | ||||||||||||
448 | - | |||||||||||||
449 | delete m_blitProgram; | - | ||||||||||||
450 | m_blitProgram = 0; | - | ||||||||||||
451 | - | |||||||||||||
452 | m_w = 0; | - | ||||||||||||
453 | m_h = 0; | - | ||||||||||||
454 | m_cx = 0; | - | ||||||||||||
455 | m_cy = 0; | - | ||||||||||||
456 | m_currentRowHeight = 0; | - | ||||||||||||
457 | coords.clear(); | - | ||||||||||||
458 | } never executed: end of block | 0 | ||||||||||||
459 | - | |||||||||||||
460 | QT_END_NAMESPACE | - | ||||||||||||
Source code | Switch to Preprocessed file |