From e335b7b74aa9cfdb036dd5f87678c064ee916585 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Wed, 6 Feb 2013 16:02:26 -0700 Subject: [PATCH 1/4] Make frame state available before rendering frame Without this change, tiles that are enqueued on the first rendering will always get priority `ol.TileQueue.DROP` because `map.frameState_` is not yet defined (meaning a single render call doesn't result in any tiles loading). --- src/ol/map.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ol/map.js b/src/ol/map.js index 58925d8443..50e9347ff8 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -754,8 +754,8 @@ ol.Map.prototype.renderFrame_ = function(time) { frameState.extent = ol.Extent.boundingExtent.apply(null, corners); } - this.renderer_.renderFrame(frameState); this.frameState_ = frameState; + this.renderer_.renderFrame(frameState); this.dirty_ = false; if (!goog.isNull(frameState)) { From 2bd29ff60e1223a84cec0d10a2cdd0f2b3bc2ceb Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Wed, 6 Feb 2013 16:08:24 -0700 Subject: [PATCH 2/4] Only track tiles that are actually wanted Instead of keeping track of wanted tile ranges, we can instead track wanted tiles individually. This provides enough for the map to know how to prioritize tiles and should be more efficient (no extra calls to extend tile ranges or check for tile containment within a range). --- src/ol/framestate.js | 2 +- src/ol/map.js | 5 ++--- .../canvas/canvastilelayerrenderer.js | 2 +- src/ol/renderer/dom/domtilelayerrenderer.js | 2 +- src/ol/renderer/layerrenderer.js | 21 +++++++------------ .../renderer/webgl/webgltilelayerrenderer.js | 2 +- 6 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/ol/framestate.js b/src/ol/framestate.js index bbe89d10a0..9e45ce99b6 100644 --- a/src/ol/framestate.js +++ b/src/ol/framestate.js @@ -31,7 +31,7 @@ goog.require('ol.layer.LayerState'); * usedTiles: Object.>, * view2DState: ol.View2DState, * viewHints: Array., - * wantedTiles: Object.>}} + * wantedTiles: Object.>}} */ ol.FrameState; diff --git a/src/ol/map.js b/src/ol/map.js index 50e9347ff8..d134cae46c 100644 --- a/src/ol/map.js +++ b/src/ol/map.js @@ -500,9 +500,8 @@ ol.Map.prototype.getTilePriority = function(tile, tileSourceKey, tileCenter) { if (goog.isNull(frameState) || !(tileSourceKey in frameState.wantedTiles)) { return ol.TileQueue.DROP; } - var zKey = tile.tileCoord.z.toString(); - if (!(zKey in frameState.wantedTiles[tileSourceKey]) || - !frameState.wantedTiles[tileSourceKey][zKey].contains(tile.tileCoord)) { + var coordKey = tile.tileCoord.toString(); + if (!frameState.wantedTiles[tileSourceKey][coordKey]) { return ol.TileQueue.DROP; } var center = frameState.view2DState.center; diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 59b0c6051c..c2987af91b 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -167,6 +167,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { + this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); } else if (tileState == ol.TileState.LOADED) { @@ -216,7 +217,6 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = if (!allTilesLoaded) { frameState.animate = true; - this.updateWantedTiles(frameState.wantedTiles, tileSource, z, tileRange); } this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index a92d34a0d2..0676d629d6 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -131,6 +131,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { + this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); } else if (tileState == ol.TileState.LOADED) { @@ -234,7 +235,6 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = if (!allTilesLoaded) { frameState.animate = true; - this.updateWantedTiles(frameState.wantedTiles, tileSource, z, tileRange); } this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 4ff6f66cab..982a454d72 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -4,6 +4,7 @@ goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('ol.FrameState'); goog.require('ol.Object'); +goog.require('ol.TileCoord'); goog.require('ol.TileRange'); goog.require('ol.layer.Layer'); goog.require('ol.layer.LayerProperty'); @@ -197,24 +198,16 @@ ol.renderer.Layer.prototype.updateUsedTiles = /** * @protected - * @param {Object.>} wantedTiles Wanted - * tile ranges. + * @param {Object.>} wantedTiles Wanted tiles. * @param {ol.source.Source} source Source. - * @param {number} z Z. - * @param {ol.TileRange} tileRange Tile range. + * @param {ol.TileCoord} tileCoord Tile coordinate. */ ol.renderer.Layer.prototype.updateWantedTiles = - function(wantedTiles, source, z, tileRange) { + function(wantedTiles, source, tileCoord) { var sourceKey = goog.getUid(source).toString(); - var zKey = z.toString(); - if (sourceKey in wantedTiles) { - if (zKey in wantedTiles[sourceKey]) { - wantedTiles[sourceKey][zKey].extend(tileRange); - } else { - wantedTiles[sourceKey][zKey] = tileRange; - } - } else { + var coordKey = tileCoord.toString(); + if (!(sourceKey in wantedTiles)) { wantedTiles[sourceKey] = {}; - wantedTiles[sourceKey][zKey] = tileRange; } + wantedTiles[sourceKey][coordKey] = true; }; diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 3663948de8..77cf37aa79 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -393,6 +393,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { + this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); } else if (tileState == ol.TileState.LOADED) { @@ -457,7 +458,6 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = this.renderedTileRange_ = null; this.renderedFramebufferExtent_ = null; frameState.animate = true; - this.updateWantedTiles(frameState.wantedTiles, tileSource, z, tileRange); } } From e079c1941319aeba5bc14d8750b351d3ba4318d7 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Wed, 6 Feb 2013 16:10:46 -0700 Subject: [PATCH 3/4] Don't repeatedly render while waiting for tiles to load Instead of going into an unnecessary animation loop, we can simply wait to be notified when tiles load. The WebGL renderer still sets frameState.animate true, but I think this too should be unnecessary (full page example works without it, side-by-side example shows it cannot yet be removed). --- src/ol/renderer/canvas/canvastilelayerrenderer.js | 6 ++---- src/ol/renderer/dom/domtilelayerrenderer.js | 6 ++---- src/ol/renderer/layerrenderer.js | 15 +++++++++++++++ src/ol/renderer/webgl/webgltilelayerrenderer.js | 2 ++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index c2987af91b..da9ef99a2b 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -167,6 +167,8 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { + goog.events.listen(tile, goog.events.EventType.CHANGE, + this.handleTileChange, false, this); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); @@ -215,10 +217,6 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = } } - if (!allTilesLoaded) { - frameState.animate = true; - } - this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); this.scheduleExpireCache(frameState, tileSource); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 0676d629d6..537ff16e52 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -131,6 +131,8 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { + goog.events.listen(tile, goog.events.EventType.CHANGE, + this.handleTileChange, false, this); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); @@ -233,10 +235,6 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = this.renderedVisible_ = true; } - if (!allTilesLoaded) { - frameState.animate = true; - } - this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange); this.scheduleExpireCache(frameState, tileSource); diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 982a454d72..fab64889fc 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -4,8 +4,10 @@ goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('ol.FrameState'); goog.require('ol.Object'); +goog.require('ol.Tile'); goog.require('ol.TileCoord'); goog.require('ol.TileRange'); +goog.require('ol.TileState'); goog.require('ol.layer.Layer'); goog.require('ol.layer.LayerProperty'); goog.require('ol.layer.LayerState'); @@ -147,6 +149,19 @@ ol.renderer.Layer.prototype.handleLayerVisibleChange = function() { }; +/** + * Handle changes in tile state. + * @param {goog.events.Event} event Tile change event. + * @protected + */ +ol.renderer.Layer.prototype.handleTileChange = function(event) { + var tile = /** @type {ol.Tile} */ (event.target); + if (tile.getState() === ol.TileState.LOADED) { + this.getMap().requestRenderFrame(); + } +}; + + /** * @param {ol.FrameState} frameState Frame state. * @param {ol.layer.LayerState} layerState Layer state. diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 77cf37aa79..068a9687c3 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -393,6 +393,8 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { + goog.events.listen(tile, goog.events.EventType.CHANGE, + this.handleTileChange, false, this); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); From 3c4d218ec5372c3f26aaba564580ab25433e5ca3 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Thu, 7 Feb 2013 14:06:05 -0700 Subject: [PATCH 4/4] Only listen for first event --- src/ol/renderer/canvas/canvastilelayerrenderer.js | 2 +- src/ol/renderer/dom/domtilelayerrenderer.js | 2 +- src/ol/renderer/webgl/webgltilelayerrenderer.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index da9ef99a2b..02e5e904ff 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -167,7 +167,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listen(tile, goog.events.EventType.CHANGE, + goog.events.listenOnce(tile, goog.events.EventType.CHANGE, this.handleTileChange, false, this); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index 537ff16e52..094d6a3009 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -131,7 +131,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listen(tile, goog.events.EventType.CHANGE, + goog.events.listenOnce(tile, goog.events.EventType.CHANGE, this.handleTileChange, false, this); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 068a9687c3..27c0cbadab 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -393,7 +393,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listen(tile, goog.events.EventType.CHANGE, + goog.events.listenOnce(tile, goog.events.EventType.CHANGE, this.handleTileChange, false, this); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord);