1*c8dee2aaSAndroid Build Coastguard Worker// Adds compile-time JS functions to augment the CanvasKit interface. 2*c8dee2aaSAndroid Build Coastguard Worker// Specifically, anything that should only be on the WebGL version of canvaskit. 3*c8dee2aaSAndroid Build Coastguard Worker// Functions in this file are supplemented by cpu.js. 4*c8dee2aaSAndroid Build Coastguard Worker(function(CanvasKit){ 5*c8dee2aaSAndroid Build Coastguard Worker CanvasKit._extraInitializations = CanvasKit._extraInitializations || []; 6*c8dee2aaSAndroid Build Coastguard Worker CanvasKit._extraInitializations.push(function() { 7*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.MakeGPUDeviceContext = function(device) { 8*c8dee2aaSAndroid Build Coastguard Worker if (!device) { 9*c8dee2aaSAndroid Build Coastguard Worker return null; 10*c8dee2aaSAndroid Build Coastguard Worker } 11*c8dee2aaSAndroid Build Coastguard Worker 12*c8dee2aaSAndroid Build Coastguard Worker // This allows native code to access this device by calling 13*c8dee2aaSAndroid Build Coastguard Worker // `emscripten_webgpu_get_device().` 14*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.preinitializedWebGPUDevice = device; 15*c8dee2aaSAndroid Build Coastguard Worker var context = this._MakeGrContext(); 16*c8dee2aaSAndroid Build Coastguard Worker context._device = device; 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard Worker return context; 19*c8dee2aaSAndroid Build Coastguard Worker }; 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.MakeGPUCanvasContext = function(devCtx, canvas, opts) { 22*c8dee2aaSAndroid Build Coastguard Worker var canvasCtx = canvas.getContext('webgpu'); 23*c8dee2aaSAndroid Build Coastguard Worker if (!canvasCtx) { 24*c8dee2aaSAndroid Build Coastguard Worker return null; 25*c8dee2aaSAndroid Build Coastguard Worker } 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker let format = (opts && opts.format) ? opts.format : navigator.gpu.getPreferredCanvasFormat(); 28*c8dee2aaSAndroid Build Coastguard Worker // GPUCanvasConfiguration 29*c8dee2aaSAndroid Build Coastguard Worker canvasCtx.configure({ 30*c8dee2aaSAndroid Build Coastguard Worker device: devCtx._device, 31*c8dee2aaSAndroid Build Coastguard Worker format: format, 32*c8dee2aaSAndroid Build Coastguard Worker alphaMode: (opts && opts.alphaMode) ? opts.alphaMode : undefined, 33*c8dee2aaSAndroid Build Coastguard Worker }); 34*c8dee2aaSAndroid Build Coastguard Worker 35*c8dee2aaSAndroid Build Coastguard Worker var context = { 36*c8dee2aaSAndroid Build Coastguard Worker '_inner': canvasCtx, 37*c8dee2aaSAndroid Build Coastguard Worker '_deviceContext': devCtx, 38*c8dee2aaSAndroid Build Coastguard Worker '_textureFormat': format, 39*c8dee2aaSAndroid Build Coastguard Worker }; 40*c8dee2aaSAndroid Build Coastguard Worker context['requestAnimationFrame'] = function(callback) { 41*c8dee2aaSAndroid Build Coastguard Worker requestAnimationFrame(function() { 42*c8dee2aaSAndroid Build Coastguard Worker const surface = CanvasKit.MakeGPUCanvasSurface(context); 43*c8dee2aaSAndroid Build Coastguard Worker if (!surface) { 44*c8dee2aaSAndroid Build Coastguard Worker console.error('Failed to initialize Surface for current canvas swapchain texture'); 45*c8dee2aaSAndroid Build Coastguard Worker return; 46*c8dee2aaSAndroid Build Coastguard Worker } 47*c8dee2aaSAndroid Build Coastguard Worker callback(surface.getCanvas()); 48*c8dee2aaSAndroid Build Coastguard Worker surface.flush(); 49*c8dee2aaSAndroid Build Coastguard Worker surface.dispose(); 50*c8dee2aaSAndroid Build Coastguard Worker }); 51*c8dee2aaSAndroid Build Coastguard Worker }; 52*c8dee2aaSAndroid Build Coastguard Worker return context; 53*c8dee2aaSAndroid Build Coastguard Worker }; 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.MakeGPUCanvasSurface = function(canvasCtx, colorSpace, width, height) { 56*c8dee2aaSAndroid Build Coastguard Worker let context = canvasCtx._inner; 57*c8dee2aaSAndroid Build Coastguard Worker if (!width) { 58*c8dee2aaSAndroid Build Coastguard Worker width = context.canvas.width; 59*c8dee2aaSAndroid Build Coastguard Worker } 60*c8dee2aaSAndroid Build Coastguard Worker if (!height) { 61*c8dee2aaSAndroid Build Coastguard Worker height = context.canvas.height; 62*c8dee2aaSAndroid Build Coastguard Worker } 63*c8dee2aaSAndroid Build Coastguard Worker let surface = this.MakeGPUTextureSurface(canvasCtx._deviceContext, 64*c8dee2aaSAndroid Build Coastguard Worker context.getCurrentTexture(), 65*c8dee2aaSAndroid Build Coastguard Worker canvasCtx._textureFormat, 66*c8dee2aaSAndroid Build Coastguard Worker width, height, colorSpace); 67*c8dee2aaSAndroid Build Coastguard Worker surface._canvasContext = canvasCtx; 68*c8dee2aaSAndroid Build Coastguard Worker return surface; 69*c8dee2aaSAndroid Build Coastguard Worker }; 70*c8dee2aaSAndroid Build Coastguard Worker 71*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.MakeGPUTextureSurface = function (devCtx, texture, textureFormat, width, height, colorSpace) { 72*c8dee2aaSAndroid Build Coastguard Worker colorSpace = colorSpace || null; 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard Worker // JsValStore and WebGPU are objects in Emscripten's library_html5_webgpu.js utility 75*c8dee2aaSAndroid Build Coastguard Worker // library. JsValStore allows a WebGPU object to be imported by native code by calling the 76*c8dee2aaSAndroid Build Coastguard Worker // various `emscripten_webgpu_import_*` functions. 77*c8dee2aaSAndroid Build Coastguard Worker // 78*c8dee2aaSAndroid Build Coastguard Worker // The CanvasKit WASM module is responsible for removing entries from the value store by 79*c8dee2aaSAndroid Build Coastguard Worker // calling `emscripten_webgpu_release_js_handle` after importing the object. 80*c8dee2aaSAndroid Build Coastguard Worker // 81*c8dee2aaSAndroid Build Coastguard Worker // (see 82*c8dee2aaSAndroid Build Coastguard Worker // https://github.com/emscripten-core/emscripten/blob/0e63f74f36b06849ef1c777b130783a43316ade0/src/library_html5_webgpu.js 83*c8dee2aaSAndroid Build Coastguard Worker // for reference) 84*c8dee2aaSAndroid Build Coastguard Worker return this._MakeGPUTextureSurface( 85*c8dee2aaSAndroid Build Coastguard Worker devCtx, 86*c8dee2aaSAndroid Build Coastguard Worker this.JsValStore.add(texture), 87*c8dee2aaSAndroid Build Coastguard Worker this.WebGPU.TextureFormat.indexOf(textureFormat), 88*c8dee2aaSAndroid Build Coastguard Worker width, height, 89*c8dee2aaSAndroid Build Coastguard Worker colorSpace); 90*c8dee2aaSAndroid Build Coastguard Worker }; 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Surface.prototype.assignCurrentSwapChainTexture = function() { 93*c8dee2aaSAndroid Build Coastguard Worker // This feature is only supported for a Surface that was created via MakeGPUCanvasSurface. 94*c8dee2aaSAndroid Build Coastguard Worker if (!this._canvasContext) { 95*c8dee2aaSAndroid Build Coastguard Worker console.log('Surface is not bound to a canvas context'); 96*c8dee2aaSAndroid Build Coastguard Worker return false; 97*c8dee2aaSAndroid Build Coastguard Worker } 98*c8dee2aaSAndroid Build Coastguard Worker let ctx = this._canvasContext._inner; 99*c8dee2aaSAndroid Build Coastguard Worker return this._replaceBackendTexture( 100*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.JsValStore.add(ctx.getCurrentTexture()), 101*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.WebGPU.TextureFormat.indexOf(this._canvasContext._textureFormat), 102*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.width, ctx.canvas.height); 103*c8dee2aaSAndroid Build Coastguard Worker }; 104*c8dee2aaSAndroid Build Coastguard Worker 105*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Surface.prototype.requestAnimationFrame = function(callback, dirtyRect) { 106*c8dee2aaSAndroid Build Coastguard Worker if (!this.reportBackendTypeIsGPU()) { 107*c8dee2aaSAndroid Build Coastguard Worker return this._requestAnimationFrameInternal(callback, dirtyRect); 108*c8dee2aaSAndroid Build Coastguard Worker } 109*c8dee2aaSAndroid Build Coastguard Worker 110*c8dee2aaSAndroid Build Coastguard Worker return requestAnimationFrame(function() { 111*c8dee2aaSAndroid Build Coastguard Worker // Replace the render target of the Surface with the current swapchain surface if this is 112*c8dee2aaSAndroid Build Coastguard Worker // bound to a canvas context. 113*c8dee2aaSAndroid Build Coastguard Worker if (this._canvasContext && !this.assignCurrentSwapChainTexture()) { 114*c8dee2aaSAndroid Build Coastguard Worker console.log('failed to replace GPU backend texture'); 115*c8dee2aaSAndroid Build Coastguard Worker return; 116*c8dee2aaSAndroid Build Coastguard Worker } 117*c8dee2aaSAndroid Build Coastguard Worker callback(this.getCanvas()); 118*c8dee2aaSAndroid Build Coastguard Worker this.flush(dirtyRect); 119*c8dee2aaSAndroid Build Coastguard Worker }.bind(this)); 120*c8dee2aaSAndroid Build Coastguard Worker }; 121*c8dee2aaSAndroid Build Coastguard Worker 122*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Surface.prototype.drawOnce = function(callback, dirtyRect) { 123*c8dee2aaSAndroid Build Coastguard Worker if (!this.reportBackendTypeIsGPU()) { 124*c8dee2aaSAndroid Build Coastguard Worker this._drawOnceInternal(callback, dirtyRect); 125*c8dee2aaSAndroid Build Coastguard Worker return; 126*c8dee2aaSAndroid Build Coastguard Worker } 127*c8dee2aaSAndroid Build Coastguard Worker 128*c8dee2aaSAndroid Build Coastguard Worker requestAnimationFrame(function() { 129*c8dee2aaSAndroid Build Coastguard Worker // Replace the render target of the Surface with the current swapchain surface if this is 130*c8dee2aaSAndroid Build Coastguard Worker // bound to a canvas context. 131*c8dee2aaSAndroid Build Coastguard Worker if (this._canvasContext && !this.assignCurrentSwapChainTexture()) { 132*c8dee2aaSAndroid Build Coastguard Worker console.log('failed to replace GPU backend texture'); 133*c8dee2aaSAndroid Build Coastguard Worker return; 134*c8dee2aaSAndroid Build Coastguard Worker } 135*c8dee2aaSAndroid Build Coastguard Worker callback(this.getCanvas()); 136*c8dee2aaSAndroid Build Coastguard Worker this.flush(dirtyRect); 137*c8dee2aaSAndroid Build Coastguard Worker this.dispose(); 138*c8dee2aaSAndroid Build Coastguard Worker }.bind(this)); 139*c8dee2aaSAndroid Build Coastguard Worker }; 140*c8dee2aaSAndroid Build Coastguard Worker }); 141*c8dee2aaSAndroid Build Coastguard Worker}(Module)); // When this file is loaded in, the high level object is "Module". 142