1*c8dee2aaSAndroid Build Coastguard Workerdescribe('Runtime shader effects', () => { 2*c8dee2aaSAndroid Build Coastguard Worker let container; 3*c8dee2aaSAndroid Build Coastguard Worker 4*c8dee2aaSAndroid Build Coastguard Worker beforeEach(async () => { 5*c8dee2aaSAndroid Build Coastguard Worker await EverythingLoaded; 6*c8dee2aaSAndroid Build Coastguard Worker container = document.createElement('div'); 7*c8dee2aaSAndroid Build Coastguard Worker container.innerHTML = ` 8*c8dee2aaSAndroid Build Coastguard Worker <canvas width=600 height=600 id=test></canvas> 9*c8dee2aaSAndroid Build Coastguard Worker <canvas width=600 height=600 id=report></canvas>`; 10*c8dee2aaSAndroid Build Coastguard Worker document.body.appendChild(container); 11*c8dee2aaSAndroid Build Coastguard Worker }); 12*c8dee2aaSAndroid Build Coastguard Worker 13*c8dee2aaSAndroid Build Coastguard Worker afterEach(() => { 14*c8dee2aaSAndroid Build Coastguard Worker document.body.removeChild(container); 15*c8dee2aaSAndroid Build Coastguard Worker }); 16*c8dee2aaSAndroid Build Coastguard Worker 17*c8dee2aaSAndroid Build Coastguard Worker const spiralSkSL = ` 18*c8dee2aaSAndroid Build Coastguard Workeruniform float rad_scale; 19*c8dee2aaSAndroid Build Coastguard Workeruniform int2 in_center; 20*c8dee2aaSAndroid Build Coastguard Workeruniform float4 in_colors0; 21*c8dee2aaSAndroid Build Coastguard Workeruniform float4 in_colors1; 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Workerhalf4 main(float2 p) { 24*c8dee2aaSAndroid Build Coastguard Worker float2 pp = p - float2(in_center); 25*c8dee2aaSAndroid Build Coastguard Worker float radius = sqrt(dot(pp, pp)); 26*c8dee2aaSAndroid Build Coastguard Worker radius = sqrt(radius); 27*c8dee2aaSAndroid Build Coastguard Worker float angle = atan(pp.y / pp.x); 28*c8dee2aaSAndroid Build Coastguard Worker float t = (angle + 3.1415926/2) / (3.1415926); 29*c8dee2aaSAndroid Build Coastguard Worker t += radius * rad_scale; 30*c8dee2aaSAndroid Build Coastguard Worker t = fract(t); 31*c8dee2aaSAndroid Build Coastguard Worker return half4(mix(in_colors0, in_colors1, t)); 32*c8dee2aaSAndroid Build Coastguard Worker}`; 33*c8dee2aaSAndroid Build Coastguard Worker 34*c8dee2aaSAndroid Build Coastguard Worker // TODO(kjlubick) rewrite testRTShader and callers to use gm. 35*c8dee2aaSAndroid Build Coastguard Worker const testRTShader = (name, done, localMatrix) => { 36*c8dee2aaSAndroid Build Coastguard Worker const surface = CanvasKit.MakeCanvasSurface('test'); 37*c8dee2aaSAndroid Build Coastguard Worker expect(surface).toBeTruthy('Could not make surface'); 38*c8dee2aaSAndroid Build Coastguard Worker if (!surface) { 39*c8dee2aaSAndroid Build Coastguard Worker return; 40*c8dee2aaSAndroid Build Coastguard Worker } 41*c8dee2aaSAndroid Build Coastguard Worker const spiral = CanvasKit.RuntimeEffect.Make(spiralSkSL); 42*c8dee2aaSAndroid Build Coastguard Worker expect(spiral).toBeTruthy('could not compile program'); 43*c8dee2aaSAndroid Build Coastguard Worker 44*c8dee2aaSAndroid Build Coastguard Worker expect(spiral.getUniformCount() ).toEqual(4); 45*c8dee2aaSAndroid Build Coastguard Worker expect(spiral.getUniformFloatCount()).toEqual(11); 46*c8dee2aaSAndroid Build Coastguard Worker const center = spiral.getUniform(1); 47*c8dee2aaSAndroid Build Coastguard Worker expect(center).toBeTruthy('could not fetch numbered uniform'); 48*c8dee2aaSAndroid Build Coastguard Worker expect(center.slot ).toEqual(1); 49*c8dee2aaSAndroid Build Coastguard Worker expect(center.columns ).toEqual(2); 50*c8dee2aaSAndroid Build Coastguard Worker expect(center.rows ).toEqual(1); 51*c8dee2aaSAndroid Build Coastguard Worker expect(center.isInteger).toEqual(true); 52*c8dee2aaSAndroid Build Coastguard Worker const color_0 = spiral.getUniform(2); 53*c8dee2aaSAndroid Build Coastguard Worker expect(color_0).toBeTruthy('could not fetch numbered uniform'); 54*c8dee2aaSAndroid Build Coastguard Worker expect(color_0.slot ).toEqual(3); 55*c8dee2aaSAndroid Build Coastguard Worker expect(color_0.columns ).toEqual(4); 56*c8dee2aaSAndroid Build Coastguard Worker expect(color_0.rows ).toEqual(1); 57*c8dee2aaSAndroid Build Coastguard Worker expect(color_0.isInteger).toEqual(false); 58*c8dee2aaSAndroid Build Coastguard Worker expect(spiral.getUniformName(2)).toEqual('in_colors0'); 59*c8dee2aaSAndroid Build Coastguard Worker 60*c8dee2aaSAndroid Build Coastguard Worker const canvas = surface.getCanvas(); 61*c8dee2aaSAndroid Build Coastguard Worker const paint = new CanvasKit.Paint(); 62*c8dee2aaSAndroid Build Coastguard Worker canvas.clear(CanvasKit.BLACK); // black should not be visible 63*c8dee2aaSAndroid Build Coastguard Worker const shader = spiral.makeShader([ 64*c8dee2aaSAndroid Build Coastguard Worker 0.3, 65*c8dee2aaSAndroid Build Coastguard Worker CANVAS_WIDTH/2, CANVAS_HEIGHT/2, 66*c8dee2aaSAndroid Build Coastguard Worker 1, 0, 0, 1, // solid red 67*c8dee2aaSAndroid Build Coastguard Worker 0, 1, 0, 1], // solid green 68*c8dee2aaSAndroid Build Coastguard Worker localMatrix); 69*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(shader); 70*c8dee2aaSAndroid Build Coastguard Worker canvas.drawRect(CanvasKit.LTRBRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), paint); 71*c8dee2aaSAndroid Build Coastguard Worker 72*c8dee2aaSAndroid Build Coastguard Worker paint.delete(); 73*c8dee2aaSAndroid Build Coastguard Worker shader.delete(); 74*c8dee2aaSAndroid Build Coastguard Worker spiral.delete(); 75*c8dee2aaSAndroid Build Coastguard Worker 76*c8dee2aaSAndroid Build Coastguard Worker reportSurface(surface, name, done); 77*c8dee2aaSAndroid Build Coastguard Worker }; 78*c8dee2aaSAndroid Build Coastguard Worker 79*c8dee2aaSAndroid Build Coastguard Worker it('can compile custom shader code', (done) => { 80*c8dee2aaSAndroid Build Coastguard Worker testRTShader('rtshader_spiral', done); 81*c8dee2aaSAndroid Build Coastguard Worker }); 82*c8dee2aaSAndroid Build Coastguard Worker 83*c8dee2aaSAndroid Build Coastguard Worker it('can apply a matrix to the shader', (done) => { 84*c8dee2aaSAndroid Build Coastguard Worker testRTShader('rtshader_spiral_translated', done, CanvasKit.Matrix.translated(-200, 100)); 85*c8dee2aaSAndroid Build Coastguard Worker }); 86*c8dee2aaSAndroid Build Coastguard Worker 87*c8dee2aaSAndroid Build Coastguard Worker it('can provide a error handler for compilation errors', () => { 88*c8dee2aaSAndroid Build Coastguard Worker let error = ''; 89*c8dee2aaSAndroid Build Coastguard Worker const spiral = CanvasKit.RuntimeEffect.Make(`invalid sksl code, I hope`, (e) => { 90*c8dee2aaSAndroid Build Coastguard Worker error = e; 91*c8dee2aaSAndroid Build Coastguard Worker }); 92*c8dee2aaSAndroid Build Coastguard Worker expect(spiral).toBeFalsy(); 93*c8dee2aaSAndroid Build Coastguard Worker expect(error).toContain('error'); 94*c8dee2aaSAndroid Build Coastguard Worker }); 95*c8dee2aaSAndroid Build Coastguard Worker 96*c8dee2aaSAndroid Build Coastguard Worker it('can generate a debug trace', () => { 97*c8dee2aaSAndroid Build Coastguard Worker // We don't support debug tracing on GPU, so we always request a software canvas here. 98*c8dee2aaSAndroid Build Coastguard Worker const surface = CanvasKit.MakeSWCanvasSurface('test'); 99*c8dee2aaSAndroid Build Coastguard Worker expect(surface).toBeTruthy('Could not make surface'); 100*c8dee2aaSAndroid Build Coastguard Worker if (!surface) { 101*c8dee2aaSAndroid Build Coastguard Worker return; 102*c8dee2aaSAndroid Build Coastguard Worker } 103*c8dee2aaSAndroid Build Coastguard Worker const spiral = CanvasKit.RuntimeEffect.Make(spiralSkSL); 104*c8dee2aaSAndroid Build Coastguard Worker expect(spiral).toBeTruthy('could not compile program'); 105*c8dee2aaSAndroid Build Coastguard Worker 106*c8dee2aaSAndroid Build Coastguard Worker const canvas = surface.getCanvas(); 107*c8dee2aaSAndroid Build Coastguard Worker const paint = new CanvasKit.Paint(); 108*c8dee2aaSAndroid Build Coastguard Worker const shader = spiral.makeShader([ 109*c8dee2aaSAndroid Build Coastguard Worker 0.3, 110*c8dee2aaSAndroid Build Coastguard Worker CANVAS_WIDTH/2, CANVAS_HEIGHT/2, 111*c8dee2aaSAndroid Build Coastguard Worker 1, 0, 0, 1, // solid red 112*c8dee2aaSAndroid Build Coastguard Worker 0, 1, 0, 1]); // solid green 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker const traced = CanvasKit.RuntimeEffect.MakeTraced(shader, CANVAS_WIDTH/2, CANVAS_HEIGHT/2); 115*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(traced.shader); 116*c8dee2aaSAndroid Build Coastguard Worker canvas.drawRect(CanvasKit.LTRBRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), paint); 117*c8dee2aaSAndroid Build Coastguard Worker 118*c8dee2aaSAndroid Build Coastguard Worker const traceData = traced.debugTrace.writeTrace(); 119*c8dee2aaSAndroid Build Coastguard Worker paint.delete(); 120*c8dee2aaSAndroid Build Coastguard Worker shader.delete(); 121*c8dee2aaSAndroid Build Coastguard Worker spiral.delete(); 122*c8dee2aaSAndroid Build Coastguard Worker traced.shader.delete(); 123*c8dee2aaSAndroid Build Coastguard Worker traced.debugTrace.delete(); 124*c8dee2aaSAndroid Build Coastguard Worker surface.delete(); 125*c8dee2aaSAndroid Build Coastguard Worker 126*c8dee2aaSAndroid Build Coastguard Worker const parsedTrace = JSON.parse(traceData); 127*c8dee2aaSAndroid Build Coastguard Worker expect(parsedTrace).toBeTruthy('could not parse trace JSON'); 128*c8dee2aaSAndroid Build Coastguard Worker expect(parsedTrace.functions).toBeTruthy('debug trace does not include function list'); 129*c8dee2aaSAndroid Build Coastguard Worker expect(parsedTrace.slots).toBeTruthy('debug trace does not include slot list'); 130*c8dee2aaSAndroid Build Coastguard Worker expect(parsedTrace.trace).toBeTruthy('debug trace does not include trace data'); 131*c8dee2aaSAndroid Build Coastguard Worker expect(parsedTrace.nonsense).toBeFalsy('debug trace includes a nonsense key'); 132*c8dee2aaSAndroid Build Coastguard Worker expect(parsedTrace.mystery).toBeFalsy('debug trace includes a mystery key'); 133*c8dee2aaSAndroid Build Coastguard Worker expect(parsedTrace.source).toEqual([ 134*c8dee2aaSAndroid Build Coastguard Worker "", 135*c8dee2aaSAndroid Build Coastguard Worker "uniform float rad_scale;", 136*c8dee2aaSAndroid Build Coastguard Worker "uniform int2 in_center;", 137*c8dee2aaSAndroid Build Coastguard Worker "uniform float4 in_colors0;", 138*c8dee2aaSAndroid Build Coastguard Worker "uniform float4 in_colors1;", 139*c8dee2aaSAndroid Build Coastguard Worker "", 140*c8dee2aaSAndroid Build Coastguard Worker "half4 main(float2 p) {", 141*c8dee2aaSAndroid Build Coastguard Worker " float2 pp = p - float2(in_center);", 142*c8dee2aaSAndroid Build Coastguard Worker " float radius = sqrt(dot(pp, pp));", 143*c8dee2aaSAndroid Build Coastguard Worker " radius = sqrt(radius);", 144*c8dee2aaSAndroid Build Coastguard Worker " float angle = atan(pp.y / pp.x);", 145*c8dee2aaSAndroid Build Coastguard Worker " float t = (angle + 3.1415926/2) / (3.1415926);", 146*c8dee2aaSAndroid Build Coastguard Worker " t += radius * rad_scale;", 147*c8dee2aaSAndroid Build Coastguard Worker " t = fract(t);", 148*c8dee2aaSAndroid Build Coastguard Worker " return half4(mix(in_colors0, in_colors1, t));", 149*c8dee2aaSAndroid Build Coastguard Worker "}" 150*c8dee2aaSAndroid Build Coastguard Worker ]); 151*c8dee2aaSAndroid Build Coastguard Worker }); 152*c8dee2aaSAndroid Build Coastguard Worker 153*c8dee2aaSAndroid Build Coastguard Worker const loadBrick = fetch( 154*c8dee2aaSAndroid Build Coastguard Worker '/assets/brickwork-texture.jpg') 155*c8dee2aaSAndroid Build Coastguard Worker .then((response) => response.arrayBuffer()); 156*c8dee2aaSAndroid Build Coastguard Worker const loadMandrill = fetch( 157*c8dee2aaSAndroid Build Coastguard Worker '/assets/mandrill_512.png') 158*c8dee2aaSAndroid Build Coastguard Worker .then((response) => response.arrayBuffer()); 159*c8dee2aaSAndroid Build Coastguard Worker 160*c8dee2aaSAndroid Build Coastguard Worker const thresholdSkSL = ` 161*c8dee2aaSAndroid Build Coastguard Workeruniform shader before_map; 162*c8dee2aaSAndroid Build Coastguard Workeruniform shader after_map; 163*c8dee2aaSAndroid Build Coastguard Workeruniform shader threshold_map; 164*c8dee2aaSAndroid Build Coastguard Worker 165*c8dee2aaSAndroid Build Coastguard Workeruniform float cutoff; 166*c8dee2aaSAndroid Build Coastguard Workeruniform float slope; 167*c8dee2aaSAndroid Build Coastguard Worker 168*c8dee2aaSAndroid Build Coastguard Workerfloat smooth_cutoff(float x) { 169*c8dee2aaSAndroid Build Coastguard Worker x = x * slope + (0.5 - slope * cutoff); 170*c8dee2aaSAndroid Build Coastguard Worker return clamp(x, 0, 1); 171*c8dee2aaSAndroid Build Coastguard Worker} 172*c8dee2aaSAndroid Build Coastguard Worker 173*c8dee2aaSAndroid Build Coastguard Workerhalf4 main(float2 xy) { 174*c8dee2aaSAndroid Build Coastguard Worker half4 before = before_map.eval(xy); 175*c8dee2aaSAndroid Build Coastguard Worker half4 after = after_map.eval(xy); 176*c8dee2aaSAndroid Build Coastguard Worker 177*c8dee2aaSAndroid Build Coastguard Worker float m = smooth_cutoff(threshold_map.eval(xy).r); 178*c8dee2aaSAndroid Build Coastguard Worker return mix(before, after, half(m)); 179*c8dee2aaSAndroid Build Coastguard Worker}`; 180*c8dee2aaSAndroid Build Coastguard Worker 181*c8dee2aaSAndroid Build Coastguard Worker // TODO(kjlubick) rewrite testChildrenShader and callers to use gm. 182*c8dee2aaSAndroid Build Coastguard Worker const testChildrenShader = (name, done, localMatrix) => { 183*c8dee2aaSAndroid Build Coastguard Worker Promise.all([loadBrick, loadMandrill]).then((values) => { 184*c8dee2aaSAndroid Build Coastguard Worker catchException(done, () => { 185*c8dee2aaSAndroid Build Coastguard Worker const [brickData, mandrillData] = values; 186*c8dee2aaSAndroid Build Coastguard Worker const brickImg = CanvasKit.MakeImageFromEncoded(brickData); 187*c8dee2aaSAndroid Build Coastguard Worker expect(brickImg).toBeTruthy('brick image could not be loaded'); 188*c8dee2aaSAndroid Build Coastguard Worker const mandrillImg = CanvasKit.MakeImageFromEncoded(mandrillData); 189*c8dee2aaSAndroid Build Coastguard Worker expect(mandrillImg).toBeTruthy('mandrill image could not be loaded'); 190*c8dee2aaSAndroid Build Coastguard Worker 191*c8dee2aaSAndroid Build Coastguard Worker const thresholdEffect = CanvasKit.RuntimeEffect.Make(thresholdSkSL); 192*c8dee2aaSAndroid Build Coastguard Worker expect(thresholdEffect).toBeTruthy('threshold did not compile'); 193*c8dee2aaSAndroid Build Coastguard Worker const spiralEffect = CanvasKit.RuntimeEffect.Make(spiralSkSL); 194*c8dee2aaSAndroid Build Coastguard Worker expect(spiralEffect).toBeTruthy('spiral did not compile'); 195*c8dee2aaSAndroid Build Coastguard Worker 196*c8dee2aaSAndroid Build Coastguard Worker const brickShader = brickImg.makeShaderCubic( 197*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.TileMode.Decal, CanvasKit.TileMode.Decal, 198*c8dee2aaSAndroid Build Coastguard Worker 1/3 /*B*/, 1/3 /*C*/, 199*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.scaled(CANVAS_WIDTH/brickImg.width(), 200*c8dee2aaSAndroid Build Coastguard Worker CANVAS_HEIGHT/brickImg.height())); 201*c8dee2aaSAndroid Build Coastguard Worker const mandrillShader = mandrillImg.makeShaderCubic( 202*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.TileMode.Decal, CanvasKit.TileMode.Decal, 203*c8dee2aaSAndroid Build Coastguard Worker 1/3 /*B*/, 1/3 /*C*/, 204*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.scaled(CANVAS_WIDTH/mandrillImg.width(), 205*c8dee2aaSAndroid Build Coastguard Worker CANVAS_HEIGHT/mandrillImg.height())); 206*c8dee2aaSAndroid Build Coastguard Worker const spiralShader = spiralEffect.makeShader([ 207*c8dee2aaSAndroid Build Coastguard Worker 0.8, 208*c8dee2aaSAndroid Build Coastguard Worker CANVAS_WIDTH/2, CANVAS_HEIGHT/2, 209*c8dee2aaSAndroid Build Coastguard Worker 1, 1, 1, 1, 210*c8dee2aaSAndroid Build Coastguard Worker 0, 0, 0, 1]); 211*c8dee2aaSAndroid Build Coastguard Worker 212*c8dee2aaSAndroid Build Coastguard Worker const blendShader = thresholdEffect.makeShaderWithChildren( 213*c8dee2aaSAndroid Build Coastguard Worker [0.5, 5], 214*c8dee2aaSAndroid Build Coastguard Worker [brickShader, mandrillShader, spiralShader], localMatrix); 215*c8dee2aaSAndroid Build Coastguard Worker 216*c8dee2aaSAndroid Build Coastguard Worker const surface = CanvasKit.MakeCanvasSurface('test'); 217*c8dee2aaSAndroid Build Coastguard Worker expect(surface).toBeTruthy('Could not make surface'); 218*c8dee2aaSAndroid Build Coastguard Worker const canvas = surface.getCanvas(); 219*c8dee2aaSAndroid Build Coastguard Worker const paint = new CanvasKit.Paint(); 220*c8dee2aaSAndroid Build Coastguard Worker 221*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(blendShader); 222*c8dee2aaSAndroid Build Coastguard Worker canvas.drawRect(CanvasKit.LTRBRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), paint); 223*c8dee2aaSAndroid Build Coastguard Worker 224*c8dee2aaSAndroid Build Coastguard Worker brickImg.delete(); 225*c8dee2aaSAndroid Build Coastguard Worker mandrillImg.delete(); 226*c8dee2aaSAndroid Build Coastguard Worker thresholdEffect.delete(); 227*c8dee2aaSAndroid Build Coastguard Worker spiralEffect.delete(); 228*c8dee2aaSAndroid Build Coastguard Worker brickShader.delete(); 229*c8dee2aaSAndroid Build Coastguard Worker mandrillShader.delete(); 230*c8dee2aaSAndroid Build Coastguard Worker spiralShader.delete(); 231*c8dee2aaSAndroid Build Coastguard Worker blendShader.delete(); 232*c8dee2aaSAndroid Build Coastguard Worker paint.delete(); 233*c8dee2aaSAndroid Build Coastguard Worker 234*c8dee2aaSAndroid Build Coastguard Worker reportSurface(surface, name, done); 235*c8dee2aaSAndroid Build Coastguard Worker })(); 236*c8dee2aaSAndroid Build Coastguard Worker }); 237*c8dee2aaSAndroid Build Coastguard Worker } 238*c8dee2aaSAndroid Build Coastguard Worker 239*c8dee2aaSAndroid Build Coastguard Worker it('take other shaders as fragment processors', (done) => { 240*c8dee2aaSAndroid Build Coastguard Worker testChildrenShader('rtshader_children', done); 241*c8dee2aaSAndroid Build Coastguard Worker }); 242*c8dee2aaSAndroid Build Coastguard Worker 243*c8dee2aaSAndroid Build Coastguard Worker it('apply a local matrix to the children-based shader', (done) => { 244*c8dee2aaSAndroid Build Coastguard Worker testChildrenShader('rtshader_children_rotated', done, CanvasKit.Matrix.rotated(Math.PI/12)); 245*c8dee2aaSAndroid Build Coastguard Worker }); 246*c8dee2aaSAndroid Build Coastguard Worker 247*c8dee2aaSAndroid Build Coastguard Worker it('can generate runtime blender', (done) => { 248*c8dee2aaSAndroid Build Coastguard Worker const loadBrick = fetch( 249*c8dee2aaSAndroid Build Coastguard Worker '/assets/brickwork-texture.jpg') 250*c8dee2aaSAndroid Build Coastguard Worker .then((response) => response.arrayBuffer()); 251*c8dee2aaSAndroid Build Coastguard Worker const loadMandrill = fetch( 252*c8dee2aaSAndroid Build Coastguard Worker '/assets/mandrill_512.png') 253*c8dee2aaSAndroid Build Coastguard Worker .then((response) => response.arrayBuffer()); 254*c8dee2aaSAndroid Build Coastguard Worker Promise.all([loadBrick, loadMandrill]).then((values) => { 255*c8dee2aaSAndroid Build Coastguard Worker catchException(done, () => { 256*c8dee2aaSAndroid Build Coastguard Worker const screenSkSL = ` 257*c8dee2aaSAndroid Build Coastguard Worker vec4 main(vec4 src, vec4 dst) { 258*c8dee2aaSAndroid Build Coastguard Worker return src + dst - src * dst; 259*c8dee2aaSAndroid Build Coastguard Worker } 260*c8dee2aaSAndroid Build Coastguard Worker `; 261*c8dee2aaSAndroid Build Coastguard Worker 262*c8dee2aaSAndroid Build Coastguard Worker const [brickData, mandrillData] = values; 263*c8dee2aaSAndroid Build Coastguard Worker const brickImg = CanvasKit.MakeImageFromEncoded(brickData); 264*c8dee2aaSAndroid Build Coastguard Worker expect(brickImg) 265*c8dee2aaSAndroid Build Coastguard Worker .withContext('brick image could not be loaded') 266*c8dee2aaSAndroid Build Coastguard Worker .toBeTruthy(); 267*c8dee2aaSAndroid Build Coastguard Worker const mandrillImg = CanvasKit.MakeImageFromEncoded(mandrillData); 268*c8dee2aaSAndroid Build Coastguard Worker expect(mandrillImg) 269*c8dee2aaSAndroid Build Coastguard Worker .withContext('mandrill image could not be loaded') 270*c8dee2aaSAndroid Build Coastguard Worker .toBeTruthy(); 271*c8dee2aaSAndroid Build Coastguard Worker 272*c8dee2aaSAndroid Build Coastguard Worker const brickShader = brickImg.makeShaderCubic( 273*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.TileMode.Decal, CanvasKit.TileMode.Decal, 274*c8dee2aaSAndroid Build Coastguard Worker 1/3 /*B*/, 1/3 /*C*/, 275*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.scaled(CANVAS_WIDTH/brickImg.width(), 276*c8dee2aaSAndroid Build Coastguard Worker CANVAS_HEIGHT/brickImg.height())); 277*c8dee2aaSAndroid Build Coastguard Worker const mandrillShader = mandrillImg.makeShaderCubic( 278*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.TileMode.Decal, CanvasKit.TileMode.Decal, 279*c8dee2aaSAndroid Build Coastguard Worker 1/3 /*B*/, 1/3 /*C*/, 280*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.scaled(CANVAS_WIDTH/mandrillImg.width(), 281*c8dee2aaSAndroid Build Coastguard Worker CANVAS_HEIGHT/mandrillImg.height())); 282*c8dee2aaSAndroid Build Coastguard Worker 283*c8dee2aaSAndroid Build Coastguard Worker const surface = CanvasKit.MakeCanvasSurface('test'); 284*c8dee2aaSAndroid Build Coastguard Worker expect(surface) 285*c8dee2aaSAndroid Build Coastguard Worker .withContext('Could not make surface') 286*c8dee2aaSAndroid Build Coastguard Worker .toBeTruthy(); 287*c8dee2aaSAndroid Build Coastguard Worker const canvas = surface.getCanvas(); 288*c8dee2aaSAndroid Build Coastguard Worker const paint = new CanvasKit.Paint(); 289*c8dee2aaSAndroid Build Coastguard Worker 290*c8dee2aaSAndroid Build Coastguard Worker const screenEffect = CanvasKit.RuntimeEffect.MakeForBlender(screenSkSL); 291*c8dee2aaSAndroid Build Coastguard Worker expect(screenEffect) 292*c8dee2aaSAndroid Build Coastguard Worker .withContext('could not compile program') 293*c8dee2aaSAndroid Build Coastguard Worker .toBeTruthy(); 294*c8dee2aaSAndroid Build Coastguard Worker expect(screenEffect.getUniformCount() ).toEqual(0); 295*c8dee2aaSAndroid Build Coastguard Worker expect(screenEffect.getUniformFloatCount()).toEqual(0); 296*c8dee2aaSAndroid Build Coastguard Worker const screenBlender = screenEffect.makeBlender([]); 297*c8dee2aaSAndroid Build Coastguard Worker 298*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(brickShader); 299*c8dee2aaSAndroid Build Coastguard Worker canvas.drawRect(CanvasKit.LTRBRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), paint); 300*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(mandrillShader); 301*c8dee2aaSAndroid Build Coastguard Worker paint.setBlender(screenBlender); 302*c8dee2aaSAndroid Build Coastguard Worker canvas.drawRect(CanvasKit.LTRBRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), paint); 303*c8dee2aaSAndroid Build Coastguard Worker 304*c8dee2aaSAndroid Build Coastguard Worker brickImg.delete(); 305*c8dee2aaSAndroid Build Coastguard Worker mandrillImg.delete(); 306*c8dee2aaSAndroid Build Coastguard Worker brickShader.delete(); 307*c8dee2aaSAndroid Build Coastguard Worker mandrillShader.delete(); 308*c8dee2aaSAndroid Build Coastguard Worker paint.delete(); 309*c8dee2aaSAndroid Build Coastguard Worker screenBlender.delete(); 310*c8dee2aaSAndroid Build Coastguard Worker screenEffect.delete(); 311*c8dee2aaSAndroid Build Coastguard Worker 312*c8dee2aaSAndroid Build Coastguard Worker reportSurface(surface, 'rtblender', done); 313*c8dee2aaSAndroid Build Coastguard Worker })(); 314*c8dee2aaSAndroid Build Coastguard Worker }); 315*c8dee2aaSAndroid Build Coastguard Worker }); 316*c8dee2aaSAndroid Build Coastguard Worker}); 317