import { defined } from "../../Source/Cesium.js"; import { getTimestamp } from "../../Source/Cesium.js"; import { FrameRateMonitor } from "../../Source/Cesium.js"; import createScene from "../createScene.js"; describe( "Scene/FrameRateMonitor", function () { var scene; beforeAll(function () { scene = createScene(); }); afterAll(function () { scene.destroyForSpecs(); }); var monitor; afterEach(function () { if (defined(monitor)) { monitor.destroy(); monitor = undefined; } }); function spinWait(milliseconds) { var endTime = getTimestamp() + milliseconds; /*eslint-disable no-empty*/ while (getTimestamp() < endTime) {} /*eslint-enable no-empty*/ } it("throws when constructed without a scene", function () { expect(function () { monitor = new FrameRateMonitor(); }).toThrowDeveloperError(); expect(function () { monitor = new FrameRateMonitor({}); }).toThrowDeveloperError(); }); it("can be constructed with just a scene", function () { monitor = new FrameRateMonitor({ scene: scene, }); expect(monitor.samplingWindow).toBe(5.0); expect(monitor.quietPeriod).toBe(2.0); expect(monitor.warmupPeriod).toBe(5.0); expect(monitor.minimumFrameRateDuringWarmup).toBe(4); expect(monitor.minimumFrameRateAfterWarmup).toBe(8); expect(monitor.scene).toBe(scene); expect(monitor.lowFrameRate.numberOfListeners).toBe(0); expect(monitor.nominalFrameRate.numberOfListeners).toBe(0); }); it("honors parameters to the constructor", function () { monitor = new FrameRateMonitor({ scene: scene, samplingWindow: 3.0, quietPeriod: 1.0, warmupPeriod: 6.0, minimumFrameRateDuringWarmup: 1, minimumFrameRateAfterWarmup: 2, }); expect(monitor.samplingWindow).toBe(3.0); expect(monitor.quietPeriod).toBe(1.0); expect(monitor.warmupPeriod).toBe(6.0); expect(monitor.minimumFrameRateDuringWarmup).toBe(1); expect(monitor.minimumFrameRateAfterWarmup).toBe(2); expect(monitor.scene).toBe(scene); }); it("raises the lowFrameRate event on low frame rate", function () { monitor = new FrameRateMonitor({ scene: scene, quietPeriod: 0.001, warmupPeriod: 0.001, samplingWindow: 0.001, minimumFrameRateDuringWarmup: 1000, minimumFrameRateAfterWarmup: 1000, }); var spyListener = jasmine.createSpy("listener"); monitor.lowFrameRate.addEventListener(spyListener); // Rendering once starts the quiet period scene.render(); // Wait until we're well past the end of the quiet period. spinWait(2); // Rendering again records our first sample. scene.render(); // Wait well over a millisecond, which is the maximum frame time allowed by this instance. spinWait(2); // Record our second sample. The monitor should notice that our frame rate is too low. scene.render(); expect(monitor.lastFramesPerSecond).toBeLessThan(1000); expect(spyListener).toHaveBeenCalled(); }); it("does not monitor frame rate while paused", function () { monitor = new FrameRateMonitor({ scene: scene, quietPeriod: 0.001, warmupPeriod: 0.001, samplingWindow: 0.001, minimumFrameRateDuringWarmup: 1000, minimumFrameRateAfterWarmup: 1000, }); var spyListener = jasmine.createSpy("listener"); monitor.lowFrameRate.addEventListener(spyListener); // Rendering once starts the quiet period scene.render(); // Wait until we're well past the end of the quiet period. spinWait(2); // Rendering again records our first sample. scene.render(); monitor.pause(); // Wait well over a millisecond, which is the maximum frame time allowed by this instance. spinWait(2); // Record our second sample. The monitor would notice that our frame rate is too low, // but it's paused. scene.render(); monitor.unpause(); scene.render(); expect(spyListener).not.toHaveBeenCalled(); }); it("pausing multiple times requires unpausing multiple times", function () { monitor = new FrameRateMonitor({ scene: scene, quietPeriod: 0.001, warmupPeriod: 0.001, samplingWindow: 0.001, minimumFrameRateDuringWarmup: 1000, minimumFrameRateAfterWarmup: 1000, }); var spyListener = jasmine.createSpy("listener"); monitor.lowFrameRate.addEventListener(spyListener); monitor.pause(); monitor.pause(); monitor.unpause(); // Rendering once starts the quiet period scene.render(); // Wait until we're well past the end of the quiet period. spinWait(2); // Rendering again records our first sample. scene.render(); // Wait well over a millisecond, which is the maximum frame time allowed by this instance. spinWait(2); // Record our second sample. The monitor would notice that our frame rate is too low, // but it's paused. scene.render(); monitor.unpause(); scene.render(); expect(spyListener).not.toHaveBeenCalled(); }); it("does not report a low frame rate during the quiet period", function () { monitor = new FrameRateMonitor({ scene: scene, quietPeriod: 1.0, warmupPeriod: 0.001, samplingWindow: 0.001, minimumFrameRateDuringWarmup: 1000, minimumFrameRateAfterWarmup: 1000, }); var spyListener = jasmine.createSpy("listener"); monitor.lowFrameRate.addEventListener(spyListener); // Rendering once starts the quiet period scene.render(); // Wait well over a millisecond, which is the maximum frame time allowed by this instance. spinWait(2); // Render again. Even though our frame rate is too low, the monitor shouldn't raise the event because we're in the quiet period. scene.render(); expect(spyListener).not.toHaveBeenCalled(); }); it("the nominalFrameRate event is raised after the warmup period if the frame rate returns to nominal", function () { monitor = new FrameRateMonitor({ scene: scene, quietPeriod: 0.001, warmupPeriod: 0.001, samplingWindow: 0.001, minimumFrameRateDuringWarmup: 10, minimumFrameRateAfterWarmup: 10, }); var lowListener = jasmine.createSpy("lowFrameRate"); monitor.lowFrameRate.addEventListener(lowListener); var nominalListener = jasmine.createSpy("nominalFrameRate"); monitor.nominalFrameRate.addEventListener(nominalListener); // Rendering once starts the quiet period scene.render(); // Wait until we're well past the end of the quiet period. spinWait(2); // Rendering again records our first sample. scene.render(); // Wait 120 millseconds, which is over the maximum frame time allowed by this instance. spinWait(120); // Record our second sample. The monitor should notice that our frame rate is too low. scene.render(); expect(monitor.lastFramesPerSecond).toBeLessThan(10); expect(lowListener).toHaveBeenCalled(); // Render as fast as possible for a samplingWindow, quietPeriod, and warmupPeriod. var endTime = getTimestamp() + 50; while (getTimestamp() < endTime) { scene.render(); } // The nominalFrameRate event should have been raised. expect(monitor.lastFramesPerSecond).toBeGreaterThanOrEqualTo(10); expect(nominalListener).toHaveBeenCalled(); }); }, "WebGL" );