From ad6dafee9be288bcef6b2c4b318b234d2995abff Mon Sep 17 00:00:00 2001 From: aavit Date: Mon, 10 May 2010 16:23:44 +0200 Subject: Optimize QPixmapIconEngine's pixmap() function Replace needlessly expensive cache key generation Task-number: QTBUG-9850 Reviewed-by: Trond --- src/gui/image/qicon.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 891b1db..5ef0ff9 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -261,21 +261,28 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height())) actualSize.scale(size, Qt::KeepAspectRatio); - QString key = QLatin1String("$qt_icon_") - + QString::number(pm.cacheKey()) - + QString::number(pe->mode) - + QString::number(QApplication::palette().cacheKey()) - + QLatin1Char('_') - + QString::number(actualSize.width()) - + QLatin1Char('_') - + QString::number(actualSize.height()) - + QLatin1Char('_'); - + struct { + quint64 pmc; + qint32 w; + qint32 h; + quint64 pac; + qint32 m; // Make struct size a multiple of 4, for safety's sake + } dill; + + dill.pmc = pm.cacheKey(); + dill.w = actualSize.width(); + dill.h = actualSize.height(); + dill.pac = QApplication::palette().cacheKey(); + dill.m = pe->mode; + + QString keyBase = QLatin1String("$qt_icon_") + + QString::fromRawData((QChar *)&dill, sizeof(dill)/sizeof(QChar)); + QString key = keyBase + QString::number(mode, 16); if (mode == QIcon::Active) { - if (QPixmapCache::find(key + QString::number(mode), pm)) + if (QPixmapCache::find(key, pm)) return pm; // horray - if (QPixmapCache::find(key + QString::number(QIcon::Normal), pm)) { + if (QPixmapCache::find(keyBase + QString::number(QIcon::Normal, 16), pm)) { QStyleOption opt(0); opt.palette = QApplication::palette(); QPixmap active = QApplication::style()->generatedIconPixmap(QIcon::Active, pm, &opt); @@ -284,7 +291,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St } } - if (!QPixmapCache::find(key + QString::number(mode), pm)) { + if (!QPixmapCache::find(key, pm)) { if (pm.size() != actualSize) pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); if (pe->mode != mode && mode != QIcon::Normal) { @@ -294,7 +301,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St if (!generated.isNull()) pm = generated; } - QPixmapCache::insert(key + QString::number(mode), pm); + QPixmapCache::insert(key, pm); } return pm; } -- cgit v0.12 From 3f775da6fec8b5cfb5e538100b7889401d14c410 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Fri, 14 May 2010 08:04:54 +0200 Subject: Add missing file! Amendment to 812f78e55aa3db4d51ec8617320358d80c4a71d5. --- examples/graphicsview/padnavigator/form.ui | 208 +++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 examples/graphicsview/padnavigator/form.ui diff --git a/examples/graphicsview/padnavigator/form.ui b/examples/graphicsview/padnavigator/form.ui new file mode 100644 index 0000000..fc7d123 --- /dev/null +++ b/examples/graphicsview/padnavigator/form.ui @@ -0,0 +1,208 @@ + + Form + + + + 0 + 0 + 378 + 385 + + + + BackSide + + + + + + Settings + + + true + + + true + + + + + + Title: + + + + + + + Pad Navigator Example + + + + + + + Modified: + + + + + + + Extent + + + + + + + + + 42 + + + Qt::Horizontal + + + + + + + 42 + + + + + + + + + + + + + + + Other input + + + true + + + true + + + + + + + Widgets On Graphics View + + + + + QGraphicsProxyWidget + + + + QGraphicsWidget + + + + QObject + + + + + QGraphicsItem + + + + + QGraphicsLayoutItem + + + + + + + QGraphicsGridLayout + + + + QGraphicsLayout + + + + QGraphicsLayoutItem + + + + + + + QGraphicsLinearLayout + + + + QGraphicsLayout + + + + QGraphicsLayoutItem + + + + + + + + + + + + + groupBox + hostName + dateTimeEdit + horizontalSlider + spinBox + groupBox_2 + treeWidget + + + + + horizontalSlider + valueChanged(int) + spinBox + setValue(int) + + + 184 + 125 + + + 275 + 127 + + + + + spinBox + valueChanged(int) + horizontalSlider + setValue(int) + + + 272 + 114 + + + 190 + 126 + + + + + -- cgit v0.12 From 9a69656bd64016933124813ea5403e7e5d454719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Fri, 14 May 2010 15:42:43 +0200 Subject: Added workarounds for two MBX/SGX specific GL ES bugs/problems. The workaround flags are put into the platform independent section for now, since there might be a general need for these as we expand our GL and GL ES usage. The workaround_needsFullClearOnEveryFrame flag covers the case where you get a performance penalty on PowerVR hw if all rendering buffers are not cleared. The workaround_brokenFBOReadBack flag covers the case where copying pixels from a texture (e.g. via glCopyTexSubImage2d()) bound in an FBO doesn't work. Task-number: QTBUG-10670 Reviewed-by: Gunnar --- .../gl2paintengineex/qtextureglyphcache_gl.cpp | 18 +++++------------- .../gl2paintengineex/qtextureglyphcache_gl_p.h | 2 -- src/opengl/qgl.cpp | 3 +++ src/opengl/qgl.h | 1 + src/opengl/qgl_egl.cpp | 20 +++++++++++++++++++- src/opengl/qgl_p.h | 8 +++++++- src/opengl/qglpaintdevice.cpp | 5 ++++- 7 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 452d37d..cc42c63 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -57,21 +57,13 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph , ctx(context) , m_width(0) , m_height(0) - , m_broken_fbo_readback(false) { // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The // workaround is to use a system-memory copy of the glyph cache for this device. // Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and // be slower, so that is not desireable. -#if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL) - if (QByteArray((char*) glGetString(GL_RENDERER)).contains("SGX")) { - QGLContextPrivate *ctxd = context->d_func(); - m_broken_fbo_readback = QByteArray((char *) eglQueryString(ctxd->eglContext->display(), EGL_VERSION)).contains("1.3"); - } -#endif - - if (!m_broken_fbo_readback) + if (!ctx->d_ptr->workaround_brokenFBOReadBack) glGenFramebuffers(1, &m_fbo); connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)), @@ -83,7 +75,7 @@ QGLTextureGlyphCache::~QGLTextureGlyphCache() if (ctx) { QGLShareContextScope scope(ctx); - if (!m_broken_fbo_readback) + if (!ctx->d_ptr->workaround_brokenFBOReadBack) glDeleteFramebuffers(1, &m_fbo); if (m_width || m_height) @@ -96,7 +88,7 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) // create in QImageTextureGlyphCache baseclass is meant to be called // only to create the initial image and does not preserve the content, // so we don't call when this function is called from resize. - if (m_broken_fbo_readback && image().isNull()) + if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull()) QImageTextureGlyphCache::createTextureData(width, height); glGenTextures(1, &m_texture); @@ -126,7 +118,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) GLuint oldTexture = m_texture; createTextureData(width, height); - if (m_broken_fbo_readback) { + if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); @@ -209,7 +201,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) { - if (m_broken_fbo_readback) { + if (ctx->d_ptr->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::fillTexture(c, glyph); glBindTexture(GL_TEXTURE_2D, m_texture); diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index efb7435..6bcd655 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -115,8 +115,6 @@ private: int m_height; QGLShaderProgram *m_program; - - bool m_broken_fbo_readback; }; QT_END_NAMESPACE diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 7c457de..922a96c 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1612,6 +1612,9 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) current_fbo = 0; default_fbo = 0; active_engine = 0; + workaround_needsFullClearOnEveryFrame = false; + workaround_brokenFBOReadBack = false; + workaroundsCached = false; for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) vertexAttributeArraysEnabledState[i] = false; } diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index 92a064f..f297009 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -431,6 +431,7 @@ private: friend class QGLFramebufferObjectPrivate; friend class QGLFBOGLPaintDevice; friend class QGLPaintDevice; + friend class QGLWidgetGLPaintDevice; friend class QX11GLPixmapData; friend class QX11GLSharedContexts; private: diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index 0fbbbf9..44e8ae9 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -185,8 +185,26 @@ void QGLContext::makeCurrent() return; } - if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) + if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) { QGLContextPrivate::setCurrentContext(this); + if (!d->workaroundsCached) { + d->workaroundsCached = true; + const char *renderer = reinterpret_cast(glGetString(GL_RENDERER)); + if (strstr(renderer, "SGX") || strstr(renderer, "MBX")) { + // PowerVR MBX/SGX chips needs to clear all buffers when starting to render + // a new frame, otherwise there will be a performance penalty to pay for + // each frame. + d->workaround_needsFullClearOnEveryFrame = true; + + // Older PowerVR SGX drivers (like the one in the N900) have a + // bug which prevents glCopyTexSubImage2D() to work with a POT + // or GL_ALPHA texture bound to an FBO. The only way to + // identify that driver is to check the EGL version number for it. + if (strstr(eglQueryString(d->eglContext->display(), EGL_VERSION), "1.3")) + d->workaround_brokenFBOReadBack = true; + } + } + } } void QGLContext::doneCurrent() diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index f19e394..d92f963 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -345,7 +345,7 @@ public: HDC hbitmap_hdc; #endif #ifndef QT_NO_EGL - bool ownsEglContext; + uint ownsEglContext : 1; QEglContext *eglContext; EGLSurface eglSurface; void destroyEglSurfaceForDevice(); @@ -382,6 +382,12 @@ public: uint internal_context : 1; uint version_flags_cached : 1; uint extension_flags_cached : 1; + + // workarounds for driver/hw bugs on different platforms + uint workaround_needsFullClearOnEveryFrame : 1; + uint workaround_brokenFBOReadBack : 1; + uint workaroundsCached : 1; + QPaintDevice *paintDevice; QColor transpColor; QGLContext *q_ptr; diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp index e874e85..e1dcbfd 100644 --- a/src/opengl/qglpaintdevice.cpp +++ b/src/opengl/qglpaintdevice.cpp @@ -175,7 +175,10 @@ void QGLWidgetGLPaintDevice::beginPaint() float alpha = c.alphaF(); glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha); } - glClear(GL_COLOR_BUFFER_BIT); + if (context()->d_func()->workaround_needsFullClearOnEveryFrame) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT); } } -- cgit v0.12 From c60045ad8df097ebcb7efa89a5fc18b3a4614df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Fri, 14 May 2010 16:37:48 +0200 Subject: Limit the lower glyph texture cache size to 16x16 in GL. The SGX chip has a limitation regarding FBOs in that it doesn't support FBO sizes that are POT and less than 16 pixels in width/height. Since the FBO we use in the GL glyph cache always mirrors the size of the texture itself, we limit that instead to avoid creating invalid FBOs. Task-number: QTBUG-10645 Reviewed-by: Gunnar --- src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index cc42c63..410cf21 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -91,6 +91,12 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull()) QImageTextureGlyphCache::createTextureData(width, height); + // Make the lower glyph texture size 16 x 16. + if (width < 16) + width = 16; + if (height < 16) + height = 16; + glGenTextures(1, &m_texture); glBindTexture(GL_TEXTURE_2D, m_texture); @@ -115,6 +121,12 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) int oldWidth = m_width; int oldHeight = m_height; + // Make the lower glyph texture size 16 x 16. + if (width < 16) + width = 16; + if (height < 16) + height = 16; + GLuint oldTexture = m_texture; createTextureData(width, height); -- cgit v0.12 From 77ddabd7fdf0c8ba2e15951e83abbcce18270285 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 14 May 2010 20:06:15 +0200 Subject: Revert "Optimize QPixmapIconEngine's pixmap() function" This reverts commit ad6dafee9be288bcef6b2c4b318b234d2995abff. This is replaced by commit c8d2e18c4b431870560f324a17f20904bb47ae68 --- src/gui/image/qicon.cpp | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 5ef0ff9..891b1db 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -261,28 +261,21 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height())) actualSize.scale(size, Qt::KeepAspectRatio); - struct { - quint64 pmc; - qint32 w; - qint32 h; - quint64 pac; - qint32 m; // Make struct size a multiple of 4, for safety's sake - } dill; - - dill.pmc = pm.cacheKey(); - dill.w = actualSize.width(); - dill.h = actualSize.height(); - dill.pac = QApplication::palette().cacheKey(); - dill.m = pe->mode; - - QString keyBase = QLatin1String("$qt_icon_") - + QString::fromRawData((QChar *)&dill, sizeof(dill)/sizeof(QChar)); - QString key = keyBase + QString::number(mode, 16); + QString key = QLatin1String("$qt_icon_") + + QString::number(pm.cacheKey()) + + QString::number(pe->mode) + + QString::number(QApplication::palette().cacheKey()) + + QLatin1Char('_') + + QString::number(actualSize.width()) + + QLatin1Char('_') + + QString::number(actualSize.height()) + + QLatin1Char('_'); + if (mode == QIcon::Active) { - if (QPixmapCache::find(key, pm)) + if (QPixmapCache::find(key + QString::number(mode), pm)) return pm; // horray - if (QPixmapCache::find(keyBase + QString::number(QIcon::Normal, 16), pm)) { + if (QPixmapCache::find(key + QString::number(QIcon::Normal), pm)) { QStyleOption opt(0); opt.palette = QApplication::palette(); QPixmap active = QApplication::style()->generatedIconPixmap(QIcon::Active, pm, &opt); @@ -291,7 +284,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St } } - if (!QPixmapCache::find(key, pm)) { + if (!QPixmapCache::find(key + QString::number(mode), pm)) { if (pm.size() != actualSize) pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); if (pe->mode != mode && mode != QIcon::Normal) { @@ -301,7 +294,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St if (!generated.isNull()) pm = generated; } - QPixmapCache::insert(key, pm); + QPixmapCache::insert(key + QString::number(mode), pm); } return pm; } -- cgit v0.12