source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.WinUI.Wasm/WasmScripts/SkiaSharp.Views.Uno.Wasm.js (183 lines of code) (raw):
var SkiaSharp;
(function (SkiaSharp) {
var Views;
(function (Views) {
var Windows;
(function (Windows) {
class SKXamlCanvas {
static buffers = [];
static invalidateCanvas(pData, canvasId, width, height) {
var htmlCanvas = document.getElementById(canvasId);
if (!htmlCanvas) {
return false;
}
htmlCanvas.width = width;
htmlCanvas.height = height;
var ctx = htmlCanvas.getContext('2d');
if (!ctx)
return false;
var byteLength = width * height * 4;
if (isSecureContext) {
// In a secure context (e.g. with threading enabled), creating a view
// from Module.HEAPU8.buffer is not supported, so we're making an
// explicit copy of the wasm memory.
var buffer = SKXamlCanvas.buffers[canvasId];
if (!buffer || buffer.length != byteLength) {
SKXamlCanvas.buffers[canvasId] = buffer = new Uint8ClampedArray(new ArrayBuffer(byteLength));
}
var slice = Module.HEAPU8.buffer.slice(pData, pData + byteLength);
buffer.set(new Uint8ClampedArray(slice), 0);
var imageData = new ImageData(buffer, width, height);
ctx.putImageData(imageData, 0, 0);
}
else {
var buffer = new Uint8ClampedArray(Module.HEAPU8.buffer, byteLength);
var imageData = new ImageData(buffer, width, height);
ctx.putImageData(imageData, 0, 0);
}
return true;
}
static clearCanvas(canvasId) {
if (isSecureContext) {
delete SKXamlCanvas.buffers[canvasId];
}
}
}
class SKSwapChainPanel {
static activeInstances = {};
constructor(managedHandle) {
this.managedHandle = managedHandle;
this.canvas = undefined;
this.renderLoop = false;
this.currentRequest = 0;
this.requestRender = undefined;
this.buildImports();
}
async buildImports() {
if (Module.getAssemblyExports !== undefined) {
const skiaSharpExports = await Module.getAssemblyExports("SkiaSharp.Views.Windows");
this.requestRender = () => skiaSharpExports.SkiaSharp.Views.Windows.SKSwapChainPanel.RenderFrame(this.managedHandle);
}
else {
this.requestRender =
() => Uno.Foundation.Interop.ManagedObject.dispatch(this.managedHandle, 'RenderFrame', null);
}
}
// JSObject
static createInstanceLegacy(managedHandle, jsHandle) {
SKSwapChainPanel.activeInstances[jsHandle] = new SKSwapChainPanel(managedHandle);
}
static getInstanceLegacy(jsHandle) {
return SKSwapChainPanel.activeInstances[jsHandle];
}
static destroyInstanceLegacy(jsHandle) {
delete SKSwapChainPanel.activeInstances[jsHandle];
}
static createInstance(managedHandle) {
return new SKSwapChainPanel(managedHandle);
}
requestAnimationFrame(renderLoop) {
// optionally update the render loop
if (renderLoop !== undefined && this.renderLoop !== renderLoop)
this.setEnableRenderLoop(renderLoop);
// skip because we have a render loop
if (this.currentRequest !== 0)
return;
// make sure the canvas is scaled correctly for the drawing
this.resizeCanvas();
// add the draw to the next frame
this.currentRequest = window.requestAnimationFrame(() => {
if (this.requestRender) {
// make current for this canvas instance
GL.makeContextCurrent(this.glCtx);
this.requestRender();
}
this.currentRequest = 0;
// we may want to draw the next frame
if (this.renderLoop)
this.requestAnimationFrame();
});
}
resizeCanvas() {
if (!this.canvas)
return;
var scale = window.devicePixelRatio || 1;
var w = this.canvas.clientWidth * scale
var h = this.canvas.clientHeight * scale;
if (this.canvas.width !== w)
this.canvas.width = w;
if (this.canvas.height !== h)
this.canvas.height = h;
}
static setEnableRenderLoop(instance, enable) {
instance.setEnableRenderLoopInternal(enable);
}
setEnableRenderLoopInternal(enable) {
this.renderLoop = enable;
// either start the new frame or cancel the existing one
if (enable) {
this.requestAnimationFrame();
} else if (this.currentRequest !== 0) {
window.cancelAnimationFrame(this.currentRequest);
this.currentRequest = 0;
}
}
createContextLegacy(canvasOrCanvasId) {
var jsInfo = this.createContext(canvasOrCanvasId);
// format as array for nicer parsing
jsInfo = [
info.ctx,
info.fbo ? info.fbo.id : 0,
info.stencil,
info.sample,
info.depth,
];
return jsInfo;
}
static createContextStatic(instance, canvasOrCanvasId) {
return instance.createContext(canvasOrCanvasId);
}
createContext(canvasOrCanvasId) {
if (!canvasOrCanvasId)
throw 'No <canvas> element or ID was provided';
var canvas = canvasOrCanvasId;
if (canvas.tagName !== 'CANVAS') {
canvas = document.getElementById(canvasOrCanvasId);
if (!canvas)
throw `No <canvas> with id ${canvasOrCanvasId} was found`;
}
this.glCtx = SKSwapChainPanel.createWebGLContext(canvas);
if (!this.glCtx || this.glCtx < 0)
throw `Failed to create WebGL context: err ${ctx}`;
// make current
GL.makeContextCurrent(this.glCtx);
// Starting from .NET 7 the GLctx is defined in an inaccessible scope
// when the current GL context changes. We need to pick it up from the
// GL.currentContext instead.
let currentGLctx = GL.currentContext && GL.currentContext.GLctx;
if (!currentGLctx)
throw `Failed to get current WebGL context`;
// read values
this.canvas = canvas;
return {
ctx: this.glCtx,
fbo: currentGLctx.getParameter(currentGLctx.FRAMEBUFFER_BINDING),
stencil: currentGLctx.getParameter(currentGLctx.STENCIL_BITS),
sample: 0, // TODO: currentGLctx.getParameter(GLctx.SAMPLES)
depth: currentGLctx.getParameter(currentGLctx.DEPTH_BITS),
};
}
static createWebGLContext(canvas) {
var contextAttributes = {
alpha: 1,
depth: 1,
stencil: 8,
antialias: 1,
premultipliedAlpha: 1,
preserveDrawingBuffer: 0,
preferLowPowerToHighPerformance: 0,
failIfMajorPerformanceCaveat: 0,
majorVersion: 2,
minorVersion: 0,
enableExtensionsByDefault: 1,
explicitSwapControl: 0,
renderViaOffscreenBackBuffer: 0,
};
var ctx = GL.createContext(canvas, contextAttributes);
if (!ctx && contextAttributes.majorVersion > 1) {
console.warn('Falling back to WebGL 1.0');
contextAttributes.majorVersion = 1;
contextAttributes.minorVersion = 0;
ctx = GL.createContext(canvas, contextAttributes);
}
return ctx;
}
}
Windows.SKXamlCanvas = SKXamlCanvas;
Windows.SKSwapChainPanel = SKSwapChainPanel;
})(Windows = Views.Windows || (Views.Windows = {}));
})(Views = SkiaSharp.Views || (SkiaSharp.Views = {}));
})(SkiaSharp || (SkiaSharp = {}));