diff --git a/backend/src/SocketComputerServer.ts b/backend/src/SocketComputerServer.ts index 8d55184..8d2d432 100644 --- a/backend/src/SocketComputerServer.ts +++ b/backend/src/SocketComputerServer.ts @@ -136,7 +136,7 @@ class VirtualMachine extends EventEmitter { super(); this.vm = vm; - this.timer = new ExtendableTimer(2); + this.timer = new ExtendableTimer(15); this.timer.on('expired', async () => { // bye bye! diff --git a/qemu/src/QemuDisplay.ts b/qemu/src/QemuDisplay.ts index c1504e8..cd6157f 100644 --- a/qemu/src/QemuDisplay.ts +++ b/qemu/src/QemuDisplay.ts @@ -1,6 +1,7 @@ import { VncClient } from './rfb/client.js'; import { EventEmitter } from 'node:events'; import { Canvas, CanvasRenderingContext2D, createImageData } from 'canvas'; +import { BatchRects, Size, Rect } from './QemuUtil.js'; const kQemuFps = 30; @@ -77,7 +78,7 @@ export class QemuDisplay extends EventEmitter { this.displayCanvas.height = height; }); - let rects: VncRect[] = []; + let rects: Rect[] = []; this.displayVnc.on('rectUpdateProcessed', (rect) => { rects.push(rect); @@ -89,9 +90,13 @@ export class QemuDisplay extends EventEmitter { // TODO: optimize the rects a bit. using guacamole's cheap method // of just flushing the whole screen if the area of all the updated rects gets too big // might just work. - for (const rect of rects) { - this.emit('rect', rect.x, rect.y, this.displayCtx.getImageData(rect.x, rect.y, rect.width, rect.height)); - } + //for (const rect of rects) { + // this.emit('rect', rect.x, rect.y, this.displayCtx.getImageData(rect.x, rect.y, rect.width, rect.height)); + //} + + // cvmts batcher + let batched = BatchRects(this.Size(), rects); + this.emit('rect', batched.x, batched.y, this.displayCtx.getImageData(batched.x, batched.y, batched.width, batched.height)); rects = []; @@ -126,7 +131,7 @@ export class QemuDisplay extends EventEmitter { return this.displayCanvas; } - Size() { + Size(): Size { return { width: this.displayVnc.clientWidth, height: this.displayVnc.clientHeight diff --git a/qemu/src/QemuUtil.ts b/qemu/src/QemuUtil.ts index 9f0dd65..4754b88 100644 --- a/qemu/src/QemuUtil.ts +++ b/qemu/src/QemuUtil.ts @@ -4,8 +4,48 @@ import { execa } from 'execa'; import * as crypto from 'node:crypto'; -/// Temporary path base for hard drive images. -const kVmHdaTmpPathBase = `/mnt/vmi/tmp/crusttest-hda`; +export type Size = { width: number, height: number }; +export type Rect = {height:number,width:number,x:number,y:number}; + +export function BatchRects(size: Size, rects: Array): Rect { + var mergedX = size.width; + var mergedY = size.height; + var mergedHeight = 0; + var mergedWidth = 0; + + // can't batch these + if(rects.length == 0) { + return { + x: 0, + y: 0, + width: size.width, + height: size.height + }; + } + + if(rects.length == 1) { + if(rects[0].width == size.width && rects[0].height == size.height) { + return rects[0]; + } + } + + rects.forEach((r) => { + if (r.x < mergedX) mergedX = r.x; + if (r.y < mergedY) mergedY = r.y; + }); + + rects.forEach(r => { + if (((r.height + r.y) - mergedY) > mergedHeight) mergedHeight = (r.height + r.y) - mergedY; + if (((r.width + r.x) - mergedX) > mergedWidth) mergedWidth = (r.width + r.x) - mergedX; + }); + + return { + x: mergedX, + y: mergedY, + width: mergedWidth, + height: mergedHeight + }; +} // Generates a random unicast/local MAC address. export async function GenMacAddress(): Promise {