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

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