From 2e1e1cff3696c93f983db78c99e564a791d5d0ef Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 1 Jun 2010 09:39:57 +0200 Subject: Avoid unnecessary detach / deep copy in QGraphicsItem::scroll(). QGraphicsItem::scroll() scrolls the cache pixmap when cacheMode is enabled (for ItemCoordinateCache only). Because the pixmap exists both in the cache and in a temp QPixmap copy, the ref count is 2, so the scroll operation has to do a deep copy. To avoid this, we remove the pixmap from the cache before and reinsert it again after calling QPixmap::scroll(). Reviewed-by: Alexis Menard --- src/gui/graphicsview/qgraphicsitem.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 36d21a6..d284a29 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5687,11 +5687,13 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) return; } + // Find pixmap in cache, then remove to avoid deep copy when modifying.s QPixmap cachedPixmap; if (!QPixmapCache::find(cache->key, &cachedPixmap)) { update(rect); return; } + QPixmapCache::remove(cache->key); QRegion exposed; const bool scrollEntirePixmap = rect.isNull(); @@ -5707,7 +5709,8 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed); } - QPixmapCache::replace(cache->key, cachedPixmap); + // Reinsert into cache. + cache->key = QPixmapCache::insert(cachedPixmap); // Translate the existing expose. for (int i = 0; i < cache->exposed.size(); ++i) { -- cgit v0.12 From 7b581310ceb106664077052abeabbde217ea30dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 1 Jun 2010 09:19:16 +0200 Subject: Make sure we don't pull inn /usr/X11 stuff in the qws mkspek conf Reviewed-by: paul --- mkspecs/common/qws.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mkspecs/common/qws.conf b/mkspecs/common/qws.conf index 96341a7..225f0ff 100644 --- a/mkspecs/common/qws.conf +++ b/mkspecs/common/qws.conf @@ -14,6 +14,10 @@ QMAKE_INCDIR_X11 = QMAKE_LIBDIR_X11 = QMAKE_INCDIR_OPENGL = QMAKE_LIBDIR_OPENGL = +QMAKE_INCDIR_OPENGL_ES1 = +QMAKE_LIBDIR_OPENGL_ES1 = +QMAKE_INCDIR_OPENGL_ES2 = +QMAKE_LIBDIR_OPENGL_ES2 = QMAKE_LIBS_X11 = QMAKE_LIBS_X11SM = QMAKE_LIBS_OPENGL = -- cgit v0.12 From 1b6d41deebdd8103e2d8abb53bd2bb1dd26bd0ae Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 1 Jun 2010 10:50:30 +0200 Subject: Fix bug in QGraphicsItem::scroll() when called with no QRectF argument. With a null rect argument, QGraphicsItem::scroll() is supposed to scroll the whole item. When using ItemCoordinateCache, currently the only supported mode for scroll optimization, we simple scrolled the whole cache pixmap. Problem: The cache pixmap has a border of 2 pixels. So we scroll the contents _and_ the border. This leaves white/transparent horizontal and vertical line artifacts when scrolling. This change unifies the two cases - partial and full scrolling - into one (shorter) approach that works without scrolling the margin as well. Reviewed-by: Alexis Menard --- src/gui/graphicsview/qgraphicsitem.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index d284a29..9d7354a 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5695,19 +5695,12 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) } QPixmapCache::remove(cache->key); + QRect scrollRect = (rect.isNull() ? boundingRect() : rect).toAlignedRect(); + if (!scrollRect.intersects(cache->boundingRect)) + return; // Nothing to scroll. + QRegion exposed; - const bool scrollEntirePixmap = rect.isNull(); - if (scrollEntirePixmap) { - // Scroll entire pixmap. - cachedPixmap.scroll(dx, dy, cachedPixmap.rect(), &exposed); - } else { - if (!rect.intersects(cache->boundingRect)) - return; // Nothing to scroll. - // Scroll sub-rect of pixmap. The rect is in item coordinates - // so we have to translate it to pixmap coordinates. - QRect scrollRect = rect.toAlignedRect(); - cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed); - } + cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed); // Reinsert into cache. cache->key = QPixmapCache::insert(cachedPixmap); @@ -5715,7 +5708,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) // Translate the existing expose. for (int i = 0; i < cache->exposed.size(); ++i) { QRectF &e = cache->exposed[i]; - if (!scrollEntirePixmap && !e.intersects(rect)) + if (!rect.isNull() && !e.intersects(rect)) continue; e.translate(dx, dy); } -- cgit v0.12 From 805126ebc2aa9a683edefbc21d4ee7362ae26f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Tue, 1 Jun 2010 10:50:47 +0200 Subject: Fixed a problem where QPixmaps where re-bound in non-sharing contexts. If you have two non-sharing GL contexts and try to draw the same QPixmap in both of them, they will wind up competing for a spot in the texture cache. Make the context group a part of the cache key to avoid that. Task-number: QT-3462 Reviewed-by: Kim --- src/opengl/qgl.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++------- src/opengl/qgl_p.h | 36 +++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 922a96c..c8502c2 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -91,6 +91,7 @@ #include "qcolormap.h" #include "qfile.h" #include "qlibrary.h" +#include QT_BEGIN_NAMESPACE @@ -1515,10 +1516,33 @@ bool operator!=(const QGLFormat& a, const QGLFormat& b) return !(a == b); } +struct QGLContextGroupList { + void append(QGLContextGroup *group) { + QMutexLocker locker(&m_mutex); + m_list.append(group); + } + + void remove(QGLContextGroup *group) { + QMutexLocker locker(&m_mutex); + m_list.removeOne(group); + } + + QList m_list; + QMutex m_mutex; +}; + +Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups) + /***************************************************************************** QGLContext implementation *****************************************************************************/ +QGLContextGroup::QGLContextGroup(const QGLContext *context) + : m_context(context), m_guards(0), m_refs(1) +{ + qt_context_groups()->append(this); +} + QGLContextGroup::~QGLContextGroup() { // Clear any remaining QGLSharedResourceGuard objects on the group. @@ -1528,6 +1552,7 @@ QGLContextGroup::~QGLContextGroup() guard->m_id = 0; guard = guard->m_next; } + qt_context_groups()->remove(this); } void QGLContextGroup::addGuard(QGLSharedResourceGuard *guard) @@ -1736,7 +1761,7 @@ void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, i QWriteLocker locker(&m_lock); if (m_cache.totalCost() + cost > m_cache.maxCost()) { // the cache is full - make an attempt to remove something - const QList keys = m_cache.keys(); + const QList keys = m_cache.keys(); int i = 0; while (i < m_cache.count() && (m_cache.totalCost() + cost > m_cache.maxCost())) { @@ -1746,13 +1771,26 @@ void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, i ++i; } } - m_cache.insert(key, texture, cost); + const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)}; + m_cache.insert(cacheKey, texture, cost); +} + +void QGLTextureCache::remove(qint64 key) +{ + QWriteLocker locker(&m_lock); + QMutexLocker groupLocker(&qt_context_groups()->m_mutex); + QList::const_iterator it = qt_context_groups()->m_list.constBegin(); + while (it != qt_context_groups()->m_list.constEnd()) { + const QGLTextureCacheKey cacheKey = {key, *it}; + m_cache.remove(cacheKey); + ++it; + } } bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId) { QWriteLocker locker(&m_lock); - QList keys = m_cache.keys(); + QList keys = m_cache.keys(); for (int i = 0; i < keys.size(); ++i) { QGLTexture *tex = m_cache.object(keys.at(i)); if (tex->id == textureId && tex->context == ctx) { @@ -1767,9 +1805,9 @@ bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId) void QGLTextureCache::removeContextTextures(QGLContext* ctx) { QWriteLocker locker(&m_lock); - QList keys = m_cache.keys(); + QList keys = m_cache.keys(); for (int i = 0; i < keys.size(); ++i) { - const qint64 &key = keys.at(i); + const QGLTextureCacheKey &key = keys.at(i); if (m_cache.object(key)->context == ctx) m_cache.remove(key); } @@ -1782,7 +1820,6 @@ void QGLTextureCache::removeContextTextures(QGLContext* ctx) void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey) { qt_gl_texture_cache()->remove(cacheKey); - Q_ASSERT(qt_gl_texture_cache()->getTexture(cacheKey) == 0); } @@ -2425,7 +2462,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target) { Q_Q(QGLContext); - QGLTexture *texture = QGLTextureCache::instance()->getTexture(key); + QGLTexture *texture = QGLTextureCache::instance()->getTexture(q, key); if (texture && texture->target == target && (texture->context == q || QGLContext::areSharing(q, texture->context))) { diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index d92f963..16c225f 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -230,7 +230,7 @@ public: static void addShare(const QGLContext *context, const QGLContext *share); static void removeShare(const QGLContext *context); private: - QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { } + QGLContextGroup(const QGLContext *context); QGLExtensionFuncs m_extensionFuncs; const QGLContext *m_context; // context group's representative @@ -522,17 +522,33 @@ public: QSize bindCompressedTexturePVR(const char *buf, int len); }; +struct QGLTextureCacheKey { + qint64 key; + QGLContextGroup *group; +}; + +inline bool operator==(const QGLTextureCacheKey &a, const QGLTextureCacheKey &b) +{ + return a.key == b.key && a.group == b.group; +} + +inline uint qHash(const QGLTextureCacheKey &key) +{ + return qHash(key.key) ^ qHash(key.group); +} + + class Q_AUTOTEST_EXPORT QGLTextureCache { public: QGLTextureCache(); ~QGLTextureCache(); void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost); - inline void remove(quint64 key); + void remove(qint64 key); inline int size(); inline void setMaxCost(int newMax); inline int maxCost(); - inline QGLTexture* getTexture(quint64 key); + inline QGLTexture* getTexture(QGLContext *ctx, qint64 key); bool remove(QGLContext *ctx, GLuint textureId); void removeContextTextures(QGLContext *ctx); @@ -542,7 +558,7 @@ public: static void cleanupBeforePixmapDestruction(QPixmapData* pixmap); private: - QCache m_cache; + QCache m_cache; QReadWriteLock m_lock; }; @@ -563,19 +579,13 @@ int QGLTextureCache::maxCost() return m_cache.maxCost(); } -QGLTexture* QGLTextureCache::getTexture(quint64 key) +QGLTexture* QGLTextureCache::getTexture(QGLContext *ctx, qint64 key) { QReadLocker locker(&m_lock); - return m_cache.object(key); + const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)}; + return m_cache.object(cacheKey); } -void QGLTextureCache::remove(quint64 key) -{ - QWriteLocker locker(&m_lock); - m_cache.remove(key); -} - - extern Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine(); bool qt_gl_preferGL2Engine(); -- cgit v0.12 From f5cc4e9a020e78f0bf0d929ff2780b5bf01749ae Mon Sep 17 00:00:00 2001 From: Andreas Hartmetz Date: Tue, 1 Jun 2010 10:35:30 +0200 Subject: Added environment variable graphicssystem switch. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add environment variable switch for graphicssystem so a default can be set at runtime without passing a command-line parameter. Merge-request: 622 Reviewed-by: Samuel Rødal --- src/gui/kernel/qapplication.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index a2c058a..09a3bfe 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -780,6 +780,9 @@ void QApplicationPrivate::construct( qt_is_gui_used = (qt_appType != QApplication::Tty); process_cmdline(); + // the environment variable has the lowest precedence of runtime graphicssystem switches + if (graphics_system_name.isEmpty()) + graphics_system_name = QString::fromLocal8Bit(qgetenv("QT_GRAPHICSSYSTEM")); // Must be called before initialize() qt_init(this, qt_appType #ifdef Q_WS_X11 @@ -1560,10 +1563,18 @@ QStyle* QApplication::setStyle(const QString& style) on-screen widgets and QPixmaps. The available systems are \c{"native"}, \c{"raster"} and \c{"opengl"}. - This function call overrides both the application commandline - \c{-graphicssystem} switch and the configure \c{-graphicssystem} switch. + There are several ways to set the graphics backend, in order of decreasing + precedence: + \list + \o the application commandline \c{-graphicssystem} switch + \o QApplication::setGraphicsSystem() + \o the QT_GRAPHICSSYSTEM environment variable + \o the Qt configure \c{-graphicssystem} switch + \endlist + If the highest precedence switch sets an invalid name, the error will be + ignored and the default backend will be used. - \warning This function must be called before the QApplication constructor + \warning This function is only effective before the QApplication constructor is called. \note The \c{"opengl"} option is currently experimental. -- cgit v0.12 From 94f0369e21cb4db41f6f10358ba1967fe1d0e8a1 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Sun, 2 May 2010 00:19:25 -0600 Subject: Doc: QAbstractItemModel: note unexpected behavior with beginMoveRows The meaning of the destinationChild parameter differs when moving down in the same parent, contrary to statements by the previous docs. Reviewed-by: Olivier Goffart Merge-Request: 600 --- src/corelib/kernel/qabstractitemmodel.cpp | 92 +++++++++++++++++-------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 24c26b6..b0e2f48 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -2508,29 +2508,35 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star When reimplementing a subclass, this method simplifies moving entities in your model. This method is responsible for moving persistent indexes in the model, which you would otherwise be - required to do yourself. - - Using beginMoveRows and endMoveRows is an alternative to emitting - layoutAboutToBeChanged and layoutChanged directly along with - changePersistentIndexes. layoutAboutToBeChanged is emitted by - this method for compatibility reasons. + required to do yourself. Using beginMoveRows and endMoveRows + is an alternative to emitting layoutAboutToBeChanged and + layoutChanged directly along with changePersistentIndexes. + layoutAboutToBeChanged is emitted by this method for compatibility + reasons. The \a sourceParent index corresponds to the parent from which the - rows are moved; \a sourceFirst and \a sourceLast are the row - numbers of the rows to be moved. The \a destinationParent index - corresponds to the parent into which the rows are moved. The \a + rows are moved; \a sourceFirst and \a sourceLast are the first and last + row numbers of the rows to be moved. The \a destinationParent index + corresponds to the parent into which those rows are moved. The \a destinationChild is the row to which the rows will be moved. That is, the index at row \a sourceFirst in \a sourceParent will become - row \a destinationChild in \a destinationParent. Its siblings will - be moved correspondingly. - - Note that \a sourceParent and \a destinationParent may be the - same, in which case you must ensure that the \a destinationChild is - not within the range of \a sourceFirst and \a sourceLast. You - must also ensure that you do not attempt to move a row to one of - its own children or ancestors. This method returns false if either - condition is true, in which case you should abort your move - operation. + row \a destinationChild in \a destinationParent, followed by all other + rows up to \a sourceLast. + + However, when moving rows down in the same parent (\a sourceParent + and \a destinationParent are equal), the rows will be placed before the + \a destinationChild index. That is, if you wish to move rows 0 and 1 so + they will become rows 1 and 2, \a destinationChild should be 3. In this + case, the new index for the source row \c i (which is between + \a sourceFirst and \a sourceLast) is equal to + \c {(destinationChild-sourceLast-1+i)}. + + Note that if \a sourceParent and \a destinationParent are the same, + you must ensure that the \a destinationChild is not within the range + of \a sourceFirst and \a sourceLast + 1. You must also ensure that you + do not attempt to move a row to one of its own children or ancestors. + This method returns false if either condition is true, in which case you + should abort your move operation. \table 80% \row @@ -2761,29 +2767,35 @@ void QAbstractItemModel::endRemoveColumns() When reimplementing a subclass, this method simplifies moving entities in your model. This method is responsible for moving persistent indexes in the model, which you would otherwise be - required to do yourself. - - Using beginMoveColumns and endMoveColumns is an alternative to - emitting layoutAboutToBeChanged and layoutChanged directly along - with changePersistentIndexes. layoutAboutToBeChanged is emitted - by this method for compatibility reasons. + required to do yourself. Using beginMoveRows and endMoveRows + is an alternative to emitting layoutAboutToBeChanged and + layoutChanged directly along with changePersistentIndexes. + layoutAboutToBeChanged is emitted by this method for compatibility + reasons. The \a sourceParent index corresponds to the parent from which the - columns are moved; \a sourceFirst and \a sourceLast are the column - numbers of the columns to be moved. The \a destinationParent index - corresponds to the parent into which the columns are moved. The \a - destinationChild is the column to which the columns will be - moved. That is, the index at column \a sourceFirst in \a - sourceParent will become column \a destinationChild in \a - destinationParent. Its siblings will be moved correspondingly. - - Note that \a sourceParent and \a destinationParent may be the - same, in which case you must ensure that the \a destinationChild - is not within the range of \a sourceFirst and \a sourceLast. You - must also ensure that you do not attempt to move a row to one of - its own chilren or ancestors. This method returns false if either - condition is true, in which case you should abort your move - operation. + columns are moved; \a sourceFirst and \a sourceLast are the first and last + column numbers of the columns to be moved. The \a destinationParent index + corresponds to the parent into which those columns are moved. The \a + destinationChild is the column to which the columns will be moved. That + is, the index at column \a sourceFirst in \a sourceParent will become + column \a destinationChild in \a destinationParent, followed by all other + columns up to \a sourceLast. + + However, when moving columns down in the same parent (\a sourceParent + and \a destinationParent are equal), the columnss will be placed before the + \a destinationChild index. That is, if you wish to move columns 0 and 1 so + they will become columns 1 and 2, \a destinationChild should be 3. In this + case, the new index for the source column \c i (which is between + \a sourceFirst and \a sourceLast) is equal to + \c {(destinationChild-sourceLast-1+i)}. + + Note that if \a sourceParent and \a destinationParent are the same, + you must ensure that the \a destinationChild is not within the range + of \a sourceFirst and \a sourceLast + 1. You must also ensure that you + do not attempt to move a column to one of its own children or ancestors. + This method returns false if either condition is true, in which case you + should abort your move operation. \sa endMoveColumns() -- cgit v0.12 From 4e85c1015c2dfa58560e0567af4fa17a412441a5 Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Tue, 1 Jun 2010 12:16:17 +0200 Subject: Doc: Fixed a typo Task-number: QTBUG-10951 --- doc/src/examples/waitconditions.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/examples/waitconditions.qdoc b/doc/src/examples/waitconditions.qdoc index 1d3ff84..d4f680e 100644 --- a/doc/src/examples/waitconditions.qdoc +++ b/doc/src/examples/waitconditions.qdoc @@ -92,7 +92,7 @@ Together, the wait conditions, the mutex, and the \c numUsedBytes counter ensure that the producer is never more than \c BufferSize bytes ahead of the consumer, and that the consumer never reads - data that the consumer hasn't generated yet. + data that the producer hasn't generated yet. \section1 Producer Class -- cgit v0.12