blob: 0e937d41b47798c23dbbd2ea1d0c735e334f4291 [file] [log] [blame]
// Adds compile-time JS functions to augment the CanvasKit interface.
// Specifically, anything that should only be on the WebGL version of canvaskit.
// Functions in this file are supplemented by cpu.js.
(function(CanvasKit){
CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
CanvasKit._extraInitializations.push(function() {
CanvasKit.MakeGPUDeviceContext = function(device) {
if (!device) {
return null;
}
// This allows native code to access this device by calling
// `emscripten_webgpu_get_device().`
CanvasKit.preinitializedWebGPUDevice = device;
var context = this._MakeGrContext();
context._device = device;
return context;
};
CanvasKit.MakeGPUCanvasContext = function(devCtx, canvas, opts) {
var canvasCtx = canvas.getContext('webgpu');
if (!canvasCtx) {
return null;
}
let format = (opts && opts.format) ? opts.format : navigator.gpu.getPreferredCanvasFormat();
// GPUCanvasConfiguration
canvasCtx.configure({
device: devCtx._device,
format: format,
alphaMode: (opts && opts.alphaMode) ? opts.alphaMode : undefined,
});
var context = {
'_inner': canvasCtx,
'_deviceContext': devCtx,
'_textureFormat': format,
};
context['requestAnimationFrame'] = function(callback) {
requestAnimationFrame(function() {
const surface = CanvasKit.MakeGPUCanvasSurface(context);
if (!surface) {
console.error('Failed to initialize Surface for current canvas swapchain texture');
return;
}
callback(surface.getCanvas());
surface.flush();
surface.dispose();
});
};
return context;
};
CanvasKit.MakeGPUCanvasSurface = function(canvasCtx, colorSpace, width, height) {
let context = canvasCtx._inner;
if (!width) {
width = context.canvas.width;
}
if (!height) {
height = context.canvas.height;
}
let surface = this.MakeGPUTextureSurface(canvasCtx._deviceContext,
context.getCurrentTexture(),
canvasCtx._textureFormat,
width, height, colorSpace);
surface._canvasContext = canvasCtx;
return surface;
};
CanvasKit.MakeGPUTextureSurface = function (devCtx, texture, textureFormat, width, height, colorSpace) {
colorSpace = colorSpace || null;
// JsValStore and WebGPU are objects in Emscripten's library_html5_webgpu.js utility
// library. JsValStore allows a WebGPU object to be imported by native code by calling the
// various `emscripten_webgpu_import_*` functions.
//
// The CanvasKit WASM module is responsible for removing entries from the value store by
// calling `emscripten_webgpu_release_js_handle` after importing the object.
//
// (see
// https://github.com/emscripten-core/emscripten/blob/0e63f74f36b06849ef1c777b130783a43316ade0/src/library_html5_webgpu.js
// for reference)
return this._MakeGPUTextureSurface(
devCtx,
this.JsValStore.add(texture),
this.WebGPU.TextureFormat.indexOf(textureFormat),
width, height,
colorSpace);
};
CanvasKit.Surface.prototype.assignCurrentSwapChainTexture = function() {
// This feature is only supported for a Surface that was created via MakeGPUCanvasSurface.
if (!this._canvasContext) {
console.log('Surface is not bound to a canvas context');
return false;
}
let ctx = this._canvasContext._inner;
return this._replaceBackendTexture(
CanvasKit.JsValStore.add(ctx.getCurrentTexture()),
CanvasKit.WebGPU.TextureFormat.indexOf(this._canvasContext._textureFormat),
ctx.canvas.width, ctx.canvas.height);
};
CanvasKit.Surface.prototype.requestAnimationFrame = function(callback, dirtyRect) {
if (!this.reportBackendTypeIsGPU()) {
return this._requestAnimationFrameInternal(callback, dirtyRect);
}
return requestAnimationFrame(function() {
// Replace the render target of the Surface with the current swapchain surface if this is
// bound to a canvas context.
if (this._canvasContext && !this.assignCurrentSwapChainTexture()) {
console.log('failed to replace GPU backend texture');
return;
}
callback(this.getCanvas());
this.flush(dirtyRect);
}.bind(this));
};
CanvasKit.Surface.prototype.drawOnce = function(callback, dirtyRect) {
if (!this.reportBackendTypeIsGPU()) {
this._drawOnceInternal(callback, dirtyRect);
return;
}
requestAnimationFrame(function() {
// Replace the render target of the Surface with the current swapchain surface if this is
// bound to a canvas context.
if (this._canvasContext && !this.assignCurrentSwapChainTexture()) {
console.log('failed to replace GPU backend texture');
return;
}
callback(this.getCanvas());
this.flush(dirtyRect);
this.dispose();
}.bind(this));
};
});
}(Module)); // When this file is loaded in, the high level object is "Module".