Commit 490d471c authored by Joel Martin's avatar Joel Martin

Remove support for non-HTML5 browsers.

Display API change:
    - getTile -> startTile (no longer returns a tile)
    - setSubTile -> subTile (drop img/tile first parameter)
    - putTile -> finishTile (no longer takes img/tile paramter)

The Display tile logic uses canvas image data directly and
caches/reuses a 16x16 imageData tile (for other sizes, the tile is
create for each call). This gives a 30% speedup on Chrome
13 (and no significant change for Firefox 3.6/4.0).

Other:

- Remove rgbxImageFill and cmapImageFill routines.

- Simplify constructor tests and just error if createImageData is not
  supported by canvas instead of .

- Remove webkit canvas bug workaround that effects Chrome 7. Chrome
  7 usage share is now less than 0.5 percent and the workaround is
  ugly. Drop the function wrapping in the constructor and the canvas
  flush() routine.

- Remove support for getImageData (Opera 11+ now required)

Update browser support list:

    - Chrome 8+ (really any except 7)
    - Firefox 3.6+
    - Safari 4+
    - Opera 11+
    - IE9+
    - iOS 4.2+
parent 859fc7f1
...@@ -19,11 +19,9 @@ var that = {}, // Public API methods ...@@ -19,11 +19,9 @@ var that = {}, // Public API methods
c_ctx = null, c_ctx = null,
c_forceCanvas = false, c_forceCanvas = false,
c_imageData, c_rgbxImage, c_cmapImage,
// Predefine function variables (jslint) // Predefine function variables (jslint)
imageDataCreate, imageDataGet, rgbxImageData, cmapImageData, imageDataGet, rgbxImageData, cmapImageData,
rgbxImageFill, cmapImageFill, setFillColor, rescale, flush, setFillColor, rescale,
// The full frame buffer (logical canvas) size // The full frame buffer (logical canvas) size
fb_width = 0, fb_width = 0,
...@@ -33,9 +31,11 @@ var that = {}, // Public API methods ...@@ -33,9 +31,11 @@ var that = {}, // Public API methods
cleanRect = {'x1': 0, 'y1': 0, 'x2': -1, 'y2': -1}, cleanRect = {'x1': 0, 'y1': 0, 'x2': -1, 'y2': -1},
c_prevStyle = "", c_prevStyle = "",
tile = null,
tile16x16 = null,
tile_x = 0,
tile_y = 0;
c_webkit_bug = false,
c_flush_timer = null;
// Configuration attributes // Configuration attributes
Util.conf_defaults(conf, that, defaults, [ Util.conf_defaults(conf, that, defaults, [
...@@ -66,15 +66,6 @@ that.get_width = function() { return fb_width; }; ...@@ -66,15 +66,6 @@ that.get_width = function() { return fb_width; };
that.set_height = function (val) { that.resize(fb_width, val); }; that.set_height = function (val) { that.resize(fb_width, val); };
that.get_height = function() { return fb_height; }; that.get_height = function() { return fb_height; };
that.set_prefer_js = function(val) {
if (val && c_forceCanvas) {
Util.Warn("Preferring Javascript to Canvas ops is not supported");
return false;
}
conf.prefer_js = val;
return true;
};
// //
...@@ -85,7 +76,7 @@ that.set_prefer_js = function(val) { ...@@ -85,7 +76,7 @@ that.set_prefer_js = function(val) {
function constructor() { function constructor() {
Util.Debug(">> Display.constructor"); Util.Debug(">> Display.constructor");
var c, func, imgTest, tval, i, curDat, curSave, var c, func, i, curDat, curSave,
has_imageData = false, UE = Util.Engine; has_imageData = false, UE = Util.Engine;
if (! conf.target) { throw("target must be set"); } if (! conf.target) { throw("target must be set"); }
...@@ -108,70 +99,19 @@ function constructor() { ...@@ -108,70 +99,19 @@ function constructor() {
that.clear(); that.clear();
/* // Check canvas features
* Determine browser Canvas feature support if ('createImageData' in c_ctx) {
* and select fastest rendering methods conf.render_mode = "canvas rendering";
*/ } else {
tval = 0; throw("Canvas does not support createImageData");
try {
imgTest = c_ctx.getImageData(0, 0, 1,1);
imgTest.data[0] = 123;
imgTest.data[3] = 255;
c_ctx.putImageData(imgTest, 0, 0);
tval = c_ctx.getImageData(0, 0, 1, 1).data[0];
if (tval === 123) {
has_imageData = true;
}
} catch (exc1) {}
if (has_imageData) {
Util.Info("Canvas supports imageData");
c_forceCanvas = false;
if (c_ctx.createImageData) {
// If it's there, it's faster
Util.Info("Using Canvas createImageData");
conf.render_mode = "createImageData rendering";
c_imageData = imageDataCreate;
} else if (c_ctx.getImageData) {
// I think this is mostly just Opera
Util.Info("Using Canvas getImageData");
conf.render_mode = "getImageData rendering";
c_imageData = imageDataGet;
} }
Util.Info("Prefering javascript operations");
if (conf.prefer_js === null) { if (conf.prefer_js === null) {
Util.Info("Prefering javascript operations");
conf.prefer_js = true; conf.prefer_js = true;
} }
c_rgbxImage = rgbxImageData;
c_cmapImage = cmapImageData; // Initialize cached tile imageData
} else { tile16x16 = c_ctx.createImageData(16, 16);
Util.Warn("Canvas lacks imageData, using fillRect (slow)");
conf.render_mode = "fillRect rendering (slow)";
c_forceCanvas = true;
conf.prefer_js = false;
c_rgbxImage = rgbxImageFill;
c_cmapImage = cmapImageFill;
}
if (UE.webkit && UE.webkit >= 534.7 && UE.webkit <= 534.9) {
// Workaround WebKit canvas rendering bug #46319
conf.render_mode += ", webkit bug workaround";
Util.Debug("Working around WebKit bug #46319");
c_webkit_bug = true;
for (func in {"fillRect":1, "copyImage":1, "rgbxImage":1,
"cmapImage":1, "blitStringImage":1}) {
that[func] = (function() {
var myfunc = that[func]; // Save original function
//Util.Debug("Wrapping " + func);
return function() {
myfunc.apply(this, arguments);
if (!c_flush_timer) {
c_flush_timer = setTimeout(flush, 100);
}
};
}());
}
}
/* /*
* Determine browser support for setting the cursor via data URI * Determine browser support for setting the cursor via data URI
...@@ -425,18 +365,6 @@ that.absY = function(y) { ...@@ -425,18 +365,6 @@ that.absY = function(y) {
} }
// Force canvas redraw (for webkit bug #46319 workaround)
flush = function() {
var old_val;
//Util.Debug(">> flush");
old_val = conf.target.style.marginRight;
conf.target.style.marginRight = "1px";
c_flush_timer = null;
setTimeout(function () {
conf.target.style.marginRight = old_val;
}, 1);
};
setFillColor = function(color) { setFillColor = function(color) {
var rgb, newStyle; var rgb, newStyle;
if (conf.true_color) { if (conf.true_color) {
...@@ -498,10 +426,16 @@ that.copyImage = function(old_x, old_y, new_x, new_y, w, h) { ...@@ -498,10 +426,16 @@ that.copyImage = function(old_x, old_y, new_x, new_y, w, h) {
* faster than direct Canvas fillStyle, fillRect rendering. In * faster than direct Canvas fillStyle, fillRect rendering. In
* gecko, Javascript array handling is much slower. * gecko, Javascript array handling is much slower.
*/ */
that.getTile = function(x, y, width, height, color) { that.startTile = function(x, y, width, height, color) {
var img, data = [], rgb, red, green, blue, i; var data, rgb, red, green, blue, i;
img = {'x': x, 'y': y, 'width': width, 'height': height, tile_x = x;
'data': data}; tile_y = y;
if ((width === 16) && (height === 16)) {
tile = tile16x16;
} else {
tile = c_ctx.createImageData(width, height);
}
data = tile.data;
if (conf.prefer_js) { if (conf.prefer_js) {
if (conf.true_color) { if (conf.true_color) {
rgb = color; rgb = color;
...@@ -515,18 +449,18 @@ that.getTile = function(x, y, width, height, color) { ...@@ -515,18 +449,18 @@ that.getTile = function(x, y, width, height, color) {
data[i ] = red; data[i ] = red;
data[i + 1] = green; data[i + 1] = green;
data[i + 2] = blue; data[i + 2] = blue;
data[i + 3] = 255;
} }
} else { } else {
that.fillRect(x, y, width, height, color); that.fillRect(x, y, width, height, color);
} }
return img;
}; };
that.setSubTile = function(img, x, y, w, h, color) { that.subTile = function(x, y, w, h, color) {
var data, p, rgb, red, green, blue, width, j, i, xend, yend; var data, p, rgb, red, green, blue, width, j, i, xend, yend;
if (conf.prefer_js) { if (conf.prefer_js) {
data = img.data; data = tile.data;
width = img.width; width = tile.width;
if (conf.true_color) { if (conf.true_color) {
rgb = color; rgb = color;
} else { } else {
...@@ -543,25 +477,19 @@ that.setSubTile = function(img, x, y, w, h, color) { ...@@ -543,25 +477,19 @@ that.setSubTile = function(img, x, y, w, h, color) {
data[p ] = red; data[p ] = red;
data[p + 1] = green; data[p + 1] = green;
data[p + 2] = blue; data[p + 2] = blue;
data[p + 3] = 255;
} }
} }
} else { } else {
that.fillRect(img.x + x, img.y + y, w, h, color); that.fillRect(tile_x + x, tile_y + y, w, h, color);
} }
}; };
that.putTile = function(img) { that.finishTile = function() {
if (conf.prefer_js) { if (conf.prefer_js) {
c_rgbxImage(img.x, img.y, img.width, img.height, img.data, 0); c_ctx.putImageData(tile, tile_x - viewport.x, tile_y - viewport.y)
} }
// else: No-op, under gecko already done by setSubTile // else: No-op, if not prefer_js then already done by setSubTile
};
imageDataGet = function(width, height) {
return c_ctx.getImageData(0, 0, width, height);
};
imageDataCreate = function(width, height) {
return c_ctx.createImageData(width, height);
}; };
rgbxImageData = function(x, y, width, height, arr, offset) { rgbxImageData = function(x, y, width, height, arr, offset) {
...@@ -569,12 +497,11 @@ rgbxImageData = function(x, y, width, height, arr, offset) { ...@@ -569,12 +497,11 @@ rgbxImageData = function(x, y, width, height, arr, offset) {
/* /*
if ((x - v.x >= v.w) || (y - v.y >= v.h) || if ((x - v.x >= v.w) || (y - v.y >= v.h) ||
(x - v.x + width < 0) || (y - v.y + height < 0)) { (x - v.x + width < 0) || (y - v.y + height < 0)) {
//console.log("skipping, out of bounds: ", x, y);
// Skipping because outside of viewport // Skipping because outside of viewport
return; return;
} }
*/ */
img = c_imageData(width, height); img = c_ctx.createImageData(width, height);
data = img.data; data = img.data;
for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) { for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) {
data[i ] = arr[j ]; data[i ] = arr[j ];
...@@ -585,22 +512,9 @@ rgbxImageData = function(x, y, width, height, arr, offset) { ...@@ -585,22 +512,9 @@ rgbxImageData = function(x, y, width, height, arr, offset) {
c_ctx.putImageData(img, x - v.x, y - v.y); c_ctx.putImageData(img, x - v.x, y - v.y);
}; };
// really slow fallback if we don't have imageData
rgbxImageFill = function(x, y, width, height, arr, offset) {
var i, j, sx = 0, sy = 0;
for (i=0, j=offset; i < (width * height); i+=1, j+=4) {
that.fillRect(x+sx, y+sy, 1, 1, [arr[j], arr[j+1], arr[j+2]]);
sx += 1;
if ((sx % width) === 0) {
sx = 0;
sy += 1;
}
}
};
cmapImageData = function(x, y, width, height, arr, offset) { cmapImageData = function(x, y, width, height, arr, offset) {
var img, i, j, data, rgb, cmap; var img, i, j, data, rgb, cmap;
img = c_imageData(width, height); img = c_ctx.createImageData(width, height);
data = img.data; data = img.data;
cmap = conf.colourMap; cmap = conf.colourMap;
for (i=0, j=offset; i < (width * height * 4); i+=4, j+=1) { for (i=0, j=offset; i < (width * height * 4); i+=4, j+=1) {
...@@ -613,25 +527,11 @@ cmapImageData = function(x, y, width, height, arr, offset) { ...@@ -613,25 +527,11 @@ cmapImageData = function(x, y, width, height, arr, offset) {
c_ctx.putImageData(img, x - viewport.x, y - viewport.y); c_ctx.putImageData(img, x - viewport.x, y - viewport.y);
}; };
cmapImageFill = function(x, y, width, height, arr, offset) {
var i, j, sx = 0, sy = 0, cmap;
cmap = conf.colourMap;
for (i=0, j=offset; i < (width * height); i+=1, j+=1) {
that.fillRect(x+sx, y+sy, 1, 1, [arr[j]]);
sx += 1;
if ((sx % width) === 0) {
sx = 0;
sy += 1;
}
}
};
that.blitImage = function(x, y, width, height, arr, offset) { that.blitImage = function(x, y, width, height, arr, offset) {
if (conf.true_color) { if (conf.true_color) {
c_rgbxImage(x, y, width, height, arr, offset); rgbxImageData(x, y, width, height, arr, offset);
} else { } else {
c_cmapImage(x, y, width, height, arr, offset); cmapImageData(x, y, width, height, arr, offset);
} }
}; };
......
...@@ -1096,7 +1096,7 @@ encHandlers.RRE = function display_rre() { ...@@ -1096,7 +1096,7 @@ encHandlers.RRE = function display_rre() {
encHandlers.HEXTILE = function display_hextile() { encHandlers.HEXTILE = function display_hextile() {
//Util.Debug(">> display_hextile"); //Util.Debug(">> display_hextile");
var subencoding, subrects, tile, color, cur_tile, var subencoding, subrects, color, cur_tile,
tile_x, x, w, tile_y, y, h, xy, s, sx, sy, wh, sw, sh, tile_x, x, w, tile_y, y, h, xy, s, sx, sy, wh, sw, sh,
rQ = ws.get_rQ(), rQi = ws.get_rQi(); rQ = ws.get_rQ(), rQi = ws.get_rQi();
...@@ -1185,7 +1185,7 @@ encHandlers.HEXTILE = function display_hextile() { ...@@ -1185,7 +1185,7 @@ encHandlers.HEXTILE = function display_hextile() {
rQi += fb_Bpp; rQi += fb_Bpp;
} }
tile = display.getTile(x, y, w, h, FBU.background); display.startTile(x, y, w, h, FBU.background);
if (FBU.subencoding & 0x08) { // AnySubrects if (FBU.subencoding & 0x08) { // AnySubrects
subrects = rQ[rQi]; subrects = rQ[rQi];
rQi += 1; rQi += 1;
...@@ -1206,10 +1206,10 @@ encHandlers.HEXTILE = function display_hextile() { ...@@ -1206,10 +1206,10 @@ encHandlers.HEXTILE = function display_hextile() {
sw = (wh >> 4) + 1; sw = (wh >> 4) + 1;
sh = (wh & 0x0f) + 1; sh = (wh & 0x0f) + 1;
display.setSubTile(tile, sx, sy, sw, sh, color); display.subTile(sx, sy, sw, sh, color);
} }
} }
display.putTile(tile); display.finishTile();
} }
ws.set_rQi(rQi); ws.set_rQi(rQi);
FBU.lastsubencoding = FBU.subencoding; FBU.lastsubencoding = FBU.subencoding;
......
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