fix bugs in async frame sync

This commit is contained in:
mattmcclaskey 2023-10-05 06:02:33 -04:00
parent aef462ce62
commit f243b54ac9
No known key found for this signature in database
1 changed files with 30 additions and 26 deletions

View File

@ -110,9 +110,6 @@ export default class Display {
this.onflush = () => { }; // A flush request has finished this.onflush = () => { }; // A flush request has finished
// Use requestAnimationFrame to write to canvas, to match display refresh rate
this._animationFrameID = window.requestAnimationFrame( () => { this._pushAsyncFrame(); });
if (!this._isPrimaryDisplay) { if (!this._isPrimaryDisplay) {
this._screens[0].channel = new BroadcastChannel(`screen_${this._screenID}_channel`); this._screens[0].channel = new BroadcastChannel(`screen_${this._screenID}_channel`);
this._screens[0].channel.addEventListener('message', this._handleSecondaryDisplayMessage.bind(this)); this._screens[0].channel.addEventListener('message', this._handleSecondaryDisplayMessage.bind(this));
@ -482,10 +479,10 @@ export default class Display {
*/ */
flush(onflush_message=true) { flush(onflush_message=true) {
//force oldest frame to render //force oldest frame to render
this._asyncFrameComplete(0, true); window.requestAnimationFrame( () => { this._pushAsyncFrame(); });
if (onflush_message) if (onflush_message)
this._flushing = true; this.onflush();
} }
/* /*
@ -501,7 +498,6 @@ export default class Display {
*/ */
dispose() { dispose() {
clearInterval(this._frameStatsInterval); clearInterval(this._frameStatsInterval);
cancelAnimationFrame(this._animationFrameID);
this.clear(); this.clear();
} }
@ -714,40 +710,45 @@ export default class Display {
//console.log(`${rect.type} Rect: x: ${pos.x}, y: ${pos.y}, w: ${rect.width}, h: ${rect.height}`) //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': case 'copy':
//this.copyImage(rect.oldX, rect.oldY, pos.x, pos.y, rect.width, rect.height, rect.frame_id, true); this.copyImage(rect.oldX, rect.oldY, pos.x, pos.y, rect.width, rect.height, rect.frame_id, true);
this._asyncRenderQPush(rect); //this._asyncRenderQPush(rect);
break; break;
case 'fill': case 'fill':
this._asyncRenderQPush(rect); //this._asyncRenderQPush(rect);
//this.fillRect(pos.x, pos.y, rect.width, rect.height, rect.color, rect.frame_id, true); this.fillRect(pos.x, pos.y, rect.width, rect.height, rect.color, rect.frame_id, true);
break; break;
case 'blit': case 'blit':
this._asyncRenderQPush(rect); //this._asyncRenderQPush(rect);
//this.blitImage(pos.x, pos.y, rect.width, rect.height, rect.data, 0, rect.frame_id, true); this.blitImage(pos.x, pos.y, rect.width, rect.height, rect.data, 0, rect.frame_id, true);
break; break;
case 'blitQ': case 'blitQ':
//this._asyncRenderQPush(rect);
this._asyncRenderQPush(rect); this.blitQoi(pos.x, pos.y, rect.width, rect.height, rect.data, 0, rect.frame_id, true);
//this.blitQoi(pos.x, pos.y, rect.width, rect.height, rect.data, 0, rect.frame_id, true);
break; 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); //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); //this._asyncRenderQPush(rect);
break; break;
} }
break; break;
case 'frameComplete': case 'frameComplete':
this.flip(event.data.frameId, event.data.rectCnt); //this.flip(event.data.frameId, event.data.rectCnt);
break; break;
case 'registered': case 'registered':
@ -847,10 +848,15 @@ export default class Display {
} }
} }
while (currentFrameRectIx < this._asyncFrameQueue[frameIx][2].length) { while (currentFrameRectIx < this._asyncFrameQueue[frameIx][2].length) {
if (this._asyncFrameQueue[frameIx][2][currentFrameRectIx].type == 'img' && !this._asyncFrameQueue[frameIx][2][currentFrameRectIx].img.complete) { if (this._asyncFrameQueue[frameIx][2][currentFrameRectIx].type == 'img') {
this._asyncFrameQueue[frameIx][2][currentFrameRectIx].type = 'skip'; if (this._asyncFrameQueue[frameIx][2][currentFrameRectIx].img && !this._asyncFrameQueue[frameIx][2][currentFrameRectIx].img.complete) {
this._droppedRects++; this._asyncFrameQueue[frameIx][2][currentFrameRectIx].type = 'skip';
this._droppedRects++;
} else {
Log.Warn(`Oh snap, an image rect without an image: ${this._asyncFrameQueue[frameIx][2][currentFrameRectIx]}`)
}
} }
currentFrameRectIx++; currentFrameRectIx++;
} }
} else { } else {
@ -868,6 +874,8 @@ export default class Display {
} }
this._asyncFrameQueue[frameIx][4] = currentFrameRectIx; this._asyncFrameQueue[frameIx][4] = currentFrameRectIx;
this._asyncFrameQueue[frameIx][3] = true; this._asyncFrameQueue[frameIx][3] = true;
window.requestAnimationFrame( () => { this._pushAsyncFrame(); });
} }
/* /*
@ -962,10 +970,6 @@ export default class Display {
this._pushAsyncFrame(true); this._pushAsyncFrame(true);
} }
} }
if (!force) {
window.requestAnimationFrame( () => { this._pushAsyncFrame(); });
}
} }
_processRectScreens(rect) { _processRectScreens(rect) {