qopengltexturecache.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/opengl/qopengltexturecache.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
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 https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://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 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qopengltexturecache_p.h"-
41#include <qmath.h>-
42#include <qopenglfunctions.h>-
43#include <private/qopenglcontext_p.h>-
44#include <private/qopenglextensions_p.h>-
45#include <private/qimagepixmapcleanuphooks_p.h>-
46#include <qpa/qplatformpixmap.h>-
47-
48QT_BEGIN_NAMESPACE-
49-
50#ifndef GL_RED-
51#define GL_RED 0x1903-
52#endif-
53-
54#ifndef GL_RGB10_A2-
55#define GL_RGB10_A2 0x8059-
56#endif-
57-
58#ifndef GL_BGR-
59#define GL_BGR 0x80E0-
60#endif-
61-
62#ifndef GL_BGRA-
63#define GL_BGRA 0x80E1-
64#endif-
65-
66#ifndef GL_UNSIGNED_INT_8_8_8_8_REV-
67#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367-
68#endif-
69-
70#ifndef GL_UNSIGNED_INT_2_10_10_10_REV-
71#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368-
72#endif-
73-
74class QOpenGLTextureCacheWrapper-
75{-
76public:-
77 QOpenGLTextureCacheWrapper()-
78 {-
79 QImagePixmapCleanupHooks::instance()->addPlatformPixmapModificationHook(cleanupTexturesForPixmapData);-
80 QImagePixmapCleanupHooks::instance()->addPlatformPixmapDestructionHook(cleanupTexturesForPixmapData);-
81 QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);-
82 }
never executed: end of block
0
83-
84 ~QOpenGLTextureCacheWrapper()-
85 {-
86 QImagePixmapCleanupHooks::instance()->removePlatformPixmapModificationHook(cleanupTexturesForPixmapData);-
87 QImagePixmapCleanupHooks::instance()->removePlatformPixmapDestructionHook(cleanupTexturesForPixmapData);-
88 QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);-
89 }
never executed: end of block
0
90-
91 QOpenGLTextureCache *cacheForContext(QOpenGLContext *context) {-
92 QMutexLocker lock(&m_mutex);-
93 return m_resource.value<QOpenGLTextureCache>(context);
never executed: return m_resource.value<QOpenGLTextureCache>(context);
0
94 }-
95-
96 static void cleanupTexturesForCacheKey(qint64 key);-
97 static void cleanupTexturesForPixmapData(QPlatformPixmap *pmd);-
98-
99private:-
100 QOpenGLMultiGroupSharedResource m_resource;-
101 QMutex m_mutex;-
102};-
103-
104Q_GLOBAL_STATIC(QOpenGLTextureCacheWrapper, qt_texture_caches)
never executed: end of block
never executed: guard.store(QtGlobalStatic::Destroyed);
never executed: return &holder.value;
guard.load() =...c::InitializedDescription
TRUEnever evaluated
FALSEnever evaluated
0
105-
106QOpenGLTextureCache *QOpenGLTextureCache::cacheForContext(QOpenGLContext *context)-
107{-
108 return qt_texture_caches()->cacheForContext(context);
never executed: return qt_texture_caches()->cacheForContext(context);
0
109}-
110-
111void QOpenGLTextureCacheWrapper::cleanupTexturesForCacheKey(qint64 key)-
112{-
113 QList<QOpenGLSharedResource *> resources = qt_texture_caches()->m_resource.resources();-
114 for (QList<QOpenGLSharedResource *>::iterator it = resources.begin(); it != resources.end(); ++it)
it != resources.end()Description
TRUEnever evaluated
FALSEnever evaluated
0
115 static_cast<QOpenGLTextureCache *>(*it)->invalidate(key);
never executed: static_cast<QOpenGLTextureCache *>(*it)->invalidate(key);
0
116}
never executed: end of block
0
117-
118void QOpenGLTextureCacheWrapper::cleanupTexturesForPixmapData(QPlatformPixmap *pmd)-
119{-
120 cleanupTexturesForCacheKey(pmd->cacheKey());-
121}
never executed: end of block
0
122-
123QOpenGLTextureCache::QOpenGLTextureCache(QOpenGLContext *ctx)-
124 : QOpenGLSharedResource(ctx->shareGroup())-
125 , m_cache(64 * 1024) // 64 MB cache-
126{-
127}
never executed: end of block
0
128-
129QOpenGLTextureCache::~QOpenGLTextureCache()-
130{-
131}-
132-
133GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &pixmap, BindOptions options)-
134{-
135 if (pixmap.isNull())
pixmap.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
136 return 0;
never executed: return 0;
0
137 QMutexLocker locker(&m_mutex);-
138 qint64 key = pixmap.cacheKey();-
139-
140 // A QPainter is active on the image - take the safe route and replace the texture.-
141 if (!pixmap.paintingActive()) {
!pixmap.paintingActive()Description
TRUEnever evaluated
FALSEnever evaluated
0
142 QOpenGLCachedTexture *entry = m_cache.object(key);-
143 if (entry && entry->options() == options) {
entryDescription
TRUEnever evaluated
FALSEnever evaluated
entry->options() == optionsDescription
TRUEnever evaluated
FALSEnever evaluated
0
144 context->functions()->glBindTexture(GL_TEXTURE_2D, entry->id());-
145 return entry->id();
never executed: return entry->id();
0
146 }-
147 }
never executed: end of block
0
148-
149 GLuint id = bindTexture(context, key, pixmap.toImage(), options);-
150 if (id > 0)
id > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
151 QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
never executed: QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
0
152-
153 return id;
never executed: return id;
0
154}-
155-
156GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image, BindOptions options)-
157{-
158 if (image.isNull())
image.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
159 return 0;
never executed: return 0;
0
160 QMutexLocker locker(&m_mutex);-
161 qint64 key = image.cacheKey();-
162-
163 // A QPainter is active on the image - take the safe route and replace the texture.-
164 if (!image.paintingActive()) {
!image.paintingActive()Description
TRUEnever evaluated
FALSEnever evaluated
0
165 QOpenGLCachedTexture *entry = m_cache.object(key);-
166 if (entry && entry->options() == options) {
entryDescription
TRUEnever evaluated
FALSEnever evaluated
entry->options() == optionsDescription
TRUEnever evaluated
FALSEnever evaluated
0
167 context->functions()->glBindTexture(GL_TEXTURE_2D, entry->id());-
168 return entry->id();
never executed: return entry->id();
0
169 }-
170 }
never executed: end of block
0
171-
172 QImage img = image;-
173 if (!context->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)) {
!context->func...:NPOTTextures)Description
TRUEnever evaluated
FALSEnever evaluated
0
174 // Scale the pixmap if needed. GL textures needs to have the-
175 // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL-
176 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target-
177 int tx_w = qNextPowerOfTwo(image.width() - 1);-
178 int tx_h = qNextPowerOfTwo(image.height() - 1);-
179 if (tx_w != image.width() || tx_h != image.height()) {
tx_w != image.width()Description
TRUEnever evaluated
FALSEnever evaluated
tx_h != image.height()Description
TRUEnever evaluated
FALSEnever evaluated
0
180 img = img.scaled(tx_w, tx_h);-
181 }
never executed: end of block
0
182 }
never executed: end of block
0
183-
184 GLuint id = bindTexture(context, key, img, options);-
185 if (id > 0)
id > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
186 QImagePixmapCleanupHooks::enableCleanupHooks(image);
never executed: QImagePixmapCleanupHooks::enableCleanupHooks(image);
0
187-
188 return id;
never executed: return id;
0
189}-
190-
191GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, BindOptions options)-
192{-
193 GLuint id;-
194 QOpenGLFunctions *funcs = context->functions();-
195 funcs->glGenTextures(1, &id);-
196 funcs->glBindTexture(GL_TEXTURE_2D, id);-
197-
198 QImage tx;-
199 GLenum externalFormat;-
200 GLenum internalFormat;-
201 GLuint pixelType;-
202 QImage::Format targetFormat = QImage::Format_Invalid;-
203 const bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
!context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
context->forma...Version() >= 2Description
TRUEnever evaluated
FALSEnever evaluated
context->forma...Version() >= 2Description
TRUEnever evaluated
FALSEnever evaluated
0
204-
205 switch (image.format()) {-
206 case QImage::Format_RGB32:
never executed: case QImage::Format_RGB32:
0
207 case QImage::Format_ARGB32:
never executed: case QImage::Format_ARGB32:
0
208 case QImage::Format_ARGB32_Premultiplied:
never executed: case QImage::Format_ARGB32_Premultiplied:
0
209 if (isOpenGL12orBetter) {
isOpenGL12orBetterDescription
TRUEnever evaluated
FALSEnever evaluated
0
210 externalFormat = GL_BGRA;-
211 internalFormat = GL_RGBA;-
212 pixelType = GL_UNSIGNED_INT_8_8_8_8_REV;-
213 } else {
never executed: end of block
0
214#if Q_BYTE_ORDER == Q_BIG_ENDIAN-
215 // Without GL_UNSIGNED_INT_8_8_8_8_REV, BGRA only matches ARGB on little endian.-
216 break;-
217#endif-
218 if (static_cast<QOpenGLExtensions*>(context->functions())->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat)) {
static_cast<QO...TextureFormat)Description
TRUEnever evaluated
FALSEnever evaluated
0
219 // GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 extensions.-
220 if (context->isOpenGLES()) {
context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
221 // The GL_EXT_texture_format_BGRA8888 extension requires the internal format to match the external.-
222 externalFormat = internalFormat = GL_BGRA;-
223 } else {
never executed: end of block
0
224 // OpenGL BGRA/BGR format is not allowed as an internal format-
225 externalFormat = GL_BGRA;-
226 internalFormat = GL_RGBA;-
227 }
never executed: end of block
0
228 pixelType = GL_UNSIGNED_BYTE;-
229 } else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) {
never executed: end of block
never executed: return ba;
context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
context->hasEx...turn ba; }()))Description
TRUEnever evaluated
FALSEnever evaluated
0
230 // Is only allowed as an external format like OpenGL.-
231 externalFormat = GL_BGRA;-
232 internalFormat = GL_RGBA;-
233 pixelType = GL_UNSIGNED_BYTE;-
234 } else {
never executed: end of block
0
235 // No support for direct ARGB32 upload.-
236 break;
never executed: break;
0
237 }-
238 }-
239 targetFormat = image.format();-
240 break;
never executed: break;
0
241 case QImage::Format_BGR30:
never executed: case QImage::Format_BGR30:
0
242 case QImage::Format_A2BGR30_Premultiplied:
never executed: case QImage::Format_A2BGR30_Premultiplied:
0
243 if (isOpenGL12orBetter || (context->isOpenGLES() && context->format().majorVersion() >= 3)) {
isOpenGL12orBetterDescription
TRUEnever evaluated
FALSEnever evaluated
context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
context->forma...Version() >= 3Description
TRUEnever evaluated
FALSEnever evaluated
0
244 pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;-
245 externalFormat = GL_RGBA;-
246 internalFormat = GL_RGB10_A2;-
247 targetFormat = image.format();-
248 }
never executed: end of block
0
249 break;
never executed: break;
0
250 case QImage::Format_RGB30:
never executed: case QImage::Format_RGB30:
0
251 case QImage::Format_A2RGB30_Premultiplied:
never executed: case QImage::Format_A2RGB30_Premultiplied:
0
252 if (isOpenGL12orBetter) {
isOpenGL12orBetterDescription
TRUEnever evaluated
FALSEnever evaluated
0
253 pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;-
254 externalFormat = GL_BGRA;-
255 internalFormat = GL_RGB10_A2;-
256 targetFormat = image.format();-
257 } else if (context->isOpenGLES() && context->format().majorVersion() >= 3) {
never executed: end of block
context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
context->forma...Version() >= 3Description
TRUEnever evaluated
FALSEnever evaluated
0
258 pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;-
259 externalFormat = GL_RGBA;-
260 internalFormat = GL_RGB10_A2;-
261 targetFormat = QImage::Format_A2BGR30_Premultiplied;-
262 }
never executed: end of block
0
263 break;
never executed: break;
0
264 case QImage::Format_RGB444:
never executed: case QImage::Format_RGB444:
0
265 case QImage::Format_RGB555:
never executed: case QImage::Format_RGB555:
0
266 case QImage::Format_RGB16:
never executed: case QImage::Format_RGB16:
0
267 if (isOpenGL12orBetter || context->isOpenGLES()) {
isOpenGL12orBetterDescription
TRUEnever evaluated
FALSEnever evaluated
context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
268 externalFormat = internalFormat = GL_RGB;-
269 pixelType = GL_UNSIGNED_SHORT_5_6_5;-
270 targetFormat = QImage::Format_RGB16;-
271 }
never executed: end of block
0
272 break;
never executed: break;
0
273 case QImage::Format_RGB666:
never executed: case QImage::Format_RGB666:
0
274 case QImage::Format_RGB888:
never executed: case QImage::Format_RGB888:
0
275 externalFormat = internalFormat = GL_RGB;-
276 pixelType = GL_UNSIGNED_BYTE;-
277 targetFormat = QImage::Format_RGB888;-
278 break;
never executed: break;
0
279 case QImage::Format_RGBX8888:
never executed: case QImage::Format_RGBX8888:
0
280 case QImage::Format_RGBA8888:
never executed: case QImage::Format_RGBA8888:
0
281 case QImage::Format_RGBA8888_Premultiplied:
never executed: case QImage::Format_RGBA8888_Premultiplied:
0
282 externalFormat = internalFormat = GL_RGBA;-
283 pixelType = GL_UNSIGNED_BYTE;-
284 targetFormat = image.format();-
285 break;
never executed: break;
0
286 case QImage::Format_Indexed8:
never executed: case QImage::Format_Indexed8:
0
287 if (options & UseRedFor8BitBindOption) {
options & UseR...8BitBindOptionDescription
TRUEnever evaluated
FALSEnever evaluated
0
288 externalFormat = internalFormat = GL_RED;-
289 pixelType = GL_UNSIGNED_BYTE;-
290 targetFormat = image.format();-
291 }
never executed: end of block
0
292 break;
never executed: break;
0
293 case QImage::Format_Alpha8:
never executed: case QImage::Format_Alpha8:
0
294 if (options & UseRedFor8BitBindOption) {
options & UseR...8BitBindOptionDescription
TRUEnever evaluated
FALSEnever evaluated
0
295 externalFormat = internalFormat = GL_RED;-
296 pixelType = GL_UNSIGNED_BYTE;-
297 targetFormat = image.format();-
298 } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
never executed: end of block
context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
context->forma...t::CoreProfileDescription
TRUEnever evaluated
FALSEnever evaluated
0
299 externalFormat = internalFormat = GL_ALPHA;-
300 pixelType = GL_UNSIGNED_BYTE;-
301 targetFormat = image.format();-
302 }
never executed: end of block
0
303 break;
never executed: break;
0
304 case QImage::Format_Grayscale8:
never executed: case QImage::Format_Grayscale8:
0
305 if (options & UseRedFor8BitBindOption) {
options & UseR...8BitBindOptionDescription
TRUEnever evaluated
FALSEnever evaluated
0
306 externalFormat = internalFormat = GL_RED;-
307 pixelType = GL_UNSIGNED_BYTE;-
308 targetFormat = image.format();-
309 } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
never executed: end of block
context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
context->forma...t::CoreProfileDescription
TRUEnever evaluated
FALSEnever evaluated
0
310 externalFormat = internalFormat = GL_LUMINANCE;-
311 pixelType = GL_UNSIGNED_BYTE;-
312 targetFormat = image.format();-
313 }
never executed: end of block
0
314 break;
never executed: break;
0
315 default:
never executed: default:
0
316 break;
never executed: break;
0
317 }-
318-
319 if (targetFormat == QImage::Format_Invalid) {
targetFormat =...Format_InvalidDescription
TRUEnever evaluated
FALSEnever evaluated
0
320 externalFormat = internalFormat = GL_RGBA;-
321 pixelType = GL_UNSIGNED_BYTE;-
322 if (!image.hasAlphaChannel())
!image.hasAlphaChannel()Description
TRUEnever evaluated
FALSEnever evaluated
0
323 targetFormat = QImage::Format_RGBX8888;
never executed: targetFormat = QImage::Format_RGBX8888;
0
324 else-
325 targetFormat = QImage::Format_RGBA8888;
never executed: targetFormat = QImage::Format_RGBA8888;
0
326 }-
327-
328 if (options & PremultipliedAlphaBindOption) {
options & Prem...lphaBindOptionDescription
TRUEnever evaluated
FALSEnever evaluated
0
329 if (targetFormat == QImage::Format_ARGB32)
targetFormat =...:Format_ARGB32Description
TRUEnever evaluated
FALSEnever evaluated
0
330 targetFormat = QImage::Format_ARGB32_Premultiplied;
never executed: targetFormat = QImage::Format_ARGB32_Premultiplied;
0
331 else if (targetFormat == QImage::Format_RGBA8888)
targetFormat =...ormat_RGBA8888Description
TRUEnever evaluated
FALSEnever evaluated
0
332 targetFormat = QImage::Format_RGBA8888_Premultiplied;
never executed: targetFormat = QImage::Format_RGBA8888_Premultiplied;
0
333 } else {
never executed: end of block
0
334 if (targetFormat == QImage::Format_ARGB32_Premultiplied)
targetFormat =..._PremultipliedDescription
TRUEnever evaluated
FALSEnever evaluated
0
335 targetFormat = QImage::Format_ARGB32;
never executed: targetFormat = QImage::Format_ARGB32;
0
336 else if (targetFormat == QImage::Format_RGBA8888_Premultiplied)
targetFormat =..._PremultipliedDescription
TRUEnever evaluated
FALSEnever evaluated
0
337 targetFormat = QImage::Format_RGBA8888;
never executed: targetFormat = QImage::Format_RGBA8888;
0
338 }
never executed: end of block
0
339-
340 if (image.format() != targetFormat)
image.format() != targetFormatDescription
TRUEnever evaluated
FALSEnever evaluated
0
341 tx = image.convertToFormat(targetFormat);
never executed: tx = image.convertToFormat(targetFormat);
0
342 else-
343 tx = image;
never executed: tx = image;
0
344-
345 funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, const_cast<const QImage &>(tx).bits());-
346-
347 int cost = tx.width() * tx.height() * tx.depth() / (1024 * 8);-
348 m_cache.insert(key, new QOpenGLCachedTexture(id, options, context), cost);-
349-
350 return id;
never executed: return id;
0
351}-
352-
353void QOpenGLTextureCache::invalidate(qint64 key)-
354{-
355 QMutexLocker locker(&m_mutex);-
356 m_cache.remove(key);-
357}
never executed: end of block
0
358-
359void QOpenGLTextureCache::invalidateResource()-
360{-
361 m_cache.clear();-
362}
never executed: end of block
0
363-
364void QOpenGLTextureCache::freeResource(QOpenGLContext *)-
365{-
366 Q_ASSERT(false); // the texture cache lives until the context group disappears-
367}
never executed: end of block
0
368-
369static void freeTexture(QOpenGLFunctions *funcs, GLuint id)-
370{-
371 funcs->glDeleteTextures(1, &id);-
372}
never executed: end of block
0
373-
374QOpenGLCachedTexture::QOpenGLCachedTexture(GLuint id, int options, QOpenGLContext *context) : m_options(options)-
375{-
376 m_resource = new QOpenGLSharedResourceGuard(context, id, freeTexture);-
377}
never executed: end of block
0
378-
379QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9