Smarter reuse detection
This commit is contained in:
@@ -362,10 +362,12 @@ class Executor extends Disposable {
|
|||||||
const declutterArgs = intersects ?
|
const declutterArgs = intersects ?
|
||||||
[context, transform ? transform.slice(0) : null, opacity, image, originX, originY, w, h, x, y, scale] :
|
[context, transform ? transform.slice(0) : null, opacity, image, originX, originY, w, h, x, y, scale] :
|
||||||
null;
|
null;
|
||||||
if (declutterArgs && fillStroke) {
|
if (declutterArgs) {
|
||||||
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
|
if (fillStroke) {
|
||||||
|
declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
|
||||||
|
}
|
||||||
|
declutterGroup.push(declutterArgs);
|
||||||
}
|
}
|
||||||
declutterGroup.push(declutterArgs);
|
|
||||||
} else if (intersects) {
|
} else if (intersects) {
|
||||||
if (fillStroke) {
|
if (fillStroke) {
|
||||||
this.replayTextBackground_(context, p1, p2, p3, p4,
|
this.replayTextBackground_(context, p1, p2, p3, p4,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import MapRenderer from './Map.js';
|
|||||||
import SourceState from '../source/State.js';
|
import SourceState from '../source/State.js';
|
||||||
import {replaceChildren} from '../dom.js';
|
import {replaceChildren} from '../dom.js';
|
||||||
import {labelCache} from '../render/canvas.js';
|
import {labelCache} from '../render/canvas.js';
|
||||||
import {altShiftKeysOnly} from '../events/condition.js';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import ViewHint from '../../ViewHint.js';
|
|||||||
import {containsExtent, intersects} from '../../extent.js';
|
import {containsExtent, intersects} from '../../extent.js';
|
||||||
import {getIntersection, isEmpty} from '../../extent.js';
|
import {getIntersection, isEmpty} from '../../extent.js';
|
||||||
import CanvasLayerRenderer from './Layer.js';
|
import CanvasLayerRenderer from './Layer.js';
|
||||||
import {compose as composeTransform, makeInverse, toString as transformToString, apply as applyTransform} from '../../transform.js';
|
import {compose as composeTransform, makeInverse, toString as transformToString} from '../../transform.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import RenderEventType from '../../render/EventType.js';
|
|||||||
import {rotateAtOffset} from '../../render/canvas.js';
|
import {rotateAtOffset} from '../../render/canvas.js';
|
||||||
import LayerRenderer from '../Layer.js';
|
import LayerRenderer from '../Layer.js';
|
||||||
import {create as createTransform, apply as applyTransform, compose as composeTransform, toString as transformToString} from '../../transform.js';
|
import {create as createTransform, apply as applyTransform, compose as composeTransform, toString as transformToString} from '../../transform.js';
|
||||||
import ContextEventType from '../../webgl/ContextEventType.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract
|
* @abstract
|
||||||
@@ -64,16 +63,20 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
*/
|
*/
|
||||||
this.context = null;
|
this.context = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.containerReused = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a rendering container from an existing target, if compatible.
|
* Get a rendering container from an existing target, if compatible.
|
||||||
* @param {HTMLElement} target Potential render target.
|
* @param {HTMLElement} target Potential render target.
|
||||||
* @param {import("../../transform").Transform} transform Transform.
|
* @param {import("../../transform").Transform} transform Transform.
|
||||||
* @return {boolean} The target is reused for this layer.
|
|
||||||
*/
|
*/
|
||||||
useContainer(target, transform) {
|
useContainer(target, transform) {
|
||||||
let reused = false;
|
const layerClassName = this.getLayer().getClassName();
|
||||||
let container, context;
|
let container, context;
|
||||||
if (target) {
|
if (target) {
|
||||||
const canvas = target.firstElementChild;
|
const canvas = target.firstElementChild;
|
||||||
@@ -82,33 +85,33 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (context && context.canvas.style.transform === transformToString(transform)) {
|
if (context && context.canvas.style.transform === transformToString(transform)) {
|
||||||
container = target;
|
// Container of the previous layer renderer can be used.
|
||||||
reused = true;
|
target.classList.add(layerClassName);
|
||||||
} else {
|
this.container = target;
|
||||||
context = null;
|
this.context = context;
|
||||||
container = this.container;
|
this.containerReused = true;
|
||||||
if (!container) {
|
} else if (this.containerReused) {
|
||||||
container = document.createElement('div');
|
// Previously reused container cannot be used any more.
|
||||||
const style = container.style;
|
this.container = null;
|
||||||
style.position = 'absolute';
|
this.context = null;
|
||||||
style.width = '100%';
|
this.containerReused = false;
|
||||||
style.height = '100%';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (container !== this.container) {
|
if (!this.container) {
|
||||||
container.classList.add(this.getLayer().getClassName());
|
container = document.createElement('div');
|
||||||
|
container.className = layerClassName;
|
||||||
|
let style = container.style;
|
||||||
|
style.position = 'absolute';
|
||||||
|
style.width = '100%';
|
||||||
|
style.height = '100%';
|
||||||
|
context = createCanvasContext2D();
|
||||||
|
const canvas = context.canvas;
|
||||||
|
container.appendChild(canvas);
|
||||||
|
style = canvas.style;
|
||||||
|
style.position = 'absolute';
|
||||||
|
style.transformOrigin = 'top left';
|
||||||
this.container = container;
|
this.container = container;
|
||||||
if (!context) {
|
|
||||||
context = createCanvasContext2D();
|
|
||||||
const canvas = context.canvas;
|
|
||||||
container.appendChild(canvas);
|
|
||||||
const style = canvas.style;
|
|
||||||
style.position = 'absolute';
|
|
||||||
style.transformOrigin = 'top left';
|
|
||||||
}
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
return reused;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import TileState from '../../TileState.js';
|
|||||||
import {createEmpty, equals, getIntersection, getTopLeft} from '../../extent.js';
|
import {createEmpty, equals, getIntersection, getTopLeft} from '../../extent.js';
|
||||||
import CanvasLayerRenderer from './Layer.js';
|
import CanvasLayerRenderer from './Layer.js';
|
||||||
import {apply as applyTransform, compose as composeTransform, makeInverse, toString as transformToString} from '../../transform.js';
|
import {apply as applyTransform, compose as composeTransform, makeInverse, toString as transformToString} from '../../transform.js';
|
||||||
import {numberSafeCompareFunction} from '../../array.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
@@ -234,7 +233,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
-width / 2, -height / 2
|
-width / 2, -height / 2
|
||||||
);
|
);
|
||||||
|
|
||||||
const reused = this.useContainer(target, this.pixelTransform_);
|
this.useContainer(target, this.pixelTransform_);
|
||||||
const context = this.context;
|
const context = this.context;
|
||||||
const canvas = context.canvas;
|
const canvas = context.canvas;
|
||||||
|
|
||||||
@@ -251,7 +250,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
if (canvas.width != width || canvas.height != height) {
|
if (canvas.width != width || canvas.height != height) {
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
} else if (!reused) {
|
} else if (!this.containerReused) {
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,17 +70,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
renderFrame(frameState, layerState, target) {
|
||||||
const context = this.context;
|
|
||||||
const canvas = context.canvas;
|
|
||||||
|
|
||||||
const replayGroup = this.replayGroup_;
|
|
||||||
if (!replayGroup || replayGroup.isEmpty()) {
|
|
||||||
if (canvas.width > 0) {
|
|
||||||
canvas.width = 0;
|
|
||||||
}
|
|
||||||
return canvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pixelRatio = frameState.pixelRatio;
|
const pixelRatio = frameState.pixelRatio;
|
||||||
|
|
||||||
@@ -88,6 +78,18 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
makeScale(this.pixelTransform_, 1 / pixelRatio, 1 / pixelRatio);
|
makeScale(this.pixelTransform_, 1 / pixelRatio, 1 / pixelRatio);
|
||||||
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
|
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
|
||||||
|
|
||||||
|
this.useContainer(target, this.pixelTransform_);
|
||||||
|
const context = this.context;
|
||||||
|
const canvas = context.canvas;
|
||||||
|
|
||||||
|
const replayGroup = this.replayGroup_;
|
||||||
|
if (!replayGroup || replayGroup.isEmpty()) {
|
||||||
|
if (!this.containerReused && canvas.width > 0) {
|
||||||
|
canvas.width = 0;
|
||||||
|
}
|
||||||
|
return this.container;
|
||||||
|
}
|
||||||
|
|
||||||
// resize and clear
|
// resize and clear
|
||||||
const width = Math.round(frameState.size[0] * pixelRatio);
|
const width = Math.round(frameState.size[0] * pixelRatio);
|
||||||
const height = Math.round(frameState.size[1] * pixelRatio);
|
const height = Math.round(frameState.size[1] * pixelRatio);
|
||||||
@@ -98,7 +100,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
if (canvas.style.transform !== canvasTransform) {
|
if (canvas.style.transform !== canvasTransform) {
|
||||||
canvas.style.transform = canvasTransform;
|
canvas.style.transform = canvasTransform;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!this.containerReused) {
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +168,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
canvas.style.opacity = opacity;
|
canvas.style.opacity = opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return canvas;
|
return this.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -123,27 +123,31 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
useContainer(target, transform) {
|
useContainer(target, transform) {
|
||||||
let context;
|
let overlayContext;
|
||||||
if (target && target.childElementCount === 2) {
|
if (target && target.childElementCount === 2) {
|
||||||
context = target.lastElementChild.getContext('2d');
|
overlayContext = target.lastElementChild.getContext('2d');
|
||||||
if (!context) {
|
if (!overlayContext) {
|
||||||
target = null;
|
target = null;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
context = this.overlayContext_;
|
|
||||||
if (!this.overlayContext_) {
|
|
||||||
context = createCanvasContext2D();
|
|
||||||
const style = context.canvas.style;
|
|
||||||
style.position = 'absolute';
|
|
||||||
style.transformOrigin = 'top left';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const reused = super.useContainer(target, transform);
|
const containerReused = this.containerReused;
|
||||||
|
super.useContainer(target, transform);
|
||||||
|
if (containerReused && !this.containerReused && !overlayContext) {
|
||||||
|
this.overlayContext_ = null;
|
||||||
|
}
|
||||||
|
if (this.containerReused && overlayContext) {
|
||||||
|
this.overlayContext_ = overlayContext;
|
||||||
|
}
|
||||||
|
if (!this.overlayContext_) {
|
||||||
|
const overlayContext = createCanvasContext2D();
|
||||||
|
const style = overlayContext.canvas.style;
|
||||||
|
style.position = 'absolute';
|
||||||
|
style.transformOrigin = 'top left';
|
||||||
|
this.overlayContext_ = overlayContext;
|
||||||
|
}
|
||||||
if (this.container.childElementCount === 1) {
|
if (this.container.childElementCount === 1) {
|
||||||
this.container.appendChild(context.canvas);
|
this.container.appendChild(this.overlayContext_.canvas);
|
||||||
}
|
}
|
||||||
this.overlayContext_ = context;
|
|
||||||
return reused;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -401,7 +405,6 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
|
|
||||||
if (!isEmpty(this.renderTileImageQueue_) && !this.extentChanged) {
|
if (!isEmpty(this.renderTileImageQueue_) && !this.extentChanged) {
|
||||||
this.renderTileImages_(hifi, frameState);
|
this.renderTileImages_(hifi, frameState);
|
||||||
return this.container;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = this.overlayContext_;
|
const context = this.overlayContext_;
|
||||||
@@ -427,7 +430,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
if (canvas.style.transform !== canvasTransform) {
|
if (canvas.style.transform !== canvasTransform) {
|
||||||
canvas.style.transform = canvasTransform;
|
canvas.style.transform = canvasTransform;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!this.containerReused) {
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,10 +499,6 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer {
|
|||||||
canvas.style.opacity = opacity;
|
canvas.style.opacity = opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have rendered the tiles we have already, let's prepare new tile images
|
|
||||||
// for the next frame
|
|
||||||
this.renderTileImages_(hifi, frameState);
|
|
||||||
|
|
||||||
return this.container;
|
return this.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user