OpenCoverage

qopenglgradientcache.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/opengl/qopenglgradientcache.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 "qopenglgradientcache_p.h"-
41#include <private/qdrawhelper_p.h>-
42#include <private/qopenglcontext_p.h>-
43#include <private/qrgba64_p.h>-
44#include <QtCore/qmutex.h>-
45#include "qopenglfunctions.h"-
46#include "qopenglextensions_p.h"-
47-
48#ifndef GL_RGBA16-
49#define GL_RGBA16 0x805B-
50#endif-
51-
52QT_BEGIN_NAMESPACE-
53-
54class QOpenGL2GradientCacheWrapper-
55{-
56public:-
57 QOpenGL2GradientCache *cacheForContext(QOpenGLContext *context) {-
58 QMutexLocker lock(&m_mutex);-
59 return m_resource.value<QOpenGL2GradientCache>(context);
never executed: return m_resource.value<QOpenGL2GradientCache>(context);
0
60 }-
61-
62private:-
63 QOpenGLMultiGroupSharedResource m_resource;-
64 QMutex m_mutex;-
65};-
66-
67Q_GLOBAL_STATIC(QOpenGL2GradientCacheWrapper, qt_gradient_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
68-
69QOpenGL2GradientCache::QOpenGL2GradientCache(QOpenGLContext *ctx)-
70 : QOpenGLSharedResource(ctx->shareGroup())-
71{-
72}
never executed: end of block
0
73-
74QOpenGL2GradientCache::~QOpenGL2GradientCache()-
75{-
76 cache.clear();-
77}
never executed: end of block
0
78-
79QOpenGL2GradientCache *QOpenGL2GradientCache::cacheForContext(QOpenGLContext *context)-
80{-
81 return qt_gradient_caches()->cacheForContext(context);
never executed: return qt_gradient_caches()->cacheForContext(context);
0
82}-
83-
84void QOpenGL2GradientCache::invalidateResource()-
85{-
86 QMutexLocker lock(&m_mutex);-
87 cache.clear();-
88}
never executed: end of block
0
89-
90void QOpenGL2GradientCache::freeResource(QOpenGLContext *)-
91{-
92 cleanCache();-
93}
never executed: end of block
0
94-
95void QOpenGL2GradientCache::cleanCache()-
96{-
97 QMutexLocker lock(&m_mutex);-
98 QOpenGLGradientColorTableHash::const_iterator it = cache.constBegin();-
99 QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();-
100 for (; it != cache.constEnd(); ++it) {
it != cache.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
101 const CacheInfo &cache_info = it.value();-
102 funcs->glDeleteTextures(1, &cache_info.texId);-
103 }
never executed: end of block
0
104 cache.clear();-
105}
never executed: end of block
0
106-
107GLuint QOpenGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity)-
108{-
109 quint64 hash_val = 0;-
110-
111 const QGradientStops stops = gradient.stops();-
112 for (int i = 0; i < stops.size() && i <= 2; i++)
i < stops.size()Description
TRUEnever evaluated
FALSEnever evaluated
i <= 2Description
TRUEnever evaluated
FALSEnever evaluated
0
113 hash_val += stops[i].second.rgba();
never executed: hash_val += stops[i].second.rgba();
0
114-
115 const QMutexLocker lock(&m_mutex);-
116 QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val);-
117-
118 if (it == cache.constEnd())
it == cache.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
119 return addCacheElement(hash_val, gradient, opacity);
never executed: return addCacheElement(hash_val, gradient, opacity);
0
120 else {-
121 do {-
122 const CacheInfo &cache_info = it.value();-
123 if (cache_info.stops == stops && cache_info.opacity == opacity
cache_info.stops == stopsDescription
TRUEnever evaluated
FALSEnever evaluated
cache_info.opacity == opacityDescription
TRUEnever evaluated
FALSEnever evaluated
0
124 && cache_info.interpolationMode == gradient.interpolationMode())
cache_info.int...polationMode()Description
TRUEnever evaluated
FALSEnever evaluated
0
125 {-
126 return cache_info.texId;
never executed: return cache_info.texId;
0
127 }-
128 ++it;-
129 } while (it != cache.constEnd() && it.key() == hash_val);
never executed: end of block
it != cache.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
it.key() == hash_valDescription
TRUEnever evaluated
FALSEnever evaluated
0
130 // an exact match for these stops and opacity was not found, create new cache-
131 return addCacheElement(hash_val, gradient, opacity);
never executed: return addCacheElement(hash_val, gradient, opacity);
0
132 }-
133}-
134-
135-
136GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)-
137{-
138 QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();-
139 if (cache.size() == maxCacheSize()) {
cache.size() == maxCacheSize()Description
TRUEnever evaluated
FALSEnever evaluated
0
140 int elem_to_remove = qrand() % maxCacheSize();-
141 quint64 key = cache.keys()[elem_to_remove];-
142-
143 // need to call glDeleteTextures on each removed cache entry:-
144 QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(key);-
145 do {-
146 funcs->glDeleteTextures(1, &it.value().texId);-
147 } while (++it != cache.constEnd() && it.key() == key);
never executed: end of block
++it != cache.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
it.key() == keyDescription
TRUEnever evaluated
FALSEnever evaluated
0
148 cache.remove(key); // may remove more than 1, but OK-
149 }
never executed: end of block
0
150-
151 CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode());-
152 funcs->glGenTextures(1, &cache_entry.texId);-
153 funcs->glBindTexture(GL_TEXTURE_2D, cache_entry.texId);-
154 if (static_cast<QOpenGLExtensions *>(funcs)->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats)) {
static_cast<QO...ized16Formats)Description
TRUEnever evaluated
FALSEnever evaluated
0
155 QRgba64 buffer[1024];-
156 generateGradientColorTable(gradient, buffer, paletteSize(), opacity);-
157 funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, paletteSize(), 1,-
158 0, GL_RGBA, GL_UNSIGNED_SHORT, buffer);-
159 } else {
never executed: end of block
0
160 uint buffer[1024];-
161 generateGradientColorTable(gradient, buffer, paletteSize(), opacity);-
162 funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1,-
163 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);-
164 }
never executed: end of block
0
165 return cache.insert(hash_val, cache_entry).value().texId;
never executed: return cache.insert(hash_val, cache_entry).value().texId;
0
166}-
167-
168-
169//TODO: Let GL generate the texture using an FBO-
170void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const-
171{-
172 int pos = 0;-
173 const QGradientStops s = gradient.stops();-
174-
175 bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);-
176-
177 uint alpha = qRound(opacity * 256);-
178 QRgba64 current_color = combineAlpha256(s[0].second.rgba64(), alpha);-
179 qreal incr = 1.0 / qreal(size);-
180 qreal fpos = 1.5 * incr;-
181 colorTable[pos++] = qPremultiply(current_color);-
182-
183 while (fpos <= s.first().first) {
fpos <= s.first().firstDescription
TRUEnever evaluated
FALSEnever evaluated
0
184 colorTable[pos] = colorTable[pos - 1];-
185 pos++;-
186 fpos += incr;-
187 }
never executed: end of block
0
188-
189 if (colorInterpolation)
colorInterpolationDescription
TRUEnever evaluated
FALSEnever evaluated
0
190 current_color = qPremultiply(current_color);
never executed: current_color = qPremultiply(current_color);
0
191-
192 const int sLast = s.size() - 1;-
193 for (int i = 0; i < sLast; ++i) {
i < sLastDescription
TRUEnever evaluated
FALSEnever evaluated
0
194 qreal delta = 1/(s[i+1].first - s[i].first);-
195 QRgba64 next_color = combineAlpha256(s[i + 1].second.rgba64(), alpha);-
196 if (colorInterpolation)
colorInterpolationDescription
TRUEnever evaluated
FALSEnever evaluated
0
197 next_color = qPremultiply(next_color);
never executed: next_color = qPremultiply(next_color);
0
198-
199 while (fpos < s[i+1].first && pos < size) {
fpos < s[i+1].firstDescription
TRUEnever evaluated
FALSEnever evaluated
pos < sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
200 int dist = int(256 * ((fpos - s[i].first) * delta));-
201 int idist = 256 - dist;-
202 if (colorInterpolation)
colorInterpolationDescription
TRUEnever evaluated
FALSEnever evaluated
0
203 colorTable[pos] = interpolate256(current_color, idist, next_color, dist);
never executed: colorTable[pos] = interpolate256(current_color, idist, next_color, dist);
0
204 else-
205 colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist));
never executed: colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist));
0
206 ++pos;-
207 fpos += incr;-
208 }
never executed: end of block
0
209 current_color = next_color;-
210 }
never executed: end of block
0
211-
212 Q_ASSERT(s.size() > 0);-
213-
214 QRgba64 last_color = qPremultiply(combineAlpha256(s[sLast].second.rgba64(), alpha));-
215 for (;pos < size; ++pos)
pos < sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
216 colorTable[pos] = last_color;
never executed: colorTable[pos] = last_color;
0
217-
218 // Make sure the last color stop is represented at the end of the table-
219 colorTable[size-1] = last_color;-
220}
never executed: end of block
0
221-
222void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const-
223{-
224 int pos = 0;-
225 const QGradientStops s = gradient.stops();-
226-
227 bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);-
228-
229 uint alpha = qRound(opacity * 256);-
230 // Qt LIES! It returns ARGB (on little-endian AND on big-endian)-
231 uint current_color = ARGB_COMBINE_ALPHA(s[0].second.rgba(), alpha);-
232 qreal incr = 1.0 / qreal(size);-
233 qreal fpos = 1.5 * incr;-
234 colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color));-
235-
236 while (fpos <= s.first().first) {
fpos <= s.first().firstDescription
TRUEnever evaluated
FALSEnever evaluated
0
237 colorTable[pos] = colorTable[pos - 1];-
238 pos++;-
239 fpos += incr;-
240 }
never executed: end of block
0
241-
242 if (colorInterpolation)
colorInterpolationDescription
TRUEnever evaluated
FALSEnever evaluated
0
243 current_color = qPremultiply(current_color);
never executed: current_color = qPremultiply(current_color);
0
244-
245 const int sLast = s.size() - 1;-
246 for (int i = 0; i < sLast; ++i) {
i < sLastDescription
TRUEnever evaluated
FALSEnever evaluated
0
247 qreal delta = 1/(s[i+1].first - s[i].first);-
248 uint next_color = ARGB_COMBINE_ALPHA(s[i + 1].second.rgba(), alpha);-
249 if (colorInterpolation)
colorInterpolationDescription
TRUEnever evaluated
FALSEnever evaluated
0
250 next_color = qPremultiply(next_color);
never executed: next_color = qPremultiply(next_color);
0
251-
252 while (fpos < s[i+1].first && pos < size) {
fpos < s[i+1].firstDescription
TRUEnever evaluated
FALSEnever evaluated
pos < sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
253 int dist = int(256 * ((fpos - s[i].first) * delta));-
254 int idist = 256 - dist;-
255 if (colorInterpolation)
colorInterpolationDescription
TRUEnever evaluated
FALSEnever evaluated
0
256 colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
never executed: colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
0
257 else-
258 colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
never executed: colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
0
259 ++pos;-
260 fpos += incr;-
261 }
never executed: end of block
0
262 current_color = next_color;-
263 }
never executed: end of block
0
264-
265 Q_ASSERT(s.size() > 0);-
266-
267 uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha)));-
268 for (;pos < size; ++pos)
pos < sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
269 colorTable[pos] = last_color;
never executed: colorTable[pos] = last_color;
0
270-
271 // Make sure the last color stop is represented at the end of the table-
272 colorTable[size-1] = last_color;-
273}
never executed: end of block
0
274-
275QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

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