From 7c8e11573b2ad85c3e46ff7c49e224a99f442e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B0=D0=BD=D0=B8=D1=97=D0=BB=20=D0=93=D1=80=D0=B8?= =?UTF-8?q?=D0=B3=D0=BE=D1=80=27=D1=94=D0=B2?= Date: Thu, 19 Jun 2025 23:11:30 +0300 Subject: [PATCH] Do not reuse canvas between savegame loads Remove lastCanvas/lastContext cache for reusing canvas as creating a new canvas does not cause performance issue. Additionaly, remove smoothing classes and buffer registration as they are not used anywhere. Finally, remove redundant stageDestroyed calls in the InGameState. --- src/js/game/core.js | 46 ++++++----------------------------------- src/js/states/ingame.js | 18 +++++++--------- 2 files changed, 14 insertions(+), 50 deletions(-) diff --git a/src/js/game/core.js b/src/js/game/core.js index 3d9130e0..e349f5b2 100644 --- a/src/js/game/core.js +++ b/src/js/game/core.js @@ -2,7 +2,7 @@ import { Application } from "../application"; /* typehints:end */ import { BufferMaintainer } from "../core/buffer_maintainer"; -import { getBufferStats, registerCanvas } from "../core/buffer_utils"; +import { getBufferStats } from "../core/buffer_utils"; import { globalConfig } from "../core/config"; import { getDeviceDPI, resizeHighDPICanvas } from "../core/dpi_manager"; import { DrawParameters } from "../core/draw_parameters"; @@ -36,12 +36,6 @@ import { GameTime } from "./time/game_time"; const logger = createLogger("ingame/core"); -// Store the canvas so we can reuse it later -/** @type {HTMLCanvasElement} */ -let lastCanvas = null; -/** @type {CanvasRenderingContext2D} */ -let lastContext = null; - /** * The core manages the root and represents the whole game. It wraps the root, since * the root class is just a data holder. @@ -208,51 +202,23 @@ export class GameCore { * Initializes the render canvas */ internalInitCanvas() { - let canvas, context; - if (!lastCanvas) { - logger.log("Creating new canvas"); - canvas = document.createElement("canvas"); - canvas.id = "ingame_Canvas"; - this.root.gameState.getDivElement().appendChild(canvas); - context = canvas.getContext("2d", { alpha: false }); - - lastCanvas = canvas; - lastContext = context; - } else { - logger.log("Reusing canvas"); - if (lastCanvas.parentElement) { - lastCanvas.parentElement.removeChild(lastCanvas); - } - this.root.gameState.getDivElement().appendChild(lastCanvas); - - canvas = lastCanvas; - context = lastContext; - - lastContext.clearRect(0, 0, lastCanvas.width, lastCanvas.height); - } - - canvas.classList.toggle("smoothed", globalConfig.smoothing.smoothMainCanvas); - - // Oof, use :not() instead - canvas.classList.toggle("unsmoothed", !globalConfig.smoothing.smoothMainCanvas); + logger.log("Creating new canvas"); + const canvas = document.createElement("canvas"); + canvas.id = "ingame_Canvas"; + this.root.gameState.getDivElement().appendChild(canvas); + const context = canvas.getContext("2d", { alpha: false }); context.imageSmoothingEnabled = globalConfig.smoothing.smoothMainCanvas; context.imageSmoothingQuality = globalConfig.smoothing.quality; this.root.canvas = canvas; this.root.context = context; - - registerCanvas(canvas, context); } /** * Destructs the root, freeing all resources */ destruct() { - if (lastCanvas && lastCanvas.parentElement) { - lastCanvas.parentElement.removeChild(lastCanvas); - } - this.root.destruct(); delete this.root; this.root = null; diff --git a/src/js/states/ingame.js b/src/js/states/ingame.js index c48e27c3..34f4c1c9 100644 --- a/src/js/states/ingame.js +++ b/src/js/states/ingame.js @@ -1,15 +1,15 @@ -import { GameState } from "../core/game_state"; -import { logSection, createLogger } from "../core/logging"; -import { waitNextFrame } from "../core/utils"; import { globalConfig } from "../core/config"; -import { GameLoadingOverlay } from "../game/game_loading_overlay"; -import { KeyActionMapper } from "../game/key_action_mapper"; -import { Savegame } from "../savegame/savegame"; +import { GameState } from "../core/game_state"; +import { createLogger, logSection } from "../core/logging"; +import { waitNextFrame } from "../core/utils"; import { GameCore } from "../game/core"; -import { MUSIC } from "../platform/sound"; +import { GameLoadingOverlay } from "../game/game_loading_overlay"; import { enumGameModeIds } from "../game/game_mode"; -import { MOD_SIGNALS } from "../mods/mod_signals"; import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs"; +import { KeyActionMapper } from "../game/key_action_mapper"; +import { MOD_SIGNALS } from "../mods/mod_signals"; +import { MUSIC } from "../platform/sound"; +import { Savegame } from "../savegame/savegame"; import { T } from "../translations"; const logger = createLogger("state/ingame"); @@ -194,7 +194,6 @@ export class InGameState extends GameState { } this.stageLeavingGame(); this.doSave().then(() => { - this.stageDestroyed(); this.moveToState(stateId, payload); }); } @@ -219,7 +218,6 @@ export class InGameState extends GameState { onInitializationFailure(err) { if (this.switchStage(GAME_LOADING_STATES.initFailed)) { logger.error("Init failure:", err); - this.stageDestroyed(); this.moveToState("MainMenuState", { loadError: err }); } }