skia2/modules/canvaskit/cpu.js
Kevin Lubick bdc214a50e [canvaskit] Change SkRects to be arrays, not objects.
This changes several APIs, so there are lots of breaking
notes in the Changelog.

This made the "draw 100 colored regions" benchmark about
20% faster (1ms -> .8ms).

In theory, rendering should stay the same.

Change-Id: Ib80b15e2d980ad5d568fff4460d2b529766c1b36
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/312491
Reviewed-by: Nathaniel Nifong <nifong@google.com>
2020-09-02 20:10:30 +00:00

104 lines
4.2 KiB
JavaScript

// Adds compile-time JS functions to augment the CanvasKit interface.
// Implementations in this file are considerate of GPU builds, i.e. some
// behavior is predicated on whether or not this is being compiled alongside
// gpu.js.
(function(CanvasKit){
CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
CanvasKit._extraInitializations.push(function() {
// Takes in an html id or a canvas element
CanvasKit.MakeSWCanvasSurface = function(idOrElement) {
var canvas = idOrElement;
if (canvas.tagName !== 'CANVAS') {
// TODO(nifong): unit test
canvas = document.getElementById(idOrElement);
if (!canvas) {
throw 'Canvas with id ' + idOrElement + ' was not found';
}
}
// Maybe better to use clientWidth/height. See:
// https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
var surface = CanvasKit.MakeSurface(canvas.width, canvas.height);
if (surface) {
surface._canvas = canvas;
}
return surface;
};
// Don't over-write the MakeCanvasSurface set by gpu.js if it exists.
if (!CanvasKit.MakeCanvasSurface) {
CanvasKit.MakeCanvasSurface = CanvasKit.MakeSWCanvasSurface;
}
// Note that color spaces are currently not supported in CPU surfaces. due to the limitation
// canvas.getContext('2d').putImageData imposes a limitatin of using an RGBA_8888 color type.
// TODO(nifong): support WGC color spaces while still using an RGBA_8888 color type when
// on a cpu backend.
CanvasKit.MakeSurface = function(width, height) {
/* @dict */
var imageInfo = {
'width': width,
'height': height,
'colorType': CanvasKit.ColorType.RGBA_8888,
// Since we are sending these pixels directly into the HTML canvas,
// (and those pixels are un-premultiplied, i.e. straight r,g,b,a)
'alphaType': CanvasKit.AlphaType.Unpremul,
'colorSpace': CanvasKit.SkColorSpace.SRGB,
}
var pixelLen = width * height * 4; // it's 8888, so 4 bytes per pixel
// Allocate the buffer of pixels to be drawn into.
var pixelPtr = CanvasKit._malloc(pixelLen);
var surface = this._getRasterDirectSurface(imageInfo, pixelPtr, width*4);
if (surface) {
surface._canvas = null;
surface._width = width;
surface._height = height;
surface._pixelLen = pixelLen;
surface._pixelPtr = pixelPtr;
// rasterDirectSurface does not initialize the pixels, so we clear them
// to transparent black.
surface.getCanvas().clear(CanvasKit.TRANSPARENT);
}
return surface;
};
// For GPU builds, simply proxies to native code flush. For CPU builds,
// also updates the underlying HTML canvas, optionally with dirtyRect.
CanvasKit.SkSurface.prototype.flush = function(dirtyRect) {
this._flush();
// Do we have an HTML canvas to write the pixels to?
// We will not if this a GPU build or a raster surface, for example.
if (this._canvas) {
var pixels = new Uint8ClampedArray(CanvasKit.HEAPU8.buffer, this._pixelPtr, this._pixelLen);
var imageData = new ImageData(pixels, this._width, this._height);
if (!dirtyRect) {
this._canvas.getContext('2d').putImageData(imageData, 0, 0);
} else {
this._canvas.getContext('2d').putImageData(imageData, 0, 0,
dirtyRect[0], dirtyRect[1],
dirtyRect[2] - dirtyRect[0],
dirtyRect[3] - dirtyRect[1]);
}
}
};
// Call dispose() instead of delete to clean up the underlying memory
CanvasKit.SkSurface.prototype.dispose = function() {
if (this._pixelPtr) {
CanvasKit._free(this._pixelPtr);
}
this.delete();
}
CanvasKit.currentContext = CanvasKit.currentContext || function() {
// no op if this is a cpu-only build.
};
CanvasKit.setCurrentContext = CanvasKit.setCurrentContext || function() {
// no op if this is a cpu-only build.
};
});
}(Module)); // When this file is loaded in, the high level object is "Module";