[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    branches/marble/marble-1.1/src/lib
From:       Bernhard Beschow <bbeschow () cs ! tu-berlin ! de>
Date:       2011-01-19 17:12:54
Message-ID: 20110119171254.AB9D8AC8B9 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1215805 by beschow:

forward-port r1211246: introduce a pixmap cache for texture mapping

* have the texture mappers rather than the StackedTileLoader emit signals when tile \
updates are avialable

REVIEW: 6250

 M  +1 -0      AbstractScanlineTextureMapper.h  
 M  +4 -0      EquirectScanlineTextureMapper.cpp  
 M  +4 -0      MercatorScanlineTextureMapper.cpp  
 M  +5 -0      SphericalScanlineTextureMapper.cpp  
 M  +4 -4      StackedTileLoader.cpp  
 M  +2 -1      StackedTileLoader.h  
 M  +6 -3      TextureLayer.cpp  
 M  +68 -8     TileScalingTextureMapper.cpp  
 M  +16 -2     TileScalingTextureMapper.h  


--- branches/marble/marble-1.1/src/lib/AbstractScanlineTextureMapper.h \
#1215804:1215805 @@ -55,6 +55,7 @@
 
  Q_SIGNALS:
     void tileLevelChanged( int newTileLevel );
+    void tileUpdatesAvailable();
 
  protected:
     void pixelValueF( const qreal lon, const qreal lat,
--- branches/marble/marble-1.1/src/lib/EquirectScanlineTextureMapper.cpp \
#1215804:1215805 @@ -37,6 +37,10 @@
       m_oldCenterLon( 0.0 ),
       m_oldYPaintedTop( 0 )
 {
+    connect( m_tileLoader, SIGNAL( tileUpdateAvailable( const TileId & ) ),
+             this, SIGNAL( tileUpdatesAvailable() ) );
+    connect( m_tileLoader, SIGNAL( tileUpdatesAvailable() ),
+             this, SIGNAL( tileUpdatesAvailable() ) );
 }
 
 void EquirectScanlineTextureMapper::mapTexture( GeoPainter *painter,
--- branches/marble/marble-1.1/src/lib/MercatorScanlineTextureMapper.cpp \
#1215804:1215805 @@ -39,6 +39,10 @@
       m_oldCenterLon( 0.0 ),
       m_oldYPaintedTop( 0 )
 {
+    connect( m_tileLoader, SIGNAL( tileUpdateAvailable( const TileId & ) ),
+             this, SIGNAL( tileUpdatesAvailable() ) );
+    connect( m_tileLoader, SIGNAL( tileUpdatesAvailable() ),
+             this, SIGNAL( tileUpdatesAvailable() ) );
 }
 
 void MercatorScanlineTextureMapper::mapTexture( GeoPainter *painter,
--- branches/marble/marble-1.1/src/lib/SphericalScanlineTextureMapper.cpp \
#1215804:1215805 @@ -35,6 +35,11 @@
     , m_repaintNeeded( true )
 {
     m_interlaced = false;
+
+    connect( m_tileLoader, SIGNAL( tileUpdateAvailable( const TileId & ) ),
+             this, SIGNAL( tileUpdatesAvailable() ) );
+    connect( m_tileLoader, SIGNAL( tileUpdatesAvailable() ),
+             this, SIGNAL( tileUpdatesAvailable() ) );
 }
 
 void SphericalScanlineTextureMapper::mapTexture( GeoPainter *painter,
--- branches/marble/marble-1.1/src/lib/StackedTileLoader.cpp #1215804:1215805
@@ -401,14 +401,14 @@
     if ( displayedTile ) {
         displayedTile->initResultTile();
         mergeDecorations( displayedTile );
-        emit tileUpdateAvailable();
+        emit tileUpdateAvailable( stackedTileId );
     }
     else {
         StackedTile * const cachedTile = d->m_tileCache.object( stackedTileId );
         if ( cachedTile ) {
             cachedTile->initResultTile();
             mergeDecorations( cachedTile );
-            emit tileUpdateAvailable();
+            emit tileUpdateAvailable( stackedTileId );
         }
     }
 }
@@ -418,7 +418,7 @@
     mDebug() << "StackedTileLoader::update()";
     flush(); // trigger a reload of all tiles that are currently in use
     d->m_tileCache.clear(); // clear the tile cache in physical memory
-    emit tileUpdateAvailable();
+    emit tileUpdatesAvailable();
 }
 
 // 
@@ -472,7 +472,7 @@
     }
     cachedTile->initResultTile();
     mergeDecorations( cachedTile );
-    emit tileUpdateAvailable();
+    emit tileUpdateAvailable( cachedTile->id() );
 }
 
 }
