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