Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/quick/scenegraph/util/qsgatlastexture.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 QtQuick 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 "qsgatlastexture_p.h" | - | ||||||||||||||||||||||||
41 | - | |||||||||||||||||||||||||
42 | #include <QtCore/QVarLengthArray> | - | ||||||||||||||||||||||||
43 | #include <QtCore/QElapsedTimer> | - | ||||||||||||||||||||||||
44 | #include <QtCore/QtMath> | - | ||||||||||||||||||||||||
45 | - | |||||||||||||||||||||||||
46 | #include <QtGui/QOpenGLContext> | - | ||||||||||||||||||||||||
47 | #include <QtGui/QOpenGLTexture> | - | ||||||||||||||||||||||||
48 | #include <QtGui/QOpenGLFunctions> | - | ||||||||||||||||||||||||
49 | #include <QtGui/QGuiApplication> | - | ||||||||||||||||||||||||
50 | #include <QtGui/QScreen> | - | ||||||||||||||||||||||||
51 | #include <QtGui/QSurface> | - | ||||||||||||||||||||||||
52 | #include <QtGui/QWindow> | - | ||||||||||||||||||||||||
53 | #include <QtGui/qpa/qplatformnativeinterface.h> | - | ||||||||||||||||||||||||
54 | - | |||||||||||||||||||||||||
55 | #include <private/qqmlglobal_p.h> | - | ||||||||||||||||||||||||
56 | #include <private/qsgtexture_p.h> | - | ||||||||||||||||||||||||
57 | #include <private/qsgcompressedtexture_p.h> | - | ||||||||||||||||||||||||
58 | #include <private/qsgcompressedatlastexture_p.h> | - | ||||||||||||||||||||||||
59 | - | |||||||||||||||||||||||||
60 | #include <private/qquickprofiler_p.h> | - | ||||||||||||||||||||||||
61 | - | |||||||||||||||||||||||||
62 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||||||||
63 | - | |||||||||||||||||||||||||
64 | #ifndef GL_BGRA | - | ||||||||||||||||||||||||
65 | #define GL_BGRA 0x80E1 | - | ||||||||||||||||||||||||
66 | #endif | - | ||||||||||||||||||||||||
67 | - | |||||||||||||||||||||||||
68 | int qt_sg_envInt(const char *name, int defaultValue); | - | ||||||||||||||||||||||||
69 | - | |||||||||||||||||||||||||
70 | static QElapsedTimer qsg_renderer_timer; | - | ||||||||||||||||||||||||
71 | - | |||||||||||||||||||||||||
72 | DEFINE_BOOL_CONFIG_OPTION(qsgEnableCompressedAtlas, QSG_ENABLE_COMPRESSED_ATLAS) never executed: status = Yes; never executed: end of block never executed: end of block never executed: return status == Yes;
| 0 | ||||||||||||||||||||||||
73 | - | |||||||||||||||||||||||||
74 | namespace QSGAtlasTexture | - | ||||||||||||||||||||||||
75 | { | - | ||||||||||||||||||||||||
76 | - | |||||||||||||||||||||||||
77 | Manager::Manager() | - | ||||||||||||||||||||||||
78 | : m_atlas(nullptr) | - | ||||||||||||||||||||||||
79 | { | - | ||||||||||||||||||||||||
80 | QOpenGLContext *gl = QOpenGLContext::currentContext(); | - | ||||||||||||||||||||||||
81 | Q_ASSERT(gl); | - | ||||||||||||||||||||||||
82 | QSurface *surface = gl->surface(); | - | ||||||||||||||||||||||||
83 | QSize surfaceSize = surface->size(); | - | ||||||||||||||||||||||||
84 | int max; | - | ||||||||||||||||||||||||
85 | gl->functions()->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max); | - | ||||||||||||||||||||||||
86 | - | |||||||||||||||||||||||||
87 | int w = qMin(max, qt_sg_envInt("QSG_ATLAS_WIDTH", qMax(512U, qNextPowerOfTwo(surfaceSize.width() - 1)))); | - | ||||||||||||||||||||||||
88 | int h = qMin(max, qt_sg_envInt("QSG_ATLAS_HEIGHT", qMax(512U, qNextPowerOfTwo(surfaceSize.height() - 1)))); | - | ||||||||||||||||||||||||
89 | - | |||||||||||||||||||||||||
90 | if (surface->surfaceClass() == QSurface::Window) {
| 114-3010 | ||||||||||||||||||||||||
91 | QWindow *window = static_cast<QWindow *>(surface); | - | ||||||||||||||||||||||||
92 | // Coverwindows, optimize for memory rather than speed | - | ||||||||||||||||||||||||
93 | if ((window->type() & Qt::CoverWindow) == Qt::CoverWindow) {
| 0-3010 | ||||||||||||||||||||||||
94 | w /= 2; | - | ||||||||||||||||||||||||
95 | h /= 2; | - | ||||||||||||||||||||||||
96 | } never executed: end of block | 0 | ||||||||||||||||||||||||
97 | } executed 3010 times by 74 tests: end of block Executed by:
| 3010 | ||||||||||||||||||||||||
98 | - | |||||||||||||||||||||||||
99 | m_atlas_size_limit = qt_sg_envInt("QSG_ATLAS_SIZE_LIMIT", qMax(w, h) / 2); | - | ||||||||||||||||||||||||
100 | m_atlas_size = QSize(w, h); | - | ||||||||||||||||||||||||
101 | - | |||||||||||||||||||||||||
102 | qCDebug(QSG_LOG_INFO, "texture atlas dimensions: %dx%d", w, h); never executed: QMessageLogger(__FILE__, 102, __PRETTY_FUNCTION__, QSG_LOG_INFO().categoryName()).debug("texture atlas dimensions: %dx%d", w, h);
| 0-3124 | ||||||||||||||||||||||||
103 | } executed 3124 times by 76 tests: end of block Executed by:
| 3124 | ||||||||||||||||||||||||
104 | - | |||||||||||||||||||||||||
105 | - | |||||||||||||||||||||||||
106 | Manager::~Manager() | - | ||||||||||||||||||||||||
107 | { | - | ||||||||||||||||||||||||
108 | Q_ASSERT(m_atlas == nullptr); | - | ||||||||||||||||||||||||
109 | Q_ASSERT(m_atlases.isEmpty()); | - | ||||||||||||||||||||||||
110 | } executed 3098 times by 70 tests: end of block Executed by:
| 3098 | ||||||||||||||||||||||||
111 | - | |||||||||||||||||||||||||
112 | void Manager::invalidate() | - | ||||||||||||||||||||||||
113 | { | - | ||||||||||||||||||||||||
114 | if (m_atlas) {
| 137-2987 | ||||||||||||||||||||||||
115 | m_atlas->invalidate(); | - | ||||||||||||||||||||||||
116 | m_atlas->deleteLater(); | - | ||||||||||||||||||||||||
117 | m_atlas = nullptr; | - | ||||||||||||||||||||||||
118 | } executed 137 times by 8 tests: end of block Executed by:
| 137 | ||||||||||||||||||||||||
119 | - | |||||||||||||||||||||||||
120 | QHash<unsigned int, QSGCompressedAtlasTexture::Atlas*>::iterator i = m_atlases.begin(); | - | ||||||||||||||||||||||||
121 | while (i != m_atlases.end()) {
| 0-3124 | ||||||||||||||||||||||||
122 | i.value()->invalidate(); | - | ||||||||||||||||||||||||
123 | i.value()->deleteLater(); | - | ||||||||||||||||||||||||
124 | ++i; | - | ||||||||||||||||||||||||
125 | } never executed: end of block | 0 | ||||||||||||||||||||||||
126 | m_atlases.clear(); | - | ||||||||||||||||||||||||
127 | } executed 3124 times by 76 tests: end of block Executed by:
| 3124 | ||||||||||||||||||||||||
128 | - | |||||||||||||||||||||||||
129 | QSGTexture *Manager::create(const QImage &image, bool hasAlphaChannel) | - | ||||||||||||||||||||||||
130 | { | - | ||||||||||||||||||||||||
131 | Texture *t = nullptr; | - | ||||||||||||||||||||||||
132 | if (image.width() < m_atlas_size_limit && image.height() < m_atlas_size_limit) {
| 6-307 | ||||||||||||||||||||||||
133 | if (!m_atlas)
| 137-164 | ||||||||||||||||||||||||
134 | m_atlas = new Atlas(m_atlas_size); executed 137 times by 8 tests: m_atlas = new Atlas(m_atlas_size); Executed by:
| 137 | ||||||||||||||||||||||||
135 | // t may be null for atlas allocation failure | - | ||||||||||||||||||||||||
136 | t = m_atlas->create(image); | - | ||||||||||||||||||||||||
137 | if (t && !hasAlphaChannel && t->hasAlphaChannel())
| 0-289 | ||||||||||||||||||||||||
138 | t->setHasAlphaChannel(false); never executed: t->setHasAlphaChannel(false); | 0 | ||||||||||||||||||||||||
139 | } executed 301 times by 8 tests: end of block Executed by:
| 301 | ||||||||||||||||||||||||
140 | return t; executed 367 times by 8 tests: return t; Executed by:
| 367 | ||||||||||||||||||||||||
141 | } | - | ||||||||||||||||||||||||
142 | - | |||||||||||||||||||||||||
143 | QSGTexture *Manager::create(const QSGCompressedTextureFactory *factory) | - | ||||||||||||||||||||||||
144 | { | - | ||||||||||||||||||||||||
145 | QSGTexture *t = nullptr; | - | ||||||||||||||||||||||||
146 | if (!qsgEnableCompressedAtlas() || !factory->m_textureData || !factory->m_textureData->isValid())
| 0 | ||||||||||||||||||||||||
147 | return t; never executed: return t; | 0 | ||||||||||||||||||||||||
148 | - | |||||||||||||||||||||||||
149 | // TODO: further abstract the atlas and remove this restriction | - | ||||||||||||||||||||||||
150 | unsigned int format = factory->m_textureData->format; | - | ||||||||||||||||||||||||
151 | switch (format) { | - | ||||||||||||||||||||||||
152 | case QOpenGLTexture::RGB8_ETC1: never executed: case QOpenGLTexture::RGB8_ETC1: | 0 | ||||||||||||||||||||||||
153 | case QOpenGLTexture::RGB8_ETC2: never executed: case QOpenGLTexture::RGB8_ETC2: | 0 | ||||||||||||||||||||||||
154 | case QOpenGLTexture::RGBA8_ETC2_EAC: never executed: case QOpenGLTexture::RGBA8_ETC2_EAC: | 0 | ||||||||||||||||||||||||
155 | case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2: never executed: case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2: | 0 | ||||||||||||||||||||||||
156 | break; never executed: break; | 0 | ||||||||||||||||||||||||
157 | default: never executed: default: | 0 | ||||||||||||||||||||||||
158 | return t; never executed: return t; | 0 | ||||||||||||||||||||||||
159 | } | - | ||||||||||||||||||||||||
160 | - | |||||||||||||||||||||||||
161 | QSize size = factory->m_textureData->size; | - | ||||||||||||||||||||||||
162 | if (size.width() < m_atlas_size_limit && size.height() < m_atlas_size_limit) {
| 0 | ||||||||||||||||||||||||
163 | QHash<unsigned int, QSGCompressedAtlasTexture::Atlas*>::iterator i = m_atlases.find(format); | - | ||||||||||||||||||||||||
164 | if (i == m_atlases.end())
| 0 | ||||||||||||||||||||||||
165 | i = m_atlases.insert(format, new QSGCompressedAtlasTexture::Atlas(m_atlas_size, format)); never executed: i = m_atlases.insert(format, new QSGCompressedAtlasTexture::Atlas(m_atlas_size, format)); | 0 | ||||||||||||||||||||||||
166 | // must be multiple of 4 | - | ||||||||||||||||||||||||
167 | QSize paddedSize(((size.width() + 3) / 4) * 4, ((size.height() + 3) / 4) * 4); | - | ||||||||||||||||||||||||
168 | QByteArray data = factory->m_textureData->data; | - | ||||||||||||||||||||||||
169 | t = i.value()->create(data, factory->m_textureData->sizeInBytes(), factory->m_textureData->dataOffset, size, paddedSize); | - | ||||||||||||||||||||||||
170 | } never executed: end of block | 0 | ||||||||||||||||||||||||
171 | return t; never executed: return t; | 0 | ||||||||||||||||||||||||
172 | } | - | ||||||||||||||||||||||||
173 | - | |||||||||||||||||||||||||
174 | AtlasBase::AtlasBase(const QSize &size) | - | ||||||||||||||||||||||||
175 | : m_allocator(size) | - | ||||||||||||||||||||||||
176 | , m_texture_id(0) | - | ||||||||||||||||||||||||
177 | , m_size(size) | - | ||||||||||||||||||||||||
178 | , m_allocated(false) | - | ||||||||||||||||||||||||
179 | { | - | ||||||||||||||||||||||||
180 | } executed 137 times by 8 tests: end of block Executed by:
| 137 | ||||||||||||||||||||||||
181 | - | |||||||||||||||||||||||||
182 | AtlasBase::~AtlasBase() | - | ||||||||||||||||||||||||
183 | { | - | ||||||||||||||||||||||||
184 | Q_ASSERT(!m_texture_id); | - | ||||||||||||||||||||||||
185 | } executed 135 times by 8 tests: end of block Executed by:
| 135 | ||||||||||||||||||||||||
186 | - | |||||||||||||||||||||||||
187 | void AtlasBase::invalidate() | - | ||||||||||||||||||||||||
188 | { | - | ||||||||||||||||||||||||
189 | if (m_texture_id && QOpenGLContext::currentContext())
| 0-113 | ||||||||||||||||||||||||
190 | QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_texture_id); executed 113 times by 8 tests: QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_texture_id); Executed by:
| 113 | ||||||||||||||||||||||||
191 | m_texture_id = 0; | - | ||||||||||||||||||||||||
192 | } executed 137 times by 8 tests: end of block Executed by:
| 137 | ||||||||||||||||||||||||
193 | - | |||||||||||||||||||||||||
194 | int AtlasBase::textureId() const | - | ||||||||||||||||||||||||
195 | { | - | ||||||||||||||||||||||||
196 | if (!m_texture_id) {
| 68-86668 | ||||||||||||||||||||||||
197 | Q_ASSERT(QOpenGLContext::currentContext()); | - | ||||||||||||||||||||||||
198 | QOpenGLContext::currentContext()->functions()->glGenTextures(1, &const_cast<AtlasBase *>(this)->m_texture_id); | - | ||||||||||||||||||||||||
199 | } executed 68 times by 3 tests: end of block Executed by:
| 68 | ||||||||||||||||||||||||
200 | - | |||||||||||||||||||||||||
201 | return m_texture_id; executed 86736 times by 4 tests: return m_texture_id; Executed by:
| 86736 | ||||||||||||||||||||||||
202 | } | - | ||||||||||||||||||||||||
203 | - | |||||||||||||||||||||||||
204 | void AtlasBase::bind(QSGTexture::Filtering filtering) | - | ||||||||||||||||||||||||
205 | { | - | ||||||||||||||||||||||||
206 | QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); | - | ||||||||||||||||||||||||
207 | if (!m_allocated) {
| 113-1324 | ||||||||||||||||||||||||
208 | m_allocated = true; | - | ||||||||||||||||||||||||
209 | - | |||||||||||||||||||||||||
210 | while (funcs->glGetError() != GL_NO_ERROR) ; never executed: ;
| 0-113 | ||||||||||||||||||||||||
211 | - | |||||||||||||||||||||||||
212 | funcs->glGenTextures(1, &m_texture_id); | - | ||||||||||||||||||||||||
213 | funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id); | - | ||||||||||||||||||||||||
214 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | - | ||||||||||||||||||||||||
215 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | - | ||||||||||||||||||||||||
216 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | - | ||||||||||||||||||||||||
217 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | - | ||||||||||||||||||||||||
218 | #if !defined(QT_OPENGL_ES_2) | - | ||||||||||||||||||||||||
219 | if (!QOpenGLContext::currentContext()->isOpenGLES())
| 0-113 | ||||||||||||||||||||||||
220 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); executed 113 times by 8 tests: funcs->glTexParameteri( 0x0DE1 , 0x813D , 0); Executed by:
| 113 | ||||||||||||||||||||||||
221 | #endif | - | ||||||||||||||||||||||||
222 | generateTexture(); | - | ||||||||||||||||||||||||
223 | - | |||||||||||||||||||||||||
224 | GLenum errorCode = funcs->glGetError(); | - | ||||||||||||||||||||||||
225 | if (errorCode == GL_OUT_OF_MEMORY) {
| 0-113 | ||||||||||||||||||||||||
226 | qDebug("QSGTextureAtlas: texture atlas allocation failed, out of memory"); | - | ||||||||||||||||||||||||
227 | funcs->glDeleteTextures(1, &m_texture_id); | - | ||||||||||||||||||||||||
228 | m_texture_id = 0; | - | ||||||||||||||||||||||||
229 | } else if (errorCode != GL_NO_ERROR) { never executed: end of block
| 0-113 | ||||||||||||||||||||||||
230 | qDebug("QSGTextureAtlas: texture atlas allocation failed, code=%x", errorCode); | - | ||||||||||||||||||||||||
231 | funcs->glDeleteTextures(1, &m_texture_id); | - | ||||||||||||||||||||||||
232 | m_texture_id = 0; | - | ||||||||||||||||||||||||
233 | } never executed: end of block | 0 | ||||||||||||||||||||||||
234 | } else { executed 113 times by 8 tests: end of block Executed by:
| 113 | ||||||||||||||||||||||||
235 | funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id); | - | ||||||||||||||||||||||||
236 | } executed 1324 times by 7 tests: end of block Executed by:
| 1324 | ||||||||||||||||||||||||
237 | - | |||||||||||||||||||||||||
238 | if (m_texture_id == 0)
| 0-1437 | ||||||||||||||||||||||||
239 | return; never executed: return; | 0 | ||||||||||||||||||||||||
240 | - | |||||||||||||||||||||||||
241 | // Upload all pending images.. | - | ||||||||||||||||||||||||
242 | for (int i=0; i<m_pending_uploads.size(); ++i) {
| 263-1437 | ||||||||||||||||||||||||
243 | - | |||||||||||||||||||||||||
244 | bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled(); | - | ||||||||||||||||||||||||
245 | if (profileFrames)
| 0-263 | ||||||||||||||||||||||||
246 | qsg_renderer_timer.start(); never executed: qsg_renderer_timer.start(); | 0 | ||||||||||||||||||||||||
247 | - | |||||||||||||||||||||||||
248 | Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphTexturePrepare); never executed: end of block executed 263 times by 8 tests: (void)0; Executed by:
| 0-263 | ||||||||||||||||||||||||
249 | - | |||||||||||||||||||||||||
250 | // Skip bind, convert, swizzle; they're irrelevant | - | ||||||||||||||||||||||||
251 | Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, never executed: end of block executed 263 times by 8 tests: (void)0 ; Executed by:
| 0-263 | ||||||||||||||||||||||||
252 | QQuickProfiler::SceneGraphTexturePrepareStart, 3); executed 263 times by 8 tests: (void)0 ; Executed by:
| 263 | ||||||||||||||||||||||||
253 | - | |||||||||||||||||||||||||
254 | uploadPendingTexture(i); | - | ||||||||||||||||||||||||
255 | - | |||||||||||||||||||||||||
256 | Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare, never executed: end of block executed 263 times by 8 tests: (void)0 ; Executed by:
| 0-263 | ||||||||||||||||||||||||
257 | QQuickProfiler::SceneGraphTexturePrepareUpload); executed 263 times by 8 tests: (void)0 ; Executed by:
| 263 | ||||||||||||||||||||||||
258 | - | |||||||||||||||||||||||||
259 | // Skip mipmap; unused | - | ||||||||||||||||||||||||
260 | Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, never executed: end of block executed 263 times by 8 tests: (void)0 ; Executed by:
| 0-263 | ||||||||||||||||||||||||
261 | QQuickProfiler::SceneGraphTexturePrepareUpload, 1); executed 263 times by 8 tests: (void)0 ; Executed by:
| 263 | ||||||||||||||||||||||||
262 | Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphTexturePrepare, never executed: end of block executed 263 times by 8 tests: (void)0 ; Executed by:
| 0-263 | ||||||||||||||||||||||||
263 | QQuickProfiler::SceneGraphTexturePrepareMipmap); executed 263 times by 8 tests: (void)0 ; Executed by:
| 263 | ||||||||||||||||||||||||
264 | } | - | ||||||||||||||||||||||||
265 | - | |||||||||||||||||||||||||
266 | GLenum f = filtering == QSGTexture::Nearest ? GL_NEAREST : GL_LINEAR;
| 32-1405 | ||||||||||||||||||||||||
267 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f); | - | ||||||||||||||||||||||||
268 | funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f); | - | ||||||||||||||||||||||||
269 | - | |||||||||||||||||||||||||
270 | m_pending_uploads.clear(); | - | ||||||||||||||||||||||||
271 | } executed 1437 times by 8 tests: end of block Executed by:
| 1437 | ||||||||||||||||||||||||
272 | - | |||||||||||||||||||||||||
273 | void AtlasBase::remove(TextureBase *t) | - | ||||||||||||||||||||||||
274 | { | - | ||||||||||||||||||||||||
275 | QRect atlasRect = t->atlasSubRect(); | - | ||||||||||||||||||||||||
276 | m_allocator.deallocate(atlasRect); | - | ||||||||||||||||||||||||
277 | m_pending_uploads.removeOne(t); | - | ||||||||||||||||||||||||
278 | } executed 289 times by 8 tests: end of block Executed by:
| 289 | ||||||||||||||||||||||||
279 | - | |||||||||||||||||||||||||
280 | Atlas::Atlas(const QSize &size) | - | ||||||||||||||||||||||||
281 | : AtlasBase(size) | - | ||||||||||||||||||||||||
282 | , m_atlas_transient_image_threshold(0) | - | ||||||||||||||||||||||||
283 | { | - | ||||||||||||||||||||||||
284 | - | |||||||||||||||||||||||||
285 | m_internalFormat = GL_RGBA; | - | ||||||||||||||||||||||||
286 | m_externalFormat = GL_BGRA; | - | ||||||||||||||||||||||||
287 | - | |||||||||||||||||||||||||
288 | #ifndef QT_OPENGL_ES | - | ||||||||||||||||||||||||
289 | if (QOpenGLContext::currentContext()->isOpenGLES()) {
| 0-137 | ||||||||||||||||||||||||
290 | #endif | - | ||||||||||||||||||||||||
291 | - | |||||||||||||||||||||||||
292 | #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) | - | ||||||||||||||||||||||||
293 | QString *deviceName = | - | ||||||||||||||||||||||||
294 | static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName")); | - | ||||||||||||||||||||||||
295 | static bool wrongfullyReportsBgra8888Support = deviceName != 0 | - | ||||||||||||||||||||||||
296 | && (deviceName->compare(QLatin1String("samsung SM-T211"), Qt::CaseInsensitive) == 0 | - | ||||||||||||||||||||||||
297 | || deviceName->compare(QLatin1String("samsung SM-T210"), Qt::CaseInsensitive) == 0 | - | ||||||||||||||||||||||||
298 | || deviceName->compare(QLatin1String("samsung SM-T215"), Qt::CaseInsensitive) == 0); | - | ||||||||||||||||||||||||
299 | #else | - | ||||||||||||||||||||||||
300 | static bool wrongfullyReportsBgra8888Support = false; | - | ||||||||||||||||||||||||
301 | // The Raspberry Pi (both 1 and 2) GPU refuses framebuffers with BGRA color attachments. | - | ||||||||||||||||||||||||
302 | const GLubyte *renderer = QOpenGLContext::currentContext()->functions()->glGetString(GL_RENDERER); | - | ||||||||||||||||||||||||
303 | if (renderer && strstr((const char *) renderer, "VideoCore IV"))
| 0 | ||||||||||||||||||||||||
304 | wrongfullyReportsBgra8888Support = true; never executed: wrongfullyReportsBgra8888Support = true; | 0 | ||||||||||||||||||||||||
305 | #endif // ANDROID | - | ||||||||||||||||||||||||
306 | - | |||||||||||||||||||||||||
307 | if (qEnvironmentVariableIsSet("QSG_ATLAS_NO_BGRA_WORKAROUNDS"))
| 0 | ||||||||||||||||||||||||
308 | wrongfullyReportsBgra8888Support = false; never executed: wrongfullyReportsBgra8888Support = false; | 0 | ||||||||||||||||||||||||
309 | - | |||||||||||||||||||||||||
310 | const char *ext = (const char *) QOpenGLContext::currentContext()->functions()->glGetString(GL_EXTENSIONS); | - | ||||||||||||||||||||||||
311 | if (ext && !wrongfullyReportsBgra8888Support
| 0 | ||||||||||||||||||||||||
312 | && (strstr(ext, "GL_EXT_bgra")
| 0 | ||||||||||||||||||||||||
313 | || strstr(ext, "GL_EXT_texture_format_BGRA8888")
| 0 | ||||||||||||||||||||||||
314 | || strstr(ext, "GL_IMG_texture_format_BGRA8888"))) {
| 0 | ||||||||||||||||||||||||
315 | m_internalFormat = m_externalFormat = GL_BGRA; | - | ||||||||||||||||||||||||
316 | #if defined(Q_OS_DARWIN) && !defined(Q_OS_OSX) | - | ||||||||||||||||||||||||
317 | } else if (ext && strstr(ext, "GL_APPLE_texture_format_BGRA8888")) { | - | ||||||||||||||||||||||||
318 | m_internalFormat = GL_RGBA; | - | ||||||||||||||||||||||||
319 | m_externalFormat = GL_BGRA; | - | ||||||||||||||||||||||||
320 | #endif // IOS || TVOS | - | ||||||||||||||||||||||||
321 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
322 | m_internalFormat = m_externalFormat = GL_RGBA; | - | ||||||||||||||||||||||||
323 | } never executed: end of block | 0 | ||||||||||||||||||||||||
324 | - | |||||||||||||||||||||||||
325 | #ifndef QT_OPENGL_ES | - | ||||||||||||||||||||||||
326 | } | - | ||||||||||||||||||||||||
327 | #endif | - | ||||||||||||||||||||||||
328 | - | |||||||||||||||||||||||||
329 | m_use_bgra_fallback = qEnvironmentVariableIsSet("QSG_ATLAS_USE_BGRA_FALLBACK"); | - | ||||||||||||||||||||||||
330 | m_debug_overlay = qEnvironmentVariableIsSet("QSG_ATLAS_OVERLAY"); | - | ||||||||||||||||||||||||
331 | - | |||||||||||||||||||||||||
332 | // images smaller than this will retain their QImage. | - | ||||||||||||||||||||||||
333 | // by default no images are retained (favoring memory) | - | ||||||||||||||||||||||||
334 | // set to a very large value to retain all images (allowing quick removal from the atlas) | - | ||||||||||||||||||||||||
335 | m_atlas_transient_image_threshold = qt_sg_envInt("QSG_ATLAS_TRANSIENT_IMAGE_THRESHOLD", 0); | - | ||||||||||||||||||||||||
336 | } executed 137 times by 8 tests: end of block Executed by:
| 137 | ||||||||||||||||||||||||
337 | - | |||||||||||||||||||||||||
338 | Atlas::~Atlas() | - | ||||||||||||||||||||||||
339 | { | - | ||||||||||||||||||||||||
340 | } | - | ||||||||||||||||||||||||
341 | - | |||||||||||||||||||||||||
342 | Texture *Atlas::create(const QImage &image) | - | ||||||||||||||||||||||||
343 | { | - | ||||||||||||||||||||||||
344 | // No need to lock, as manager already locked it. | - | ||||||||||||||||||||||||
345 | QRect rect = m_allocator.allocate(QSize(image.width() + 2, image.height() + 2)); | - | ||||||||||||||||||||||||
346 | if (rect.width() > 0 && rect.height() > 0) {
| 0-289 | ||||||||||||||||||||||||
347 | Texture *t = new Texture(this, rect, image); | - | ||||||||||||||||||||||||
348 | m_pending_uploads << t; | - | ||||||||||||||||||||||||
349 | return t; executed 289 times by 8 tests: return t; Executed by:
| 289 | ||||||||||||||||||||||||
350 | } | - | ||||||||||||||||||||||||
351 | return nullptr; executed 12 times by 1 test: return nullptr; Executed by:
| 12 | ||||||||||||||||||||||||
352 | } | - | ||||||||||||||||||||||||
353 | - | |||||||||||||||||||||||||
354 | static void swizzleBGRAToRGBA(QImage *image) | - | ||||||||||||||||||||||||
355 | { | - | ||||||||||||||||||||||||
356 | const int width = image->width(); | - | ||||||||||||||||||||||||
357 | const int height = image->height(); | - | ||||||||||||||||||||||||
358 | uint *p = (uint *) image->bits(); | - | ||||||||||||||||||||||||
359 | int stride = image->bytesPerLine() / 4; | - | ||||||||||||||||||||||||
360 | for (int i = 0; i < height; ++i) {
| 0 | ||||||||||||||||||||||||
361 | for (int x = 0; x < width; ++x)
| 0 | ||||||||||||||||||||||||
362 | p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00); never executed: p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00); | 0 | ||||||||||||||||||||||||
363 | p += stride; | - | ||||||||||||||||||||||||
364 | } never executed: end of block | 0 | ||||||||||||||||||||||||
365 | } never executed: end of block | 0 | ||||||||||||||||||||||||
366 | - | |||||||||||||||||||||||||
367 | void Atlas::upload(Texture *texture) | - | ||||||||||||||||||||||||
368 | { | - | ||||||||||||||||||||||||
369 | const QImage &image = texture->image(); | - | ||||||||||||||||||||||||
370 | const QRect &r = texture->atlasSubRect(); | - | ||||||||||||||||||||||||
371 | - | |||||||||||||||||||||||||
372 | QImage tmp(r.width(), r.height(), QImage::Format_ARGB32_Premultiplied); | - | ||||||||||||||||||||||||
373 | { | - | ||||||||||||||||||||||||
374 | QPainter p(&tmp); | - | ||||||||||||||||||||||||
375 | p.setCompositionMode(QPainter::CompositionMode_Source); | - | ||||||||||||||||||||||||
376 | - | |||||||||||||||||||||||||
377 | int w = r.width(); | - | ||||||||||||||||||||||||
378 | int h = r.height(); | - | ||||||||||||||||||||||||
379 | int iw = image.width(); | - | ||||||||||||||||||||||||
380 | int ih = image.height(); | - | ||||||||||||||||||||||||
381 | - | |||||||||||||||||||||||||
382 | p.drawImage(1, 1, image); | - | ||||||||||||||||||||||||
383 | p.drawImage(1, 0, image, 0, 0, iw, 1); | - | ||||||||||||||||||||||||
384 | p.drawImage(1, h - 1, image, 0, ih - 1, iw, 1); | - | ||||||||||||||||||||||||
385 | p.drawImage(0, 1, image, 0, 0, 1, ih); | - | ||||||||||||||||||||||||
386 | p.drawImage(w - 1, 1, image, iw - 1, 0, 1, ih); | - | ||||||||||||||||||||||||
387 | p.drawImage(0, 0, image, 0, 0, 1, 1); | - | ||||||||||||||||||||||||
388 | p.drawImage(0, h - 1, image, 0, ih - 1, 1, 1); | - | ||||||||||||||||||||||||
389 | p.drawImage(w - 1, 0, image, iw - 1, 0, 1, 1); | - | ||||||||||||||||||||||||
390 | p.drawImage(w - 1, h - 1, image, iw - 1, ih - 1, 1, 1); | - | ||||||||||||||||||||||||
391 | if (m_debug_overlay) {
| 0 | ||||||||||||||||||||||||
392 | p.setCompositionMode(QPainter::CompositionMode_SourceAtop); | - | ||||||||||||||||||||||||
393 | p.fillRect(0, 0, iw, ih, QBrush(QColor::fromRgbF(1, 0, 1, 0.5))); | - | ||||||||||||||||||||||||
394 | } never executed: end of block | 0 | ||||||||||||||||||||||||
395 | } | - | ||||||||||||||||||||||||
396 | - | |||||||||||||||||||||||||
397 | if (m_externalFormat == GL_RGBA)
| 0 | ||||||||||||||||||||||||
398 | swizzleBGRAToRGBA(&tmp); never executed: swizzleBGRAToRGBA(&tmp); | 0 | ||||||||||||||||||||||||
399 | QOpenGLContext::currentContext()->functions()->glTexSubImage2D(GL_TEXTURE_2D, 0, | - | ||||||||||||||||||||||||
400 | r.x(), r.y(), r.width(), r.height(), | - | ||||||||||||||||||||||||
401 | m_externalFormat, GL_UNSIGNED_BYTE, tmp.constBits()); | - | ||||||||||||||||||||||||
402 | } never executed: end of block | 0 | ||||||||||||||||||||||||
403 | - | |||||||||||||||||||||||||
404 | void Atlas::uploadBgra(Texture *texture) | - | ||||||||||||||||||||||||
405 | { | - | ||||||||||||||||||||||||
406 | QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); | - | ||||||||||||||||||||||||
407 | const QRect &r = texture->atlasSubRect(); | - | ||||||||||||||||||||||||
408 | QImage image = texture->image(); | - | ||||||||||||||||||||||||
409 | - | |||||||||||||||||||||||||
410 | if (image.isNull())
| 0-263 | ||||||||||||||||||||||||
411 | return; never executed: return; | 0 | ||||||||||||||||||||||||
412 | - | |||||||||||||||||||||||||
413 | if (image.format() != QImage::Format_ARGB32_Premultiplied
| 72-191 | ||||||||||||||||||||||||
414 | && image.format() != QImage::Format_RGB32) {
| 0-72 | ||||||||||||||||||||||||
415 | image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); | - | ||||||||||||||||||||||||
416 | } never executed: end of block | 0 | ||||||||||||||||||||||||
417 | - | |||||||||||||||||||||||||
418 | if (m_debug_overlay) {
| 0-263 | ||||||||||||||||||||||||
419 | QPainter p(&image); | - | ||||||||||||||||||||||||
420 | p.setCompositionMode(QPainter::CompositionMode_SourceAtop); | - | ||||||||||||||||||||||||
421 | p.fillRect(0, 0, image.width(), image.height(), QBrush(QColor::fromRgbF(0, 1, 1, 0.5))); | - | ||||||||||||||||||||||||
422 | } never executed: end of block | 0 | ||||||||||||||||||||||||
423 | - | |||||||||||||||||||||||||
424 | QVarLengthArray<quint32, 512> tmpBits(qMax(image.width() + 2, image.height() + 2)); | - | ||||||||||||||||||||||||
425 | int iw = image.width(); | - | ||||||||||||||||||||||||
426 | int ih = image.height(); | - | ||||||||||||||||||||||||
427 | int bpl = image.bytesPerLine() / 4; | - | ||||||||||||||||||||||||
428 | const quint32 *src = (const quint32 *) image.constBits(); | - | ||||||||||||||||||||||||
429 | quint32 *dst = tmpBits.data(); | - | ||||||||||||||||||||||||
430 | - | |||||||||||||||||||||||||
431 | // top row, padding corners | - | ||||||||||||||||||||||||
432 | dst[0] = src[0]; | - | ||||||||||||||||||||||||
433 | memcpy(dst + 1, src, iw * sizeof(quint32)); | - | ||||||||||||||||||||||||
434 | dst[1 + iw] = src[iw-1]; | - | ||||||||||||||||||||||||
435 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), iw + 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, dst); | - | ||||||||||||||||||||||||
436 | - | |||||||||||||||||||||||||
437 | // bottom row, padded corners | - | ||||||||||||||||||||||||
438 | const quint32 *lastRow = src + bpl * (ih - 1); | - | ||||||||||||||||||||||||
439 | dst[0] = lastRow[0]; | - | ||||||||||||||||||||||||
440 | memcpy(dst + 1, lastRow, iw * sizeof(quint32)); | - | ||||||||||||||||||||||||
441 | dst[1 + iw] = lastRow[iw-1]; | - | ||||||||||||||||||||||||
442 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y() + ih + 1, iw + 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, dst); | - | ||||||||||||||||||||||||
443 | - | |||||||||||||||||||||||||
444 | // left column | - | ||||||||||||||||||||||||
445 | for (int i=0; i<ih; ++i)
| 263-20294 | ||||||||||||||||||||||||
446 | dst[i] = src[i * bpl]; executed 20294 times by 8 tests: dst[i] = src[i * bpl]; Executed by:
| 20294 | ||||||||||||||||||||||||
447 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst); | - | ||||||||||||||||||||||||
448 | - | |||||||||||||||||||||||||
449 | // right column | - | ||||||||||||||||||||||||
450 | for (int i=0; i<ih; ++i)
| 263-20294 | ||||||||||||||||||||||||
451 | dst[i] = src[i * bpl + iw - 1]; executed 20294 times by 8 tests: dst[i] = src[i * bpl + iw - 1]; Executed by:
| 20294 | ||||||||||||||||||||||||
452 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + iw + 1, r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst); | - | ||||||||||||||||||||||||
453 | - | |||||||||||||||||||||||||
454 | // Inner part of the image.... | - | ||||||||||||||||||||||||
455 | if (bpl != iw) {
| 0-263 | ||||||||||||||||||||||||
456 | int sy = r.y() + 1; | - | ||||||||||||||||||||||||
457 | int ey = sy + r.height() - 2; | - | ||||||||||||||||||||||||
458 | for (int y = sy; y < ey; ++y) {
| 0 | ||||||||||||||||||||||||
459 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, y, r.width() - 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, src); | - | ||||||||||||||||||||||||
460 | src += bpl; | - | ||||||||||||||||||||||||
461 | } never executed: end of block | 0 | ||||||||||||||||||||||||
462 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
463 | funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, m_externalFormat, GL_UNSIGNED_BYTE, src); | - | ||||||||||||||||||||||||
464 | } executed 263 times by 8 tests: end of block Executed by:
| 263 | ||||||||||||||||||||||||
465 | } | - | ||||||||||||||||||||||||
466 | - | |||||||||||||||||||||||||
467 | void Atlas::generateTexture() | - | ||||||||||||||||||||||||
468 | { | - | ||||||||||||||||||||||||
469 | QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); | - | ||||||||||||||||||||||||
470 | funcs->glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, nullptr); | - | ||||||||||||||||||||||||
471 | - | |||||||||||||||||||||||||
472 | #if 0 | - | ||||||||||||||||||||||||
473 | QImage pink(m_size.width(), m_size.height(), QImage::Format_ARGB32_Premultiplied); | - | ||||||||||||||||||||||||
474 | pink.fill(0); | - | ||||||||||||||||||||||||
475 | QPainter p(&pink); | - | ||||||||||||||||||||||||
476 | QLinearGradient redGrad(0, 0, m_size.width(), 0); | - | ||||||||||||||||||||||||
477 | redGrad.setColorAt(0, Qt::black); | - | ||||||||||||||||||||||||
478 | redGrad.setColorAt(1, Qt::red); | - | ||||||||||||||||||||||||
479 | p.fillRect(0, 0, m_size.width(), m_size.height(), redGrad); | - | ||||||||||||||||||||||||
480 | p.setCompositionMode(QPainter::CompositionMode_Plus); | - | ||||||||||||||||||||||||
481 | QLinearGradient blueGrad(0, 0, 0, m_size.height()); | - | ||||||||||||||||||||||||
482 | blueGrad.setColorAt(0, Qt::black); | - | ||||||||||||||||||||||||
483 | blueGrad.setColorAt(1, Qt::blue); | - | ||||||||||||||||||||||||
484 | p.fillRect(0, 0, m_size.width(), m_size.height(), blueGrad); | - | ||||||||||||||||||||||||
485 | p.end(); | - | ||||||||||||||||||||||||
486 | - | |||||||||||||||||||||||||
487 | funcs->glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, pink.constBits()); | - | ||||||||||||||||||||||||
488 | #endif | - | ||||||||||||||||||||||||
489 | } executed 113 times by 8 tests: end of block Executed by:
| 113 | ||||||||||||||||||||||||
490 | - | |||||||||||||||||||||||||
491 | void Atlas::uploadPendingTexture(int i) | - | ||||||||||||||||||||||||
492 | { | - | ||||||||||||||||||||||||
493 | Texture *t = static_cast<Texture*>(m_pending_uploads.at(i)); | - | ||||||||||||||||||||||||
494 | if (m_externalFormat == GL_BGRA &&
| 0-263 | ||||||||||||||||||||||||
495 | !m_use_bgra_fallback) {
| 0-263 | ||||||||||||||||||||||||
496 | uploadBgra(t); | - | ||||||||||||||||||||||||
497 | } else { executed 263 times by 8 tests: end of block Executed by:
| 263 | ||||||||||||||||||||||||
498 | upload(t); | - | ||||||||||||||||||||||||
499 | } never executed: end of block | 0 | ||||||||||||||||||||||||
500 | const QSize textureSize = t->textureSize(); | - | ||||||||||||||||||||||||
501 | if (textureSize.width() > m_atlas_transient_image_threshold ||
| 0-263 | ||||||||||||||||||||||||
502 | textureSize.height() > m_atlas_transient_image_threshold)
| 0 | ||||||||||||||||||||||||
503 | t->releaseImage(); executed 263 times by 8 tests: t->releaseImage(); Executed by:
| 263 | ||||||||||||||||||||||||
504 | - | |||||||||||||||||||||||||
505 | qCDebug(QSG_LOG_TIME_TEXTURE, "atlastexture uploaded in: %lldms (%dx%d)", never executed: QMessageLogger( __FILE__ , 508 , __PRETTY_FUNCTION__, QSG_LOG_TIME_TEXTURE().categoryName()).debug("atlastexture uploaded in: %lldms (%dx%d)", qsg_renderer_timer.elapsed(), t->textureSize().width(), t->textureSize().height()) ;
| 0-263 | ||||||||||||||||||||||||
506 | qsg_renderer_timer.elapsed(), never executed: QMessageLogger( __FILE__ , 508 , __PRETTY_FUNCTION__, QSG_LOG_TIME_TEXTURE().categoryName()).debug("atlastexture uploaded in: %lldms (%dx%d)", qsg_renderer_timer.elapsed(), t->textureSize().width(), t->textureSize().height()) ; | 0 | ||||||||||||||||||||||||
507 | t->textureSize().width(), never executed: QMessageLogger( __FILE__ , 508 , __PRETTY_FUNCTION__, QSG_LOG_TIME_TEXTURE().categoryName()).debug("atlastexture uploaded in: %lldms (%dx%d)", qsg_renderer_timer.elapsed(), t->textureSize().width(), t->textureSize().height()) ; | 0 | ||||||||||||||||||||||||
508 | t->textureSize().height()); never executed: QMessageLogger( __FILE__ , 508 , __PRETTY_FUNCTION__, QSG_LOG_TIME_TEXTURE().categoryName()).debug("atlastexture uploaded in: %lldms (%dx%d)", qsg_renderer_timer.elapsed(), t->textureSize().width(), t->textureSize().height()) ; | 0 | ||||||||||||||||||||||||
509 | } executed 263 times by 8 tests: end of block Executed by:
| 263 | ||||||||||||||||||||||||
510 | - | |||||||||||||||||||||||||
511 | TextureBase::TextureBase(AtlasBase *atlas, const QRect &textureRect) | - | ||||||||||||||||||||||||
512 | : m_allocated_rect(textureRect) | - | ||||||||||||||||||||||||
513 | , m_atlas(atlas) | - | ||||||||||||||||||||||||
514 | { | - | ||||||||||||||||||||||||
515 | } executed 289 times by 8 tests: end of block Executed by:
| 289 | ||||||||||||||||||||||||
516 | - | |||||||||||||||||||||||||
517 | TextureBase::~TextureBase() | - | ||||||||||||||||||||||||
518 | { | - | ||||||||||||||||||||||||
519 | m_atlas->remove(this); | - | ||||||||||||||||||||||||
520 | } executed 289 times by 8 tests: end of block Executed by:
| 289 | ||||||||||||||||||||||||
521 | - | |||||||||||||||||||||||||
522 | void TextureBase::bind() | - | ||||||||||||||||||||||||
523 | { | - | ||||||||||||||||||||||||
524 | m_atlas->bind(filtering()); | - | ||||||||||||||||||||||||
525 | } executed 1437 times by 8 tests: end of block Executed by:
| 1437 | ||||||||||||||||||||||||
526 | - | |||||||||||||||||||||||||
527 | Texture::Texture(Atlas *atlas, const QRect &textureRect, const QImage &image) | - | ||||||||||||||||||||||||
528 | : TextureBase(atlas, textureRect) | - | ||||||||||||||||||||||||
529 | , m_image(image) | - | ||||||||||||||||||||||||
530 | , m_nonatlas_texture(nullptr) | - | ||||||||||||||||||||||||
531 | , m_has_alpha(image.hasAlphaChannel()) | - | ||||||||||||||||||||||||
532 | { | - | ||||||||||||||||||||||||
533 | float w = atlas->size().width(); | - | ||||||||||||||||||||||||
534 | float h = atlas->size().height(); | - | ||||||||||||||||||||||||
535 | QRect nopad = atlasSubRectWithoutPadding(); | - | ||||||||||||||||||||||||
536 | m_texture_coords_rect = QRectF(nopad.x() / w, | - | ||||||||||||||||||||||||
537 | nopad.y() / h, | - | ||||||||||||||||||||||||
538 | nopad.width() / w, | - | ||||||||||||||||||||||||
539 | nopad.height() / h); | - | ||||||||||||||||||||||||
540 | } executed 289 times by 8 tests: end of block Executed by:
| 289 | ||||||||||||||||||||||||
541 | - | |||||||||||||||||||||||||
542 | Texture::~Texture() | - | ||||||||||||||||||||||||
543 | { | - | ||||||||||||||||||||||||
544 | if (m_nonatlas_texture)
| 14-275 | ||||||||||||||||||||||||
545 | delete m_nonatlas_texture; executed 14 times by 3 tests: delete m_nonatlas_texture; Executed by:
| 14 | ||||||||||||||||||||||||
546 | } executed 289 times by 8 tests: end of block Executed by:
| 289 | ||||||||||||||||||||||||
547 | - | |||||||||||||||||||||||||
548 | QSGTexture *Texture::removedFromAtlas() const | - | ||||||||||||||||||||||||
549 | { | - | ||||||||||||||||||||||||
550 | if (m_nonatlas_texture) {
| 0-14 | ||||||||||||||||||||||||
551 | m_nonatlas_texture->setMipmapFiltering(mipmapFiltering()); | - | ||||||||||||||||||||||||
552 | m_nonatlas_texture->setFiltering(filtering()); | - | ||||||||||||||||||||||||
553 | return m_nonatlas_texture; never executed: return m_nonatlas_texture; | 0 | ||||||||||||||||||||||||
554 | } | - | ||||||||||||||||||||||||
555 | - | |||||||||||||||||||||||||
556 | if (!m_image.isNull()) {
| 2-12 | ||||||||||||||||||||||||
557 | m_nonatlas_texture = new QSGPlainTexture(); | - | ||||||||||||||||||||||||
558 | m_nonatlas_texture->setImage(m_image); | - | ||||||||||||||||||||||||
559 | m_nonatlas_texture->setFiltering(filtering()); | - | ||||||||||||||||||||||||
560 | - | |||||||||||||||||||||||||
561 | } else { executed 12 times by 2 tests: end of block Executed by:
| 12 | ||||||||||||||||||||||||
562 | QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); | - | ||||||||||||||||||||||||
563 | // bind the atlas texture as an fbo and extract the texture.. | - | ||||||||||||||||||||||||
564 | - | |||||||||||||||||||||||||
565 | // First extract the currently bound fbo so we can restore it later. | - | ||||||||||||||||||||||||
566 | GLint currentFbo; | - | ||||||||||||||||||||||||
567 | f->glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤tFbo); | - | ||||||||||||||||||||||||
568 | - | |||||||||||||||||||||||||
569 | // Create an FBO and bind the atlas texture into it. | - | ||||||||||||||||||||||||
570 | GLuint fbo; | - | ||||||||||||||||||||||||
571 | f->glGenFramebuffers(1, &fbo); | - | ||||||||||||||||||||||||
572 | f->glBindFramebuffer(GL_FRAMEBUFFER, fbo); | - | ||||||||||||||||||||||||
573 | f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_atlas->textureId(), 0); | - | ||||||||||||||||||||||||
574 | - | |||||||||||||||||||||||||
575 | // Create the target texture, QSGPlainTexture below will deal with the texparams, so we don't | - | ||||||||||||||||||||||||
576 | // need to worry about those here. | - | ||||||||||||||||||||||||
577 | GLuint texture; | - | ||||||||||||||||||||||||
578 | f->glGenTextures(1, &texture); | - | ||||||||||||||||||||||||
579 | f->glBindTexture(GL_TEXTURE_2D, texture); | - | ||||||||||||||||||||||||
580 | QRect r = atlasSubRectWithoutPadding(); | - | ||||||||||||||||||||||||
581 | // and copy atlas into our texture. | - | ||||||||||||||||||||||||
582 | while (f->glGetError() != GL_NO_ERROR) ; never executed: ;
| 0-2 | ||||||||||||||||||||||||
583 | f->glCopyTexImage2D(GL_TEXTURE_2D, 0, static_cast<Atlas*>(m_atlas)->internalFormat(), r.x(), r.y(), r.width(), r.height(), 0); | - | ||||||||||||||||||||||||
584 | // BGRA may have been rejected by some GLES implementations | - | ||||||||||||||||||||||||
585 | if (f->glGetError() != GL_NO_ERROR)
| 0-2 | ||||||||||||||||||||||||
586 | f->glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, r.x(), r.y(), r.width(), r.height(), 0); never executed: f->glCopyTexImage2D( 0x0DE1 , 0, 0x1908 , r.x(), r.y(), r.width(), r.height(), 0); | 0 | ||||||||||||||||||||||||
587 | - | |||||||||||||||||||||||||
588 | m_nonatlas_texture = new QSGPlainTexture(); | - | ||||||||||||||||||||||||
589 | m_nonatlas_texture->setTextureId(texture); | - | ||||||||||||||||||||||||
590 | m_nonatlas_texture->setOwnsTexture(true); | - | ||||||||||||||||||||||||
591 | m_nonatlas_texture->setHasAlphaChannel(m_has_alpha); | - | ||||||||||||||||||||||||
592 | m_nonatlas_texture->setTextureSize(r.size()); | - | ||||||||||||||||||||||||
593 | - | |||||||||||||||||||||||||
594 | // cleanup: unbind our atlas from the fbo, rebind the old default and delete the fbo. | - | ||||||||||||||||||||||||
595 | f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); | - | ||||||||||||||||||||||||
596 | f->glBindFramebuffer(GL_FRAMEBUFFER, (GLuint) currentFbo); | - | ||||||||||||||||||||||||
597 | f->glDeleteFramebuffers(1, &fbo); | - | ||||||||||||||||||||||||
598 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||||||||
599 | - | |||||||||||||||||||||||||
600 | m_nonatlas_texture->setMipmapFiltering(mipmapFiltering()); | - | ||||||||||||||||||||||||
601 | m_nonatlas_texture->setFiltering(filtering()); | - | ||||||||||||||||||||||||
602 | return m_nonatlas_texture; executed 14 times by 3 tests: return m_nonatlas_texture; Executed by:
| 14 | ||||||||||||||||||||||||
603 | } | - | ||||||||||||||||||||||||
604 | - | |||||||||||||||||||||||||
605 | } | - | ||||||||||||||||||||||||
606 | - | |||||||||||||||||||||||||
607 | QT_END_NAMESPACE | - | ||||||||||||||||||||||||
608 | - | |||||||||||||||||||||||||
609 | #include "moc_qsgatlastexture_p.cpp" | - | ||||||||||||||||||||||||
Source code | Switch to Preprocessed file |