--- branches/marble/marble-1.1/src/lib/StackedTileLoader.h #1215804:1215805
@@ -157,7 +157,8 @@
          * This signal is emitted whenever a requested tile has been
          * downloaded and is available now.
          */
-        void tileUpdateAvailable();
+        void tileUpdateAvailable( TileId const & stacedTileId );
+        void tileUpdatesAvailable();
 
     private Q_SLOTS:
         /**
--- branches/marble/marble-1.1/src/lib/TextureLayer.cpp #1215804:1215805
@@ -13,6 +13,7 @@
 
 #include "TextureLayer.h"
 
+#include <QtCore/QCache>
 #include <QtCore/QTimer>
 
 #include "SphericalScanlineTextureMapper.h"
@@ -53,6 +54,7 @@
     TextureLayer  *const m_parent;
     TileLoader           m_loader;
     StackedTileLoader    m_tileLoader;
+    QCache<TileId, QPixmap> m_pixmapCache;
     AbstractScanlineTextureMapper *m_texmapper;
     TextureColorizer              *m_texcolorizer;
     GeoSceneDocument              *m_mapTheme;
@@ -62,6 +64,7 @@
     : m_parent( parent )
     , m_loader( downloadManager, mapThemeManager )
     , m_tileLoader( &m_loader, sunLocator )
+    , m_pixmapCache( 100 )
     , m_texmapper( 0 )
     , m_texcolorizer( 0 )
     , m_mapTheme( 0 )
@@ -95,6 +98,7 @@
     }
 
     m_tileLoader.setTextureLayers( result );
+    m_pixmapCache.clear();
 }
 
 const GeoSceneLayer *TextureLayer::Private::sceneLayer() const
@@ -134,7 +138,6 @@
     : QObject()
     , d( new Private( mapThemeManager, downloadManager, sunLocator, this ) )
 {
-    connect( &d->m_tileLoader, SIGNAL( tileUpdateAvailable() ), SLOT( mapChanged() ) \
);  }
 
 TextureLayer::~TextureLayer()
@@ -179,7 +182,7 @@
             break;
         case Mercator:
             if ( d->m_tileLoader.tileProjection() == GeoSceneTexture::Mercator ) {
-                d->m_texmapper = new TileScalingTextureMapper( &d->m_tileLoader, \
this ); +                d->m_texmapper = new TileScalingTextureMapper( \
&d->m_tileLoader, &d->m_pixmapCache, this );  } else {
                 d->m_texmapper = new MercatorScanlineTextureMapper( \
&d->m_tileLoader, this );  }
@@ -189,6 +192,7 @@
     }
     Q_ASSERT( d->m_texmapper );
     connect( d->m_texmapper, SIGNAL( tileLevelChanged( int )), SIGNAL( \
tileLevelChanged( int ))); +    connect( d->m_texmapper, SIGNAL( \
tileUpdatesAvailable() ), SLOT( mapChanged() ) );  }
 
 void TextureLayer::setNeedsUpdate()
@@ -235,7 +239,6 @@
     }
 
     d->m_mapTheme = mapTheme;
-    d->m_tileLoader.flush();
 
     if ( d->textureLayerSettings() ) {
         connect( d->textureLayerSettings(), SIGNAL( valueChanged( QString, bool )),
--- branches/marble/marble-1.1/src/lib/TileScalingTextureMapper.cpp #1215804:1215805
@@ -32,10 +32,17 @@
 using namespace Marble;
 
 TileScalingTextureMapper::TileScalingTextureMapper( StackedTileLoader *tileLoader,
+                                                    QCache<TileId, QPixmap> *cache,
                                                     QObject *parent )
     : AbstractScanlineTextureMapper( tileLoader, parent ),
-      m_repaintNeeded( true )
+      m_cache( cache ),
+      m_repaintNeeded( true ),
+      m_oldRadius( 0 )
 {
+    connect( m_tileLoader, SIGNAL( tileUpdateAvailable( const TileId & ) ),
+             this, SLOT( updateTile( const TileId & ) ) );
+    connect( m_tileLoader, SIGNAL( tileUpdatesAvailable() ),
+             this, SLOT( updateTiles() ) );
 }
 
 void TileScalingTextureMapper::mapTexture( GeoPainter *painter,
@@ -43,21 +50,25 @@
                                            const QRect &dirtyRect,
                                            TextureColorizer *texColorizer )
 {
+    if ( texColorizer || m_oldRadius != viewParams->radius() ) {
     if ( m_repaintNeeded ) {
-        mapTexture( viewParams, texColorizer );
+            mapTexture( painter, viewParams, texColorizer );
 
         m_repaintNeeded = false;
     }
 
     painter->drawImage( dirtyRect, *viewParams->canvasImage(), dirtyRect );
+    } else {
+        mapTexture( painter, viewParams, texColorizer );
 }
+}
 
 void TileScalingTextureMapper::setRepaintNeeded()
 {
     m_repaintNeeded = true;
 }
 
-void TileScalingTextureMapper::mapTexture( ViewParams *viewParams, TextureColorizer \
*texColorizer ) +void TileScalingTextureMapper::mapTexture( GeoPainter *geoPainter, \
ViewParams *viewParams, TextureColorizer *texColorizer )  {
     if ( viewParams->radius() <= 0 )
         return;
@@ -97,6 +108,9 @@
     const int minTileY = qMax( numTilesY * ( yNormalizedCenter - imageHeight/( 8.0 * \
                radius ) ), 0.0 );
     const int maxTileY = qMin( numTilesY * ( yNormalizedCenter + imageHeight/( 8.0 * \
radius ) ), numTilesY - 1.0 );  
+    if ( texColorizer || m_oldRadius != radius ) {
+        m_cache->clear();
+
     QPainter painter( canvasImage );
     painter.setRenderHint( QPainter::SmoothPixmapTransform, highQuality );
 
@@ -108,22 +122,68 @@
             const qreal yBottom = ( 4.0 * radius ) * ( ( tileY + 1 ) / \
(qreal)numTilesY - yNormalizedCenter ) + ( imageHeight / 2.0 );  
             const QRectF rect = QRectF( QPointF( xLeft, yTop ), QPointF( xRight, \
                yBottom ) );
-            const TileId id = TileId( 0, tileZoomLevel(), ( ( tileX % numTilesX ) + \
                numTilesX ) % numTilesX, tileY );
-            StackedTile *const tile = m_tileLoader->loadTile( id, DownloadBrowse );
+                const TileId stackedId = TileId( 0, tileZoomLevel(), ( ( tileX % \
numTilesX ) + numTilesX ) % numTilesX, tileY ); +                StackedTile *const \
tile = m_tileLoader->loadTile( stackedId, DownloadBrowse );  tile->setUsed( true );
 
             painter.drawImage( rect, *tile->resultTile() );
         }
     }
 
-    painter.end();
+        if ( texColorizer ) {
+            texColorizer->colorize( viewParams );
+        }
+    } else {
+        QPainter painter( geoPainter->device() );
+        painter.setRenderHint( QPainter::SmoothPixmapTransform, highQuality );
 
+        for ( int tileY = minTileY; tileY <= maxTileY; ++tileY ) {
+            for ( int tileX = minTileX; tileX <= maxTileX; ++tileX ) {
+                const qreal xLeft   = ( 4.0 * radius ) * ( ( tileX     ) / \
(qreal)numTilesX - xNormalizedCenter ) + ( imageWidth / 2.0 ); +                const \
qreal xRight  = ( 4.0 * radius ) * ( ( tileX + 1 ) / (qreal)numTilesX - \
xNormalizedCenter ) + ( imageWidth / 2.0 ); +                const qreal yTop    = ( \
4.0 * radius ) * ( ( tileY     ) / (qreal)numTilesY - yNormalizedCenter ) + ( \
imageHeight / 2.0 ); +                const qreal yBottom = ( 4.0 * radius ) * ( ( \
tileY + 1 ) / (qreal)numTilesY - yNormalizedCenter ) + ( imageHeight / 2.0 ); +
+                const QRectF rect = QRectF( QPointF( xLeft, yTop ), QPointF( xRight, \
yBottom ) ); +                const TileId stackedId = TileId( 0, tileZoomLevel(), ( \
( tileX % numTilesX ) + numTilesX ) % numTilesX, tileY ); +                \
StackedTile *const tile = m_tileLoader->loadTile( stackedId, DownloadBrowse ); +      \
tile->setUsed( true ); +
+                const QSize size = QSize( qCeil( rect.right() - rect.left() ), \
qCeil( rect.bottom() - rect.top() ) ); +                const int cacheHash = 2 * ( \
size.width() % 2 ) + ( size.height() % 2 ); +                const TileId cacheId = \
TileId( cacheHash, stackedId.zoomLevel(), stackedId.x(), stackedId.y() ); +           \
QPixmap *im = (*m_cache)[cacheId]; +                if ( im == 0 ) {
+                    im = new QPixmap( QPixmap::fromImage( \
tile->resultTile()->scaled( size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ) \
); +                    m_cache->insert( cacheId, im );
+                }
+
+                painter.drawPixmap( rect.topLeft(), *im );
+            }
+        }
+    }
+
     m_tileLoader->cleanupTilehash();
 
-    if ( texColorizer ) {
-        texColorizer->colorize( viewParams );
+    m_oldRadius = radius;
     }
+
+void TileScalingTextureMapper::updateTile( const TileId &stackedId )
+{
+    for ( int i = 0; i < 4; ++i ) {
+        const TileId id = TileId( i, stackedId.zoomLevel(), stackedId.x(), \
stackedId.y() ); +
+        m_cache->remove( id );
 }
 
+    emit tileUpdatesAvailable();
+}
 
+void TileScalingTextureMapper::updateTiles()
+{
+    m_cache->clear();
+
+    emit tileUpdatesAvailable();
+}
+
 #include "TileScalingTextureMapper.moc"
--- branches/marble/marble-1.1/src/lib/TileScalingTextureMapper.h #1215804:1215805
@@ -13,7 +13,12 @@
 
 
 #include "AbstractScanlineTextureMapper.h"
+#include "TileId.h"
 
+#include <QtCore/QCache>
+
+class QPixmap;
+
 namespace Marble
 {
 
@@ -22,7 +27,9 @@
     Q_OBJECT
 
  public:
-    TileScalingTextureMapper( StackedTileLoader *tileLoader, QObject *parent = 0 );
+    TileScalingTextureMapper( StackedTileLoader *tileLoader,
+                              QCache<TileId, QPixmap> *cache,
+                              QObject *parent = 0 );
 
     virtual void mapTexture( GeoPainter *painter,
                              ViewParams *viewParams,
@@ -31,12 +38,19 @@
 
     virtual void setRepaintNeeded();
 
+ private Q_SLOTS:
+    void updateTile( const TileId &id );
+    void updateTiles();
+
  private:
-    void mapTexture( ViewParams *viewParams,
+    void mapTexture( GeoPainter *painter,
+                     ViewParams *viewParams,
                      TextureColorizer *texColorizer );
 
  private:
+    QCache<TileId, QPixmap> *const m_cache;
     bool   m_repaintNeeded;
+    int    m_oldRadius;
 };
 
 }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic