opengl/qopenglgradientcache.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
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 Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/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 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qopenglgradientcache_p.h" -
43#include <private/qdrawhelper_p.h> -
44#include <private/qopenglcontext_p.h> -
45#include <QtCore/qmutex.h> -
46 -
47QT_BEGIN_NAMESPACE -
48 -
49class QOpenGL2GradientCacheWrapper -
50{ -
51public: -
52 QOpenGL2GradientCache *cacheForContext(QOpenGLContext *context) { -
53 QMutexLocker lock(&m_mutex);
never executed (the execution status of this line is deduced): QMutexLocker lock(&m_mutex);
-
54 return m_resource.value<QOpenGL2GradientCache>(context);
never executed: return m_resource.value<QOpenGL2GradientCache>(context);
0
55 } -
56 -
57private: -
58 QOpenGLMultiGroupSharedResource m_resource; -
59 QMutex m_mutex; -
60}; -
61 -
62Q_GLOBAL_STATIC(QOpenGL2GradientCacheWrapper, qt_gradient_caches)
never executed: delete x;
never executed: return thisGlobalStatic.pointer.load();
never evaluated: !thisGlobalStatic.pointer.testAndSetOrdered(0, x)
never evaluated: !thisGlobalStatic.pointer.load()
never evaluated: !thisGlobalStatic.destroyed
0
63 -
64QOpenGL2GradientCache::QOpenGL2GradientCache(QOpenGLContext *ctx) -
65 : QOpenGLSharedResource(ctx->shareGroup()) -
66{ -
67}
never executed: }
0
68 -
69QOpenGL2GradientCache::~QOpenGL2GradientCache() -
70{ -
71 cache.clear();
never executed (the execution status of this line is deduced): cache.clear();
-
72}
never executed: }
0
73 -
74QOpenGL2GradientCache *QOpenGL2GradientCache::cacheForContext(QOpenGLContext *context) -
75{ -
76 return qt_gradient_caches()->cacheForContext(context);
never executed: return qt_gradient_caches()->cacheForContext(context);
0
77} -
78 -
79void QOpenGL2GradientCache::invalidateResource() -
80{ -
81 QMutexLocker lock(&m_mutex);
never executed (the execution status of this line is deduced): QMutexLocker lock(&m_mutex);
-
82 cache.clear();
never executed (the execution status of this line is deduced): cache.clear();
-
83}
never executed: }
0
84 -
85void QOpenGL2GradientCache::freeResource(QOpenGLContext *) -
86{ -
87 cleanCache();
never executed (the execution status of this line is deduced): cleanCache();
-
88}
never executed: }
0
89 -
90void QOpenGL2GradientCache::cleanCache() -
91{ -
92 QMutexLocker lock(&m_mutex);
never executed (the execution status of this line is deduced): QMutexLocker lock(&m_mutex);
-
93 QOpenGLGradientColorTableHash::const_iterator it = cache.constBegin();
never executed (the execution status of this line is deduced): QOpenGLGradientColorTableHash::const_iterator it = cache.constBegin();
-
94 for (; it != cache.constEnd(); ++it) {
never evaluated: it != cache.constEnd()
0
95 const CacheInfo &cache_info = it.value();
never executed (the execution status of this line is deduced): const CacheInfo &cache_info = it.value();
-
96 glDeleteTextures(1, &cache_info.texId);
never executed (the execution status of this line is deduced): glDeleteTextures(1, &cache_info.texId);
-
97 }
never executed: }
0
98 cache.clear();
never executed (the execution status of this line is deduced): cache.clear();
-
99}
never executed: }
0
100 -
101GLuint QOpenGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) -
102{ -
103 QMutexLocker lock(&m_mutex);
never executed (the execution status of this line is deduced): QMutexLocker lock(&m_mutex);
-
104 quint64 hash_val = 0;
never executed (the execution status of this line is deduced): quint64 hash_val = 0;
-
105 -
106 QGradientStops stops = gradient.stops();
never executed (the execution status of this line is deduced): QGradientStops stops = gradient.stops();
-
107 for (int i = 0; i < stops.size() && i <= 2; i++)
never evaluated: i < stops.size()
never evaluated: i <= 2
0
108 hash_val += stops[i].second.rgba();
never executed: hash_val += stops[i].second.rgba();
0
109 -
110 QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
never executed (the execution status of this line is deduced): QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
-
111 -
112 if (it == cache.constEnd())
never evaluated: it == cache.constEnd()
0
113 return addCacheElement(hash_val, gradient, opacity);
never executed: return addCacheElement(hash_val, gradient, opacity);
0
114 else { -
115 do { -
116 const CacheInfo &cache_info = it.value();
never executed (the execution status of this line is deduced): const CacheInfo &cache_info = it.value();
-
117 if (cache_info.stops == stops && cache_info.opacity == opacity
never evaluated: cache_info.stops == stops
never evaluated: cache_info.opacity == opacity
0
118 && cache_info.interpolationMode == gradient.interpolationMode())
never evaluated: cache_info.interpolationMode == gradient.interpolationMode()
0
119 { -
120 return cache_info.texId;
never executed: return cache_info.texId;
0
121 } -
122 ++it;
never executed (the execution status of this line is deduced): ++it;
-
123 } while (it != cache.constEnd() && it.key() == hash_val);
never executed: }
never evaluated: it != cache.constEnd()
never evaluated: it.key() == hash_val
0
124 // an exact match for these stops and opacity was not found, create new cache -
125 return addCacheElement(hash_val, gradient, opacity);
never executed: return addCacheElement(hash_val, gradient, opacity);
0
126 } -
127} -
128 -
129 -
130GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity) -
131{ -
132 if (cache.size() == maxCacheSize()) {
never evaluated: cache.size() == maxCacheSize()
0
133 int elem_to_remove = qrand() % maxCacheSize();
never executed (the execution status of this line is deduced): int elem_to_remove = qrand() % maxCacheSize();
-
134 quint64 key = cache.keys()[elem_to_remove];
never executed (the execution status of this line is deduced): quint64 key = cache.keys()[elem_to_remove];
-
135 -
136 // need to call glDeleteTextures on each removed cache entry: -
137 QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(key);
never executed (the execution status of this line is deduced): QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(key);
-
138 do { -
139 glDeleteTextures(1, &it.value().texId);
never executed (the execution status of this line is deduced): glDeleteTextures(1, &it.value().texId);
-
140 } while (++it != cache.constEnd() && it.key() == key);
never executed: }
never evaluated: ++it != cache.constEnd()
never evaluated: it.key() == key
0
141 cache.remove(key); // may remove more than 1, but OK
never executed (the execution status of this line is deduced): cache.remove(key);
-
142 }
never executed: }
0
143 -
144 CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode());
never executed (the execution status of this line is deduced): CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode());
-
145 uint buffer[1024];
never executed (the execution status of this line is deduced): uint buffer[1024];
-
146 generateGradientColorTable(gradient, buffer, paletteSize(), opacity);
never executed (the execution status of this line is deduced): generateGradientColorTable(gradient, buffer, paletteSize(), opacity);
-
147 glGenTextures(1, &cache_entry.texId);
never executed (the execution status of this line is deduced): glGenTextures(1, &cache_entry.texId);
-
148 glBindTexture(GL_TEXTURE_2D, cache_entry.texId);
never executed (the execution status of this line is deduced): glBindTexture(0x0DE1, cache_entry.texId);
-
149 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1,
never executed (the execution status of this line is deduced): glTexImage2D(0x0DE1, 0, 0x1908, paletteSize(), 1,
-
150 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
never executed (the execution status of this line is deduced): 0, 0x1908, 0x1401, buffer);
-
151 return cache.insert(hash_val, cache_entry).value().texId;
never executed: return cache.insert(hash_val, cache_entry).value().texId;
0
152} -
153 -
154 -
155// GL's expects pixels in RGBA (when using GL_RGBA), bin-endian (ABGR on x86). -
156// Qt always stores in ARGB reguardless of the byte-order the mancine uses. -
157static inline uint qtToGlColor(uint c) -
158{ -
159 uint o;
never executed (the execution status of this line is deduced): uint o;
-
160#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN -
161 o = (c & 0xff00ff00) // alpha & green already in the right place
never executed (the execution status of this line is deduced): o = (c & 0xff00ff00)
-
162 | ((c >> 16) & 0x000000ff) // red
never executed (the execution status of this line is deduced): | ((c >> 16) & 0x000000ff)
-
163 | ((c << 16) & 0x00ff0000); // blue
never executed (the execution status of this line is deduced): | ((c << 16) & 0x00ff0000);
-
164#else //Q_BIG_ENDIAN -
165 o = (c << 8) -
166 | ((c >> 24) & 0x000000ff); -
167#endif // Q_BYTE_ORDER -
168 return o;
never executed: return o;
0
169} -
170 -
171//TODO: Let GL generate the texture using an FBO -
172void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const -
173{ -
174 int pos = 0;
never executed (the execution status of this line is deduced): int pos = 0;
-
175 QGradientStops s = gradient.stops();
never executed (the execution status of this line is deduced): QGradientStops s = gradient.stops();
-
176 QVector<uint> colors(s.size());
never executed (the execution status of this line is deduced): QVector<uint> colors(s.size());
-
177 -
178 for (int i = 0; i < s.size(); ++i)
never evaluated: i < s.size()
0
179 colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian)
never executed: colors[i] = s[i].second.rgba();
0
180 -
181 bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
never executed (the execution status of this line is deduced): bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
-
182 -
183 uint alpha = qRound(opacity * 256);
never executed (the execution status of this line is deduced): uint alpha = qRound(opacity * 256);
-
184 uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha);
never executed (the execution status of this line is deduced): uint current_color = ((((colors[0] >> 24) * alpha) >> 8) << 24) | (colors[0] & 0x00ffffff);
-
185 qreal incr = 1.0 / qreal(size);
never executed (the execution status of this line is deduced): qreal incr = 1.0 / qreal(size);
-
186 qreal fpos = 1.5 * incr;
never executed (the execution status of this line is deduced): qreal fpos = 1.5 * incr;
-
187 colorTable[pos++] = qtToGlColor(PREMUL(current_color));
never executed (the execution status of this line is deduced): colorTable[pos++] = qtToGlColor(PREMUL(current_color));
-
188 -
189 while (fpos <= s.first().first) {
never evaluated: fpos <= s.first().first
0
190 colorTable[pos] = colorTable[pos - 1];
never executed (the execution status of this line is deduced): colorTable[pos] = colorTable[pos - 1];
-
191 pos++;
never executed (the execution status of this line is deduced): pos++;
-
192 fpos += incr;
never executed (the execution status of this line is deduced): fpos += incr;
-
193 }
never executed: }
0
194 -
195 if (colorInterpolation)
never evaluated: colorInterpolation
0
196 current_color = PREMUL(current_color);
never executed: current_color = PREMUL(current_color);
0
197 -
198 for (int i = 0; i < s.size() - 1; ++i) {
never evaluated: i < s.size() - 1
0
199 qreal delta = 1/(s[i+1].first - s[i].first);
never executed (the execution status of this line is deduced): qreal delta = 1/(s[i+1].first - s[i].first);
-
200 uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);
never executed (the execution status of this line is deduced): uint next_color = ((((colors[i+1] >> 24) * alpha) >> 8) << 24) | (colors[i+1] & 0x00ffffff);
-
201 if (colorInterpolation)
never evaluated: colorInterpolation
0
202 next_color = PREMUL(next_color);
never executed: next_color = PREMUL(next_color);
0
203 -
204 while (fpos < s[i+1].first && pos < size) {
never evaluated: fpos < s[i+1].first
never evaluated: pos < size
0
205 int dist = int(256 * ((fpos - s[i].first) * delta));
never executed (the execution status of this line is deduced): int dist = int(256 * ((fpos - s[i].first) * delta));
-
206 int idist = 256 - dist;
never executed (the execution status of this line is deduced): int idist = 256 - dist;
-
207 if (colorInterpolation)
never evaluated: colorInterpolation
0
208 colorTable[pos] = qtToGlColor(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
never executed: colorTable[pos] = qtToGlColor(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
0
209 else -
210 colorTable[pos] = qtToGlColor(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
never executed: colorTable[pos] = qtToGlColor(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
0
211 ++pos;
never executed (the execution status of this line is deduced): ++pos;
-
212 fpos += incr;
never executed (the execution status of this line is deduced): fpos += incr;
-
213 }
never executed: }
0
214 current_color = next_color;
never executed (the execution status of this line is deduced): current_color = next_color;
-
215 }
never executed: }
0
216 -
217 Q_ASSERT(s.size() > 0);
never executed (the execution status of this line is deduced): qt_noop();
-
218 -
219 uint last_color = qtToGlColor(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha)));
never executed (the execution status of this line is deduced): uint last_color = qtToGlColor(PREMUL(((((colors[s.size() - 1] >> 24) * alpha) >> 8) << 24) | (colors[s.size() - 1] & 0x00ffffff)));
-
220 for (;pos < size; ++pos)
never evaluated: pos < size
0
221 colorTable[pos] = last_color;
never executed: colorTable[pos] = last_color;
0
222 -
223 // Make sure the last color stop is represented at the end of the table -
224 colorTable[size-1] = last_color;
never executed (the execution status of this line is deduced): colorTable[size-1] = last_color;
-
225}
never executed: }
0
226 -
227QT_END_NAMESPACE -
228 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial