mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-29 00:26:10 +03:00
Make tile-invalidated event before tile-loaded. Try to fix behavior of maxTilesperFrame
This commit is contained in:
parent
5fdeb382ea
commit
9bfdd55b2e
@ -305,7 +305,7 @@
|
||||
* @property {Number} [rotationIncrement=90]
|
||||
* The number of degrees to rotate right or left when the rotate buttons or keyboard shortcuts are activated.
|
||||
*
|
||||
* @property {Number} [maxTilesPerFrame=10]
|
||||
* @property {Number} [maxTilesPerFrame=1]
|
||||
* The number of tiles loaded per frame. As the frame rate of the client's machine is usually high (e.g., 50 fps),
|
||||
* one tile per frame should be a good choice. However, for large screens or lower frame rates, the number of
|
||||
* loaded tiles per frame can be adjusted here. Reasonable values might be 2 or 3 tiles per frame.
|
||||
@ -1345,7 +1345,7 @@ function OpenSeadragon( options ){
|
||||
preserveImageSizeOnResize: false, // requires autoResize=true
|
||||
minScrollDeltaTime: 50,
|
||||
rotationIncrement: 90,
|
||||
maxTilesPerFrame: 10,
|
||||
maxTilesPerFrame: 1,
|
||||
|
||||
//DEFAULT CONTROL SETTINGS
|
||||
showSequenceControl: true, //SEQUENCE
|
||||
|
@ -275,7 +275,8 @@ $.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, aja
|
||||
this.lastProcess = 0;
|
||||
/**
|
||||
* Transforming flag, exempt the tile from any processing since it is being transformed to a drawer-compatible
|
||||
* format. This process cannot be paused and the tile cannot be touched during the process. Used externally.
|
||||
* format. This process cannot be paused and the tile cannot be touched during the process. Used for tile-locking
|
||||
* in the data invalidation routine.
|
||||
* @member {Boolean|Number}
|
||||
* @private
|
||||
*/
|
||||
|
@ -164,13 +164,17 @@
|
||||
/**
|
||||
* @private
|
||||
* Access of the data by drawers, synchronous function. Should always access a valid main cache, e.g.
|
||||
* cache swap should be atomic.
|
||||
* cache swap performed on working cache (consumeCache()) must be synchronous such that cache is always
|
||||
* ready to render, and swaps atomically between render calls.
|
||||
*
|
||||
* @param {OpenSeadragon.DrawerBase} drawer
|
||||
* @param {OpenSeadragon.Tile} tileDrawn
|
||||
* @param {OpenSeadragon.DrawerBase} drawer drawer reference which requests the data: the drawer
|
||||
* defines the supported formats this cache should return **synchronously**
|
||||
* @param {OpenSeadragon.Tile} tileToDraw reference to the tile that is in the process of drawing and
|
||||
* for which we request the data; if we attempt to draw such tile while main cache target is destroyed,
|
||||
* attempt to reset the tile state to force system to re-download it again
|
||||
* @returns {any|undefined} desired data if available, undefined if conversion must be done
|
||||
*/
|
||||
getDataForRendering(drawer, tileDrawn) {
|
||||
getDataForRendering(drawer, tileToDraw ) {
|
||||
const supportedTypes = drawer.getSupportedDataFormats(),
|
||||
keepInternalCopy = drawer.options.usePrivateCache;
|
||||
if (this.loaded && supportedTypes.includes(this.type)) {
|
||||
@ -179,7 +183,7 @@
|
||||
|
||||
if (this._destroyed) {
|
||||
$.console.error("Attempt to draw tile with destroyed main cache!");
|
||||
tileDrawn._unload(); // try to restore the state so that the tile is later on fetched again
|
||||
tileToDraw._unload(); // try to restore the state so that the tile is later on fetched again
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,7 @@ $.TiledImage = function( options ) {
|
||||
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation,
|
||||
subPixelRoundingForTransparency: $.DEFAULT_SETTINGS.subPixelRoundingForTransparency,
|
||||
maxTilesPerFrame: $.DEFAULT_SETTINGS.maxTilesPerFrame,
|
||||
_currentMaxTilesPerFrame: (options.maxTilesPerFrame || $.DEFAULT_SETTINGS.maxTilesPerFrame) * 10
|
||||
}, options );
|
||||
|
||||
this._preload = this.preload;
|
||||
@ -299,6 +300,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
*/
|
||||
reset: function() {
|
||||
this._tileCache.clearTilesFor(this);
|
||||
this._currentMaxTilesPerFrame = this.maxTilesPerFrame * 10;
|
||||
this.lastResetTime = $.now();
|
||||
this._needsDraw = true;
|
||||
this._fullyLoaded = false;
|
||||
@ -1817,7 +1819,11 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
this._tilesLoading++;
|
||||
} else if (!loadingCoverage) {
|
||||
// add tile to best tiles to load only when not loaded already
|
||||
best = this._compareTiles( best, tile, this.maxTilesPerFrame );
|
||||
best = this._compareTiles( best, tile, this._currentMaxTilesPerFrame );
|
||||
// TODO: test 'Viewer headers can be updated' fail if we start decreasing the number since not enough tiles get invoked
|
||||
// if (this._currentMaxTilesPerFrame > this.maxTilesPerFrame) {
|
||||
// this._currentMaxTilesPerFrame = Math.max(Math.ceil(this.maxTilesPerFrame / 2), this.maxTilesPerFrame);
|
||||
// }
|
||||
}
|
||||
|
||||
return {
|
||||
@ -2129,55 +2135,10 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
tile.hasTransparency = tile.hasTransparency || _this.source.hasTransparency(
|
||||
undefined, tile.getUrl(), tile.ajaxHeaders, tile.postData
|
||||
);
|
||||
// tile.updateRenderTarget(true);
|
||||
// //make sure cache data is ready for drawing, if not, request the desired format
|
||||
// const cache = tile.getCache(),
|
||||
// requiredTypes = _this._drawer.getSupportedDataFormats();
|
||||
// if (!cache) {
|
||||
// $.console.warn("Tile %s not cached or not loaded at the end of tile-loaded event: tile will not be drawn - it has no data!", tile);
|
||||
// resolver();
|
||||
// } else if (!requiredTypes.includes(cache.type)) {
|
||||
// //initiate conversion as soon as possible if incompatible with the drawer
|
||||
// //either the cache is a new item in the system (do process), or the cache inherits data from elsewhere (no-op),
|
||||
// // or the cache was processed in this call
|
||||
// tile.transforming = now; // block any updates on the tile
|
||||
// cache.prepareForRendering(_this._drawer.getId(), requiredTypes, _this._drawer.options.usePrivateCache).then(cacheRef => {
|
||||
// if (!cacheRef) {
|
||||
// return cache.transformTo(requiredTypes);
|
||||
// }
|
||||
// if (tile.processing === now) {
|
||||
// tile.updateRenderTarget();
|
||||
// }
|
||||
// return cacheRef;
|
||||
// }).then(resolver);
|
||||
// } else {
|
||||
// resolver();
|
||||
// }
|
||||
|
||||
// TODO consider first running this event before we call tile-loaded...
|
||||
if (!tileCacheCreated) {
|
||||
// Tile-loaded not called on each tile, but only on tiles with new data! Verify we share the main cache
|
||||
const origCache = tile.getCache(tile.originalCacheKey);
|
||||
for (let t of origCache._tiles) {
|
||||
// if there exists a tile that has different main cache, inherit it as a main cache
|
||||
if (t.cacheKey !== tile.cacheKey) {
|
||||
// add reference also to the main cache, no matter what the other tile state has
|
||||
// completion of the invaldate event should take care of all such tiles
|
||||
const targetMainCache = t.getCache();
|
||||
tile.addCache(t.cacheKey, () => {
|
||||
$.console.error("Attempt to share main cache with existing tile should not trigger data getter!");
|
||||
return targetMainCache.data;
|
||||
}, targetMainCache.type, true, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
resolver();
|
||||
return;
|
||||
}
|
||||
// In case we did not succeed in tile restoration, request invalidation todo what about catch
|
||||
const updatePromise = _this.viewer.world.requestTileInvalidateEvent([tile], now, false, true);
|
||||
updatePromise.then(resolver);
|
||||
tile.loading = false;
|
||||
tile.loaded = true;
|
||||
_this.redraw();
|
||||
resolver(tile);
|
||||
}
|
||||
|
||||
function getCompletionCallback() {
|
||||
@ -2189,80 +2150,82 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
||||
return completionCallback;
|
||||
}
|
||||
|
||||
const fallbackCompletion = getCompletionCallback();
|
||||
function markTileAsReady() {
|
||||
tile.lastProcess = false;
|
||||
tile.processing = false;
|
||||
tile.transforming = false;
|
||||
|
||||
// if (!tileCacheCreated) {
|
||||
// // Tile-loaded not called on each tile, but only on tiles with new data! Verify we share the main cache
|
||||
// const origCache = tile.getCache(tile.originalCacheKey);
|
||||
// if (!origCache.__invStamp) {
|
||||
// for (let t of origCache._tiles) {
|
||||
// if (t.cacheKey !== tile.cacheKey) {
|
||||
// const targetMainCache = t.getCache();
|
||||
// tile.addCache(t.cacheKey, targetMainCache.data, targetMainCache.type, true, false);
|
||||
// fallbackCompletion();
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // else todo: what if we somehow managed to finish before this tile gets attached? probably impossible if the tile is joined by original cache...
|
||||
// }
|
||||
const fallbackCompletion = getCompletionCallback();
|
||||
|
||||
// // TODO ENSURE ONLY THESE TWO EVENTS CAN CALL TILE UPDATES
|
||||
// // prepare for the fact that tile routine can be called here too
|
||||
// tile.lastProcess = false;
|
||||
// tile.processing = now;
|
||||
// tile.transforming = false;
|
||||
/**
|
||||
* Triggered when a tile has just been loaded in memory. That means that the
|
||||
* image has been downloaded and can be modified before being drawn to the canvas.
|
||||
* This event is _awaiting_, it supports asynchronous functions or functions that return a promise.
|
||||
*
|
||||
* @event tile-loaded
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {Image|*} image - The image (data) of the tile. Deprecated.
|
||||
* @property {*} data image data, the data sent to ImageJob.prototype.finish(),
|
||||
* by default an Image object. Deprecated
|
||||
* @property {String} dataType type of the data
|
||||
* @property {OpenSeadragon.TiledImage} tiledImage - The tiled image of the loaded tile.
|
||||
* @property {OpenSeadragon.Tile} tile - The tile which has been loaded.
|
||||
* @property {XMLHttpRequest} tileRequest - The AJAX request that loaded this tile (if applicable).
|
||||
* @property {OpenSeadragon.Promise} - Promise resolved when the tile gets fully loaded.
|
||||
* NOTE: do no await the promise in the handler: you will create a deadlock!
|
||||
* @property {function} getCompletionCallback - deprecated
|
||||
*/
|
||||
_this.viewer.raiseEventAwaiting("tile-loaded", {
|
||||
tile: tile,
|
||||
tiledImage: _this,
|
||||
tileRequest: tileRequest,
|
||||
promise: new $.Promise(resolve => {
|
||||
resolver = resolve;
|
||||
}),
|
||||
get image() {
|
||||
$.console.error("[tile-loaded] event 'image' has been deprecated. Use 'tile.getData()' instead.");
|
||||
return data;
|
||||
},
|
||||
get data() {
|
||||
$.console.error("[tile-loaded] event 'data' has been deprecated. Use 'tile.getData()' instead.");
|
||||
return data;
|
||||
},
|
||||
getCompletionCallback: function () {
|
||||
$.console.error("[tile-loaded] getCompletionCallback is deprecated: it introduces race conditions: " +
|
||||
"use async event handlers instead, execution order is deducted by addHandler(...) priority");
|
||||
return getCompletionCallback();
|
||||
},
|
||||
}).catch(() => {
|
||||
$.console.error("[tile-loaded] event finished with failure: there might be a problem with a plugin you are using.");
|
||||
}).then(fallbackCompletion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when a tile has just been loaded in memory. That means that the
|
||||
* image has been downloaded and can be modified before being drawn to the canvas.
|
||||
* This event is _awaiting_, it supports asynchronous functions or functions that return a promise.
|
||||
*
|
||||
* @event tile-loaded
|
||||
* @memberof OpenSeadragon.Viewer
|
||||
* @type {object}
|
||||
* @property {Image|*} image - The image (data) of the tile. Deprecated.
|
||||
* @property {*} data image data, the data sent to ImageJob.prototype.finish(),
|
||||
* by default an Image object. Deprecated
|
||||
* @property {String} dataType type of the data
|
||||
* @property {OpenSeadragon.TiledImage} tiledImage - The tiled image of the loaded tile.
|
||||
* @property {OpenSeadragon.Tile} tile - The tile which has been loaded.
|
||||
* @property {XMLHttpRequest} tileRequest - The AJAX request that loaded this tile (if applicable).
|
||||
* @property {OpenSeadragon.Promise} - Promise resolved when the tile gets fully loaded.
|
||||
* NOTE: do no await the promise in the handler: you will create a deadlock!
|
||||
* @property {function} getCompletionCallback - deprecated
|
||||
*/
|
||||
this.viewer.raiseEventAwaiting("tile-loaded", {
|
||||
tile: tile,
|
||||
tiledImage: this,
|
||||
tileRequest: tileRequest,
|
||||
promise: new $.Promise(resolve => {
|
||||
resolver = () => {
|
||||
tile.loading = false;
|
||||
tile.loaded = true;
|
||||
tile.lastProcess = false;
|
||||
tile.processing = false;
|
||||
tile.transforming = false;
|
||||
this.redraw();
|
||||
resolve(tile);
|
||||
};
|
||||
}),
|
||||
get image() {
|
||||
$.console.error("[tile-loaded] event 'image' has been deprecated. Use 'tile.getData()' instead.");
|
||||
return data;
|
||||
},
|
||||
get data() {
|
||||
$.console.error("[tile-loaded] event 'data' has been deprecated. Use 'tile.getData()' instead.");
|
||||
return data;
|
||||
},
|
||||
getCompletionCallback: function () {
|
||||
$.console.error("[tile-loaded] getCompletionCallback is deprecated: it introduces race conditions: " +
|
||||
"use async event handlers instead, execution order is deducted by addHandler(...) priority");
|
||||
return getCompletionCallback();
|
||||
},
|
||||
}).catch(() => {
|
||||
$.console.error("[tile-loaded] event finished with failure: there might be a problem with a plugin you are using.");
|
||||
}).then(fallbackCompletion);
|
||||
|
||||
if (tileCacheCreated) {
|
||||
const updatePromise = _this.viewer.world.requestTileInvalidateEvent([tile], now, false, true);
|
||||
updatePromise.then(markTileAsReady);
|
||||
} else {
|
||||
// In case we did not succeed in tile restoration, request invalidation
|
||||
// Tile-loaded not called on each tile, but only on tiles with new data! Verify we share the main cache
|
||||
const origCache = tile.getCache(tile.originalCacheKey);
|
||||
for (let t of origCache._tiles) {
|
||||
|
||||
// if there exists a tile that has different main cache, inherit it as a main cache
|
||||
if (t.cacheKey !== tile.cacheKey) {
|
||||
|
||||
// add reference also to the main cache, no matter what the other tile state has
|
||||
// completion of the invaldate event should take care of all such tiles
|
||||
const targetMainCache = t.getCache();
|
||||
tile.addCache(t.cacheKey, () => {
|
||||
$.console.error("Attempt to share main cache with existing tile should not trigger data getter!");
|
||||
return targetMainCache.data;
|
||||
}, targetMainCache.type, true, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
markTileAsReady();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
@ -75,9 +75,6 @@
|
||||
if (self.filterIncrement !== currentIncrement) {
|
||||
break;
|
||||
}
|
||||
if (contextCopy.canvas.width === 0) {
|
||||
debugger;
|
||||
}
|
||||
await processors[i](contextCopy);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user