[canvaskit] Use Raster instead of RasterDirect for Canvas2D surface

This also refactors some internal names to be more consistent
with the normal naming convention.

Bug: skia:10717
Change-Id: I69a0d95aaca359e121b3ff84002d0b5f7cadb260
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/334041
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Nathaniel Nifong <nifong@google.com>
This commit is contained in:
Kevin Lubick 2020-11-11 16:48:30 -05:00
parent e4387382c2
commit 15d7a38b04
5 changed files with 55 additions and 44 deletions

View File

@ -31,6 +31,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `CanvasKit.Shader.Blend`, `...Color`, and `...Lerp` have been renamed to
`CanvasKit.Shader.MakeBlend`, `...MakeColor` and `...MakeLerp` to align with naming conventions.
The old names will be removed in an upcoming release.
- `CanvasKit.MakeSurface` no longer uses a RasterDirect surface internally. This means
creating Images from this raster surface should be faster.
- `CanvasKit.MakeSurface` is Premul instead of Unpremul, which should be more performant when
drawing.
### Removed
- `CanvasKit.MakePathFromCmds`; Was deprecated in favor of `CanvasKit.Path.MakeFromCmds`.

View File

@ -197,8 +197,8 @@ export interface CanvasKit {
opts?: WebGLOptions): Surface | null;
/**
* Returns a CPU backed surface with the given dimensions, an SRGB colorspace, Unpremul
* alphaType and 8888 color type. The pixels belonging to this surface will be in memory and
* Returns a CPU backed surface with the given dimensions, an SRGB colorspace, Premul
* alphaType and 8888 color type. The pixels belonging to this surface will be in memory and
* not visible.
* @param width - number of pixels of the width of the drawable area.
* @param height - number of pixels of the height of the drawable area.

View File

@ -763,13 +763,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
sk_sp<SkData> bytes = SkData::MakeFromMalloc(imgData, length);
return SkImage::MakeFromEncoded(std::move(bytes));
}), allow_raw_pointers());
function("_getRasterDirectSurface", optional_override([](const SimpleImageInfo ii,
uintptr_t /* uint8_t* */ pPtr,
size_t rowBytes)->sk_sp<SkSurface> {
uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
SkImageInfo imageInfo = toSkImageInfo(ii);
return SkSurface::MakeRasterDirect(imageInfo, pixels, rowBytes, nullptr);
}), allow_raw_pointers());
function("getDataBytes", &getSkDataBytes, allow_raw_pointers());
@ -1019,7 +1012,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
.function("markCTM", optional_override([](SkCanvas& self, std::string marker) {
self.markCTM(marker.c_str());
}))
.function("_readPixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
uintptr_t /* uint8_t* */ pPtr,
size_t dstRowBytes, int srcX, int srcY) {
@ -1028,6 +1020,18 @@ EMSCRIPTEN_BINDINGS(Skia) {
return self.readPixels(dstInfo, pixels, dstRowBytes, srcX, srcY);
}))
// This is an internal override for quickly flushing to a Canvas2D. We hard-code the
// image info values so we don't need to pass them all over the wire.
.function("_readPixelsForCanvas2D", optional_override([](SkCanvas& self,
uintptr_t /* uint8_t* */ pPtr,
int width, int height) {
uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
// Reminder: Canvas2D's putImageData is unpremul
SkImageInfo dstInfo = SkImageInfo::Make(width, height,
SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kUnpremul_SkAlphaType);
return self.readPixels(dstInfo, pixels, width*4, 0, 0);
}))
.function("restore", &SkCanvas::restore)
.function("restoreToCount", &SkCanvas::restoreToCount)
.function("rotate", select_overload<void (SkScalar, SkScalar, SkScalar)>(&SkCanvas::rotate))
@ -1651,6 +1655,17 @@ EMSCRIPTEN_BINDINGS(Skia) {
class_<SkSurface>("Surface")
.smart_ptr<sk_sp<SkSurface>>("sk_sp<Surface>")
.class_function("_makeRaster", optional_override([](const SimpleImageInfo ii)->sk_sp<SkSurface> {
SkImageInfo imageInfo = toSkImageInfo(ii);
return SkSurface::MakeRaster(imageInfo);
}), allow_raw_pointers())
.class_function("_makeRasterDirect", optional_override([](const SimpleImageInfo ii,
uintptr_t /* uint8_t* */ pPtr,
size_t rowBytes)->sk_sp<SkSurface> {
uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
SkImageInfo imageInfo = toSkImageInfo(ii);
return SkSurface::MakeRasterDirect(imageInfo, pixels, rowBytes, nullptr);
}), allow_raw_pointers())
.function("_flush", optional_override([](SkSurface& self) {
self.flushAndSubmit(false);
}))

View File

@ -7,19 +7,27 @@
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';
}
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';
}
}
var width = canvas.width;
var height = canvas.height;
// Maybe better to use clientWidth/height. See:
// https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
var surface = CanvasKit.MakeSurface(canvas.width, canvas.height);
var surface = CanvasKit.MakeSurface(width, height);
if (surface) {
// Set the properties we need in order to flush to the canvas.
surface._canvas = canvas;
surface._width = width;
surface._height = height;
surface._pixelLen = width * height * 4; // it's 8888, so 4 bytes per pixel
// Allocate the buffer of pixels that will be used for readPixels into.
surface._pixelPtr = CanvasKit._malloc(surface._pixelLen);
}
return surface;
};
@ -34,38 +42,18 @@
// 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,
'alphaType': CanvasKit.AlphaType.Premul,
'colorSpace': CanvasKit.ColorSpace.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);
// TODO(kjlubick) don't use RDS, as it will always copy if snapping off an SkImage.
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;
};
return CanvasKit.Surface._makeRaster(imageInfo);
};
CanvasKit.MakeRasterDirectSurface = function(imageInfo, mallocObj, bytesPerRow) {
return this._getRasterDirectSurface(imageInfo, mallocObj['byteOffset'], bytesPerRow);
return CanvasKit.Surface._makeRasterDirect(imageInfo, mallocObj['byteOffset'], bytesPerRow);
};
// For GPU builds, simply proxies to native code flush. For CPU builds,
@ -73,8 +61,10 @@
CanvasKit.Surface.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.
// We will not have a canvas if this a GPU build, for example.
if (this._canvas) {
// TODO(kjlubick) can this be modified to only read the pixels in dirtyRect?
this.getCanvas()._readPixelsForCanvas2D(this._pixelPtr, this._width, this._height);
var pixels = new Uint8ClampedArray(CanvasKit.HEAPU8.buffer, this._pixelPtr, this._pixelLen);
var imageData = new ImageData(pixels, this._width, this._height);

View File

@ -84,7 +84,6 @@ var CanvasKit = {
_decodeAnimatedImage: function() {},
_decodeImage: function() {},
_drawShapedText: function() {},
_getRasterDirectSurface: function() {},
// The testing object is meant to expose internal functions
// for more fine-grained testing, e.g. parseColor
@ -271,6 +270,7 @@ var CanvasKit = {
_getLocalToDevice: function() {},
_getTotalMatrix: function() {},
_readPixels: function() {},
_readPixelsForCanvas2D: function() {},
_saveLayer: function() {},
_writePixels: function() {},
delete: function() {},
@ -647,6 +647,8 @@ var CanvasKit = {
// private API
_flush: function() {},
_makeImageSnapshot: function() {},
_makeRaster: function() {},
_makeRasterDirect: function() {},
delete: function() {},
},