From fd6aaff2f5d7d1c9e448e345d6291d311822de53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 5 Mar 2013 16:04:01 +0100 Subject: [PATCH 1/3] Remove listeners when dropping tiles --- src/ol/tile.js | 7 +++++++ src/ol/tilequeue.js | 9 +++++++++ test/spec/ol/tilequeue.test.js | 27 +++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/ol/tile.js b/src/ol/tile.js index c9cf6bed73..ce00f9a1db 100644 --- a/src/ol/tile.js +++ b/src/ol/tile.js @@ -28,6 +28,13 @@ ol.Tile = function(tileCoord) { goog.base(this); + /** + * A count incremented each time the tile is inQueue in a tile queue, + * and decremented each time the tile is dequeued from a tile queue. + * @type {number} + */ + this.inQueue = 0; + /** * @type {ol.TileCoord} */ diff --git a/src/ol/tilequeue.js b/src/ol/tilequeue.js index c5788df972..7e20822308 100644 --- a/src/ol/tilequeue.js +++ b/src/ol/tilequeue.js @@ -89,6 +89,8 @@ ol.TileQueue.prototype.dequeue_ = function() { } var tileKey = tile.getKey(); delete this.queuedTileKeys_[tileKey]; + tile.inQueue--; + goog.asserts.assert(tile.inQueue >= 0); return tile; }; @@ -110,6 +112,8 @@ ol.TileQueue.prototype.enqueue = function(tile, tileSourceKey, tileCenter) { this.heap_.push([priority, tile, tileSourceKey, tileCenter]); this.queuedTileKeys_[tileKey] = true; this.siftDown_(0, this.heap_.length - 1); + tile.inQueue++; + goog.asserts.assert(tile.inQueue > 0); } } }; @@ -246,6 +250,11 @@ ol.TileQueue.prototype.reprioritize = function() { if (priority == ol.TileQueue.DROP) { tileKey = tile.getKey(); delete this.queuedTileKeys_[tileKey]; + tile.inQueue--; + goog.asserts.assert(tile.inQueue >= 0); + if (tile.inQueue === 0) { + goog.events.removeAll(tile); + } } else { node[0] = priority; heap[n++] = node; diff --git a/test/spec/ol/tilequeue.test.js b/test/spec/ol/tilequeue.test.js index 3ca38a2981..57db2b2f8c 100644 --- a/test/spec/ol/tilequeue.test.js +++ b/test/spec/ol/tilequeue.test.js @@ -21,13 +21,20 @@ describe('ol.TileQueue', function() { } function addRandomPriorityTiles(tq, num) { + var tiles = []; var i, tile, priority; for (i = 0; i < num; i++) { tile = new ol.Tile(); + tile.toDrop = (i % 2 === 0) ? true : false; + goog.events.listen(tile, goog.events.EventType.CHANGE, + goog.nullFunction); priority = Math.floor(Math.random() * 100); tq.heap_.push([priority, tile, '', new ol.Coordinate(0, 0)]); tq.queuedTileKeys_[tile.getKey()] = true; + tile.inQueue++; + tiles.push(tile); } + return tiles; } describe('heapify', function() { @@ -45,16 +52,15 @@ describe('ol.TileQueue', function() { it('does reprioritize the array', function() { var tq = new ol.TileQueue(function() {}); - addRandomPriorityTiles(tq, 100); + var tiles = addRandomPriorityTiles(tq, 100); tq.heapify_(); // now reprioritize, changing the priority of 50 tiles and removing the // rest - var i = 0; - tq.tilePriorityFunction_ = function() { - if ((i++) % 2 === 0) { + tq.tilePriorityFunction_ = function(tile) { + if (tile.toDrop) { return ol.TileQueue.DROP; } return Math.floor(Math.random() * 100); @@ -64,10 +70,23 @@ describe('ol.TileQueue', function() { expect(tq.heap_.length).toEqual(50); expect(isHeap(tq)).toBeTruthy(); + var i, tile; + for (i = 0; i < tiles.length; ++i) { + tile = tiles[i]; + var hasListener = goog.events.hasListener(tile); + if (tile.toDrop) { + expect(hasListener).toBeFalsy(); + } else { + expect(hasListener).toBeTruthy(); + } + } + }); }); }); +goog.require('goog.events'); +goog.require('goog.events.EventType'); goog.require('ol.Coordinate'); goog.require('ol.Tile'); goog.require('ol.TileQueue'); From 4e758f87aef7def99b7187c6e846fa9bea754ca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 5 Mar 2013 16:41:06 +0100 Subject: [PATCH 2/3] Do not register multiple listeners on same tile --- .../canvas/canvastilelayerrenderer.js | 3 +-- src/ol/renderer/dom/domtilelayerrenderer.js | 3 +-- src/ol/renderer/layerrenderer.js | 26 +++++++++++++++++-- .../renderer/webgl/webgltilelayerrenderer.js | 3 +-- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/ol/renderer/canvas/canvastilelayerrenderer.js b/src/ol/renderer/canvas/canvastilelayerrenderer.js index 1374457df6..216625d560 100644 --- a/src/ol/renderer/canvas/canvastilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvastilelayerrenderer.js @@ -158,8 +158,7 @@ ol.renderer.canvas.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listenOnce(tile, goog.events.EventType.CHANGE, - this.handleTileChange, false, this); + this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); diff --git a/src/ol/renderer/dom/domtilelayerrenderer.js b/src/ol/renderer/dom/domtilelayerrenderer.js index afe7463db1..da2dd226a8 100644 --- a/src/ol/renderer/dom/domtilelayerrenderer.js +++ b/src/ol/renderer/dom/domtilelayerrenderer.js @@ -116,8 +116,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listenOnce(tile, goog.events.EventType.CHANGE, - this.handleTileChange, false, this); + this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); diff --git a/src/ol/renderer/layerrenderer.js b/src/ol/renderer/layerrenderer.js index 6a6f1d4aff..736afc0605 100644 --- a/src/ol/renderer/layerrenderer.js +++ b/src/ol/renderer/layerrenderer.js @@ -40,6 +40,12 @@ ol.renderer.Layer = function(mapRenderer, layer) { */ this.layer_ = layer; + /** + * @protected + * @type {Object.} + */ + this.observedTileKeys = {}; + goog.events.listen(this.layer_, ol.Object.getChangedEventType(ol.layer.LayerProperty.BRIGHTNESS), this.handleLayerBrightnessChange, false, this); @@ -167,13 +173,29 @@ ol.renderer.Layer.prototype.handleLayerVisibleChange = function() { /** * Handle changes in tile state. * @param {goog.events.Event} event Tile change event. - * @protected + * @private */ -ol.renderer.Layer.prototype.handleTileChange = function(event) { +ol.renderer.Layer.prototype.handleTileChange_ = function(event) { var tile = /** @type {ol.Tile} */ (event.target); if (tile.getState() === ol.TileState.LOADED) { this.getMap().requestRenderFrame(); } + delete this.observedTileKeys[tile.getKey()]; +}; + + +/** + * Listen once to titileKey, le change event. + * @param {ol.Tile} tile Tile. + * @protected + */ +ol.renderer.Layer.prototype.listenToTileChange = function(tile) { + var tileKey = tile.getKey(); + if (!(tileKey in this.observedTileKeys)) { + this.observedTileKeys[tileKey] = true; + goog.events.listenOnce(tile, goog.events.EventType.CHANGE, + this.handleTileChange_, false, this); + } }; diff --git a/src/ol/renderer/webgl/webgltilelayerrenderer.js b/src/ol/renderer/webgl/webgltilelayerrenderer.js index 4059509e0a..0058746bab 100644 --- a/src/ol/renderer/webgl/webgltilelayerrenderer.js +++ b/src/ol/renderer/webgl/webgltilelayerrenderer.js @@ -391,8 +391,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = tileState = tile.getState(); if (tileState == ol.TileState.IDLE) { - goog.events.listenOnce(tile, goog.events.EventType.CHANGE, - this.handleTileChange, false, this); + this.listenToTileChange(tile); this.updateWantedTiles(frameState.wantedTiles, tileSource, tileCoord); tileCenter = tileGrid.getTileCoordCenter(tileCoord); frameState.tileQueue.enqueue(tile, tileSourceKey, tileCenter); From a4afcd533fce7d577a9aae75bf8351e87009b126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 5 Mar 2013 18:06:57 +0100 Subject: [PATCH 3/3] Add FIXME --- src/ol/tile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ol/tile.js b/src/ol/tile.js index ce00f9a1db..6b8956352b 100644 --- a/src/ol/tile.js +++ b/src/ol/tile.js @@ -1,3 +1,5 @@ +// FIXME should inQueue be private? + goog.provide('ol.Tile'); goog.provide('ol.TileState');