aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/util/qsgatlastexture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/util/qsgatlastexture.cpp')
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp145
1 files changed, 63 insertions, 82 deletions
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 53b31104b3..a9cbbe1dc3 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -1,40 +1,32 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -43,11 +35,13 @@
#include <QtCore/QVarLengthArray>
#include <QtCore/QElapsedTimer>
+#include <QtCore/QtMath>
#include <QtGui/QOpenGLContext>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QSurface>
+#include <QtGui/QWindow>
#include <QtGui/qpa/qplatformnativeinterface.h>
#include <private/qsgtexture_p.h>
@@ -61,26 +55,11 @@ QT_BEGIN_NAMESPACE
#endif
-#ifndef QSG_NO_RENDER_TIMING
-static bool qsg_render_timing = !qgetenv("QSG_RENDER_TIMING").isEmpty();
static QElapsedTimer qsg_renderer_timer;
-#endif
namespace QSGAtlasTexture
{
-static inline int qsg_powerOfTwo(int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- ++v;
- return v;
-}
-
static int qsg_envInt(const char *name, int defaultValue)
{
QByteArray content = qgetenv(name);
@@ -98,16 +77,24 @@ Manager::Manager()
QSurface *surface = gl->surface();
QSize surfaceSize = surface->size();
int max;
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
+ gl->functions()->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
+
+ int w = qMin(max, qsg_envInt("QSG_ATLAS_WIDTH", qMax(512U, qNextPowerOfTwo(surfaceSize.width() - 1))));
+ int h = qMin(max, qsg_envInt("QSG_ATLAS_HEIGHT", qMax(512U, qNextPowerOfTwo(surfaceSize.height() - 1))));
- int w = qMin(max, qsg_envInt("QSG_ATLAS_WIDTH", qMax(512, qsg_powerOfTwo(surfaceSize.width()))));
- int h = qMin(max, qsg_envInt("QSG_ATLAS_HEIGHT", qMax(512, qsg_powerOfTwo(surfaceSize.height()))));
+ if (surface->surfaceClass() == QSurface::Window) {
+ QWindow *window = static_cast<QWindow *>(surface);
+ // Coverwindows, optimize for memory rather than speed
+ if ((window->type() & Qt::CoverWindow) == Qt::CoverWindow) {
+ w /= 2;
+ h /= 2;
+ }
+ }
m_atlas_size_limit = qsg_envInt("QSG_ATLAS_SIZE_LIMIT", qMax(w, h) / 2);
m_atlas_size = QSize(w, h);
- if (qEnvironmentVariableIsSet("QSG_INFO"))
- qDebug() << "QSG: texture atlas dimensions:" << w << "x" << h;
+ qCDebug(QSG_LOG_INFO, "texture atlas dimensions: %dx%d", w, h);
}
@@ -161,7 +148,7 @@ Atlas::Atlas(const QSize &size)
static bool wrongfullyReportsBgra8888Support = false;
#endif // ANDROID
- const char *ext = (const char *) glGetString(GL_EXTENSIONS);
+ const char *ext = (const char *) QOpenGLContext::currentContext()->functions()->glGetString(GL_EXTENSIONS);
if (!wrongfullyReportsBgra8888Support
&& (strstr(ext, "GL_EXT_bgra")
|| strstr(ext, "GL_EXT_texture_format_BGRA8888")
@@ -191,11 +178,9 @@ Atlas::~Atlas()
void Atlas::invalidate()
{
- Q_ASSERT(QOpenGLContext::currentContext());
- if (m_texture_id) {
- glDeleteTextures(1, &m_texture_id);
- m_texture_id = 0;
- }
+ if (m_texture_id && QOpenGLContext::currentContext())
+ QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_texture_id);
+ m_texture_id = 0;
}
Texture *Atlas::create(const QImage &image)
@@ -215,7 +200,7 @@ int Atlas::textureId() const
{
if (!m_texture_id) {
Q_ASSERT(QOpenGLContext::currentContext());
- glGenTextures(1, &const_cast<Atlas *>(this)->m_texture_id);
+ QOpenGLContext::currentContext()->functions()->glGenTextures(1, &const_cast<Atlas *>(this)->m_texture_id);
}
return m_texture_id;
@@ -266,11 +251,14 @@ void Atlas::upload(Texture *texture)
if (m_externalFormat == GL_RGBA)
swizzleBGRAToRGBA(&tmp);
- glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), r.width(), r.height(), m_externalFormat, GL_UNSIGNED_BYTE, tmp.constBits());
+ QOpenGLContext::currentContext()->functions()->glTexSubImage2D(GL_TEXTURE_2D, 0,
+ r.x(), r.y(), r.width(), r.height(),
+ m_externalFormat, GL_UNSIGNED_BYTE, tmp.constBits());
}
void Atlas::uploadBgra(Texture *texture)
{
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
const QRect &r = texture->atlasSubRect();
QImage image = texture->image();
@@ -299,57 +287,57 @@ void Atlas::uploadBgra(Texture *texture)
dst[0] = src[0];
memcpy(dst + 1, src, iw * sizeof(quint32));
dst[1 + iw] = src[iw-1];
- glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), iw + 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, dst);
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), iw + 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, dst);
// bottom row, padded corners
const quint32 *lastRow = src + bpl * (ih - 1);
dst[0] = lastRow[0];
memcpy(dst + 1, lastRow, iw * sizeof(quint32));
dst[1 + iw] = lastRow[iw-1];
- glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y() + ih + 1, iw + 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, dst);
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y() + ih + 1, iw + 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, dst);
// left column
for (int i=0; i<ih; ++i)
dst[i] = src[i * bpl];
- glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst);
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst);
// right column
for (int i=0; i<ih; ++i)
dst[i] = src[i * bpl + iw - 1];
- glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + iw + 1, r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst);
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + iw + 1, r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst);
// Inner part of the image....
if (bpl != iw) {
int sy = r.y() + 1;
int ey = sy + r.height() - 2;
for (int y = sy; y < ey; ++y) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, y, r.width() - 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, src);
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, y, r.width() - 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, src);
src += bpl;
}
} else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, m_externalFormat, GL_UNSIGNED_BYTE, src);
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, m_externalFormat, GL_UNSIGNED_BYTE, src);
}
-
}
void Atlas::bind(QSGTexture::Filtering filtering)
{
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
if (!m_allocated) {
m_allocated = true;
- while (glGetError() != GL_NO_ERROR) ;
+ while (funcs->glGetError() != GL_NO_ERROR) ;
- glGenTextures(1, &m_texture_id);
- glBindTexture(GL_TEXTURE_2D, m_texture_id);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ funcs->glGenTextures(1, &m_texture_id);
+ funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#if !defined(QT_OPENGL_ES_2)
if (!QOpenGLContext::currentContext()->isOpenGLES())
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
#endif
- glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, 0);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, 0);
#if 0
QImage pink(m_size.width(), m_size.height(), QImage::Format_ARGB32_Premultiplied);
@@ -366,21 +354,21 @@ void Atlas::bind(QSGTexture::Filtering filtering)
p.fillRect(0, 0, m_size.width(), m_size.height(), blueGrad);
p.end();
- glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, pink.constBits());
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, pink.constBits());
#endif
- GLenum errorCode = glGetError();
+ GLenum errorCode = funcs->glGetError();
if (errorCode == GL_OUT_OF_MEMORY) {
qDebug("QSGTextureAtlas: texture atlas allocation failed, out of memory");
- glDeleteTextures(1, &m_texture_id);
+ funcs->glDeleteTextures(1, &m_texture_id);
m_texture_id = 0;
} else if (errorCode != GL_NO_ERROR) {
qDebug("QSGTextureAtlas: texture atlas allocation failed, code=%x", errorCode);
- glDeleteTextures(1, &m_texture_id);
+ funcs->glDeleteTextures(1, &m_texture_id);
m_texture_id = 0;
}
} else {
- glBindTexture(GL_TEXTURE_2D, m_texture_id);
+ funcs->glBindTexture(GL_TEXTURE_2D, m_texture_id);
}
if (m_texture_id == 0)
@@ -389,11 +377,9 @@ void Atlas::bind(QSGTexture::Filtering filtering)
// Upload all pending images..
for (int i=0; i<m_pending_uploads.size(); ++i) {
-#ifndef QSG_NO_RENDER_TIMING
- bool profileFrames = qsg_render_timing || QQuickProfiler::enabled;
+ bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled() || QQuickProfiler::enabled;
if (profileFrames)
qsg_renderer_timer.start();
-#endif
if (m_externalFormat == GL_BGRA &&
!m_use_bgra_fallback) {
@@ -402,26 +388,21 @@ void Atlas::bind(QSGTexture::Filtering filtering)
upload(m_pending_uploads.at(i));
}
-#ifndef QSG_NO_RENDER_TIMING
- if (qsg_render_timing) {
- qDebug(" - AtlasTexture(%dx%d), uploaded in %d ms",
- m_pending_uploads.at(i)->image().width(),
- m_pending_uploads.at(i)->image().height(),
- (int) (qsg_renderer_timer.elapsed()));
- }
+ qCDebug(QSG_LOG_TIME_TEXTURE).nospace() << "atlastexture uploaded in: " << qsg_renderer_timer.elapsed()
+ << "ms (" << m_pending_uploads.at(i)->image().width() << "x"
+ << m_pending_uploads.at(i)->image().height() << ")";
- Q_QUICK_SG_PROFILE1(QQuickProfiler::SceneGraphTexturePrepare, (
+ Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphTexturePrepare, (
0, // bind (not relevant)
0, // convert (not relevant)
0, // swizzle (not relevant)
qsg_renderer_timer.nsecsElapsed(), // (upload all of the above)
0)); // mipmap (not used ever...)
-#endif
}
GLenum f = filtering == QSGTexture::Nearest ? GL_NEAREST : GL_LINEAR;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, f);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, f);
m_pending_uploads.clear();
}