void StackedTileLoader::updateTile( TileId const &tileId, QImage const &tileImage ) { Q_ASSERT( !tileImage.isNull() ); d->detectMaxTileLevel(); const TileId stackedTileId( 0, tileId.zoomLevel(), tileId.x(), tileId.y() ); StackedTile * displayedTile = d->m_tilesOnDisplay.take( stackedTileId ); if ( displayedTile ) { Q_ASSERT( !d->m_tileCache.contains( stackedTileId ) ); QVector<QSharedPointer<TextureTile> > tiles = displayedTile->tiles(); delete displayedTile; displayedTile = 0; for ( int i = 0; i < tiles.count(); ++ i) { if ( tiles[i]->id() == tileId ) { const Blending *blending = tiles[i]->blending(); tiles[i] = QSharedPointer<TextureTile>( new TextureTile( tileId, tileImage, blending ) ); } } const QImage resultImage = d->m_layerDecorator.merge( stackedTileId, tiles ); displayedTile = new StackedTile( stackedTileId, resultImage, tiles ); d->m_tilesOnDisplay.insert( stackedTileId, displayedTile ); emit tileUpdateAvailable( stackedTileId ); } else { d->m_tileCache.remove( stackedTileId ); } }
const StackedTile* StackedTileLoader::loadTile( TileId const & stackedTileId ) { // check if the tile is in the hash d->m_cacheLock.lockForRead(); StackedTile * stackedTile = d->m_tilesOnDisplay.value( stackedTileId, 0 ); d->m_cacheLock.unlock(); if ( stackedTile ) { stackedTile->setUsed( true ); return stackedTile; } // here ends the performance critical section of this method d->m_cacheLock.lockForWrite(); // has another thread loaded our tile due to a race condition? stackedTile = d->m_tilesOnDisplay.value( stackedTileId, 0 ); if ( stackedTile ) { Q_ASSERT( stackedTile->used() && "other thread should have marked tile as used" ); d->m_cacheLock.unlock(); return stackedTile; } // the tile was not in the hash so check if it is in the cache stackedTile = d->m_tileCache.take( stackedTileId ); if ( stackedTile ) { Q_ASSERT( !stackedTile->used() && "tiles in m_tileCache are invisible and should thus be marked as unused" ); stackedTile->setUsed( true ); d->m_tilesOnDisplay[ stackedTileId ] = stackedTile; d->m_cacheLock.unlock(); return stackedTile; } // tile (valid) has not been found in hash or cache, so load it from disk // and place it in the hash from where it will get transferred to the cache mDebug() << "load tile from disk:" << stackedTileId; stackedTile = d->m_layerDecorator->loadTile( stackedTileId ); Q_ASSERT( stackedTile ); stackedTile->setUsed( true ); d->m_tilesOnDisplay[ stackedTileId ] = stackedTile; d->m_cacheLock.unlock(); emit tileLoaded( stackedTileId ); return stackedTile; }
const StackedTile* StackedTileLoader::loadTile( TileId const & stackedTileId ) { // check if the tile is in the hash d->m_cacheLock.lockForRead(); StackedTile * stackedTile = d->m_tilesOnDisplay.value( stackedTileId, 0 ); d->m_cacheLock.unlock(); if ( stackedTile ) { stackedTile->setUsed( true ); return stackedTile; } // here ends the performance critical section of this method d->m_cacheLock.lockForWrite(); // has another thread loaded our tile due to a race condition? stackedTile = d->m_tilesOnDisplay.value( stackedTileId, 0 ); if ( stackedTile ) { stackedTile->setUsed( true ); d->m_cacheLock.unlock(); return stackedTile; } mDebug() << "StackedTileLoader::loadTile" << stackedTileId.toString(); // the tile was not in the hash so check if it is in the cache stackedTile = d->m_tileCache.take( stackedTileId ); if ( stackedTile ) { stackedTile->setUsed( true ); d->m_tilesOnDisplay[ stackedTileId ] = stackedTile; d->m_cacheLock.unlock(); return stackedTile; } // tile (valid) has not been found in hash or cache, so load it from disk // and place it in the hash from where it will get transferred to the cache // mDebug() << "load Tile from Disk: " << stackedTileId.toString(); QVector<QSharedPointer<TextureTile> > tiles; QVector<GeoSceneTexture const *> const textureLayers = d->findRelevantTextureLayers( stackedTileId ); QVector<GeoSceneTexture const *>::const_iterator pos = textureLayers.constBegin(); QVector<GeoSceneTexture const *>::const_iterator const end = textureLayers.constEnd(); for (; pos != end; ++pos ) { GeoSceneTexture const * const textureLayer = *pos; TileId const tileId( textureLayer->sourceDir(), stackedTileId.zoomLevel(), stackedTileId.x(), stackedTileId.y() ); mDebug() << "StackedTileLoader::loadTile: tile" << textureLayer->sourceDir() << tileId.toString() << textureLayer->tileSize(); const QImage tileImage = d->m_tileLoader->loadTile( tileId, DownloadBrowse ); const Blending *blending = d->m_blendingFactory.findBlending( textureLayer->blending() ); if ( blending == 0 && !textureLayer->blending().isEmpty() ) { mDebug() << Q_FUNC_INFO << "could not find blending" << textureLayer->blending(); } QSharedPointer<TextureTile> tile( new TextureTile( tileId, tileImage, blending ) ); tiles.append( tile ); } Q_ASSERT( !tiles.isEmpty() ); const QImage resultImage = d->m_layerDecorator.merge( stackedTileId, tiles ); stackedTile = new StackedTile( stackedTileId, resultImage, tiles ); stackedTile->setUsed( true ); d->m_tilesOnDisplay[ stackedTileId ] = stackedTile; d->m_cacheLock.unlock(); return stackedTile; }