blob: 9602f3aa927d3886747f3f8eb8ab99518a3435e0 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'dart:typed_data';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
import 'package:web_engine_tester/golden_tester.dart';
import '../common/fake_asset_manager.dart';
import '../common/test_initialization.dart';
import 'utils.dart';
void main() {
internalBootstrapBrowserTest(() => testMain);
}
// This fragment shader generates some voronoi noise. It uses a pseudo-random
// number generator implemented in the shader itself, so its output is
// deterministic.
const String kVoronoiShaderSksl = r'''
{
"sksl": "// This SkSL shader is autogenerated by spirv-cross.\n\nfloat4 flutter_FragCoord;\n\nuniform float uTileSize;\n\nvec4 fragColor;\n\nvec2 FLT_flutter_local_FlutterFragCoord()\n{\n return flutter_FragCoord.xy;\n}\n\nfloat FLT_flutter_local_rand(vec2 co)\n{\n return fract(sin(dot(co, vec2(12.98980045318603515625, 78.233001708984375))) * 43758.546875);\n}\n\nvec2 FLT_flutter_local_fuzzGridPoint(vec2 coordinate)\n{\n vec2 param = coordinate * 400.0;\n vec2 param_1 = coordinate * 400.0;\n return coordinate + vec2((FLT_flutter_local_rand(param) - 0.5) * 0.800000011920928955078125, (FLT_flutter_local_rand(param_1) - 0.5) * 0.800000011920928955078125);\n}\n\nvec3 FLT_flutter_local_getColorForGridPoint(vec2 coordinate)\n{\n vec2 param = coordinate * 100.0;\n vec2 param_1 = coordinate * 200.0;\n vec2 param_2 = coordinate * 300.0;\n return vec3(FLT_flutter_local_rand(param), FLT_flutter_local_rand(param_1), FLT_flutter_local_rand(param_2));\n}\n\nvoid FLT_main()\n{\n vec2 uv = FLT_flutter_local_FlutterFragCoord() / vec2(uTileSize);\n vec2 upperLeft = floor(uv);\n vec2 upperRight = vec2(ceil(uv.x), floor(uv.y));\n vec2 bottomLeft = vec2(floor(uv.x), ceil(uv.y));\n vec2 bottomRight = ceil(uv);\n vec2 closestPoint = upperLeft;\n vec2 param_3 = upperLeft;\n float dist = distance(uv, FLT_flutter_local_fuzzGridPoint(param_3));\n vec2 param_4 = upperRight;\n float upperRightDistance = distance(uv, FLT_flutter_local_fuzzGridPoint(param_4));\n if (upperRightDistance < dist)\n {\n dist = upperRightDistance;\n closestPoint = upperRight;\n }\n vec2 param_5 = bottomLeft;\n float bottomLeftDistance = distance(uv, FLT_flutter_local_fuzzGridPoint(param_5));\n if (bottomLeftDistance < dist)\n {\n dist = bottomLeftDistance;\n closestPoint = bottomLeft;\n }\n vec2 param_6 = bottomRight;\n float bottomRightDistance = distance(uv, FLT_flutter_local_fuzzGridPoint(param_6));\n if (bottomRightDistance < dist)\n {\n dist = bottomRightDistance;\n closestPoint = bottomRight;\n }\n vec2 param_7 = closestPoint;\n fragColor = vec4(FLT_flutter_local_getColorForGridPoint(param_7), 1.0);\n}\n\nhalf4 main(float2 iFragCoord)\n{\n flutter_FragCoord = float4(iFragCoord, 0, 0);\n FLT_main();\n return fragColor;\n}\n",
"stage": 1,
"target_platform": 2,
"uniforms": [
{
"array_elements": 0,
"bit_width": 32,
"columns": 1,
"location": 0,
"name": "uTileSize",
"rows": 1,
"type": 10
}
]
}
''';
Future<void> testMain() async {
setUpUnitTests(
withImplicitView: true,
setUpTestViewDimensions: false,
);
const ui.Rect region = ui.Rect.fromLTWH(0, 0, 300, 300);
late FakeAssetScope assetScope;
setUp(() {
assetScope = fakeAssetManager.pushAssetScope();
assetScope.setAsset(
'voronoi_shader',
ByteData.sublistView(utf8.encode(kVoronoiShaderSksl))
);
});
tearDown(() {
fakeAssetManager.popAssetScope(assetScope);
});
test('fragment shader', () async {
final ui.FragmentProgram program = await renderer.createFragmentProgram('voronoi_shader');
final ui.FragmentShader shader = program.fragmentShader();
Future<void> drawCircle(String goldenFilename) async {
final ui.PictureRecorder recorder = ui.PictureRecorder();
final ui.Canvas canvas = ui.Canvas(recorder, region);
canvas.drawCircle(const ui.Offset(150, 150), 100, ui.Paint()..shader = shader);
await drawPictureUsingCurrentRenderer(recorder.endRecording());
await matchGoldenFile(goldenFilename, region: region);
}
shader.setFloat(0, 10.0);
await drawCircle('fragment_shader_voronoi_tile10px.png');
// Make sure we can reuse the shader object with a new uniform value.
shader.setFloat(0, 25.0);
await drawCircle('fragment_shader_voronoi_tile25px.png');
}, skip: isHtml); // Fragment shaders are not supported by the HTML renderer.
}