diff --git a/simulator/src/compositor.ts b/simulator/src/compositor.ts index a7fd853..56064a4 100644 --- a/simulator/src/compositor.ts +++ b/simulator/src/compositor.ts @@ -106,7 +106,7 @@ export class WebGLCompositor { gl.vertexAttribPointer(positionAttrib, 2, GL.FLOAT, false, 0, 0); } - composite (framebuffer: Framebuffer) { + composite (framebuffer: Framebuffer): number { const gl = this.gl; const bytes = framebuffer.bytes; @@ -115,5 +115,7 @@ export class WebGLCompositor { // Draw the fullscreen quad gl.drawArrays(GL.TRIANGLES, 0, 6); + + return framebuffer.countChangedPixelsAndReset(); } } diff --git a/simulator/src/framebuffer.ts b/simulator/src/framebuffer.ts index 3eaa169..80fa6ab 100644 --- a/simulator/src/framebuffer.ts +++ b/simulator/src/framebuffer.ts @@ -8,17 +8,27 @@ import { FONT } from "./font"; export class Framebuffer { bytes: Uint16Array; + pixelsChanged: number; constructor (memory: ArrayBuffer) { this.bytes = new Uint16Array(memory, ADDR_FRAMEBUFFER, WIDTH * HEIGHT); + this.pixelsChanged = 0; + } + + countChangedPixelsAndReset (): number { + const result = this.pixelsChanged; + this.pixelsChanged = 0; + return result; } fillScreen (color: number): void { this.bytes.fill(color); + this.pixelsChanged += this.bytes.length; } drawPoint (color: number, x: number, y: number) { this.bytes[WIDTH * y + x] = color; + this.pixelsChanged += 1; } drawPointUnclipped (color: number, x: number, y: number) { @@ -30,6 +40,7 @@ export class Framebuffer { drawHLineFast(color: number, startX: number, y: number, endX: number) { const yOff = WIDTH * y; this.bytes.fill(color, yOff + startX, yOff + endX); + this.pixelsChanged += endX - startX; } drawHLineUnclipped(color: number, startX: number, y: number, endX: number) { diff --git a/simulator/src/runtime.ts b/simulator/src/runtime.ts index 4588db8..7bf0537 100644 --- a/simulator/src/runtime.ts +++ b/simulator/src/runtime.ts @@ -5,6 +5,8 @@ import { Framebuffer } from "./framebuffer"; import { WebGLCompositor } from "./compositor"; import { pack565, unpack565 } from "./ui/utils"; +const PIXELS_PER_MILLISECOND = 512; // about 25 FPS for full screen refreshes. + export class Runtime { canvas: HTMLCanvasElement; memory: WebAssembly.Memory; @@ -258,7 +260,9 @@ export class Runtime { } composite () { - this.compositor.composite(this.framebuffer); + const changedPixels = this.compositor.composite(this.framebuffer); + const screenUpdateTimeMs = changedPixels / PIXELS_PER_MILLISECOND; + return screenUpdateTimeMs; } } diff --git a/simulator/src/ui/app.ts b/simulator/src/ui/app.ts index 65d17be..16436d9 100644 --- a/simulator/src/ui/app.ts +++ b/simulator/src/ui/app.ts @@ -373,7 +373,12 @@ export class App extends LitElement { } if (calledUpdate) { - runtime.composite(); + const extraTimePenalty = runtime.composite(); + const screenDoneTime = timeFrameStart + extraTimePenalty; + if (screenDoneTime > timeNextUpdate) { + console.log("throttled by pixels!"); + timeNextUpdate = screenDoneTime; + } // if (import.meta.env.DEV) { // // FIXED(2023-12-13): Pass the correct FPS for display