add cvmts rect batcher (abstracted to only deal with rects & size since vnc library draws to the buffer beforehand)

This commit is contained in:
Lily Tsuru 2024-04-02 11:22:16 -04:00
parent 126a6f6f56
commit dcc6310dd4
3 changed files with 53 additions and 8 deletions

View file

@ -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!

View file

@ -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

View file

@ -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>): 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<string> {