add syncronous frames for secondary display

This commit is contained in:
mattmcclaskey 2023-10-05 07:51:50 -04:00
parent f243b54ac9
commit 56a2e2dec9
No known key found for this signature in database
2 changed files with 60 additions and 30 deletions

View File

@ -58,7 +58,7 @@ export default {
/* Every four characters is 3 resulting numbers */ /* Every four characters is 3 resulting numbers */
const resultLength = (dataLength >> 2) * 3 + Math.floor((dataLength % 4) / 1.5); const resultLength = (dataLength >> 2) * 3 + Math.floor((dataLength % 4) / 1.5);
const result = new Array(resultLength); const result = new Uint8Array(resultLength);
// Convert one by one. // Convert one by one.

View File

@ -12,6 +12,7 @@ import Base64 from "./base64.js";
import { toSigned32bit } from './util/int.js'; import { toSigned32bit } from './util/int.js';
import { isWindows } from './util/browser.js'; import { isWindows } from './util/browser.js';
import { uuidv4 } from './util/strings.js'; import { uuidv4 } from './util/strings.js';
import base64 from './base64.js';
export default class Display { export default class Display {
constructor(target, isPrimaryDisplay) { constructor(target, isPrimaryDisplay) {
@ -31,6 +32,7 @@ export default class Display {
this._asyncFrameQueue = []; this._asyncFrameQueue = [];
this._maxAsyncFrameQueue = 3; this._maxAsyncFrameQueue = 3;
this._clearAsyncQueue(); this._clearAsyncQueue();
this._syncFrameQueue = [];
this._flushing = false; this._flushing = false;
@ -706,50 +708,24 @@ export default class Display {
//overwrite screen locations when received on the secondary display //overwrite screen locations when received on the secondary display
rect.screenLocations = [ rect.screenLocations[event.data.screenLocationIndex] ] rect.screenLocations = [ rect.screenLocations[event.data.screenLocationIndex] ]
rect.screenLocations[0].screenIndex = 0; rect.screenLocations[0].screenIndex = 0;
let pos = rect.screenLocations[0];
//console.log(`${rect.type} Rect: x: ${pos.x}, y: ${pos.y}, w: ${rect.width}, h: ${rect.height}`)
switch (rect.type) { switch (rect.type) {
case 'copy':
this.copyImage(rect.oldX, rect.oldY, pos.x, pos.y, rect.width, rect.height, rect.frame_id, true);
//this._asyncRenderQPush(rect);
break;
case 'fill':
//this._asyncRenderQPush(rect);
this.fillRect(pos.x, pos.y, rect.width, rect.height, rect.color, rect.frame_id, true);
break;
case 'blit':
//this._asyncRenderQPush(rect);
this.blitImage(pos.x, pos.y, rect.width, rect.height, rect.data, 0, rect.frame_id, true);
break;
case 'blitQ':
//this._asyncRenderQPush(rect);
this.blitQoi(pos.x, pos.y, rect.width, rect.height, rect.data, 0, rect.frame_id, true);
break;
case 'img': case 'img':
case '_img': case '_img':
rect.img = new Image(); rect.img = new Image();
rect.img.src = rect.src; rect.img.src = rect.src;
rect.type = 'img'; rect.type = 'img';
//this._asyncRenderQPush(rect);
if (!rect.img.complete) {
rect.img.addEventListener('load', (rect) => {
this.drawImage(rect.img, rect.x, rect.y, rect.width, rect.height);
});
}
break; break;
case 'transparent': case 'transparent':
let imageBmpPromise = createImageBitmap(rect.arr); let imageBmpPromise = createImageBitmap(rect.arr);
imageBmpPromise.then(function(rect, img) { imageBmpPromise.then(function(rect, img) {
//rect.img.complete = true; rect.img.complete = true;
this.drawImage(img, rect.x, rect.y, rect.width, rect.height);
}).bind(this, rect); }).bind(this, rect);
//this._asyncRenderQPush(rect);
break; break;
} }
this._syncFrameQueue.push(rect);
break; break;
case 'frameComplete': case 'frameComplete':
//this.flip(event.data.frameId, event.data.rectCnt); window.requestAnimationFrame( () => { this._pushSyncRects(); });
break; break;
case 'registered': case 'registered':
if (!this._isPrimaryDisplay) { if (!this._isPrimaryDisplay) {
@ -761,6 +737,59 @@ export default class Display {
} }
} }
_pushSyncRects() {
whileLoop:
while (this._syncFrameQueue.length > 0) {
const a = this._syncFrameQueue[0];
const pos = a.screenLocations[0];
switch (a.type) {
case 'copy':
this.copyImage(pos.oldX, pos.oldY, pos.x, pos.y, a.width, a.height, a.frame_id, true);
break;
case 'fill':
this.fillRect(pos.x, pos.y, a.width, a.height, a.color, a.frame_id, true);
break;
case 'blit':
this.blitImage(pos.x, pos.y, a.width, a.height, a.data, 0, a.frame_id, true);
break;
case 'blitQ':
this.blitQoi(pos.x, pos.y, a.width, a.height, a.data, 0, a.frame_id, true);
break;
case 'img':
if (a.img.complete) {
this.drawImage(a.img, pos.x, pos.y, a.width, a.height);
} else {
if (this._syncFrameQueue.length > 1000) {
this._syncFrameQueue.shift();
this._droppedRects++;
} else {
break whileLoop;
}
}
break;
case 'transparent':
if (a.img.complete) {
this.drawImage(a.img, pos.x, pos.y, a.width, a.height);
} else {
if (this._syncFrameQueue.length > 1000) {
this._syncFrameQueue.shift();
this._droppedRects++;
} else {
break whileLoop;
}
}
break;
default:
Log.Warn(`Unknown rect type: ${rect}`);
}
this._syncFrameQueue.shift();
}
if (this._syncFrameQueue.length > 0) {
window.requestAnimationFrame( () => { this._pushSyncRects(); });
}
}
/* /*
Process incoming rects into a frame buffer, assume rects are out of order due to either UDP or parallel processing of decoding Process incoming rects into a frame buffer, assume rects are out of order due to either UDP or parallel processing of decoding
*/ */
@ -924,6 +953,7 @@ export default class Display {
if (a.img) { if (a.img) {
a.img = null; a.img = null;
} }
if (a.type !== 'flip') { if (a.type !== 'flip') {
secondaryScreenRects++; secondaryScreenRects++;
this._screens[screenLocation.screenIndex].channel.postMessage({ eventType: 'rect', rect: a, screenLocationIndex: sI }); this._screens[screenLocation.screenIndex].channel.postMessage({ eventType: 'rect', rect: a, screenLocationIndex: sI });