Commit 34d8b844 authored by Joel Martin's avatar Joel Martin

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).
parent a0726a4b
......@@ -19,9 +19,12 @@ var that = {}, // Public API methods
c_ctx = null,
c_forceCanvas = false,
// Queued drawing actions for in-order rendering
renderQ = [],
// Predefine function variables (jslint)
imageDataGet, rgbImageData, bgrxImageData, cmapImageData,
setFillColor, rescale,
setFillColor, rescale, scan_renderQ,
// The full frame buffer (logical canvas) size
fb_width = 0,
......@@ -412,6 +415,8 @@ that.clear = function() {
c_ctx.clearRect(0, 0, viewport.w, viewport.h);
}
renderQ = [];
// No benefit over default ("source-over") in Chrome and firefox
//c_ctx.globalCompositeOperation = "copy";
};
......@@ -582,6 +587,50 @@ that.drawImage = function(img, x, 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) {
if (conf.cursor_uri === false) {
......
......@@ -26,7 +26,7 @@ var that = {}, // Public API methods
pixelFormat, clientEncodings, fbUpdateRequest, fbUpdateRequests,
keyEvent, pointerEvent, clientCutText,
getTightCLength, extract_data_uri, scan_tight_imgQ,
getTightCLength, extract_data_uri,
keyPress, mouseButton, mouseMove,
checkEvents, // Overridable for testing
......@@ -93,7 +93,6 @@ var that = {}, // Public API methods
encoding : 0,
subencoding : -1,
background : null,
imgQ : [], // TIGHT_PNG image queue
zlibs : [] // TIGHT zlib streams
},
......@@ -103,7 +102,6 @@ var that = {}, // Public API methods
fb_height = 0,
fb_name = "",
scan_imgQ_rate = 40, // 25 times per second or so
last_req_time = 0,
rre_chunk_sz = 100,
......@@ -314,7 +312,6 @@ init_vars = function() {
FBU.subrects = 0; // RRE and HEXTILE
FBU.lines = 0; // RAW
FBU.tiles = 0; // HEXTILE
FBU.imgQ = []; // TIGHT_PNG image queue
FBU.zlibs = []; // TIGHT zlib encoders
mouse_buttonMask = 0;
mouse_arr = [];
......@@ -888,7 +885,6 @@ init_msg = function() {
/* Start pushing/polling */
setTimeout(checkEvents, conf.check_rate);
setTimeout(scan_tight_imgQ, scan_imgQ_rate);
if (conf.encrypt) {
updateState('normal', "Connected (encrypted) to: " + fb_name);
......@@ -1409,9 +1405,9 @@ function display_tight(isTightPNG) {
}
}
FBU.imgQ.push({
'type': 'rgb',
'img': {'complete': true, 'data': dest},
display.renderQ_push({
'type': 'blitRgb',
'data': dest,
'x': FBU.x,
'y': FBU.y,
'width': FBU.width,
......@@ -1440,9 +1436,9 @@ function display_tight(isTightPNG) {
data = decompress(ws.rQshiftBytes(clength[1]));
}
FBU.imgQ.push({
'type': 'rgb',
'img': {'complete': true, 'data': data},
display.renderQ_push({
'type': 'blitRgb',
'data': data,
'x': FBU.x,
'y': FBU.y,
'width': FBU.width,
......@@ -1489,9 +1485,8 @@ function display_tight(isTightPNG) {
case "fill":
ws.rQshift8(); // shift off ctl
color = ws.rQshiftBytes(fb_depth);
FBU.imgQ.push({
display.renderQ_push({
'type': 'fill',
'img': {'complete': true},
'x': FBU.x,
'y': FBU.y,
'width': FBU.width,
......@@ -1509,14 +1504,13 @@ function display_tight(isTightPNG) {
// clength[0] + ", clength[1]: " + clength[1]);
ws.rQshiftBytes(1 + clength[0]); // shift off ctl + compact length
img = new Image();
//img.onload = scan_tight_imgQ;
FBU.imgQ.push({
img.src = "data:image/" + cmode +
extract_data_uri(ws.rQshiftBytes(clength[1]));
display.renderQ_push({
'type': 'img',
'img': img,
'x': FBU.x,
'y': FBU.y});
img.src = "data:image/" + cmode +
extract_data_uri(ws.rQshiftBytes(clength[1]));
img = null;
break;
case "filter":
......@@ -1550,25 +1544,6 @@ extract_data_uri = function(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_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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment