summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSolly Ross <sross@redhat.com>2015-06-02 15:32:14 -0400
committerSolly Ross <sross@redhat.com>2015-08-06 14:47:03 -0400
commitf00193e08f7c55a7b0b55556ef96b10b41dd3bc3 (patch)
treec31862ccaef56d65013a3749b11b677625bd9853
parentb0b5fc55e1fe5c575855104e9ce6df79329a8db7 (diff)
downloadnovnc-feature/more-perf-improvements.tar.gz
Skip unnecessary render queue object creationfeature/more-perf-improvements
This commit skips object creation for the render queue when not needed. Instead of pushing an object onto the queue, and then immediately running the result, you call the function directly. Then, if the render queue is not empty, an object is created and pushed onto the queue. Otherwise, the functionality is just run directly.
-rw-r--r--include/display.js110
-rw-r--r--include/rfb.js57
2 files changed, 93 insertions, 74 deletions
diff --git a/include/display.js b/include/display.js
index 418b431..c30a977 100644
--- a/include/display.js
+++ b/include/display.js
@@ -339,18 +339,41 @@ var Display;
this._renderQ = [];
},
- fillRect: function (x, y, width, height, color) {
- this._setFillColor(color);
- this._drawCtx.fillRect(x - this._viewportLoc.x, y - this._viewportLoc.y, width, height);
- },
-
- copyImage: function (old_x, old_y, new_x, new_y, w, h) {
- var x1 = old_x - this._viewportLoc.x;
- var y1 = old_y - this._viewportLoc.y;
- var x2 = new_x - this._viewportLoc.x;
- var y2 = new_y - this._viewportLoc.y;
+ fillRect: function (x, y, width, height, color, from_queue) {
+ if (this._renderQ.length !== 0 && !from_queue) {
+ this.renderQ_push({
+ 'type': 'fill',
+ 'x': x,
+ 'y': y,
+ 'width': width,
+ 'height': height,
+ 'color': color
+ });
+ } else {
+ this._setFillColor(color);
+ this._drawCtx.fillRect(x - this._viewportLoc.x, y - this._viewportLoc.y, width, height);
+ }
+ },
+
+ copyImage: function (old_x, old_y, new_x, new_y, w, h, from_queue) {
+ if (this._renderQ.length !== 0 && !from_queue) {
+ this.renderQ_push({
+ 'type': 'copy',
+ 'old_x': old_x,
+ 'old_y': old_y,
+ 'x': new_x,
+ 'y': new_y,
+ 'width': w,
+ 'height': h,
+ });
+ } else {
+ var x1 = old_x - this._viewportLoc.x;
+ var y1 = old_y - this._viewportLoc.y;
+ var x2 = new_x - this._viewportLoc.x;
+ var y2 = new_y - this._viewportLoc.y;
- this._drawCtx.drawImage(this._target, x1, y1, w, h, x2, y2, w, h);
+ this._drawCtx.drawImage(this._target, x1, y1, w, h, x2, y2, w, h);
+ }
},
// start updating a tile
@@ -382,7 +405,7 @@ var Display;
data[i + 3] = 255;
}
} else {
- this.fillRect(x, y, width, height, color);
+ this.fillRect(x, y, width, height, color, true);
}
},
@@ -413,7 +436,7 @@ var Display;
}
}
} else {
- this.fillRect(this._tile_x + x, this._tile_y + y, w, h, color);
+ this.fillRect(this._tile_x + x, this._tile_y + y, w, h, color, true);
}
},
@@ -426,16 +449,34 @@ var Display;
// else: No-op -- already done by setSubTile
},
- blitImage: function (x, y, width, height, arr, offset) {
- if (this._true_color) {
+ blitImage: function (x, y, width, height, arr, offset, from_queue) {
+ if (this._renderQ.length !== 0 && !from_queue) {
+ this.renderQ_push({
+ 'type': 'blit',
+ 'data': arr,
+ 'x': x,
+ 'y': y,
+ 'width': width,
+ 'height': height,
+ });
+ } else if (this._true_color) {
this._bgrxImageData(x, y, this._viewportLoc.x, this._viewportLoc.y, width, height, arr, offset);
} else {
this._cmapImageData(x, y, this._viewportLoc.x, this._viewportLoc.y, width, height, arr, offset);
}
},
- blitRgbImage: function (x, y , width, height, arr, offset) {
- if (this._true_color) {
+ blitRgbImage: function (x, y , width, height, arr, offset, from_queue) {
+ if (this._renderQ.length !== 0 && !from_queue) {
+ this.renderQ_push({
+ 'type': 'blitRgb',
+ 'data': arr,
+ 'x': x,
+ 'y': y,
+ 'width': width,
+ 'height': height,
+ });
+ } else if (this._true_color) {
this._rgbImageData(x, y, this._viewportLoc.x, this._viewportLoc.y, width, height, arr, offset);
} else {
// probably wrong?
@@ -443,8 +484,24 @@ var Display;
}
},
- blitRgbxImage: function (x, y, width, height, arr, offset) {
- this._rgbxImageData(x, y, this._viewportLoc.x, this._viewportLoc.y, width, height, arr, offset);
+ blitRgbxImage: function (x, y, width, height, arr, offset, from_queue) {
+ if (this._renderQ.length !== 0 && !from_queue) {
+ // NB(directxman12): it's technically more performant here to use preallocated arrays, but it
+ // but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
+ // this probably isn't getting called *nearly* as much
+ var new_arr = new Uint8Array(width * height * 4);
+ new_arr.set(new Uint8Array(arr.buffer, 0, new_arr.length));
+ this.renderQ_push({
+ 'type': 'blitRgbx',
+ 'data': new_arr,
+ 'x': x,
+ 'y': y,
+ 'width': width,
+ 'height': height,
+ });
+ } else {
+ this._rgbxImageData(x, y, this._viewportLoc.x, this._viewportLoc.y, width, height, arr, offset);
+ }
},
blitStringImage: function (str, x, y) {
@@ -626,13 +683,12 @@ var Display;
_rgbxImageData: function (x, y, vx, vy, width, height, arr, offset) {
// NB(directxman12): arr must be an Type Array view
- // NB(directxman12): this only works
var img;
if (SUPPORTS_IMAGEDATA_CONSTRUCTOR) {
- img = new ImageData(new Uint8ClampedArray(arr.buffer, 0, width * height * 4), width, height);
+ img = new ImageData(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4), width, height);
} else {
img = this._drawCtx.createImageData(width, height);
- img.data.set(new Uint8ClampedArray(arr.buffer, 0, width * height * 4));
+ img.data.set(new Uint8ClampedArray(arr.buffer, arr.byteOffset, width * height * 4));
}
this._drawCtx.putImageData(img, x - vx, y - vy);
},
@@ -657,19 +713,19 @@ var Display;
var a = this._renderQ[0];
switch (a.type) {
case 'copy':
- this.copyImage(a.old_x, a.old_y, a.x, a.y, a.width, a.height);
+ this.copyImage(a.old_x, a.old_y, a.x, a.y, a.width, a.height, true);
break;
case 'fill':
- this.fillRect(a.x, a.y, a.width, a.height, a.color);
+ this.fillRect(a.x, a.y, a.width, a.height, a.color, true);
break;
case 'blit':
- this.blitImage(a.x, a.y, a.width, a.height, a.data, 0);
+ this.blitImage(a.x, a.y, a.width, a.height, a.data, 0, true);
break;
case 'blitRgb':
- this.blitRgbImage(a.x, a.y, a.width, a.height, a.data, 0);
+ this.blitRgbImage(a.x, a.y, a.width, a.height, a.data, 0, true);
break;
case 'blitRgbx':
- this.blitRgbxImage(a.x, a.y, a.width, a.height, a.data, 0);
+ this.blitRgbxImage(a.x, a.y, a.width, a.height, a.data, 0, true);
break;
case 'img':
if (a.img.complete) {
diff --git a/include/rfb.js b/include/rfb.js
index b8615af..b7a811d 100644
--- a/include/rfb.js
+++ b/include/rfb.js
@@ -1483,15 +1483,10 @@ var RFB;
COPYRECT: function () {
this._FBU.bytes = 4;
if (this._sock.rQwait("COPYRECT", 4)) { return false; }
- this._display.renderQ_push({
- 'type': 'copy',
- 'old_x': this._sock.rQshift16(),
- 'old_y': this._sock.rQshift16(),
- 'x': this._FBU.x,
- 'y': this._FBU.y,
- 'width': this._FBU.width,
- 'height': this._FBU.height
- });
+ this._display.copyImage(this._sock.rQshift16(), this._sock.rQshift16(),
+ this._FBU.x, this._FBU.y, this._FBU.width,
+ this._FBU.height);
+
this._FBU.rects--;
this._FBU.bytes = 0;
return true;
@@ -1842,28 +1837,10 @@ var RFB;
var rgbx;
if (numColors == 2) {
rgbx = indexedToRGBX2Color(data, this._paletteBuff, this._FBU.width, this._FBU.height);
-
- /*this._display.renderQ_push({
- 'type': 'blitRgbx',
- 'data': rgbx,
- 'x': this._FBU.x,
- 'y': this._FBU.y,
- 'width': this._FBU.width,
- 'height': this._FBU.height
- });*/
- this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0);
+ this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false);
} else {
rgbx = indexedToRGBX(data, this._paletteBuff, this._FBU.width, this._FBU.height);
-
- /*this._display.renderQ_push({
- 'type': 'blitRgbx',
- 'data': rgbx,
- 'x': this._FBU.x,
- 'y': this._FBU.y,
- 'width': this._FBU.width,
- 'height': this._FBU.height
- });*/
- this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0);
+ this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false);
}
@@ -1905,14 +1882,7 @@ var RFB;
data = decompress(this._sock.rQshiftBytes(cl_data));
}
- this._display.renderQ_push({
- 'type': 'blitRgb',
- 'data': data,
- 'x': this._FBU.x,
- 'y': this._FBU.y,
- 'width': this._FBU.width,
- 'height': this._FBU.height
- });
+ this._display.blitRgbImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, data, 0, false);
return true;
}.bind(this);
@@ -1960,16 +1930,9 @@ var RFB;
// Determine FBU.bytes
switch (cmode) {
case "fill":
- this._sock.rQskip8(); // shift off ctl
- var color = this._sock.rQshiftBytes(this._fb_depth);
- this._display.renderQ_push({
- 'type': 'fill',
- 'x': this._FBU.x,
- 'y': this._FBU.y,
- 'width': this._FBU.width,
- 'height': this._FBU.height,
- 'color': [color[2], color[1], color[0]]
- });
+ // skip ctl byte
+ this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, [rQ[rQi + 3], rQ[rQi + 2], rQ[rQi + 1]], false);
+ this._sock.rQskipBytes(4);
break;
case "png":
case "jpeg":