Move render queue processing to Display and use requestAnimationFrame
The imgQ code in RFB should be a generic rendering queue system in Display. The reason for the render queue in the first place is that images loaded from raw data URI strings aren't immediately ready to display so we have to wait for them to complete 'loading'. However, when data URI images are mixed with other types of rendering actions then things can get out of order. This is the reason for the rendering queue. Currently this only keeps display actions for tight and tightPNG related actions in order (because they use a mix of fills, raw pixel data and data URI images).
This commit is contained in:
parent
a0726a4b56
commit
34d8b844ae
|
@ -19,9 +19,12 @@ var that = {}, // Public API methods
|
||||||
c_ctx = null,
|
c_ctx = null,
|
||||||
c_forceCanvas = false,
|
c_forceCanvas = false,
|
||||||
|
|
||||||
|
// Queued drawing actions for in-order rendering
|
||||||
|
renderQ = [],
|
||||||
|
|
||||||
// Predefine function variables (jslint)
|
// Predefine function variables (jslint)
|
||||||
imageDataGet, rgbImageData, bgrxImageData, cmapImageData,
|
imageDataGet, rgbImageData, bgrxImageData, cmapImageData,
|
||||||
setFillColor, rescale,
|
setFillColor, rescale, scan_renderQ,
|
||||||
|
|
||||||
// The full frame buffer (logical canvas) size
|
// The full frame buffer (logical canvas) size
|
||||||
fb_width = 0,
|
fb_width = 0,
|
||||||
|
@ -412,6 +415,8 @@ that.clear = function() {
|
||||||
c_ctx.clearRect(0, 0, viewport.w, viewport.h);
|
c_ctx.clearRect(0, 0, viewport.w, viewport.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderQ = [];
|
||||||
|
|
||||||
// No benefit over default ("source-over") in Chrome and firefox
|
// No benefit over default ("source-over") in Chrome and firefox
|
||||||
//c_ctx.globalCompositeOperation = "copy";
|
//c_ctx.globalCompositeOperation = "copy";
|
||||||
};
|
};
|
||||||
|
@ -582,6 +587,50 @@ that.drawImage = function(img, x, y) {
|
||||||
c_ctx.drawImage(img, x - viewport.x, y - viewport.y);
|
c_ctx.drawImage(img, x - viewport.x, y - viewport.y);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
that.renderQ_push = function(action) {
|
||||||
|
renderQ.push(action);
|
||||||
|
if (renderQ.length === 1) {
|
||||||
|
// Check if it can be rendered immediately
|
||||||
|
scan_renderQ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scan_renderQ = function() {
|
||||||
|
var a, ready = true;
|
||||||
|
while (ready && renderQ.length > 0) {
|
||||||
|
a = renderQ[0];
|
||||||
|
switch (a.type) {
|
||||||
|
case 'copy':
|
||||||
|
that.copyImage(a.old_x, a.old_y, a.x, a.y, a.width, a.height);
|
||||||
|
break;
|
||||||
|
case 'fill':
|
||||||
|
that.fillRect(a.x, a.y, a.width, a.height, a.color);
|
||||||
|
break;
|
||||||
|
case 'blit':
|
||||||
|
that.blitImage(a.x, a.y, a.width, a.height, a.data, 0);
|
||||||
|
break;
|
||||||
|
case 'blitRgb':
|
||||||
|
that.blitRgbImage(a.x, a.y, a.width, a.height, a.data, 0);
|
||||||
|
break;
|
||||||
|
case 'img':
|
||||||
|
if (a.img.complete) {
|
||||||
|
that.drawImage(a.img, a.x, a.y);
|
||||||
|
} else {
|
||||||
|
// We need to wait for this image to 'load'
|
||||||
|
// to keep things in-order
|
||||||
|
ready = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ready) {
|
||||||
|
a = renderQ.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (renderQ.length > 0) {
|
||||||
|
requestAnimFrame(scan_renderQ);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
that.changeCursor = function(pixels, mask, hotx, hoty, w, h) {
|
that.changeCursor = function(pixels, mask, hotx, hoty, w, h) {
|
||||||
if (conf.cursor_uri === false) {
|
if (conf.cursor_uri === false) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ var that = {}, // Public API methods
|
||||||
pixelFormat, clientEncodings, fbUpdateRequest, fbUpdateRequests,
|
pixelFormat, clientEncodings, fbUpdateRequest, fbUpdateRequests,
|
||||||
keyEvent, pointerEvent, clientCutText,
|
keyEvent, pointerEvent, clientCutText,
|
||||||
|
|
||||||
getTightCLength, extract_data_uri, scan_tight_imgQ,
|
getTightCLength, extract_data_uri,
|
||||||
keyPress, mouseButton, mouseMove,
|
keyPress, mouseButton, mouseMove,
|
||||||
|
|
||||||
checkEvents, // Overridable for testing
|
checkEvents, // Overridable for testing
|
||||||
|
@ -93,7 +93,6 @@ var that = {}, // Public API methods
|
||||||
encoding : 0,
|
encoding : 0,
|
||||||
subencoding : -1,
|
subencoding : -1,
|
||||||
background : null,
|
background : null,
|
||||||
imgQ : [], // TIGHT_PNG image queue
|
|
||||||
zlibs : [] // TIGHT zlib streams
|
zlibs : [] // TIGHT zlib streams
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -103,7 +102,6 @@ var that = {}, // Public API methods
|
||||||
fb_height = 0,
|
fb_height = 0,
|
||||||
fb_name = "",
|
fb_name = "",
|
||||||
|
|
||||||
scan_imgQ_rate = 40, // 25 times per second or so
|
|
||||||
last_req_time = 0,
|
last_req_time = 0,
|
||||||
rre_chunk_sz = 100,
|
rre_chunk_sz = 100,
|
||||||
|
|
||||||
|
@ -314,7 +312,6 @@ init_vars = function() {
|
||||||
FBU.subrects = 0; // RRE and HEXTILE
|
FBU.subrects = 0; // RRE and HEXTILE
|
||||||
FBU.lines = 0; // RAW
|
FBU.lines = 0; // RAW
|
||||||
FBU.tiles = 0; // HEXTILE
|
FBU.tiles = 0; // HEXTILE
|
||||||
FBU.imgQ = []; // TIGHT_PNG image queue
|
|
||||||
FBU.zlibs = []; // TIGHT zlib encoders
|
FBU.zlibs = []; // TIGHT zlib encoders
|
||||||
mouse_buttonMask = 0;
|
mouse_buttonMask = 0;
|
||||||
mouse_arr = [];
|
mouse_arr = [];
|
||||||
|
@ -888,7 +885,6 @@ init_msg = function() {
|
||||||
|
|
||||||
/* Start pushing/polling */
|
/* Start pushing/polling */
|
||||||
setTimeout(checkEvents, conf.check_rate);
|
setTimeout(checkEvents, conf.check_rate);
|
||||||
setTimeout(scan_tight_imgQ, scan_imgQ_rate);
|
|
||||||
|
|
||||||
if (conf.encrypt) {
|
if (conf.encrypt) {
|
||||||
updateState('normal', "Connected (encrypted) to: " + fb_name);
|
updateState('normal', "Connected (encrypted) to: " + fb_name);
|
||||||
|
@ -1409,9 +1405,9 @@ function display_tight(isTightPNG) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FBU.imgQ.push({
|
display.renderQ_push({
|
||||||
'type': 'rgb',
|
'type': 'blitRgb',
|
||||||
'img': {'complete': true, 'data': dest},
|
'data': dest,
|
||||||
'x': FBU.x,
|
'x': FBU.x,
|
||||||
'y': FBU.y,
|
'y': FBU.y,
|
||||||
'width': FBU.width,
|
'width': FBU.width,
|
||||||
|
@ -1440,9 +1436,9 @@ function display_tight(isTightPNG) {
|
||||||
data = decompress(ws.rQshiftBytes(clength[1]));
|
data = decompress(ws.rQshiftBytes(clength[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
FBU.imgQ.push({
|
display.renderQ_push({
|
||||||
'type': 'rgb',
|
'type': 'blitRgb',
|
||||||
'img': {'complete': true, 'data': data},
|
'data': data,
|
||||||
'x': FBU.x,
|
'x': FBU.x,
|
||||||
'y': FBU.y,
|
'y': FBU.y,
|
||||||
'width': FBU.width,
|
'width': FBU.width,
|
||||||
|
@ -1489,9 +1485,8 @@ function display_tight(isTightPNG) {
|
||||||
case "fill":
|
case "fill":
|
||||||
ws.rQshift8(); // shift off ctl
|
ws.rQshift8(); // shift off ctl
|
||||||
color = ws.rQshiftBytes(fb_depth);
|
color = ws.rQshiftBytes(fb_depth);
|
||||||
FBU.imgQ.push({
|
display.renderQ_push({
|
||||||
'type': 'fill',
|
'type': 'fill',
|
||||||
'img': {'complete': true},
|
|
||||||
'x': FBU.x,
|
'x': FBU.x,
|
||||||
'y': FBU.y,
|
'y': FBU.y,
|
||||||
'width': FBU.width,
|
'width': FBU.width,
|
||||||
|
@ -1509,14 +1504,13 @@ function display_tight(isTightPNG) {
|
||||||
// clength[0] + ", clength[1]: " + clength[1]);
|
// clength[0] + ", clength[1]: " + clength[1]);
|
||||||
ws.rQshiftBytes(1 + clength[0]); // shift off ctl + compact length
|
ws.rQshiftBytes(1 + clength[0]); // shift off ctl + compact length
|
||||||
img = new Image();
|
img = new Image();
|
||||||
//img.onload = scan_tight_imgQ;
|
img.src = "data:image/" + cmode +
|
||||||
FBU.imgQ.push({
|
extract_data_uri(ws.rQshiftBytes(clength[1]));
|
||||||
|
display.renderQ_push({
|
||||||
'type': 'img',
|
'type': 'img',
|
||||||
'img': img,
|
'img': img,
|
||||||
'x': FBU.x,
|
'x': FBU.x,
|
||||||
'y': FBU.y});
|
'y': FBU.y});
|
||||||
img.src = "data:image/" + cmode +
|
|
||||||
extract_data_uri(ws.rQshiftBytes(clength[1]));
|
|
||||||
img = null;
|
img = null;
|
||||||
break;
|
break;
|
||||||
case "filter":
|
case "filter":
|
||||||
|
@ -1550,25 +1544,6 @@ extract_data_uri = function(arr) {
|
||||||
return ";base64," + Base64.encode(arr);
|
return ";base64," + Base64.encode(arr);
|
||||||
};
|
};
|
||||||
|
|
||||||
scan_tight_imgQ = function() {
|
|
||||||
var data, imgQ, ctx;
|
|
||||||
ctx = display.get_context();
|
|
||||||
if (rfb_state === 'normal') {
|
|
||||||
imgQ = FBU.imgQ;
|
|
||||||
while ((imgQ.length > 0) && (imgQ[0].img.complete)) {
|
|
||||||
data = imgQ.shift();
|
|
||||||
if (data.type === 'fill') {
|
|
||||||
display.fillRect(data.x, data.y, data.width, data.height, data.color);
|
|
||||||
} else if (data.type === 'rgb') {
|
|
||||||
display.blitRgbImage(data.x, data.y, data.width, data.height, data.img.data, 0);
|
|
||||||
} else {
|
|
||||||
display.drawImage(data.img, data.x, data.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setTimeout(scan_tight_imgQ, scan_imgQ_rate);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
encHandlers.TIGHT = function () { return display_tight(false); };
|
encHandlers.TIGHT = function () { return display_tight(false); };
|
||||||
encHandlers.TIGHT_PNG = function () { return display_tight(true); };
|
encHandlers.TIGHT_PNG = function () { return display_tight(true); };
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,21 @@ if (!Array.prototype.map)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// requestAnimationFrame shim with setTimeout fallback
|
||||||
|
//
|
||||||
|
|
||||||
|
window.requestAnimFrame = (function(){
|
||||||
|
return window.requestAnimationFrame ||
|
||||||
|
window.webkitRequestAnimationFrame ||
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
window.oRequestAnimationFrame ||
|
||||||
|
window.msRequestAnimationFrame ||
|
||||||
|
function(callback){
|
||||||
|
window.setTimeout(callback, 1000 / 60);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ------------------------------------------------------
|
* ------------------------------------------------------
|
||||||
* Namespaced in Util
|
* Namespaced in Util
|
||||||
|
|
Loading…
Reference in New Issue