[Marble-commits] KDE/kdeedu/marble/src/lib
Bernhard Beschow
bbeschow at cs.tu-berlin.de
Wed Jan 19 18:11:53 CET 2011
SVN commit 1215794 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
--- trunk/KDE/kdeedu/marble/src/lib/AbstractScanlineTextureMapper.h #1215793:1215794
@@ -55,6 +55,7 @@
Q_SIGNALS:
void tileLevelChanged( int newTileLevel );
+ void tileUpdatesAvailable();
protected:
void pixelValueF( const qreal lon, const qreal lat,
--- trunk/KDE/kdeedu/marble/src/lib/EquirectScanlineTextureMapper.cpp #1215793:1215794
@@ -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,
--- trunk/KDE/kdeedu/marble/src/lib/MercatorScanlineTextureMapper.cpp #1215793:1215794
@@ -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,
--- trunk/KDE/kdeedu/marble/src/lib/SphericalScanlineTextureMapper.cpp #1215793:1215794
@@ -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,
--- trunk/KDE/kdeedu/marble/src/lib/StackedTileLoader.cpp #1215793:1215794
@@ -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() );
}
}
--- trunk/KDE/kdeedu/marble/src/lib/StackedTileLoader.h #1215793:1215794
@@ -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:
/**
--- trunk/KDE/kdeedu/marble/src/lib/TextureLayer.cpp #1215793:1215794
@@ -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 )),
--- trunk/KDE/kdeedu/marble/src/lib/TileScalingTextureMapper.cpp #1215793:1215794
@@ -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;
@@ -98,6 +109,9 @@
qreal( 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 );
@@ -109,22 +123,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"
--- trunk/KDE/kdeedu/marble/src/lib/TileScalingTextureMapper.h #1215793:1215794
@@ -13,7 +13,12 @@
#include "AbstractScanlineTextureMapper.h"
+#include "TileId.h"
+#include <QtCore/QCache>
+
+class QPixmap;
+
namespace Marble
{
@@ -22,7 +27,9 @@
Q_OBJECT
public:
- explicit 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;
};
}
More information about the Marble-commits
mailing list