Don't update the visible canvas at 60 fps (bug 1936605)
Instead, we update the visible canvas every 500ms. With large canvas, updating at 60fps lead to a lot gfx transactions and it can take a lot of time. For example, with wuppertal_2012.pdf on Windows, displaying it at 150% takes around 14 min !!! without this patch when it takes only around 14 sec with. Even at 30% it helps to improve the performance by around 20%.
This commit is contained in:
parent
2e10ff6dd4
commit
ecc56a61e6
@ -326,8 +326,6 @@ const PDFViewerApplication = {
|
||||
}
|
||||
}
|
||||
if (params.has("pdfbug")) {
|
||||
AppOptions.setAll({ pdfBug: true, fontExtraProperties: true });
|
||||
|
||||
const enabled = params.get("pdfbug").split(",");
|
||||
try {
|
||||
await loadPDFBug();
|
||||
@ -335,6 +333,12 @@ const PDFViewerApplication = {
|
||||
} catch (ex) {
|
||||
console.error("_parseHashParams:", ex);
|
||||
}
|
||||
|
||||
const debugOpts = { pdfBug: true, fontExtraProperties: true };
|
||||
if (globalThis.StepperManager?.enabled) {
|
||||
debugOpts.minDurationToUpdateCanvas = 0;
|
||||
}
|
||||
AppOptions.setAll(debugOpts);
|
||||
}
|
||||
// It is not possible to change locale for the (various) extension builds.
|
||||
if (
|
||||
@ -519,6 +523,7 @@ const PDFViewerApplication = {
|
||||
enableHWA,
|
||||
supportsPinchToZoom: this.supportsPinchToZoom,
|
||||
enableAutoLinking: AppOptions.get("enableAutoLinking"),
|
||||
minDurationToUpdateCanvas: AppOptions.get("minDurationToUpdateCanvas"),
|
||||
}));
|
||||
|
||||
renderingQueue.setViewer(pdfViewer);
|
||||
|
||||
@ -299,6 +299,11 @@ const defaultOptions = {
|
||||
value: 2 ** 25,
|
||||
kind: OptionKind.VIEWER,
|
||||
},
|
||||
minDurationToUpdateCanvas: {
|
||||
/** @type {number} */
|
||||
value: 500, // ms
|
||||
kind: OptionKind.VIEWER,
|
||||
},
|
||||
forcePageColors: {
|
||||
/** @type {boolean} */
|
||||
value: false,
|
||||
|
||||
@ -21,12 +21,18 @@ class BasePDFPageView {
|
||||
|
||||
#loadingId = null;
|
||||
|
||||
#minDurationToUpdateCanvas = 0;
|
||||
|
||||
#renderError = null;
|
||||
|
||||
#renderingState = RenderingStates.INITIAL;
|
||||
|
||||
#showCanvas = null;
|
||||
|
||||
#startTime = 0;
|
||||
|
||||
#tempCanvas = null;
|
||||
|
||||
canvas = null;
|
||||
|
||||
/** @type {null | HTMLDivElement} */
|
||||
@ -51,6 +57,7 @@ class BasePDFPageView {
|
||||
this.id = options.id;
|
||||
this.pageColors = options.pageColors || null;
|
||||
this.renderingQueue = options.renderingQueue;
|
||||
this.#minDurationToUpdateCanvas = options.minDurationToUpdateCanvas ?? 500;
|
||||
}
|
||||
|
||||
get renderingState() {
|
||||
@ -71,6 +78,9 @@ class BasePDFPageView {
|
||||
switch (state) {
|
||||
case RenderingStates.PAUSED:
|
||||
this.div.classList.remove("loading");
|
||||
// Display the canvas as it has been drawn.
|
||||
this.#startTime = 0;
|
||||
this.#showCanvas?.(false);
|
||||
break;
|
||||
case RenderingStates.RUNNING:
|
||||
this.div.classList.add("loadingIcon");
|
||||
@ -82,10 +92,12 @@ class BasePDFPageView {
|
||||
this.div.classList.add("loading");
|
||||
this.#loadingId = null;
|
||||
}, 0);
|
||||
this.#startTime = Date.now();
|
||||
break;
|
||||
case RenderingStates.INITIAL:
|
||||
case RenderingStates.FINISHED:
|
||||
this.div.classList.remove("loadingIcon", "loading");
|
||||
this.#startTime = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -100,10 +112,41 @@ class BasePDFPageView {
|
||||
// have a final flash we just display it once all the drawing is done.
|
||||
const updateOnFirstShow = !prevCanvas && !hasHCM && !hideUntilComplete;
|
||||
|
||||
const canvas = (this.canvas = document.createElement("canvas"));
|
||||
let canvas = (this.canvas = document.createElement("canvas"));
|
||||
|
||||
this.#showCanvas = isLastShow => {
|
||||
if (updateOnFirstShow) {
|
||||
let tempCanvas = this.#tempCanvas;
|
||||
if (!isLastShow && this.#minDurationToUpdateCanvas > 0) {
|
||||
// We draw on the canvas at 60fps (in using `requestAnimationFrame`),
|
||||
// so if the canvas is large, updating it at 60fps can be a way too
|
||||
// much and can cause some serious performance issues.
|
||||
// To avoid that we only update the canvas every
|
||||
// `this.#minDurationToUpdateCanvas` ms.
|
||||
|
||||
if (Date.now() - this.#startTime < this.#minDurationToUpdateCanvas) {
|
||||
return;
|
||||
}
|
||||
if (!tempCanvas) {
|
||||
tempCanvas = this.#tempCanvas = canvas;
|
||||
canvas = this.canvas = canvas.cloneNode(false);
|
||||
onShow(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
if (tempCanvas) {
|
||||
const ctx = canvas.getContext("2d", {
|
||||
alpha: false,
|
||||
});
|
||||
ctx.drawImage(tempCanvas, 0, 0);
|
||||
if (isLastShow) {
|
||||
this.#resetTempCanvas();
|
||||
} else {
|
||||
this.#startTime = Date.now();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't add the canvas until the first draw callback, or until
|
||||
// drawing is complete when `!this.renderingQueue`, to prevent black
|
||||
// flickering.
|
||||
@ -152,6 +195,14 @@ class BasePDFPageView {
|
||||
canvas.remove();
|
||||
canvas.width = canvas.height = 0;
|
||||
this.canvas = null;
|
||||
this.#resetTempCanvas();
|
||||
}
|
||||
|
||||
#resetTempCanvas() {
|
||||
if (this.#tempCanvas) {
|
||||
this.#tempCanvas.width = this.#tempCanvas.height = 0;
|
||||
this.#tempCanvas = null;
|
||||
}
|
||||
}
|
||||
|
||||
async _drawCanvas(options, onCancel, onFinish) {
|
||||
|
||||
@ -139,6 +139,8 @@ function isValidAnnotationEditorMode(mode) {
|
||||
* The default value is `true`.
|
||||
* @property {boolean} [enableAutoLinking] - Enable creation of hyperlinks from
|
||||
* text that look like URLs. The default value is `true`.
|
||||
* @property {number} [minDurationToUpdateCanvas] - Minimum duration to wait
|
||||
* before updating the canvas. The default value is `500`.
|
||||
*/
|
||||
|
||||
class PDFPageViewBuffer {
|
||||
@ -243,6 +245,8 @@ class PDFViewer {
|
||||
|
||||
#eventAbortController = null;
|
||||
|
||||
#minDurationToUpdateCanvas = 0;
|
||||
|
||||
#mlManager = null;
|
||||
|
||||
#scrollTimeoutId = null;
|
||||
@ -342,6 +346,7 @@ class PDFViewer {
|
||||
this.#enableHWA = options.enableHWA || false;
|
||||
this.#supportsPinchToZoom = options.supportsPinchToZoom !== false;
|
||||
this.#enableAutoLinking = options.enableAutoLinking !== false;
|
||||
this.#minDurationToUpdateCanvas = options.minDurationToUpdateCanvas ?? 500;
|
||||
|
||||
this.defaultRenderingQueue = !options.renderingQueue;
|
||||
if (
|
||||
@ -1003,6 +1008,7 @@ class PDFViewer {
|
||||
layerProperties: this._layerProperties,
|
||||
enableHWA: this.#enableHWA,
|
||||
enableAutoLinking: this.#enableAutoLinking,
|
||||
minDurationToUpdateCanvas: this.#minDurationToUpdateCanvas,
|
||||
});
|
||||
this._pages.push(pageView);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user