aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-05-12 01:06:33 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-05-12 01:06:33 +0000
commit0ab7e0a746b293df559e3639cf7e47056d4838d4 (patch)
tree53d402362d31d23f351ac8ca0fb5ad235b5b6637
parent81b326bea53b93d084255cec645908d8f481a576 (diff)
parentcc4cbd01bb9e444b4052acbe8aa3aaf7861d696d (diff)
downloadskia-0ab7e0a746b293df559e3639cf7e47056d4838d4.tar.gz
Snap for 7354453 from cc4cbd01bb9e444b4052acbe8aa3aaf7861d696d to sc-release
Change-Id: Ieb7a2850b7ad4d70665f9761ddaa8177a03f6a6b
-rw-r--r--DEPS10
-rw-r--r--METADATA4
-rw-r--r--build_overrides/angle.gni2
-rw-r--r--demos.skia.org/demos/textedit/index.html141
-rw-r--r--demos.skia.org/demos/textedit/textapi_utils.js608
-rw-r--r--fuzz/FuzzTriangulation.cpp1
-rw-r--r--gm/tessellation.cpp182
-rw-r--r--include/private/SkSLLayout.h38
-rw-r--r--include/private/SkTHash.h1
-rw-r--r--include/private/SkTLogic.h4
-rw-r--r--modules/androidkit/src/Matrix.cpp42
-rw-r--r--modules/androidkit/src/Paint.cpp22
-rw-r--r--platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java31
-rw-r--r--platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java9
-rw-r--r--resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp8
-rw-r--r--resources/sksl/errors/LayoutRepeatedQualifiers.sksl2
-rw-r--r--resources/sksl/folding/BoolFolding.sksl12
-rw-r--r--resources/sksl/intrinsics/AbsFloat.sksl9
-rw-r--r--resources/sksl/intrinsics/AbsInt.sksl7
-rw-r--r--resources/sksl/intrinsics/All.sksl15
-rw-r--r--resources/sksl/intrinsics/Any.sksl15
-rw-r--r--resources/sksl/intrinsics/Not.sksl15
-rw-r--r--resources/sksl/intrinsics/SignFloat.sksl9
-rw-r--r--resources/sksl/intrinsics/SignInt.sksl9
-rw-r--r--resources/sksl/runtime_errors/IllegalIndexing.rts4
-rw-r--r--src/android/SkAnimatedImage.cpp8
-rw-r--r--src/core/SkGlyphRun.cpp4
-rw-r--r--src/core/SkGlyphRun.h14
-rw-r--r--src/core/SkSpan.h6
-rw-r--r--src/gpu/GrAATriangulator.cpp2
-rw-r--r--src/gpu/GrGeometryProcessor.h15
-rw-r--r--src/gpu/GrGpu.cpp2
-rw-r--r--src/gpu/GrPipeline.h2
-rw-r--r--src/gpu/GrRenderTaskCluster.cpp2
-rw-r--r--src/gpu/GrTriangulator.cpp61
-rw-r--r--src/gpu/GrTriangulator.h17
-rw-r--r--src/gpu/effects/GrCustomXfermode.cpp35
-rw-r--r--src/gpu/gl/GrGLCaps.cpp43
-rw-r--r--src/gpu/gl/GrGLContext.cpp20
-rw-r--r--src/gpu/gl/GrGLContext.h18
-rw-r--r--src/gpu/gl/GrGLUtil.cpp363
-rw-r--r--src/gpu/gl/GrGLUtil.h39
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp10
-rw-r--r--src/gpu/glsl/GrGLSLGeometryProcessor.h15
-rw-r--r--src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp12
-rw-r--r--src/gpu/tessellate/GrStencilPathShader.cpp354
-rw-r--r--src/gpu/tessellate/GrStencilPathShader.h18
-rw-r--r--src/gpu/tessellate/GrStrokeTessellateShader.cpp82
-rw-r--r--src/gpu/tessellate/GrStrokeTessellateShader.h9
-rw-r--r--src/gpu/text/GrTextBlob.cpp16
-rw-r--r--src/gpu/vk/GrVkGpu.cpp2
-rw-r--r--src/ports/SkFontHost_FreeType_common.cpp90
-rw-r--r--src/sksl/SkSLIRGenerator.h1
-rw-r--r--src/sksl/SkSLParser.cpp4
-rw-r--r--src/sksl/SkSLParser.h1
-rw-r--r--src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp2
-rw-r--r--src/sksl/dsl/DSLCore.cpp12
-rw-r--r--src/sksl/generated/sksl_fp.dehydrated.sksl10
-rw-r--r--src/sksl/generated/sksl_frag.dehydrated.sksl10
-rw-r--r--src/sksl/generated/sksl_geom.dehydrated.sksl12
-rw-r--r--src/sksl/generated/sksl_rt_shader.dehydrated.sksl2
-rw-r--r--src/sksl/generated/sksl_vert.dehydrated.sksl8
-rw-r--r--src/sksl/ir/SkSLFunctionCall.cpp94
-rw-r--r--tests/AnimatedImageTest.cpp35
-rw-r--r--tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp3
-rw-r--r--tests/sksl/errors/LayoutRepeatedQualifiers.glsl39
-rw-r--r--tests/sksl/folding/BoolFolding.glsl4
-rw-r--r--tests/sksl/inliner/StaticSwitch.glsl4
-rw-r--r--tests/sksl/intrinsics/AbsFloat.asm.frag81
-rw-r--r--tests/sksl/intrinsics/AbsFloat.glsl2
-rw-r--r--tests/sksl/intrinsics/AbsFloat.metal2
-rw-r--r--tests/sksl/intrinsics/AbsInt.asm.frag78
-rw-r--r--tests/sksl/intrinsics/AbsInt.glsl2
-rw-r--r--tests/sksl/intrinsics/AbsInt.metal2
-rw-r--r--tests/sksl/intrinsics/All.asm.frag188
-rw-r--r--tests/sksl/intrinsics/All.glsl11
-rw-r--r--tests/sksl/intrinsics/All.metal18
-rw-r--r--tests/sksl/intrinsics/Any.asm.frag187
-rw-r--r--tests/sksl/intrinsics/Any.glsl11
-rw-r--r--tests/sksl/intrinsics/Any.metal18
-rw-r--r--tests/sksl/intrinsics/Not.asm.frag198
-rw-r--r--tests/sksl/intrinsics/Not.glsl11
-rw-r--r--tests/sksl/intrinsics/Not.metal18
-rw-r--r--tests/sksl/intrinsics/SignFloat.asm.frag81
-rw-r--r--tests/sksl/intrinsics/SignFloat.glsl2
-rw-r--r--tests/sksl/intrinsics/SignFloat.metal2
-rw-r--r--tests/sksl/intrinsics/SignInt.asm.frag223
-rw-r--r--tests/sksl/intrinsics/SignInt.glsl11
-rw-r--r--tests/sksl/intrinsics/SignInt.metal23
-rw-r--r--tests/sksl/runtime_errors/IllegalIndexing.skvm3
-rw-r--r--tests/sksl/shared/ConstVariableComparison.asm.frag36
-rw-r--r--tests/sksl/shared/ConstVariableComparison.glsl2
-rw-r--r--tests/sksl/shared/ConstVariableComparison.metal2
-rw-r--r--tests/sksl/shared/StaticSwitchWithContinue.asm.frag45
-rw-r--r--tests/sksl/shared/StaticSwitchWithContinue.glsl2
-rw-r--r--tests/sksl/shared/StaticSwitchWithContinue.metal2
-rw-r--r--tests/sksl/spirv/ConstantVectorFromVector.asm.frag13
-rw-r--r--tools/gpu/GrContextFactory.cpp2
98 files changed, 2931 insertions, 1045 deletions
diff --git a/DEPS b/DEPS
index 35fb151680..70d152a5a9 100644
--- a/DEPS
+++ b/DEPS
@@ -11,15 +11,15 @@ vars = {
deps = {
"buildtools" : "https://chromium.googlesource.com/chromium/buildtools.git@505de88083136eefd056e5ee4ca0f01fe9b33de8",
- "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@69d593b5d6509d4698adb6e73422f20ed414a831",
+ "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@125f128e62399400f02254a09aad739056650d2a",
"third_party/externals/brotli" : "https://skia.googlesource.com/external/github.com/google/brotli.git@e61745a6b7add50d380cfd7d3883dd6c62fc2c71",
"third_party/externals/d3d12allocator" : "https://skia.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git@169895d529dfce00390a20e69c2f516066fe7a3b",
# Dawn requires jinja2 and markupsafe for the code generator, and tint for SPIRV compilation.
# When the Dawn revision is updated these should be updated from the Dawn DEPS as well.
- "third_party/externals/dawn" : "https://dawn.googlesource.com/dawn.git@26468c4071756b016468fc6c2729f702955acdcf",
+ "third_party/externals/dawn" : "https://dawn.googlesource.com/dawn.git@e2f083e4b0f5926b6ca4abe9ab13a710fac2b917",
"third_party/externals/jinja2" : "https://chromium.googlesource.com/chromium/src/third_party/jinja2@a82a4944a7f2496639f34a89c9923be5908b80aa",
"third_party/externals/markupsafe" : "https://chromium.googlesource.com/chromium/src/third_party/markupsafe@0944e71f4b2cb9a871bcbe353f95e889b64a611a",
- "third_party/externals/tint" : "https://dawn.googlesource.com/tint@6a56744b557caf555713af4afff5061746a526f2",
+ "third_party/externals/tint" : "https://dawn.googlesource.com/tint@9fdfa1e32374f8d862c98ad241757853386f66e6",
"third_party/externals/dng_sdk" : "https://android.googlesource.com/platform/external/dng_sdk.git@c8d0c9b1d16bfda56f15165d39e0ffa360a11123",
"third_party/externals/egl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@a0bca08de07c7d7651047bedc0b653cfaaa4f2ae",
"third_party/externals/expat" : "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git@e976867fb57a0cd87e3b0fe05d59e0ed63c6febb",
@@ -43,13 +43,13 @@ deps = {
"third_party/externals/spirv-cross" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@bdbef7b1f3982fe99a62d076043036abe6dd6d80",
"third_party/externals/spirv-headers" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@bcf55210f13a4fa3c3d0963b509ff1070e434c79",
"third_party/externals/spirv-tools" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@5d8c40399e1a483c168246215e4637e19551cd4f",
- "third_party/externals/swiftshader" : "https://swiftshader.googlesource.com/SwiftShader@e260190edbd2984a045ac5990b3d31429d45d27f",
+ "third_party/externals/swiftshader" : "https://swiftshader.googlesource.com/SwiftShader@dcb33711bd4bd14a9bff84db379ad59295c337a3",
#"third_party/externals/v8" : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4",
"third_party/externals/wuffs" : "https://skia.googlesource.com/external/github.com/google/wuffs.git@f49c38202914c289621f547ff016e5f02c994dda",
"third_party/externals/zlib" : "https://chromium.googlesource.com/chromium/src/third_party/zlib@c876c8f87101c5a75f6014b0f832499afeb65b73",
"../src": {
- "url": "https://chromium.googlesource.com/chromium/src.git@ed46c1e47728e5354ed01f9dcdb47f3e00d5980a",
+ "url": "https://chromium.googlesource.com/chromium/src.git@5d4a69b076e10cec343b89b90acc0af4a88850a7",
"condition": "checkout_chromium",
},
diff --git a/METADATA b/METADATA
index f7ff919359..07b6c19fd6 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://skia.googlesource.com/skia"
}
- version: "bdadfc16dffbb144a607f8580f9b10b554c745e9"
+ version: "7c328b4b42c5c5a2761ea6811573b15280f910bc"
license_type: RECIPROCAL
last_upgrade_date {
year: 2021
month: 5
- day: 10
+ day: 11
}
}
diff --git a/build_overrides/angle.gni b/build_overrides/angle.gni
index 2b38040ba7..22f0153897 100644
--- a/build_overrides/angle.gni
+++ b/build_overrides/angle.gni
@@ -1,5 +1,7 @@
angle_root = "//third_party/externals/angle2"
angle_zlib_compression_utils_dir = "//third_party/zlib"
+angle_spirv_headers_dir = "//third_party/externals/spirv-headers"
+angle_spirv_tools_dir = "//third_party/externals/spirv-tools"
# We don't have Chromium's build/ or testing/ directories.
angle_has_build = false
diff --git a/demos.skia.org/demos/textedit/index.html b/demos.skia.org/demos/textedit/index.html
new file mode 100644
index 0000000000..8c1d2f0115
--- /dev/null
+++ b/demos.skia.org/demos/textedit/index.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<title>TextEdit demo in CanvasKit</title>
+<meta charset="utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<script type="text/javascript" src="https://particles.skia.org/dist/canvaskit.js"></script>
+<script type="text/javascript" src="textapi_utils.js"></script>
+
+<style>
+canvas {
+ border: 1px dashed grey;
+}
+</style>
+
+<body>
+ <h1>TextEdit in CanvasKit</h1>
+
+ <canvas id=para2 width=600 height=600 tabindex='-1'></canvas>
+</body>
+
+<script type="text/javascript" charset="utf-8">
+ let CanvasKit;
+ onload = async () => {
+ CanvasKit = await CanvasKitInit({ locateFile: (file) => 'https://particles.skia.org/dist/'+file });
+ ParagraphAPI2();
+ };
+
+ function ParagraphAPI2() {
+ const surface = CanvasKit.MakeCanvasSurface('para2');
+ if (!surface) {
+ console.error('Could not make surface');
+ return;
+ }
+
+ const mouse = MakeMouse();
+ const cursor = MakeCursor(CanvasKit);
+ const canvas = surface.getCanvas();
+
+ const text0 = "In a hole in the ground there lived a hobbit. Not a nasty, dirty, " +
+ "wet hole full of worms and oozy smells. This was a hobbit-hole and " +
+ "that means good food, a warm hearth, and all the comforts of home.";
+ const LOC_X = 20,
+ LOC_Y = 20;
+
+ const bgPaint = new CanvasKit.Paint();
+ bgPaint.setColor([0.965, 0.965, 0.965, 1]);
+
+ const editor = MakeEditor(text0, {typeface:null, size:24}, cursor, 400);
+
+ editor.applyStyleToRange({size:100}, 0, 1);
+ editor.applyStyleToRange({italic:true}, 38, 38+6);
+ editor.applyStyleToRange({color:[1,0,0,1]}, 5, 5+4);
+
+ editor.setXY(LOC_X, LOC_Y);
+
+ function drawFrame(canvas) {
+ const lines = editor.getLines();
+
+ canvas.clear(CanvasKit.WHITE);
+
+ if (mouse.isActive()) {
+ const pos = mouse.getPos(-LOC_X, -LOC_Y);
+ const a = lines_pos_to_index(lines, pos[0], pos[1]);
+ const b = lines_pos_to_index(lines, pos[2], pos[3]);
+ if (a === b) {
+ editor.setIndex(a);
+ } else {
+ editor.setIndices(a, b);
+ }
+ }
+
+ canvas.drawRect(editor.bounds(), bgPaint);
+ editor.draw(canvas);
+
+ surface.requestAnimationFrame(drawFrame);
+ }
+ surface.requestAnimationFrame(drawFrame);
+
+ function interact(e) {
+ const type = e.type;
+ if (type === 'pointerup') {
+ mouse.setUp(e.offsetX, e.offsetY);
+ } else if (type === 'pointermove') {
+ mouse.setMove(e.offsetX, e.offsetY);
+ } else if (type === 'pointerdown') {
+ mouse.setDown(e.offsetX, e.offsetY);
+ }
+ };
+
+ function keyhandler(e) {
+ switch (e.key) {
+ case 'ArrowLeft': editor.moveDX(-1); return;
+ case 'ArrowRight': editor.moveDX(1); return;
+ case 'ArrowUp':
+ e.preventDefault();
+ editor.moveDY(-1);
+ return;
+ case 'ArrowDown':
+ e.preventDefault();
+ editor.moveDY(1);
+ return;
+ case 'Backspace':
+ editor.deleteSelection(-1);
+ return;
+ case 'Delete':
+ editor.deleteSelection(1);
+ return;
+ case 'Shift':
+ return;
+ case 'Tab': // todo: figure out how to handle...
+ e.preventDefault();
+ return;
+ }
+ if (e.ctrlKey) {
+ switch (e.key) {
+ case 'r': editor.applyStyleToSelection({color:[1,0,0,1]}); return;
+ case 'g': editor.applyStyleToSelection({color:[0,0.6,0,1]}); return;
+ case 'u': editor.applyStyleToSelection({color:[0,0,1,1]}); return;
+ case 'k': editor.applyStyleToSelection({color:[0,0,0,1]}); return;
+
+ case 'i': editor.applyStyleToSelection({italic:'toggle'}); return;
+ case 'b': editor.applyStyleToSelection({bold:'toggle'}); return;
+
+ case ']': editor.applyStyleToSelection({size_add:1}); return;
+ case '[': editor.applyStyleToSelection({size_add:-1}); return;
+ }
+ }
+ if (!e.ctrlKey && !e.metaKey) {
+ e.preventDefault(); // at least needed for 'space'
+ editor.insert(e.key);
+ }
+ }
+
+ document.getElementById('para2').addEventListener('pointermove', interact);
+ document.getElementById('para2').addEventListener('pointerdown', interact);
+ document.getElementById('para2').addEventListener('pointerup', interact);
+ document.getElementById('para2').addEventListener('keydown', keyhandler);
+ return surface;
+ }
+
+</script>
diff --git a/demos.skia.org/demos/textedit/textapi_utils.js b/demos.skia.org/demos/textedit/textapi_utils.js
new file mode 100644
index 0000000000..9cf4606f20
--- /dev/null
+++ b/demos.skia.org/demos/textedit/textapi_utils.js
@@ -0,0 +1,608 @@
+
+function ASSERT(pred) {
+ console.assert(pred, 'assert failed');
+}
+
+function LOG(...args) {
+ // comment out for non-debugging
+// console.log(args);
+}
+
+function MakeCursor(CanvasKit) {
+ const linePaint = new CanvasKit.Paint();
+ linePaint.setColor([0,0,1,1]);
+ linePaint.setStyle(CanvasKit.PaintStyle.Stroke);
+ linePaint.setStrokeWidth(2);
+ linePaint.setAntiAlias(true);
+
+ const pathPaint = new CanvasKit.Paint();
+ pathPaint.setColor([0,0,1,0.25]);
+ linePaint.setAntiAlias(true);
+
+ return {
+ _line_paint: linePaint, // wrap in weak-ref so we can delete it?
+ _path_paint: pathPaint,
+ _x: 0,
+ _top: 0,
+ _bottom: 0,
+ _path: null, // only use x,top,bottom if path is null
+ _draws_per_sec: 2,
+
+ // pass 0 for no-draw, pass inf. for always on
+ setBlinkRate: function(blinks_per_sec) {
+ this._draws_per_sec = blinks_per_sec;
+ },
+ place: function(x, top, bottom) {
+ this._x = x;
+ this._top = top;
+ this._bottom = bottom;
+
+ this.setPath(null);
+ },
+ setPath: function(path) {
+ if (this._path) {
+ this._path.delete();
+ }
+ this._path = path;
+ },
+ draw_before: function(canvas) {
+ if (this._path) {
+ canvas.drawPath(this._path, this._path_paint);
+ }
+ },
+ draw_after: function(canvas) {
+ if (this._path) {
+ return;
+ }
+ if (Math.floor(Date.now() * this._draws_per_sec / 1000) & 1) {
+ canvas.drawLine(this._x, this._top, this._x, this._bottom, this._line_paint);
+ }
+ },
+ };
+}
+
+function MakeMouse() {
+ return {
+ _start_x: 0, _start_y: 0,
+ _curr_x: 0, _curr_y: 0,
+ _active: false,
+
+ isActive: function() {
+ return this._active;
+ },
+ setDown: function(x, y) {
+ this._start_x = this._curr_x = x;
+ this._start_y = this._curr_y = y;
+ this._active = true;
+ },
+ setMove: function(x, y) {
+ this._curr_x = x;
+ this._curr_y = y;
+ },
+ setUp: function(x, y) {
+ this._curr_x = x;
+ this._curr_y = y;
+ this._active = false;
+ },
+ getPos: function(dx, dy) {
+ return [ this._start_x + dx, this._start_y + dy, this._curr_x + dx, this._curr_y + dy ];
+ },
+ };
+}
+
+function runs_x_to_index(runs, x) {
+ for (const r of runs) {
+ for (let i = 1; i < r.offsets.length; i += 1) {
+ if (x < r.positions[i*2]) {
+ const mid = (r.positions[i*2-2] + r.positions[i*2]) * 0.5;
+ if (x <= mid) {
+ return r.offsets[i-1];
+ } else {
+ return r.offsets[i];
+ }
+ }
+ }
+ }
+ const r = runs[runs.length-1];
+ return r.offsets[r.offsets.length-1];
+}
+
+function lines_pos_to_index(lines, x, y) {
+ if (y < lines[0].top) {
+ return 0;
+ }
+ const l = lines.find((l) => y <= l.bottom);
+ return l ? runs_x_to_index(l.runs, x)
+ : lines[lines.length - 1].textRange.last;
+}
+
+function runs_index_to_run(runs, index) {
+ const r = runs.find((r) => index <= r.offsets[r.offsets.length-1]);
+ // return last if no run is found
+ return r ? r : runs[runs.length-1];
+}
+
+function runs_index_to_x(runs, index) {
+ const r = runs_index_to_run(runs, index);
+ const i = r.offsets.findIndex((offset) => index === offset);
+ return i >= 0 ? r.positions[i*2]
+ : r.positions[r.positions.length-2]; // last x
+}
+
+function lines_index_to_line_index(lines, index) {
+ const l = lines.findIndex((l) => index <= l.textRange.last);
+ return l >= 0 ? l : lines.length-1;
+}
+
+function lines_index_to_line(lines, index) {
+ return lines[lines_index_to_line_index(lines, index)];
+}
+
+function lines_indices_to_path(lines, a, b, width) {
+ if (a == b) {
+ return null;
+ }
+ if (a > b) { [a, b] = [b, a]; }
+
+ const path = new CanvasKit.Path();
+ const la = lines_index_to_line(lines, a);
+ const lb = lines_index_to_line(lines, b);
+ const ax = runs_index_to_x(la.runs, a);
+ const bx = runs_index_to_x(lb.runs, b);
+ if (la == lb) {
+ path.addRect([ax, la.top, bx, la.bottom]);
+ } else {
+ path.addRect([ax, la.top, width, la.bottom]);
+ path.addRect([0, lb.top, bx, lb.bottom]);
+ if (la.bottom < lb.top) {
+ path.addRect([0, la.bottom, width, lb.top]); // extra lines inbetween
+ }
+ }
+ return path;
+}
+
+function string_del(str, start, end) {
+ return str.slice(0, start) + str.slice(end, str.length);
+}
+
+function make_default_paint() {
+ const p = new CanvasKit.Paint();
+ p.setAntiAlias(true);
+ return p;
+}
+
+function make_default_font(tf) {
+ const font = new CanvasKit.Font(tf);
+ font.setSubpixel(true);
+ return font;
+}
+
+function MakeStyle(length) {
+ return {
+ _length: length,
+ typeface: null,
+ size: null,
+ color: null,
+ bold: null,
+ italic: null,
+
+ _check_toggle: function(src, dst) {
+ if (src == 'toggle') {
+ return !dst;
+ } else {
+ return src;
+ }
+ },
+
+ // returns true if we changed something affecting layout
+ mergeFrom: function(src) {
+ let layoutChanged = false;
+
+ if (src.typeface && this.typeface !== src.typeface) {
+ this.typeface = src.typeface;
+ layoutChanged = true;
+ }
+ if (src.size && this.size !== src.size) {
+ this.size = src.size;
+ layoutChanged = true;
+ }
+ if (src.color) { this.color = src.color; }
+
+ if (src.bold) {
+ this.bold = this._check_toggle(src.bold, this.bold);
+ }
+ if (src.italic) {
+ this.italic = this._check_toggle(src.italic, this.italic);
+ }
+
+ if (src.size_add) {
+ this.size += src.size_add;
+ layoutChanged = true;
+ }
+
+ return layoutChanged;
+ }
+ };
+}
+
+function MakeEditor(text, style, cursor, width) {
+ const ed = {
+ _text: text,
+ _lines: null,
+ _cursor: cursor,
+ _width: width,
+ _index: { start: 0, end: 0 },
+ _styles: null,
+ // drawing
+ _X: 0,
+ _Y: 0,
+ _paint: make_default_paint(),
+ _font: make_default_font(style.typeface),
+
+ getLines: function() { return this._lines; },
+
+ width: function() {
+ return this._width;
+ },
+ height: function() {
+ return this._lines[this._lines.length-1].bottom;
+ },
+ bounds: function() {
+ return [this._X, this._Y, this._X + this.width(), this._Y + this.height()];
+ },
+ setXY: function(x, y) {
+ this._X = x;
+ this._Y = y;
+ },
+
+ _rebuild_selection: function() {
+ const a = this._index.start;
+ const b = this._index.end;
+ ASSERT(a >= 0 && a <= b && b <= this._text.length);
+ if (a === b) {
+ const l = lines_index_to_line(this._lines, a);
+ const x = runs_index_to_x(l.runs, a);
+ this._cursor.place(x, l.top, l.bottom);
+ } else {
+ this._cursor.setPath(lines_indices_to_path(this._lines, a, b, this._width));
+ }
+ },
+ setIndex: function(i) {
+ this._index.start = this._index.end = i;
+ this._rebuild_selection();
+ },
+ setIndices: function(a, b) {
+ if (a > b) { [a, b] = [b, a]; }
+ this._index.start = a;
+ this._index.end = b;
+ this._rebuild_selection();
+ },
+ moveDX: function(dx) {
+ let index;
+ if (this._index.start == this._index.end) {
+ // just adjust and pin
+ index = Math.max(Math.min(this._index.start + dx, this._text.length), 0);
+ } else {
+ // 'deselect' the region, and turn it into just a single index
+ index = dx < 0 ? this._index.start : this._index.end;
+ }
+ this.setIndex(index);
+ },
+ moveDY: function(dy) {
+ let index = (dy < 0) ? this._index.start : this._index.end;
+ const i = lines_index_to_line_index(this._lines, index);
+ if (dy < 0 && i === 0) {
+ index = 0;
+ } else if (dy > 0 && i == this._lines.length - 1) {
+ index = this._text.length;
+ } else {
+ const x = runs_index_to_x(this._lines[i].runs, index);
+ // todo: statefully track "original" x when an up/down sequence started,
+ // so we can avoid drift.
+ index = runs_x_to_index(this._lines[i+dy].runs, x);
+ }
+ this.setIndex(index);
+ },
+
+ _validateStyles: function() {
+ const len = this._styles.reduce((sum, style) => sum + style._length, 0);
+ ASSERT(len === this._text.length);
+ },
+ _validateBlocks: function(blocks) {
+ const len = blocks.reduce((sum, block) => sum + block.length, 0);
+ ASSERT(len === this._text.length);
+ },
+
+ _buildLines: function() {
+ this._validateStyles();
+
+ const blocks = [];
+ let block = null;
+ for (const s of this._styles) {
+ if (!block || (block.typeface === s.typeface && block.size === s.size)) {
+ if (!block) {
+ block = { length: 0, typeface: s.typeface, size: s.size };
+ }
+ block.length += s._length;
+ } else {
+ blocks.push(block);
+ block = { length: s._length, typeface: s.typeface, size: s.size };
+ }
+ }
+ blocks.push(block);
+ this._validateBlocks(blocks);
+
+ this._lines = CanvasKit.ParagraphBuilder.ShapeText(this._text, blocks, this._width);
+ this._rebuild_selection();
+
+ // add textRange to each run, to aid in drawing
+ this._runs = [];
+ for (const l of this._lines) {
+ for (const r of l.runs) {
+ r.textRange = { start: r.offsets[0], end: r.offsets[r.offsets.length-1] };
+ this._runs.push(r);
+ }
+ }
+ },
+
+ // note: this does not rebuild lines/runs, or update the cursor,
+ // but it does edit the text and styles
+ // returns true if it deleted anything
+ _deleteRange: function(start, end) {
+ ASSERT(start >= 0 && end <= this._text.length);
+ ASSERT(start <= end);
+ if (start === end) {
+ return false;
+ }
+
+ this._delete_style_range(start, end);
+ // Do this after shrink styles (we use text.length in an assert)
+ this._text = string_del(this._text, start, end);
+ },
+ deleteSelection: function(direction) {
+ let start = this._index.start;
+ if (start == this._index.end) {
+ if (direction < 0) {
+ if (start == 0) {
+ return; // nothing to do
+ }
+ this._deleteRange(start - 1, start);
+ start -= 1;
+ } else {
+ if (start >= this._text.length) {
+ return; // nothing to do
+ }
+ this._deleteRange(start, start + 1);
+ }
+ } else {
+ this._deleteRange(start, this._index.end);
+ }
+ this._index.start = this._index.end = start;
+ this._buildLines();
+ },
+ insert: function(charcode) {
+ if (this._index.start != this._index.end) {
+ this.deleteSelection();
+ }
+ const index = this._index.start;
+
+ // do this before edit the text (we use text.length in an assert)
+ const [i, prev_len] = this.find_style_index_and_prev_length(index);
+ this._styles[i]._length += 1;
+
+ // now grow the text
+ this._text = this._text.slice(0, index) + charcode + this._text.slice(index);
+
+ this._index.start = this._index.end = index + 1;
+ this._buildLines();
+ },
+
+ draw: function(canvas) {
+ canvas.save();
+ canvas.translate(this._X, this._Y);
+
+ this._cursor.draw_before(canvas);
+
+ const runs = this._runs;
+ const styles = this._styles;
+ const f = this._font;
+ const p = this._paint;
+
+ let s = styles[0];
+ let sindex = 0;
+ let s_start = 0;
+ let s_end = s._length;
+
+ let r = runs[0];
+ let rindex = 0;
+
+ let start = 0;
+ let end = 0;
+ while (start < this._text.length) {
+ while (r.textRange.end <= start) {
+ r = runs[++rindex];
+ if (!r) {
+ // ran out of runs, so the remaining text must just be WS
+ break;
+ }
+ }
+ if (!r) break;
+ while (s_end <= start) {
+ s = styles[++sindex];
+ s_start = s_end;
+ s_end += s._length;
+ }
+ end = Math.min(r.textRange.end, s_end);
+
+ LOG('New range: ', start, end,
+ 'from run', r.textRange.start, r.textRange.end,
+ 'style', s_start, s_end);
+
+ // check that we have anything to draw
+ if (r.textRange.start >= end) {
+ start = end;
+ continue; // could be a span of WS with no glyphs
+ }
+
+// f.setTypeface(r.typeface); // r.typeface is always null (for now)
+ f.setSize(r.size);
+ f.setEmbolden(s.bold);
+ f.setSkewX(s.italic ? -0.2 : 0);
+ p.setColor(s.color ? s.color : [0,0,0,1]);
+
+ let gly = r.glyphs;
+ let pos = r.positions;
+ if (start > r.textRange.start || end < r.textRange.end) {
+ // search for the subset of glyphs to draw
+ let glyph_start, glyph_end;
+ for (let i = 0; i < r.offsets.length; ++i) {
+ if (r.offsets[i] >= start) {
+ glyph_start = i;
+ break;
+ }
+ }
+ for (let i = glyph_start+1; i < r.offsets.length; ++i) {
+ if (r.offsets[i] >= end) {
+ glyph_end = i;
+ break;
+ }
+ }
+ LOG(' glyph subrange', glyph_start, glyph_end);
+ gly = gly.slice(glyph_start, glyph_end);
+ pos = pos.slice(glyph_start*2, glyph_end*2);
+ } else {
+ LOG(' use entire glyph run');
+ }
+ canvas.drawGlyphs(gly, pos, 0, 0, f, p);
+
+ start = end;
+ }
+
+ this._cursor.draw_after(canvas);
+ canvas.restore();
+ },
+
+ // Styling
+
+ // returns [index, prev total length before this style]
+ find_style_index_and_prev_length: function(index) {
+ let len = 0;
+ for (let i = 0; i < this._styles.length; ++i) {
+ const l = this._styles[i]._length;
+ len += l;
+ // < favors the latter style if index is between two styles
+ if (index < len) {
+ return [i, len - l];
+ }
+ }
+ ASSERT(len === this._text.length);
+ return [this._styles.length-1, len];
+ },
+ _delete_style_range: function(start, end) {
+ // shrink/remove styles
+ //
+ // [.....][....][....][.....] styles
+ // [..................] start...end
+ //
+ // - trim the first style
+ // - remove the middle styles
+ // - trim the last style
+
+ let N = end - start;
+ let [i, prev_len] = this.find_style_index_and_prev_length(start);
+ let s = this._styles[i];
+ if (start > prev_len) {
+ // we overlap the first style (but not entirely
+ const skip = start - prev_len;
+ ASSERT(skip < s._length);
+ const shrink = Math.min(N, s._length - skip);
+ ASSERT(shrink > 0);
+ s._length -= shrink;
+ N -= shrink;
+ if (N === 0) {
+ return;
+ }
+ i += 1;
+ ASSERT(i < this._styles.length);
+ }
+ while (N > 0) {
+ s = this._styles[i];
+ if (N >= s._length) {
+ N -= s._length;
+ this._styles.splice(i, 1);
+ } else {
+ s._length -= N;
+ break;
+ }
+ }
+ },
+
+ applyStyleToRange: function(style, start, end) {
+ if (start > end) { [start, end] = [end, start]; }
+ ASSERT(start >= 0 && end <= this._text.length);
+ if (start === end) {
+ return;
+ }
+
+ LOG('trying to apply', style, start, end);
+ let i;
+ for (i = 0; i < this._styles.length; ++i) {
+ if (start <= this._styles[i]._length) {
+ break;
+ }
+ start -= this._styles[i]._length;
+ end -= this._styles[i]._length;
+ }
+
+ let s = this._styles[i];
+ // do we need to fission off a clean subset for the head of s?
+ if (start > 0) {
+ const ns = Object.assign({}, s);
+ s._length = start;
+ ns._length -= start;
+ LOG('initial splice', i, start, s._length, ns._length);
+ i += 1;
+ this._styles.splice(i, 0, ns);
+ end -= start;
+ // we don't use start any more
+ }
+ // merge into any/all whole styles we overlap
+ let layoutChanged = false;
+ while (end >= this._styles[i]._length) {
+ LOG('whole run merging for style index', i)
+ layoutChanged |= this._styles[i].mergeFrom(style);
+ end -= this._styles[i]._length;
+ i += 1;
+ if (end == 0) {
+ break;
+ }
+ }
+ // do we partially cover the last run
+ if (end > 0) {
+ s = this._styles[i];
+ const ns = Object.assign({}, s); // the new first half
+ ns._length = end;
+ s._length -= end; // trim the (unchanged) tail
+ LOG('merging tail', i, ns._length, s._length);
+ layoutChanged |= ns.mergeFrom(style);
+ this._styles.splice(i, 0, ns);
+ }
+
+ this._validateStyles();
+ LOG('after applying styles', this._styles);
+
+ if (layoutChanged) {
+ this._buildLines();
+ }
+ },
+ applyStyleToSelection: function(style) {
+ this.applyStyleToRange(style, this._index.start, this._index.end);
+ },
+ };
+
+ const s = MakeStyle(ed._text.length);
+ s.mergeFrom(style);
+ ed._styles = [ s ];
+ ed._buildLines();
+ return ed;
+}
diff --git a/fuzz/FuzzTriangulation.cpp b/fuzz/FuzzTriangulation.cpp
index d9a54d6bb3..4a18a93833 100644
--- a/fuzz/FuzzTriangulation.cpp
+++ b/fuzz/FuzzTriangulation.cpp
@@ -29,4 +29,5 @@ DEF_FUZZ(Triangulation, fuzz) {
bool isLinear;
GrTriangulator::PathToTriangles(path, tol, clipBounds, &allocator, &isLinear);
+ allocator.detachVertexData(); // normally handled by the triangulating path renderer.
}
diff --git a/gm/tessellation.cpp b/gm/tessellation.cpp
index 84bf7c1049..1fa252a481 100644
--- a/gm/tessellation.cpp
+++ b/gm/tessellation.cpp
@@ -72,44 +72,17 @@ private:
args.fVertBuilder->declareGlobal(
GrShaderVar("P_", kFloat3_GrSLType, GrShaderVar::TypeModifier::Out));
args.fVertBuilder->codeAppendf(R"(
- P_.xy = (%s * float3(position.xy, 1)).xy;
- P_.z = position.z;)", viewMatrix);
+ P_.xy = (%s * float3(position.xy, 1)).xy;
+ P_.z = position.z;)", viewMatrix);
// GrGLProgramBuilder will call writeTess*ShaderGLSL when it is compiling.
this->writeFragmentShader(args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
}
- void writeFragmentShader(GrGLSLFPFragmentBuilder*, const char* color, const char* coverage);
- void setData(const GrGLSLProgramDataManager& pdman,
- const GrShaderCaps&,
- const GrGeometryProcessor& geomProc) override {
- pdman.setSkMatrix(fViewMatrixUniform,
- geomProc.cast<TessellationTestTriShader>().fViewMatrix);
- }
- GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
- };
-
- GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override {
- return new Impl;
- }
-
- SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
- SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
-
- const SkMatrix fViewMatrix;
-};
-
-SkString TessellationTestTriShader::getTessControlShaderGLSL(
- const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const {
- SkString code(versionAndExtensionDecls);
- code.append(R"(
+ SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override {
+ SkString code(versionAndExtensionDecls);
+ code.append(R"(
layout(vertices = 3) out;
in vec3 P_[];
@@ -121,16 +94,14 @@ SkString TessellationTestTriShader::getTessControlShaderGLSL(
gl_TessLevelInner[0] = 2.0;
})");
- return code;
-}
-
-SkString TessellationTestTriShader::getTessEvaluationShaderGLSL(
- const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const {
- SkString code(versionAndExtensionDecls);
- code.append(R"(
+ return code;
+ }
+ SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override {
+ SkString code(versionAndExtensionDecls);
+ code.append(R"(
layout(triangles, equal_spacing, cw) in;
uniform vec4 sk_RTAdjust;
@@ -164,19 +135,33 @@ SkString TessellationTestTriShader::getTessEvaluationShaderGLSL(
barycentric_coord = vec3(i, 0, 1.0 - i);
})");
- return code;
-}
-
-void TessellationTestTriShader::Impl::writeFragmentShader(
- GrGLSLFPFragmentBuilder* f, const char* color, const char* coverage) {
- f->declareGlobal(
- GrShaderVar("barycentric_coord", kFloat3_GrSLType, GrShaderVar::TypeModifier::In));
- f->codeAppendf(R"(
+ return code;
+ }
+ void writeFragmentShader(GrGLSLFPFragmentBuilder* f, const char* color,
+ const char* coverage) {
+ f->declareGlobal(GrShaderVar("barycentric_coord", kFloat3_GrSLType,
+ GrShaderVar::TypeModifier::In));
+ f->codeAppendf(R"(
half3 d = half3(1 - barycentric_coord/fwidth(barycentric_coord));
half coverage = max(max(d.x, d.y), d.z);
half4 %s = half4(0, coverage, coverage, 1);
const half4 %s = half4(1);)", color, coverage);
-}
+ }
+ void setData(const GrGLSLProgramDataManager& pdman,
+ const GrShaderCaps&,
+ const GrGeometryProcessor& geomProc) override {
+ pdman.setSkMatrix(fViewMatrixUniform,
+ geomProc.cast<TessellationTestTriShader>().fViewMatrix);
+ }
+ GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
+ };
+
+ GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override {
+ return new Impl;
+ }
+
+ const SkMatrix fViewMatrix;
+};
class TessellationTestRectShader : public GrGeometryProcessor {
public:
@@ -200,39 +185,12 @@ private:
// GrGLProgramBuilder will call writeTess*ShaderGLSL when it is compiling.
this->writeFragmentShader(args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
}
- void writeFragmentShader(GrGLSLFPFragmentBuilder*, const char* color, const char* coverage);
- void setData(const GrGLSLProgramDataManager& pdman,
- const GrShaderCaps&,
- const GrGeometryProcessor& geomProc) override {
- pdman.setSkMatrix(fViewMatrixUniform,
- geomProc.cast<TessellationTestRectShader>().fViewMatrix);
- }
- GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
- };
-
- GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override {
- return new Impl;
- }
-
- SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
- SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
-
- const SkMatrix fViewMatrix;
-};
-
-SkString TessellationTestRectShader::getTessControlShaderGLSL(
- const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps& caps) const {
- SkString code(versionAndExtensionDecls);
- code.append(R"(
+ SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override {
+ SkString code(versionAndExtensionDecls);
+ code.append(R"(
layout(vertices = 1) out;
in mat3 M_[];
@@ -248,16 +206,14 @@ SkString TessellationTestRectShader::getTessControlShaderGLSL(
gl_TessLevelOuter[3] = 8.0;
})");
- return code;
-}
-
-SkString TessellationTestRectShader::getTessEvaluationShaderGLSL(
- const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps& caps) const {
- SkString code(versionAndExtensionDecls);
- code.appendf(R"(
+ return code;
+ }
+ SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override {
+ SkString code(versionAndExtensionDecls);
+ code.appendf(R"(
layout(quads, equal_spacing, cw) in;
uniform vec4 sk_RTAdjust;
@@ -281,14 +237,13 @@ SkString TessellationTestRectShader::getTessEvaluationShaderGLSL(
}
})", kRect.left(), kRect.top(), kRect.right(), kRect.bottom());
- return code;
-}
-
-void TessellationTestRectShader::Impl::writeFragmentShader(
- GrGLSLFPFragmentBuilder* f, const char* color, const char* coverage) {
- f->declareGlobal(GrShaderVar("barycentric_coord", kFloat4_GrSLType,
- GrShaderVar::TypeModifier::In));
- f->codeAppendf(R"(
+ return code;
+ }
+ void writeFragmentShader(GrGLSLFPFragmentBuilder* f, const char* color,
+ const char* coverage) {
+ f->declareGlobal(GrShaderVar("barycentric_coord", kFloat4_GrSLType,
+ GrShaderVar::TypeModifier::In));
+ f->codeAppendf(R"(
float4 fwidths = fwidth(barycentric_coord);
half coverage = 0;
for (int i = 0; i < 4; ++i) {
@@ -298,8 +253,23 @@ void TessellationTestRectShader::Impl::writeFragmentShader(
}
half4 %s = half4(coverage, 0, coverage, 1);
const half4 %s = half4(1);)", color, coverage);
-}
+ }
+ void setData(const GrGLSLProgramDataManager& pdman,
+ const GrShaderCaps&,
+ const GrGeometryProcessor& geomProc) override {
+ pdman.setSkMatrix(fViewMatrixUniform,
+ geomProc.cast<TessellationTestRectShader>().fViewMatrix);
+ }
+ GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
+ };
+
+ GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override {
+ return new Impl;
+ }
+
+ const SkMatrix fViewMatrix;
+};
class TessellationTestOp : public GrDrawOp {
DEFINE_OP_CLASS_ID
diff --git a/include/private/SkSLLayout.h b/include/private/SkSLLayout.h
index 6de5e6a55e..8886b3c8b9 100644
--- a/include/private/SkSLLayout.h
+++ b/include/private/SkSLLayout.h
@@ -21,26 +21,25 @@ struct Layout {
enum Flag {
kOriginUpperLeft_Flag = 1 << 0,
kOverrideCoverage_Flag = 1 << 1,
- kEarlyFragmentTests_Flag = 1 << 2,
- kPushConstant_Flag = 1 << 3,
- kBlendSupportAllEquations_Flag = 1 << 4,
- kTracked_Flag = 1 << 5,
- kSRGBUnpremul_Flag = 1 << 6,
- kKey_Flag = 1 << 7,
+ kPushConstant_Flag = 1 << 2,
+ kBlendSupportAllEquations_Flag = 1 << 3,
+ kTracked_Flag = 1 << 4,
+ kSRGBUnpremul_Flag = 1 << 5,
+ kKey_Flag = 1 << 6,
// These flags indicate if the qualifier appeared, regardless of the accompanying value.
- kLocation_Flag = 1 << 8,
- kOffset_Flag = 1 << 9,
- kBinding_Flag = 1 << 10,
- kIndex_Flag = 1 << 11,
- kSet_Flag = 1 << 12,
- kBuiltin_Flag = 1 << 13,
- kInputAttachmentIndex_Flag = 1 << 14,
- kPrimitive_Flag = 1 << 15,
- kMaxVertices_Flag = 1 << 16,
- kInvocations_Flag = 1 << 17,
- kWhen_Flag = 1 << 18,
- kCType_Flag = 1 << 19,
+ kLocation_Flag = 1 << 7,
+ kOffset_Flag = 1 << 8,
+ kBinding_Flag = 1 << 9,
+ kIndex_Flag = 1 << 10,
+ kSet_Flag = 1 << 11,
+ kBuiltin_Flag = 1 << 12,
+ kInputAttachmentIndex_Flag = 1 << 13,
+ kPrimitive_Flag = 1 << 14,
+ kMaxVertices_Flag = 1 << 15,
+ kInvocations_Flag = 1 << 16,
+ kWhen_Flag = 1 << 17,
+ kCType_Flag = 1 << 18,
};
enum Primitive {
@@ -184,9 +183,6 @@ struct Layout {
if (fFlags & kOverrideCoverage_Flag) {
result += separator() + "override_coverage";
}
- if (fFlags & kEarlyFragmentTests_Flag) {
- result += separator() + "early_fragment_tests";
- }
if (fFlags & kBlendSupportAllEquations_Flag) {
result += separator() + "blend_support_all_equations";
}
diff --git a/include/private/SkTHash.h b/include/private/SkTHash.h
index 7997300fa8..79851b83fe 100644
--- a/include/private/SkTHash.h
+++ b/include/private/SkTHash.h
@@ -235,6 +235,7 @@ private:
T* uncheckedSet(T&& val) {
const K& key = Traits::GetKey(val);
+ SkASSERT(key == key);
uint32_t hash = Hash(key);
int index = hash & (fCapacity-1);
for (int n = 0; n < fCapacity; n++) {
diff --git a/include/private/SkTLogic.h b/include/private/SkTLogic.h
index ecd40a13d3..a2c2f4cfdb 100644
--- a/include/private/SkTLogic.h
+++ b/include/private/SkTLogic.h
@@ -15,6 +15,7 @@
#include <cstddef>
#include <type_traits>
#include <utility>
+#include "include/private/SkTo.h"
namespace skstd {
@@ -79,4 +80,7 @@ template <typename D, typename S> using same_cv_t = typename same_cv<D, S>::type
} // namespace sknonstd
+template <typename Container>
+constexpr int SkCount(const Container& c) { return SkTo<int>(skstd::size(c)); }
+
#endif
diff --git a/modules/androidkit/src/Matrix.cpp b/modules/androidkit/src/Matrix.cpp
index 60972432d5..d0d033ca1a 100644
--- a/modules/androidkit/src/Matrix.cpp
+++ b/modules/androidkit/src/Matrix.cpp
@@ -21,6 +21,18 @@ static jlong Matrix_Create(JNIEnv* env, jobject, jfloat m0, jfloat m4, jfloat m8
m3, m7, m11, m15));
}
+static jlong Matrix_CreateLookAt(JNIEnv* env, jobject, float eyeX, float eyeY, float eyeZ,
+ float coaX, float coaY, float coaZ,
+ float upX, float upY, float upZ) {
+ return reinterpret_cast<jlong>(new SkM44(SkM44::LookAt({eyeX, eyeY, eyeZ},
+ {coaX, coaY, coaZ},
+ {upX, upY, upZ})));
+}
+
+static jlong Matrix_CreatePerspective(JNIEnv* env, jobject, float near, float far, float angle) {
+ return reinterpret_cast<jlong>(new SkM44(SkM44::Perspective(near, far, angle)));
+}
+
static void Matrix_Release(JNIEnv* env, jobject, jlong native_matrix) {
delete reinterpret_cast<SkM44*>(native_matrix);
}
@@ -32,6 +44,19 @@ static void Matrix_PreConcat(JNIEnv* env, jobject, jlong native_matrixA, jlong n
}
}
+static long Matrix_Inverse(JNIEnv* env, jobject, jlong native_matrix) {
+ if (auto* m = reinterpret_cast<SkM44*>(native_matrix)) {
+ SkM44 inverse(SkM44::kUninitialized_Constructor);
+ if (m->invert(&inverse)) {
+ return reinterpret_cast<jlong>(new SkM44(inverse));
+ } else {
+ // matrix was not invertible, return 0 to Java and handle exception there
+ return 0;
+ }
+ }
+ return 0;
+}
+
static long Matrix_Concat(JNIEnv* env, jobject, jlong native_matrixA, jlong native_matrixB) {
if (auto* mA = reinterpret_cast<SkM44*>(native_matrixA),
* mB = reinterpret_cast<SkM44*>(native_matrixB); mA && mB) {
@@ -63,13 +88,16 @@ static void Matrix_Rotate(JNIEnv* env, jobject, jlong native_matrix, jfloat x, j
int register_androidkit_Matrix(JNIEnv* env) {
static const JNINativeMethod methods[] = {
- {"nCreate" , "(FFFFFFFFFFFFFFFF)J" , reinterpret_cast<void*>(Matrix_Create)},
- {"nRelease" , "(J)V" , reinterpret_cast<void*>(Matrix_Release)},
- {"nPreConcat" , "(JJ)V" , reinterpret_cast<void*>(Matrix_PreConcat)},
- {"nConcat" , "(JJ)J" , reinterpret_cast<void*>(Matrix_Concat)},
- {"nTranslate" , "(JFFF)V" , reinterpret_cast<void*>(Matrix_Translate)},
- {"nScale" , "(JFFF)V" , reinterpret_cast<void*>(Matrix_Scale)},
- {"nRotate" , "(JFFFF)V" , reinterpret_cast<void*>(Matrix_Rotate)},
+ {"nCreate" , "(FFFFFFFFFFFFFFFF)J" , reinterpret_cast<void*>(Matrix_Create)},
+ {"nCreateLookAt" , "(FFFFFFFFF)J" , reinterpret_cast<void*>(Matrix_CreateLookAt)},
+ {"nCreatePerspective" , "(FFF)J" , reinterpret_cast<void*>(Matrix_CreatePerspective)},
+ {"nRelease" , "(J)V" , reinterpret_cast<void*>(Matrix_Release)},
+ {"nInverse" , "(J)J" , reinterpret_cast<void*>(Matrix_Inverse)},
+ {"nPreConcat" , "(JJ)V" , reinterpret_cast<void*>(Matrix_PreConcat)},
+ {"nConcat" , "(JJ)J" , reinterpret_cast<void*>(Matrix_Concat)},
+ {"nTranslate" , "(JFFF)V" , reinterpret_cast<void*>(Matrix_Translate)},
+ {"nScale" , "(JFFF)V" , reinterpret_cast<void*>(Matrix_Scale)},
+ {"nRotate" , "(JFFFF)V" , reinterpret_cast<void*>(Matrix_Rotate)},
};
const auto clazz = env->FindClass("org/skia/androidkit/Matrix");
diff --git a/modules/androidkit/src/Paint.cpp b/modules/androidkit/src/Paint.cpp
index a3db3d23b0..aa946d5c6c 100644
--- a/modules/androidkit/src/Paint.cpp
+++ b/modules/androidkit/src/Paint.cpp
@@ -27,6 +27,18 @@ static void Paint_SetColor(JNIEnv* env, jobject, jlong native_paint,
}
}
+static void Paint_SetStroke(JNIEnv* env, jobject, jlong native_paint, jboolean stroke) {
+ if (auto* paint = reinterpret_cast<SkPaint*>(native_paint)) {
+ paint->setStroke(stroke);
+ }
+}
+
+static void Paint_SetStrokeWidth(JNIEnv* env, jobject, jlong native_paint, jfloat width) {
+ if (auto* paint = reinterpret_cast<SkPaint*>(native_paint)) {
+ paint->setStrokeWidth(width);
+ }
+}
+
static void Paint_SetShader(JNIEnv* env, jobject, jlong native_paint, jlong native_shader) {
if (auto* paint = reinterpret_cast<SkPaint*>(native_paint)) {
paint->setShader(sk_ref_sp(reinterpret_cast<SkShader*>(native_shader)));
@@ -37,10 +49,12 @@ static void Paint_SetShader(JNIEnv* env, jobject, jlong native_paint, jlong nati
int register_androidkit_Paint(JNIEnv* env) {
static const JNINativeMethod methods[] = {
- {"nCreate" , "()J" , reinterpret_cast<void*>(Paint_Create)},
- {"nRelease" , "(J)V" , reinterpret_cast<void*>(Paint_Release)},
- {"nSetColor" , "(JFFFF)V", reinterpret_cast<void*>(Paint_SetColor)},
- {"nSetShader", "(JJ)V" , reinterpret_cast<void*>(Paint_SetShader)},
+ {"nCreate" , "()J" , reinterpret_cast<void*>(Paint_Create)},
+ {"nRelease" , "(J)V" , reinterpret_cast<void*>(Paint_Release)},
+ {"nSetColor" , "(JFFFF)V", reinterpret_cast<void*>(Paint_SetColor)},
+ {"nSetStroke" , "(JZ)V" , reinterpret_cast<void*>(Paint_SetStroke)},
+ {"nSetStrokeWidth" , "(JF)V" , reinterpret_cast<void*>(Paint_SetStrokeWidth)},
+ {"nSetShader" , "(JJ)V" , reinterpret_cast<void*>(Paint_SetShader)},
};
const auto clazz = env->FindClass("org/skia/androidkit/Paint");
diff --git a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java
index cc8bd07646..84bbb2fdc9 100644
--- a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java
+++ b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Matrix.java
@@ -40,12 +40,33 @@ public class Matrix {
mNativeInstance = nativeInstance;
}
+ public static Matrix makeLookAt(float eyeX, float eyeY, float eyeZ,
+ float coaX, float coaY, float coaZ,
+ float upX, float upY, float upZ) {
+ return new Matrix(nCreateLookAt(eyeX, eyeY, eyeZ,
+ coaX, coaY, coaZ,
+ upX, upY, upZ));
+ }
+
+ public static Matrix makePerspective(float near, float far, float angle) {
+ return new Matrix(nCreatePerspective(near, far, angle));
+ }
+
+ public static Matrix makeInverse(Matrix m) throws RuntimeException {
+ long nativeMatrix = nInverse(m.getNativeInstance());
+ if (nativeMatrix == 0){
+ // extend generic exception?
+ throw new RuntimeException("Matrix m was not an invertible Matrix");
+ }
+ return new Matrix(nativeMatrix);
+ }
+
/*
* A: this Matrix
* B: Matrix passed in
* Concat A * B, return new Matrix C as result
*/
- public static Matrix Concat(Matrix a, Matrix b) {
+ public static Matrix makeConcat(Matrix a, Matrix b) {
long nativeA = a.mNativeInstance;
long nativeB = b.mNativeInstance;
long nativeC = nConcat(nativeA, nativeB);
@@ -57,10 +78,11 @@ public class Matrix {
* B: Matrix passed in
* Concat B * A, store result in Matrix A
*/
- public void preConcat(Matrix b) {
+ public Matrix preConcat(Matrix b) {
long nativeA = this.mNativeInstance;
long nativeB = b.mNativeInstance;
nPreConcat(nativeA, nativeB);
+ return this;
}
/*
@@ -133,8 +155,13 @@ public class Matrix {
float m1, float m5, float m9, float m13,
float m2, float m6, float m10, float m14,
float m3, float m7, float m11, float m15);
+ private static native long nCreateLookAt(float eyeX, float eyeY, float eyeZ,
+ float coaX, float coaY, float coaZ,
+ float upX, float upY, float upZ);
+ private static native long nCreatePerspective(float near, float far, float angle);
private static native void nRelease(long nativeInstance);
+ private static native long nInverse(long mNativeInstance);
private static native void nPreConcat(long mNativeInstanceA, long mNativeInstanceB);
private static native long nConcat(long mNativeInstanceA, long mNativeInstanceB);
private static native void nTranslate(long mNativeInstance, float x, float y, float z);
diff --git a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java
index 186e64291c..478747e0e5 100644
--- a/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java
+++ b/platform_tools/android/apps/AndroidKit/src/main/java/org/skia/androidkit/Paint.java
@@ -25,6 +25,13 @@ public class Paint {
nSetShader(mNativeInstance, shader != null ? shader.getNativeInstance() : 0);
}
+ public void setStroke(boolean stroke) {
+ nSetStroke(mNativeInstance, stroke);
+ }
+
+ public void setStrokeWidth(float w) {
+ nSetStrokeWidth(mNativeInstance, w);
+ }
/**
* Releases any resources associated with this Paint.
*/
@@ -45,5 +52,7 @@ public class Paint {
private static native void nRelease(long nativeInstance);
private static native void nSetColor(long nativeInstance, float r, float g, float b, float a);
+ private static native void nSetStroke(long nativeInstance, boolean stroke);
+ private static native void nSetStrokeWidth(long nativeInstance, float w);
private static native void nSetShader(long nativeInstance, long nativeShader);
}
diff --git a/resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp b/resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp
index 3b1be4a122..ef2889b072 100644
--- a/resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp
+++ b/resources/sksl/dslfp/GrDSLFPTest_ForStatement.fp
@@ -20,10 +20,10 @@ half4 main() {
color.g = 0;
}
-// // A for-loop with two init-variables. TODO(skia:11868): currently unsupported in DSL
-// for (half x = 0, y = 1; x <= y; ++x) {
-// color.a = x;
-// }
+ // A for-loop with two init-variables.
+ for (uint x = 0, y = 1; x <= y; ++x) {
+ color.a = half(x);
+ }
// color contains green.
return color;
diff --git a/resources/sksl/errors/LayoutRepeatedQualifiers.sksl b/resources/sksl/errors/LayoutRepeatedQualifiers.sksl
index d2454e46c2..cae4867d2d 100644
--- a/resources/sksl/errors/LayoutRepeatedQualifiers.sksl
+++ b/resources/sksl/errors/LayoutRepeatedQualifiers.sksl
@@ -1,7 +1,6 @@
layout (
origin_upper_left,
override_coverage,
- early_fragment_tests,
push_constant,
blend_support_all_equations,
tracked,
@@ -21,7 +20,6 @@ layout (
origin_upper_left,
override_coverage,
- early_fragment_tests,
push_constant,
blend_support_all_equations,
tracked,
diff --git a/resources/sksl/folding/BoolFolding.sksl b/resources/sksl/folding/BoolFolding.sksl
index 2b253d1a81..d2a3073449 100644
--- a/resources/sksl/folding/BoolFolding.sksl
+++ b/resources/sksl/folding/BoolFolding.sksl
@@ -14,12 +14,14 @@ bool test() {
const bool TRUE = true;
const bool FALSE = false;
- bool k = all(bool4(1 == 1, !false, 123 > 12, TRUE)); // all are true
- bool l = all(bool3(TRUE, 1 == 2, true)); // three out of four are true
- bool m = any(bool4(true, 1 == 2, true, TRUE)); // three out of four are true
- bool n = any(bool2(0 == 1, FALSE)); // none are true
+ bool k = all(bool4(1 == 1, !false, 123 > 12, TRUE)); // all are true
+ bool l = all(bool3(TRUE, 1 == 2, true)); // three out of four are true
+ bool m = any(bool4(true, 1 == 2, true, TRUE)); // three out of four are true
+ bool n = any(bool2(0 == 1, FALSE)); // none are true
+ bool o = any(not(bool2(0 == 1, FALSE))); // all true
+ bool p = all(not(bool4(1 == 1, !false, 123 > 12, TRUE))); // none are true
- return a && !b && c && !d && e && !f && g && !h && i && !j && k && !l && m && !n;
+ return a && !b && c && !d && e && !f && g && !h && i && !j && k && !l && m && !n && o && !p;
}
half4 main(float2 coords) {
diff --git a/resources/sksl/intrinsics/AbsFloat.sksl b/resources/sksl/intrinsics/AbsFloat.sksl
index 04df900548..48fc4fc02b 100644
--- a/resources/sksl/intrinsics/AbsFloat.sksl
+++ b/resources/sksl/intrinsics/AbsFloat.sksl
@@ -1,10 +1,15 @@
-uniform half4 testInputs;
+uniform half4 testInputs; // equals (-1.25, 0, 0.75, 2.25)
uniform half4 colorGreen, colorRed;
half4 main(float2 coords) {
+ const half4 constVal = half4(-1.25, 0, 0.75, 2.25);
half4 expected = half4(1.25, 0, 0.75, 2.25);
return (abs(testInputs.x) == expected.x &&
abs(testInputs.xy) == expected.xy &&
abs(testInputs.xyz) == expected.xyz &&
- abs(testInputs.xyzw) == expected.xyzw) ? colorGreen : colorRed;
+ abs(testInputs.xyzw) == expected.xyzw &&
+ abs(constVal.x) == expected.x &&
+ abs(constVal.xy) == expected.xy &&
+ abs(constVal.xyz) == expected.xyz &&
+ abs(constVal.xyzw) == expected.xyzw) ? colorGreen : colorRed;
}
diff --git a/resources/sksl/intrinsics/AbsInt.sksl b/resources/sksl/intrinsics/AbsInt.sksl
index 8a87d7c23e..3f0bd6887b 100644
--- a/resources/sksl/intrinsics/AbsInt.sksl
+++ b/resources/sksl/intrinsics/AbsInt.sksl
@@ -2,9 +2,14 @@ uniform half4 testInputs;
uniform half4 colorGreen, colorRed;
half4 main(float2 coords) {
+ const half4 constVal = half4(-1.25, 0, 0.75, 2.25);
int4 expected = int4(1, 0, 0, 2);
return (abs(int4(testInputs).x) == expected.x &&
abs(int4(testInputs).xy) == expected.xy &&
abs(int4(testInputs).xyz) == expected.xyz &&
- abs(int4(testInputs).xyzw) == expected.xyzw) ? colorGreen : colorRed;
+ abs(int4(testInputs).xyzw) == expected.xyzw &&
+ abs(int4(constVal).x) == expected.x &&
+ abs(int4(constVal).xy) == expected.xy &&
+ abs(int4(constVal).xyz) == expected.xyz &&
+ abs(int4(constVal).xyzw) == expected.xyzw) ? colorGreen : colorRed;
}
diff --git a/resources/sksl/intrinsics/All.sksl b/resources/sksl/intrinsics/All.sksl
index 8e42eb1bb8..c8bb4f85c8 100644
--- a/resources/sksl/intrinsics/All.sksl
+++ b/resources/sksl/intrinsics/All.sksl
@@ -1 +1,14 @@
-bool4 a; void main() { sk_FragColor.x = all(a) ? 1 : 0; }
+uniform half4 inputH4, expectedH4;
+uniform half4 colorGreen, colorRed;
+
+half4 main(float2 coords) {
+ bool4 input = bool4(inputH4);
+ bool4 expected = bool4(expectedH4);
+ const bool4 constVal = bool4(true, true, false, true);
+ return (all(input.xy) == expected.x &&
+ all(input.xyz) == expected.y &&
+ all(input.xyzw) == expected.z &&
+ all(constVal.xy) == expected.x &&
+ all(constVal.xyz) == expected.y &&
+ all(constVal.xyzw) == expected.z) ? colorGreen : colorRed;
+}
diff --git a/resources/sksl/intrinsics/Any.sksl b/resources/sksl/intrinsics/Any.sksl
index eef8e3e94e..41d6396e50 100644
--- a/resources/sksl/intrinsics/Any.sksl
+++ b/resources/sksl/intrinsics/Any.sksl
@@ -1 +1,14 @@
-bool4 a; void main() { sk_FragColor.x = any(a) ? 1 : 0; }
+uniform half4 inputH4, expectedH4;
+uniform half4 colorGreen, colorRed;
+
+half4 main(float2 coords) {
+ bool4 input = bool4(inputH4);
+ bool4 expected = bool4(expectedH4);
+ const bool4 constVal = bool4(false, false, true, false);
+ return (any(input.xy) == expected.x &&
+ any(input.xyz) == expected.y &&
+ any(input.xyzw) == expected.z &&
+ any(constVal.xy) == expected.x &&
+ any(constVal.xyz) == expected.y &&
+ any(constVal.xyzw) == expected.z) ? colorGreen : colorRed;
+}
diff --git a/resources/sksl/intrinsics/Not.sksl b/resources/sksl/intrinsics/Not.sksl
index 008f5659d0..a6ff27a81b 100644
--- a/resources/sksl/intrinsics/Not.sksl
+++ b/resources/sksl/intrinsics/Not.sksl
@@ -1 +1,14 @@
-bool4 a; void main() { sk_FragColor.x = not(a).x ? 1 : 0; }
+uniform half4 inputH4, expectedH4;
+uniform half4 colorGreen, colorRed;
+
+half4 main(float2 coords) {
+ bool4 input = bool4(inputH4);
+ bool4 expected = bool4(expectedH4);
+ const bool4 constVal = bool4(true, false, true, false);
+ return (not(input.xy) == expected.xy &&
+ not(input.xyz) == expected.xyz &&
+ not(input.xyzw) == expected.xyzw &&
+ not(constVal.xy) == expected.xy &&
+ not(constVal.xyz) == expected.xyz &&
+ not(constVal.xyzw) == expected.xyzw) ? colorGreen : colorRed;
+}
diff --git a/resources/sksl/intrinsics/SignFloat.sksl b/resources/sksl/intrinsics/SignFloat.sksl
index 2f0ef8880f..33c3d41d7a 100644
--- a/resources/sksl/intrinsics/SignFloat.sksl
+++ b/resources/sksl/intrinsics/SignFloat.sksl
@@ -1,10 +1,15 @@
-uniform half4 testInputs;
+uniform half4 testInputs; // equals (-1.25, 0, 0.75, 2.25)
uniform half4 colorGreen, colorRed;
half4 main(float2 coords) {
+ const half4 constVal = half4(-1.25, 0, 0.75, 2.25);
half4 expected = half4(-1, 0, 1, 1);
return (sign(testInputs.x) == expected.x &&
sign(testInputs.xy) == expected.xy &&
sign(testInputs.xyz) == expected.xyz &&
- sign(testInputs.xyzw) == expected.xyzw) ? colorGreen : colorRed;
+ sign(testInputs.xyzw) == expected.xyzw &&
+ sign(constVal.x) == expected.x &&
+ sign(constVal.xy) == expected.xy &&
+ sign(constVal.xyz) == expected.xyz &&
+ sign(constVal.xyzw) == expected.xyzw) ? colorGreen : colorRed;
}
diff --git a/resources/sksl/intrinsics/SignInt.sksl b/resources/sksl/intrinsics/SignInt.sksl
index e24a488089..c1debeb595 100644
--- a/resources/sksl/intrinsics/SignInt.sksl
+++ b/resources/sksl/intrinsics/SignInt.sksl
@@ -1,10 +1,15 @@
-uniform half4 minus1234;
+uniform half4 testInputs; // equals (-1.25, 0, 0.75, 2.25)
uniform half4 colorGreen, colorRed;
half4 main(float2 coords) {
+ const half4 constVal = half4(-1.25, 0, 0.75, 2.25);
int4 expected = int4(-1, 0, 0, 1);
return (sign(int4(testInputs).x) == expected.x &&
sign(int4(testInputs).xy) == expected.xy &&
sign(int4(testInputs).xyz) == expected.xyz &&
- sign(int4(testInputs).xyzw) == expected.xyzw) ? colorGreen : colorRed;
+ sign(int4(testInputs).xyzw) == expected.xyzw &&
+ sign(int4(constVal).x) == expected.x &&
+ sign(int4(constVal).xy) == expected.xy &&
+ sign(int4(constVal).xyz) == expected.xyz &&
+ sign(int4(constVal).xyzw) == expected.xyzw) ? colorGreen : colorRed;
}
diff --git a/resources/sksl/runtime_errors/IllegalIndexing.rts b/resources/sksl/runtime_errors/IllegalIndexing.rts
index 9b3789ac55..3c24417646 100644
--- a/resources/sksl/runtime_errors/IllegalIndexing.rts
+++ b/resources/sksl/runtime_errors/IllegalIndexing.rts
@@ -25,5 +25,5 @@ uniform int u;
void uniform_index() { int a[2]; a[u] = 0; }
void param_index(int p) { int a[2]; a[p] = 0; }
-// Legal in GLSL, not yet in SkSL:
-void func_index() { int a[2]; a[int(abs(-1))] = 0; } // skbug.com/10835
+// Legal in SkSL when optimization is enabled:
+void func_index() { int a[2]; a[int(abs(-1))] = 0; }
diff --git a/src/android/SkAnimatedImage.cpp b/src/android/SkAnimatedImage.cpp
index d18cb5fa01..4c87596b7e 100644
--- a/src/android/SkAnimatedImage.cpp
+++ b/src/android/SkAnimatedImage.cpp
@@ -44,8 +44,12 @@ sk_sp<SkAnimatedImage> SkAnimatedImage::Make(std::unique_ptr<SkAndroidCodec> cod
return nullptr;
}
- const auto& decodeInfo = codec->getInfo();
- const auto cropRect = SkIRect::MakeSize(decodeInfo.dimensions());
+ auto decodeInfo = codec->getInfo();
+ const auto origin = codec->codec()->getOrigin();
+ if (SkEncodedOriginSwapsWidthHeight(origin)) {
+ decodeInfo = decodeInfo.makeWH(decodeInfo.height(), decodeInfo.width());
+ }
+ const auto cropRect = SkIRect::MakeSize(decodeInfo.dimensions());
return Make(std::move(codec), decodeInfo, cropRect, nullptr);
}
diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp
index af8b8e483d..a8b638fb1b 100644
--- a/src/core/SkGlyphRun.cpp
+++ b/src/core/SkGlyphRun.cpp
@@ -86,7 +86,7 @@ SkRect SkGlyphRun::sourceBounds(const SkPaint& paint) const {
// Use conservative bounds. All glyph have a box of fontBounds size.
if (fScaledRotations.empty()) {
SkRect bounds;
- bounds.setBounds(this->positions().data(), this->positions().count());
+ bounds.setBounds(this->positions().data(), SkCount(this->positions()));
bounds.fLeft += fontBounds.left();
bounds.fTop += fontBounds.top();
bounds.fRight += fontBounds.right();
@@ -269,7 +269,7 @@ const SkGlyphRunList& SkGlyphRunBuilder::blobToGlyphRunList(
std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>>
SkGlyphRunBuilder::convertRSXForm(SkSpan<const SkRSXform> xforms) {
- const int count = xforms.count();
+ const int count = SkCount(xforms);
this->prepareBuffers(count, count);
auto positions = SkSpan(fPositions.get(), count);
auto scaledRotations = SkSpan(fScaledRotations.get(), count);
diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h
index 848e0f9449..0608ce4fd7 100644
--- a/src/core/SkGlyphRun.h
+++ b/src/core/SkGlyphRun.h
@@ -103,13 +103,13 @@ public:
SkRect sourceBounds() const { return fSourceBounds; }
const SkTextBlob* blob() const { return fOriginalTextBlob; }
- auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); }
- auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); }
- auto begin() const -> decltype(fGlyphRuns.cbegin()) { return fGlyphRuns.cbegin(); }
- auto end() const -> decltype(fGlyphRuns.cend()) { return fGlyphRuns.cend(); }
- auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); }
- auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); }
- auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; }
+ auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); }
+ auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); }
+ auto begin() const -> decltype(std::cbegin(fGlyphRuns)) { return std::cbegin(fGlyphRuns); }
+ auto end() const -> decltype(std::cend(fGlyphRuns)) { return std::cend(fGlyphRuns); }
+ auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); }
+ auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); }
+ auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; }
private:
// The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It
diff --git a/src/core/SkSpan.h b/src/core/SkSpan.h
index 44f5c828a3..a61c04ed32 100644
--- a/src/core/SkSpan.h
+++ b/src/core/SkSpan.h
@@ -13,7 +13,6 @@
#include <type_traits>
#include <utility>
#include "include/private/SkTLogic.h"
-#include "include/private/SkTo.h"
template <typename T>
class SkSpan {
@@ -40,14 +39,9 @@ public:
constexpr T& back() const { return fPtr[fSize - 1]; }
constexpr T* begin() const { return fPtr; }
constexpr T* end() const { return fPtr + fSize; }
- constexpr const T* cbegin() const { return this->begin(); }
- constexpr const T* cend() const { return this->end(); }
constexpr auto rbegin() const { return std::make_reverse_iterator(this->end()); }
constexpr auto rend() const { return std::make_reverse_iterator(this->begin()); }
- constexpr auto crbegin() const { return std::make_reverse_iterator(this->cend()); }
- constexpr auto crend() const { return std::make_reverse_iterator(this->cbegin()); }
constexpr T* data() const { return this->begin(); }
- constexpr int count() const { return SkTo<int>(fSize); }
constexpr size_t size() const { return fSize; }
constexpr bool empty() const { return fSize == 0; }
constexpr size_t size_bytes() const { return fSize * sizeof(T); }
diff --git a/src/gpu/GrAATriangulator.cpp b/src/gpu/GrAATriangulator.cpp
index 2df204cf7d..9565bd9658 100644
--- a/src/gpu/GrAATriangulator.cpp
+++ b/src/gpu/GrAATriangulator.cpp
@@ -645,6 +645,8 @@ Poly* GrAATriangulator::tessellate(const VertexList& mesh, const Comparator& c)
this->connectPartners(&fOuterMesh, c);
this->connectPartners(&innerMesh, c);
SortedMerge(&innerMesh, &fOuterMesh, &aaMesh, c);
+ TESS_LOG("\nmerged mesh:\n");
+ DUMP_MESH(aaMesh);
this->mergeCoincidentVertices(&aaMesh, c);
result = this->simplify(&aaMesh, c);
TESS_LOG("combined and simplified mesh:\n");
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index 3ab108a0c2..73c7627eb0 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -218,21 +218,6 @@ public:
the object. */
virtual GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
- // We use these methods as a temporary back door to inject OpenGL tessellation code. Once
- // tessellation is supported by SkSL we can remove these.
- virtual SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const {
- SK_ABORT("Not implemented.");
- }
- virtual SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const {
- SK_ABORT("Not implemented.");
- }
-
protected:
// GPs that need to use either float or ubyte colors can just call this to get a correctly
// configured Attribute struct
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 3d94791818..32d5f60c9c 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -624,7 +624,7 @@ void GrGpu::executeFlushInfo(SkSpan<GrSurfaceProxy*> proxies,
// We currently don't support passing in new surface state for multiple proxies here. The only
// time we have multiple proxies is if we are flushing a yuv SkImage which won't have state
// updates anyways.
- SkASSERT(!newState || proxies.count() == 1);
+ SkASSERT(!newState || proxies.size() == 1);
SkASSERT(!newState || access == SkSurface::BackendSurfaceAccess::kNoAccess);
this->prepareSurfacesForBackendAccessAndStateUpdates(proxies, access, newState);
}
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index e93da0b0c6..f5415c2cbd 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -29,7 +29,7 @@ class GrOp;
class GrSurfaceDrawContext;
/**
- * This immutable object contains information needed to set build a shader program and set API
+ * This immutable object contains information needed to build a shader program and set API
* state for a draw. It is used along with a GrGeometryProcessor and a source of geometric
* data to draw.
*/
diff --git a/src/gpu/GrRenderTaskCluster.cpp b/src/gpu/GrRenderTaskCluster.cpp
index a3ce2a996e..0cf2ea13e1 100644
--- a/src/gpu/GrRenderTaskCluster.cpp
+++ b/src/gpu/GrRenderTaskCluster.cpp
@@ -160,7 +160,7 @@ bool GrClusterRenderTasks(SkSpan<const sk_sp<GrRenderTask>> input,
SkTInternalLList<GrRenderTask>* llist) {
SkASSERT(llist->isEmpty());
- if (input.count() < 3) {
+ if (input.size() < 3) {
return false;
}
diff --git a/src/gpu/GrTriangulator.cpp b/src/gpu/GrTriangulator.cpp
index b998b4f16f..35f2131682 100644
--- a/src/gpu/GrTriangulator.cpp
+++ b/src/gpu/GrTriangulator.cpp
@@ -126,7 +126,15 @@ static inline void round(SkPoint* p) {
}
static inline SkScalar double_to_clamped_scalar(double d) {
- return SkDoubleToScalar(std::min((double) SK_ScalarMax, std::max(d, (double) -SK_ScalarMax)));
+ // Clamps large values to what's finitely representable when cast back to a float.
+ static const double kMaxLimit = (double) SK_ScalarMax;
+ // It's not perfect, but a using a value larger than float_min helps protect from denormalized
+ // values and ill-conditions in intermediate calculations on coordinates.
+ static const double kNearZeroLimit = 16 * (double) std::numeric_limits<float>::min();
+ if (std::abs(d) < kNearZeroLimit) {
+ d = 0.f;
+ }
+ return SkDoubleToScalar(std::max(-kMaxLimit, std::min(d, kMaxLimit)));
}
bool GrTriangulator::Line::intersect(const Line& other, SkPoint* point) const {
@@ -163,8 +171,8 @@ bool GrTriangulator::Edge::intersect(const Edge& other, SkPoint* p, uint8_t* alp
}
double s = sNumer / denom;
SkASSERT(s >= 0.0 && s <= 1.0);
- p->fX = SkDoubleToScalar(fTop->fPoint.fX - s * fLine.fB);
- p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fLine.fA);
+ p->fX = double_to_clamped_scalar(fTop->fPoint.fX - s * fLine.fB);
+ p->fY = double_to_clamped_scalar(fTop->fPoint.fY + s * fLine.fA);
if (alpha) {
if (fType == EdgeType::kInner || other.fType == EdgeType::kInner) {
// If the intersection is on any interior edge, it needs to stay fully opaque or later
@@ -273,6 +281,22 @@ void* GrTriangulator::emitTriangle(Vertex* prev, Vertex* curr, Vertex* next, int
return emit_triangle(prev, curr, next, fEmitCoverage, data);
}
+GrTriangulator::Poly::Poly(Vertex* v, int winding)
+ : fFirstVertex(v)
+ , fWinding(winding)
+ , fHead(nullptr)
+ , fTail(nullptr)
+ , fNext(nullptr)
+ , fPartner(nullptr)
+ , fCount(0)
+{
+#if TRIANGULATOR_LOGGING
+ static int gID = 0;
+ fID = gID++;
+ TESS_LOG("*** created Poly %d\n", fID);
+#endif
+}
+
Poly* GrTriangulator::Poly::addEdge(Edge* e, Side side, SkArenaAlloc* alloc) {
TESS_LOG("addEdge (%g -> %g) to poly %d, %s side\n",
e->fTop->fID, e->fBottom->fID, fID, side == kLeft_Side ? "left" : "right");
@@ -318,7 +342,7 @@ void* GrTriangulator::emitPoly(const Poly* poly, void *data) const {
if (poly->fCount < 3) {
return data;
}
- TESS_LOG("emit() %d, size %d\n", fID, fCount);
+ TESS_LOG("emit() %d, size %d\n", poly->fID, poly->fCount);
for (MonotonePoly* m = poly->fHead; m != nullptr; m = m->fNext) {
data = this->emitMonotonePoly(m, data);
}
@@ -894,7 +918,7 @@ Vertex* GrTriangulator::makeSortedVertex(const SkPoint& p, uint8_t alpha, Vertex
static bool nearly_flat(const Comparator& c, Edge* edge) {
SkPoint diff = edge->fBottom->fPoint - edge->fTop->fPoint;
float primaryDiff = c.fDirection == Comparator::Direction::kHorizontal ? diff.fX : diff.fY;
- return fabs(primaryDiff) < std::numeric_limits<float>::epsilon() && primaryDiff != 0.0f;
+ return fabs(primaryDiff) <= std::numeric_limits<float>::epsilon() && primaryDiff != 0.0f;
}
static SkPoint clamp(SkPoint p, SkPoint min, SkPoint max, const Comparator& c) {
@@ -944,19 +968,24 @@ bool GrTriangulator::checkForIntersection(Edge* left, Edge* right, EdgeList* act
while (top && c.sweep_lt(p, top->fPoint)) {
top = top->fPrev;
}
- if (!nearly_flat(c, left)) {
+ bool leftFlat = nearly_flat(c, left);
+ bool rightFlat = nearly_flat(c, right);
+ if (leftFlat && rightFlat) {
+ return false;
+ }
+ if (!leftFlat) {
p = clamp(p, left->fTop->fPoint, left->fBottom->fPoint, c);
}
- if (!nearly_flat(c, right)) {
+ if (!rightFlat) {
p = clamp(p, right->fTop->fPoint, right->fBottom->fPoint, c);
}
- if (p == left->fTop->fPoint) {
+ if (coincident(p, left->fTop->fPoint)) {
v = left->fTop;
- } else if (p == left->fBottom->fPoint) {
+ } else if (coincident(p, left->fBottom->fPoint)) {
v = left->fBottom;
- } else if (p == right->fTop->fPoint) {
+ } else if (coincident(p, right->fTop->fPoint)) {
v = right->fTop;
- } else if (p == right->fBottom->fPoint) {
+ } else if (coincident(p, right->fBottom->fPoint)) {
v = right->fBottom;
} else {
v = this->makeSortedVertex(p, alpha, mesh, top, c);
@@ -979,10 +1008,14 @@ void GrTriangulator::sanitizeContours(VertexList* contours, int contourCnt) cons
for (VertexList* contour = contours; contourCnt > 0; --contourCnt, ++contour) {
SkASSERT(contour->fHead);
Vertex* prev = contour->fTail;
+ prev->fPoint.fX = double_to_clamped_scalar((double) prev->fPoint.fX);
+ prev->fPoint.fY = double_to_clamped_scalar((double) prev->fPoint.fY);
if (fRoundVerticesToQuarterPixel) {
round(&prev->fPoint);
}
for (Vertex* v = contour->fHead; v;) {
+ v->fPoint.fX = double_to_clamped_scalar((double) v->fPoint.fX);
+ v->fPoint.fY = double_to_clamped_scalar((double) v->fPoint.fY);
if (fRoundVerticesToQuarterPixel) {
round(&v->fPoint);
}
@@ -1376,8 +1409,14 @@ Poly* GrTriangulator::contoursToPolys(VertexList* contours, int contourCnt) cons
: Comparator::Direction::kVertical);
VertexList mesh;
this->contoursToMesh(contours, contourCnt, &mesh, c);
+ TESS_LOG("\ninitial mesh:\n");
+ DUMP_MESH(mesh);
SortMesh(&mesh, c);
+ TESS_LOG("\nsorted mesh:\n");
+ DUMP_MESH(mesh);
this->mergeCoincidentVertices(&mesh, c);
+ TESS_LOG("\nsorted+merged mesh:\n");
+ DUMP_MESH(mesh);
this->simplify(&mesh, c);
TESS_LOG("\nsimplified mesh:\n");
DUMP_MESH(mesh);
diff --git a/src/gpu/GrTriangulator.h b/src/gpu/GrTriangulator.h
index 2b45a18ac0..97f97e59cf 100644
--- a/src/gpu/GrTriangulator.h
+++ b/src/gpu/GrTriangulator.h
@@ -465,21 +465,8 @@ struct GrTriangulator::MonotonePoly {
};
struct GrTriangulator::Poly {
- Poly(Vertex* v, int winding)
- : fFirstVertex(v)
- , fWinding(winding)
- , fHead(nullptr)
- , fTail(nullptr)
- , fNext(nullptr)
- , fPartner(nullptr)
- , fCount(0)
- {
-#if TRIANGULATOR_LOGGING
- static int gID = 0;
- fID = gID++;
- TESS_LOG("*** created Poly %d\n", fID);
-#endif
- }
+ Poly(Vertex* v, int winding);
+
Poly* addEdge(Edge* e, Side side, SkArenaAlloc* alloc);
Vertex* lastVertex() const { return fTail ? fTail->fLastEdge->fBottom : fFirstVertex; }
Vertex* fFirstVertex;
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index 951b994f67..47505111b6 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -29,27 +29,26 @@ bool GrCustomXfermode::IsSupportedMode(SkBlendMode mode) {
///////////////////////////////////////////////////////////////////////////////
static constexpr GrBlendEquation hw_blend_equation(SkBlendMode mode) {
-// In C++14 this could be a constexpr int variable.
-#define EQ_OFFSET (kOverlay_GrBlendEquation - (int)SkBlendMode::kOverlay)
- static_assert(kOverlay_GrBlendEquation == (int)SkBlendMode::kOverlay + EQ_OFFSET);
- static_assert(kDarken_GrBlendEquation == (int)SkBlendMode::kDarken + EQ_OFFSET);
- static_assert(kLighten_GrBlendEquation == (int)SkBlendMode::kLighten + EQ_OFFSET);
- static_assert(kColorDodge_GrBlendEquation == (int)SkBlendMode::kColorDodge + EQ_OFFSET);
- static_assert(kColorBurn_GrBlendEquation == (int)SkBlendMode::kColorBurn + EQ_OFFSET);
- static_assert(kHardLight_GrBlendEquation == (int)SkBlendMode::kHardLight + EQ_OFFSET);
- static_assert(kSoftLight_GrBlendEquation == (int)SkBlendMode::kSoftLight + EQ_OFFSET);
- static_assert(kDifference_GrBlendEquation == (int)SkBlendMode::kDifference + EQ_OFFSET);
- static_assert(kExclusion_GrBlendEquation == (int)SkBlendMode::kExclusion + EQ_OFFSET);
- static_assert(kMultiply_GrBlendEquation == (int)SkBlendMode::kMultiply + EQ_OFFSET);
- static_assert(kHSLHue_GrBlendEquation == (int)SkBlendMode::kHue + EQ_OFFSET);
- static_assert(kHSLSaturation_GrBlendEquation == (int)SkBlendMode::kSaturation + EQ_OFFSET);
- static_assert(kHSLColor_GrBlendEquation == (int)SkBlendMode::kColor + EQ_OFFSET);
- static_assert(kHSLLuminosity_GrBlendEquation == (int)SkBlendMode::kLuminosity + EQ_OFFSET);
+ constexpr int kEqOffset = (kOverlay_GrBlendEquation - (int)SkBlendMode::kOverlay);
+ static_assert(kOverlay_GrBlendEquation == (int)SkBlendMode::kOverlay + kEqOffset);
+ static_assert(kDarken_GrBlendEquation == (int)SkBlendMode::kDarken + kEqOffset);
+ static_assert(kLighten_GrBlendEquation == (int)SkBlendMode::kLighten + kEqOffset);
+ static_assert(kColorDodge_GrBlendEquation == (int)SkBlendMode::kColorDodge + kEqOffset);
+ static_assert(kColorBurn_GrBlendEquation == (int)SkBlendMode::kColorBurn + kEqOffset);
+ static_assert(kHardLight_GrBlendEquation == (int)SkBlendMode::kHardLight + kEqOffset);
+ static_assert(kSoftLight_GrBlendEquation == (int)SkBlendMode::kSoftLight + kEqOffset);
+ static_assert(kDifference_GrBlendEquation == (int)SkBlendMode::kDifference + kEqOffset);
+ static_assert(kExclusion_GrBlendEquation == (int)SkBlendMode::kExclusion + kEqOffset);
+ static_assert(kMultiply_GrBlendEquation == (int)SkBlendMode::kMultiply + kEqOffset);
+ static_assert(kHSLHue_GrBlendEquation == (int)SkBlendMode::kHue + kEqOffset);
+ static_assert(kHSLSaturation_GrBlendEquation == (int)SkBlendMode::kSaturation + kEqOffset);
+ static_assert(kHSLColor_GrBlendEquation == (int)SkBlendMode::kColor + kEqOffset);
+ static_assert(kHSLLuminosity_GrBlendEquation == (int)SkBlendMode::kLuminosity + kEqOffset);
// There's an illegal GrBlendEquation that corresponds to no SkBlendMode, hence the extra +1.
- static_assert(kGrBlendEquationCnt == (int)SkBlendMode::kLastMode + 1 + 1 + EQ_OFFSET);
+ static_assert(kGrBlendEquationCnt == (int)SkBlendMode::kLastMode + 1 + 1 + kEqOffset);
- return static_cast<GrBlendEquation>((int)mode + EQ_OFFSET);
+ return static_cast<GrBlendEquation>((int)mode + kEqOffset);
#undef EQ_OFFSET
}
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 9cbcacf759..4d01640c4e 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -73,7 +73,18 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
fShaderCaps.reset(new GrShaderCaps(contextOptions));
- this->init(contextOptions, ctxInfo, glInterface);
+ // All of Skia's automated testing of ANGLE and all related tuning of performance and driver
+ // workarounds is oriented around the D3D backends of ANGLE. Chrome has started using Skia
+ // on top of ANGLE's GL backend. In this case ANGLE is still interfacing the same underlying
+ // GL driver that our performance and correctness tuning was performed on. To avoid losing
+ // that we strip the ANGLE info and for the rest of caps setup pretend we're directly on top of
+ // the GL driver. Note that this means that some driver workarounds are likely implemented at
+ // two levels of the stack (Skia and ANGLE) but we haven't determined which.
+ if (ctxInfo.angleBackend() == GrGLANGLEBackend::kOpenGL) {
+ this->init(contextOptions, ctxInfo.makeNonAngle(), glInterface);
+ } else {
+ this->init(contextOptions, ctxInfo, glInterface);
+ }
}
void GrGLCaps::init(const GrContextOptions& contextOptions,
@@ -286,8 +297,8 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
#ifdef SK_BUILD_FOR_WIN
// We're assuming that on Windows Chromium we're using ANGLE.
- bool isANGLE = ctxInfo.driver() == GrGLDriver::kANGLE ||
- ctxInfo.driver() == GrGLDriver::kChromium;
+ bool isANGLE = ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown ||
+ ctxInfo.driver() == GrGLDriver::kChromium;
// Angle has slow read/write pixel paths for 32bit RGBA (but fast for BGRA).
fRGBA8888PixelsOpsAreSlow = isANGLE;
// On DX9 ANGLE reading a partial FBO is slow. TODO: Check whether this is still true and
@@ -882,11 +893,12 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
ctxInfo.glslGeneration() >= k330_GrGLSLGeneration; // This is the value for GLSL ES 3.0.
} // not sure for WebGL
- // Flat interpolation appears to be slow on Qualcomm GPUs (tested Adreno 405 and 530). ANGLE
+ // Flat interpolation appears to be slow on Qualcomm GPUs (tested Adreno 405 and 530).
// Avoid on ANGLE too, it inserts a geometry shader into the pipeline to implement flat interp.
+ // Is this only true on ANGLE's D3D backends or also on the GL backend?
shaderCaps->fPreferFlatInterpolation = shaderCaps->fFlatInterpolationSupport &&
ctxInfo.vendor() != GrGLVendor::kQualcomm &&
- ctxInfo.driver() != GrGLDriver::kANGLE;
+ ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown;
if (GR_IS_GR_GL(standard)) {
shaderCaps->fNoPerspectiveInterpolationSupport =
ctxInfo.glslGeneration() >= k130_GrGLSLGeneration;
@@ -3528,7 +3540,8 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
}
// The TransferPixelsToTexture test fails on ANGLE.
- if (ctxInfo.driver() == GrGLDriver::kANGLE) {
+ // TODO: Limit this to D3D and perhaps more specifically than that.
+ if (ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown) {
fTransferFromBufferToTextureSupport = false;
}
@@ -3594,7 +3607,7 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
// bugs seems to involve clearing too much and not skipping the clear.
// See crbug.com/768134. This is also needed for full clears and was seen on an nVidia K620
// but only for D3D11 ANGLE.
- if (GrGLANGLEBackend::kD3D11 == ctxInfo.angleBackend()) {
+ if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D11) {
fPerformColorClearsAsDraws = true;
}
@@ -3713,8 +3726,8 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
}
// http://anglebug.com/4536
- if (ctxInfo.driver() == GrGLDriver::kANGLE &&
- ctxInfo.angleBackend() != GrGLANGLEBackend::kOpenGL) {
+ if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9 ||
+ ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D11) {
fBaseVertexBaseInstanceSupport = false;
fNativeDrawIndirectSupport = false;
fMultiDrawType = MultiDrawType::kNone;
@@ -3816,7 +3829,8 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
// we've explicitly guarded the division with a check against zero. This manifests in much
// more complex ways in some of our shaders, so we use this caps bit to add an epsilon value
// to the denominator of divisions, even when we've added checks that the denominator isn't 0.
- if (ctxInfo.driver() == GrGLDriver::kANGLE || ctxInfo.driver() == GrGLDriver::kChromium) {
+ if (ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown ||
+ ctxInfo.driver() == GrGLDriver::kChromium) {
shaderCaps->fMustGuardDivisionEvenAfterExplicitZeroCheck = true;
}
#endif
@@ -3975,8 +3989,7 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
#ifdef SK_BUILD_FOR_WIN
// glDrawElementsIndirect fails GrMeshTest on every Win10 Intel bot.
if (ctxInfo.driver() == GrGLDriver::kIntel ||
- (ctxInfo.driver() == GrGLDriver::kANGLE &&
- ctxInfo.angleVendor() == GrGLANGLEVendor::kIntel &&
+ (ctxInfo.angleVendor() == GrGLVendor::kIntel &&
ctxInfo.angleBackend() == GrGLANGLEBackend::kOpenGL)) {
fNativeDrawIndexedIndirectIsBroken = true;
fUseClientSideIndirectBuffers = true;
@@ -4088,14 +4101,14 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
fMSFBOType = kNone_MSFBOType;
}
- // ANGLE doesn't support do-while loops
- if (ctxInfo.driver() == GrGLDriver::kANGLE) {
+ // ANGLE doesn't support do-while loops.
+ if (ctxInfo.angleBackend() != GrGLANGLEBackend::kUnknown) {
shaderCaps->fCanUseDoLoops = false;
}
// ANGLE's D3D9 backend + AMD GPUs are flaky with program binary caching (skbug.com/10395)
if (ctxInfo.angleBackend() == GrGLANGLEBackend::kD3D9 &&
- ctxInfo.angleVendor() == GrGLANGLEVendor::kAMD) {
+ ctxInfo.angleVendor() == GrGLVendor::kATI) {
fProgramBinarySupport = false;
}
diff --git a/src/gpu/gl/GrGLContext.cpp b/src/gpu/gl/GrGLContext.cpp
index 55b6ff2e1a..615d9b95aa 100644
--- a/src/gpu/gl/GrGLContext.cpp
+++ b/src/gpu/gl/GrGLContext.cpp
@@ -75,6 +75,26 @@ std::unique_ptr<GrGLContext> GrGLContext::Make(sk_sp<const GrGLInterface> interf
GrGLContext::~GrGLContext() {}
+GrGLContextInfo GrGLContextInfo::makeNonAngle() const {
+ GrGLContextInfo copy = *this;
+ if (fDriverInfo.fANGLEBackend == GrGLANGLEBackend::kUnknown) {
+ return copy;
+ }
+
+ copy.fDriverInfo.fVendor = copy.fDriverInfo.fANGLEVendor;
+ copy.fDriverInfo.fDriver = copy.fDriverInfo.fANGLEDriver;
+ copy.fDriverInfo.fDriverVersion = copy.fDriverInfo.fANGLEDriverVersion;
+ copy.fDriverInfo.fRenderer = copy.fDriverInfo.fANGLERenderer;
+
+ copy.fDriverInfo.fANGLEBackend = GrGLANGLEBackend::kUnknown;
+ copy.fDriverInfo.fANGLEVendor = GrGLVendor::kOther;
+ copy.fDriverInfo.fANGLEDriver = GrGLDriver::kUnknown;
+ copy.fDriverInfo.fANGLEDriverVersion = GR_GL_DRIVER_UNKNOWN_VER;
+ copy.fDriverInfo.fANGLERenderer = GrGLRenderer::kOther;
+
+ return copy;
+}
+
GrGLContextInfo::GrGLContextInfo(ConstructorArgs&& args) {
fInterface = std::move(args.fInterface);
fDriverInfo = args.fDriverInfo;
diff --git a/src/gpu/gl/GrGLContext.h b/src/gpu/gl/GrGLContext.h
index 051f7e4c98..798fe1aa10 100644
--- a/src/gpu/gl/GrGLContext.h
+++ b/src/gpu/gl/GrGLContext.h
@@ -23,8 +23,8 @@ struct GrContextOptions;
*/
class GrGLContextInfo {
public:
- GrGLContextInfo(const GrGLContextInfo&) = delete;
- GrGLContextInfo& operator=(const GrGLContextInfo&) = delete;
+ GrGLContextInfo(GrGLContextInfo&&) = default;
+ GrGLContextInfo& operator=(GrGLContextInfo&&) = default;
virtual ~GrGLContextInfo() {}
@@ -34,8 +34,8 @@ public:
GrGLVendor vendor() const { return fDriverInfo.fVendor; }
GrGLRenderer renderer() const { return fDriverInfo.fRenderer; }
GrGLANGLEBackend angleBackend() const { return fDriverInfo.fANGLEBackend; }
- GrGLANGLEVendor angleVendor() const { return fDriverInfo.fANGLEVendor; }
- GrGLANGLERenderer angleRenderer() const { return fDriverInfo.fANGLERenderer; }
+ GrGLVendor angleVendor() const { return fDriverInfo.fANGLEVendor; }
+ GrGLRenderer angleRenderer() const { return fDriverInfo.fANGLERenderer; }
/** What driver is running our GL implementation? This is not necessarily related to the vendor.
(e.g. Intel GPU being driven by Mesa) */
GrGLDriver driver() const { return fDriverInfo.fDriver; }
@@ -48,7 +48,17 @@ public:
const GrGLExtensions& extensions() const { return fInterface->fExtensions; }
+ /**
+ * Makes a version of this context info that strips the "angle-ness". It will report kUnknown
+ * for angleBackend() and report this info's angleRenderer() as renderer() and similiar for
+ * driver(), driverVersion(), and vendor().
+ */
+ GrGLContextInfo makeNonAngle() const;
+
protected:
+ GrGLContextInfo& operator=(const GrGLContextInfo&) = default;
+ GrGLContextInfo(const GrGLContextInfo&) = default;
+
struct ConstructorArgs {
sk_sp<const GrGLInterface> fInterface;
GrGLDriverInfo fDriverInfo;
diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp
index c48471f0e9..4bedee4c97 100644
--- a/src/gpu/gl/GrGLUtil.cpp
+++ b/src/gpu/gl/GrGLUtil.cpp
@@ -25,7 +25,7 @@
///////////////////////////////////////////////////////////////////////////////
GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) {
- if (nullptr == versionString) {
+ if (!versionString) {
SkDebugf("nullptr GL version string.");
return kNone_GrGLStandard;
}
@@ -62,7 +62,7 @@ GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) {
}
GrGLVersion GrGLGetVersionFromString(const char* versionString) {
- if (nullptr == versionString) {
+ if (!versionString) {
SkDebugf("nullptr GL version string.");
return GR_GL_INVALID_VER;
}
@@ -103,6 +103,7 @@ GrGLVersion GrGLGetVersionFromString(const char* versionString) {
}
GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
+ SkASSERT(gl);
const GrGLubyte* v;
GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
return GrGLGetVersionFromString((const char*)v);
@@ -159,13 +160,6 @@ static GrGLVendor get_vendor(const char* vendorString) {
return GrGLVendor::kOther;
}
-static bool is_renderer_angle(const char* rendererString) {
- SkASSERT(rendererString);
- static constexpr char kHeader[] = "ANGLE ";
- static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1;
- return rendererString && 0 == strncmp(rendererString, kHeader, kHeaderLength);
-}
-
static GrGLRenderer get_renderer(const char* rendererString, const GrGLExtensions& extensions) {
SkASSERT(rendererString);
static const char kTegraStr[] = "NVIDIA Tegra";
@@ -355,111 +349,30 @@ static GrGLRenderer get_renderer(const char* rendererString, const GrGLExtension
mali400Num < 500) {
return GrGLRenderer::kMali4xx;
}
- if (is_renderer_angle(rendererString)) {
- return GrGLRenderer::kANGLE;
- }
return GrGLRenderer::kOther;
}
-std::tuple<GrGLANGLEBackend, GrGLANGLEVendor, GrGLANGLERenderer>
-get_angle_info(const char* rendererString) {
- auto backend = GrGLANGLEBackend::kUnknown;
- auto vendor = GrGLANGLEVendor::kUnknown;
- auto renderer = GrGLANGLERenderer::kUnknown;
- if (!is_renderer_angle(rendererString)) {
- return {backend, vendor, renderer};
- }
- if (strstr(rendererString, "Intel")) {
- vendor = GrGLANGLEVendor::kIntel;
-
- const char* modelStr;
- int modelNumber;
- if ((modelStr = strstr(rendererString, "HD Graphics")) &&
- (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) ||
- 1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) {
- switch (modelNumber) {
- case 2000:
- case 3000:
- renderer = GrGLANGLERenderer::kSandyBridge;
- break;
- case 4000:
- case 2500:
- renderer = GrGLANGLERenderer::kIvyBridge;
- break;
- case 510:
- case 515:
- case 520:
- case 530:
- renderer = GrGLANGLERenderer::kSkylake;
- break;
- }
- } else if ((modelStr = strstr(rendererString, "Iris")) &&
- (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) ||
- 1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) ||
- 1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) {
- switch (modelNumber) {
- case 540:
- case 550:
- case 555:
- case 580:
- renderer = GrGLANGLERenderer::kSkylake;
- break;
- }
- }
- } else if (strstr(rendererString, "NVIDIA")) {
- vendor = GrGLANGLEVendor::kNVIDIA;
- } else if (strstr(rendererString, "Radeon")) {
- vendor = GrGLANGLEVendor::kAMD;
- }
- if (strstr(rendererString, "Direct3D11")) {
- backend = GrGLANGLEBackend::kD3D11;
- } else if (strstr(rendererString, "Direct3D9")) {
- backend = GrGLANGLEBackend::kD3D9;
- } else if (strstr(rendererString, "OpenGL")) {
- backend = GrGLANGLEBackend::kOpenGL;
- }
- return {backend, vendor, renderer};
-}
-
-GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
- if (!interface) {
- return {};
- }
- SkASSERT(interface->fStandard != kNone_GrGLStandard);
- GrGLDriverInfo info;
- info.fStandard = interface->fStandard;
-
- auto getString = [&](GrGLenum s) {
- const GrGLubyte* bytes = interface->fFunctions.fGetString(s);
- if (!bytes) {
- return "";
- }
- return reinterpret_cast<const char*>(bytes);
- };
-
- const char* const version = getString(GR_GL_VERSION);
- const char* const slversion = getString(GR_GL_SHADING_LANGUAGE_VERSION);
- const char* const renderer = getString(GR_GL_RENDERER);
- const char* const vendor = getString(GR_GL_VENDOR);
+std::tuple<GrGLDriver, GrGLDriverVersion> get_driver_and_version(GrGLStandard standard,
+ GrGLVendor vendor,
+ const char* rendererString,
+ const char* versionString) {
+ SkASSERT(rendererString);
+ SkASSERT(versionString);
- info.fVersion = GrGLGetVersionFromString(version);
- info.fGLSLVersion = get_glsl_version(slversion);
- info.fVendor = get_vendor(vendor);
- info.fRenderer = get_renderer(renderer, interface->fExtensions);
+ GrGLDriver driver = GrGLDriver::kUnknown;
+ GrGLDriverVersion driverVersion = GR_GL_DRIVER_UNKNOWN_VER;
- std::tie(info.fANGLEBackend, info.fANGLEVendor, info.fANGLERenderer) = get_angle_info(renderer);
int major, minor, rev, driverMajor, driverMinor, driverPoint;
-
static const char kChromium[] = "Chromium";
char suffix[SK_ARRAY_COUNT(kChromium)] = {0};
- if (0 == strcmp(renderer, kChromium) ||
- (3 == sscanf(version, "OpenGL ES %d.%d %8s", &major, &minor, suffix) &&
+ if (0 == strcmp(rendererString, kChromium) ||
+ (3 == sscanf(versionString, "OpenGL ES %d.%d %8s", &major, &minor, suffix) &&
0 == strcmp(kChromium, suffix))) {
- info.fDriver = GrGLDriver::kChromium;
- } else if (GR_IS_GR_GL(interface->fStandard)) {
- if (info.fVendor == GrGLVendor::kNVIDIA) {
- info.fDriver = GrGLDriver::kNVIDIA;
- int n = sscanf(version,
+ driver = GrGLDriver::kChromium;
+ } else if (GR_IS_GR_GL(standard)) {
+ if (vendor == GrGLVendor::kNVIDIA) {
+ driver = GrGLDriver::kNVIDIA;
+ int n = sscanf(versionString,
"%d.%d.%d NVIDIA %d.%d",
&major,
&minor,
@@ -468,12 +381,17 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
&driverMinor);
// Some older NVIDIA drivers don't report the driver version.
if (n == 5) {
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
+ driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
}
} else {
- int n = sscanf(version, "%d.%d Mesa %d.%d", &major, &minor, &driverMajor, &driverMinor);
+ int n = sscanf(versionString,
+ "%d.%d Mesa %d.%d",
+ &major,
+ &minor,
+ &driverMajor,
+ &driverMinor);
if (n != 4) {
- n = sscanf(version,
+ n = sscanf(versionString,
"%d.%d (Core Profile) Mesa %d.%d",
&major,
&minor,
@@ -481,14 +399,14 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
&driverMinor);
}
if (n == 4) {
- info.fDriver = GrGLDriver::kMesa;
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
+ driver = GrGLDriver::kMesa;
+ driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
}
}
- } else if (GR_IS_GR_GL_ES(interface->fStandard)) {
- if (info.fVendor == GrGLVendor::kNVIDIA) {
- info.fDriver = GrGLDriver::kNVIDIA;
- int n = sscanf(version,
+ } else if (standard) {
+ if (vendor == GrGLVendor::kNVIDIA) {
+ driver = GrGLDriver::kNVIDIA;
+ int n = sscanf(versionString,
"OpenGL ES %d.%d NVIDIA %d.%d",
&major,
&minor,
@@ -496,42 +414,31 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
&driverMinor);
// Some older NVIDIA drivers don't report the driver version.
if (n == 4) {
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
+ driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
}
} else {
- int n = sscanf(version,
+ int n = sscanf(versionString,
"OpenGL ES %d.%d Mesa %d.%d",
&major,
&minor,
&driverMajor,
&driverMinor);
if (n == 4) {
- info.fDriver = GrGLDriver::kMesa;
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
- } else if (0 == strncmp("ANGLE", renderer, 5)) {
- info.fDriver = GrGLDriver::kANGLE;
- n = sscanf(version,
- "OpenGL ES %d.%d (ANGLE %d.%d",
- &major,
- &minor,
- &driverMajor,
- &driverMinor);
- if (n == 4) {
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
- }
+ driver = GrGLDriver::kMesa;
+ driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
}
}
}
- if (info.fDriver == GrGLDriver::kUnknown) {
- if (info.fVendor == GrGLVendor::kGoogle) {
+ if (driver == GrGLDriver::kUnknown) {
+ if (vendor == GrGLVendor::kGoogle) {
// Swiftshader is the only Google vendor at the moment
- info.fDriver = GrGLDriver::kSwiftShader;
+ driver = GrGLDriver::kSwiftShader;
// Swiftshader has a strange version string: w.x.y.z Going to arbitrarily ignore
// y and assume w,x and z are major, minor, point.
// As of writing, version is 4.0.0.6
- int n = sscanf(version,
+ int n = sscanf(versionString,
"OpenGL ES %d.%d SwiftShader %d.%d.0.%d",
&major,
&minor,
@@ -539,16 +446,16 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
&driverMinor,
&driverPoint);
if (n == 5) {
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
+ driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
}
- } else if (info.fVendor == GrGLVendor::kIntel) {
+ } else if (vendor == GrGLVendor::kIntel) {
// We presume we're on the Intel driver since it hasn't identified itself as Mesa.
- info.fDriver = GrGLDriver::kIntel;
+ driver = GrGLDriver::kIntel;
// This is how the macOS version strings are structured. This might be different on
// different
// OSes.
- int n = sscanf(version,
+ int n = sscanf(versionString,
"%d.%d INTEL-%d.%d.%d",
&major,
&minor,
@@ -556,18 +463,22 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
&driverMinor,
&driverPoint);
if (n == 5) {
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
+ driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
}
- } else if (info.fVendor == GrGLVendor::kQualcomm) {
- info.fDriver = GrGLDriver::kQualcomm;
- int n = sscanf(
- version, "OpenGL ES %d.%d V@%d.%d", &major, &minor, &driverMajor, &driverMinor);
+ } else if (vendor == GrGLVendor::kQualcomm) {
+ driver = GrGLDriver::kQualcomm;
+ int n = sscanf(versionString,
+ "OpenGL ES %d.%d V@%d.%d",
+ &major,
+ &minor,
+ &driverMajor,
+ &driverMinor);
if (n == 4) {
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
+ driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
}
- } else if (info.fVendor == GrGLVendor::kImagination) {
+ } else if (vendor == GrGLVendor::kImagination) {
int revision;
- int n = sscanf(version,
+ int n = sscanf(versionString,
"OpenGL ES %d.%d build %d.%d@%d",
&major,
&minor,
@@ -577,15 +488,171 @@ GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
if (n == 5) {
// Revision is a large number (looks like a source control revision number) that
// doesn't fit into the 'patch' bits, so omit it until we need it.
- info.fDriverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
+ driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
}
} else {
static constexpr char kEmulatorPrefix[] = "Android Emulator OpenGL ES Translator";
- if (0 == strncmp(kEmulatorPrefix, renderer, strlen(kEmulatorPrefix))) {
- info.fDriver = GrGLDriver::kAndroidEmulator;
+ if (0 == strncmp(kEmulatorPrefix, rendererString, strlen(kEmulatorPrefix))) {
+ driver = GrGLDriver::kAndroidEmulator;
}
}
}
+ return {driver, driverVersion};
+}
+
+// If this is detected as ANGLE then the ANGLE backend is returned along with rendererString
+// stripped of "ANGLE(" and ")" at the start and end, respectively.
+static std::tuple<GrGLANGLEBackend, SkString> get_angle_backend(const char* rendererString) {
+ // crbug.com/1203705 ANGLE renderer will be "ANGLE (<gl-vendor>, <gl-renderer>, <gl-version>)"
+ // on ANGLE's GL backend with related substitutions for the inner strings on other backends.
+ static constexpr char kHeader[] = "ANGLE (";
+ static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1;
+ int rendererLength = strlen(rendererString);
+ if (!strncmp(rendererString, kHeader, kHeaderLength) &&
+ rendererString[rendererLength - 1] == ')') {
+ SkString innerString;
+ innerString.set(rendererString + kHeaderLength, rendererLength - kHeaderLength - 1);
+ if (strstr(rendererString, "Direct3D11")) {
+ return {GrGLANGLEBackend::kD3D11, std::move(innerString)};
+ } else if (strstr(rendererString, "Direct3D9")) {
+ return {GrGLANGLEBackend::kD3D9, std::move(innerString)};
+ } else if (strstr(rendererString, "OpenGL")) {
+ return {GrGLANGLEBackend::kOpenGL, std::move(innerString)};
+ }
+ }
+ return {GrGLANGLEBackend::kUnknown, {}};
+}
+
+std::tuple<GrGLVendor, GrGLRenderer, GrGLDriver, GrGLDriverVersion>
+get_angle_gl_vendor_and_renderer(
+ const char* innerString,
+ const GrGLExtensions& extensions) {
+ SkTArray<SkString> parts;
+ SkStrSplit(innerString, ",", &parts);
+ // This would need some fixing if we have substrings that contain commas.
+ if (parts.size() != 3) {
+ return {GrGLVendor::kOther,
+ GrGLRenderer::kOther,
+ GrGLDriver::kUnknown,
+ GR_GL_DRIVER_UNKNOWN_VER};
+ }
+
+ const char* angleVendorString = parts[0].c_str();
+ const char* angleRendererString = parts[1].c_str() + 1; // skip initial space
+ const char* angleVersionString = parts[2].c_str() + 1; // skip initial space
+
+ GrGLVendor angleVendor = get_vendor(angleVendorString);
+
+ auto [angleDriver, angleDriverVersion] = get_driver_and_version(kGLES_GrGLStandard,
+ angleVendor,
+ angleRendererString,
+ angleVersionString);
+
+ auto angleRenderer = get_renderer(angleRendererString, extensions);
+
+ return {angleVendor, angleRenderer, angleDriver, angleDriverVersion};
+}
+
+std::tuple<GrGLVendor, GrGLRenderer, GrGLDriver, GrGLDriverVersion>
+get_angle_d3d_vendor_and_renderer(const char* innerString) {
+ auto vendor = GrGLVendor::kOther;
+ auto renderer = GrGLRenderer::kOther;
+
+ if (strstr(innerString, "Intel")) {
+ vendor = GrGLVendor::kIntel;
+
+ const char* modelStr;
+ int modelNumber;
+ if ((modelStr = strstr(innerString, "HD Graphics")) &&
+ (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) ||
+ 1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) {
+ switch (modelNumber) {
+ case 2000:
+ case 3000:
+ renderer = GrGLRenderer::kIntelSandyBridge;
+ break;
+ case 4000:
+ case 2500:
+ renderer = GrGLRenderer::kIntelSandyBridge;
+ break;
+ case 510:
+ case 515:
+ case 520:
+ case 530:
+ renderer = GrGLRenderer::kIntelSkyLake;
+ break;
+ }
+ } else if ((modelStr = strstr(innerString, "Iris")) &&
+ (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) ||
+ 1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) ||
+ 1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) {
+ switch (modelNumber) {
+ case 540:
+ case 550:
+ case 555:
+ case 580:
+ renderer = GrGLRenderer::kIntelSkyLake;
+ break;
+ }
+ }
+ } else if (strstr(innerString, "NVIDIA")) {
+ vendor = GrGLVendor::kNVIDIA;
+ } else if (strstr(innerString, "Radeon")) {
+ vendor = GrGLVendor::kATI;
+ }
+ // We haven't had a need yet to parse the D3D driver string.
+ return {vendor, renderer, GrGLDriver::kUnknown, GR_GL_DRIVER_UNKNOWN_VER};
+}
+
+GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
+ if (!interface) {
+ return {};
+ }
+ SkASSERT(interface->fStandard != kNone_GrGLStandard);
+ GrGLDriverInfo info;
+ info.fStandard = interface->fStandard;
+
+ auto getString = [&](GrGLenum s) {
+ const GrGLubyte* bytes = interface->fFunctions.fGetString(s);
+ if (!bytes) {
+ return "";
+ }
+ return reinterpret_cast<const char*>(bytes);
+ };
+
+ const char* const version = getString(GR_GL_VERSION);
+ const char* const slversion = getString(GR_GL_SHADING_LANGUAGE_VERSION);
+ const char* const renderer = getString(GR_GL_RENDERER);
+ const char* const vendor = getString(GR_GL_VENDOR);
+
+ info.fVersion = GrGLGetVersionFromString(version);
+ info.fGLSLVersion = get_glsl_version(slversion);
+ info.fVendor = get_vendor(vendor);
+ info.fRenderer = get_renderer(renderer, interface->fExtensions);
+
+ std::tie(info.fDriver, info.fDriverVersion) = get_driver_and_version(interface->fStandard,
+ info.fVendor,
+ renderer,
+ version);
+
+ SkString innerAngleRendererString;
+ std::tie(info.fANGLEBackend, innerAngleRendererString) = get_angle_backend(renderer);
+
+ if (info.fANGLEBackend == GrGLANGLEBackend::kD3D9 ||
+ info.fANGLEBackend == GrGLANGLEBackend::kD3D11) {
+ std::tie(info.fANGLEVendor,
+ info.fANGLERenderer,
+ info.fANGLEDriver,
+ info.fANGLEDriverVersion) =
+ get_angle_d3d_vendor_and_renderer(innerAngleRendererString.c_str());
+ } else if (info.fANGLEBackend == GrGLANGLEBackend::kOpenGL) {
+ std::tie(info.fANGLEVendor,
+ info.fANGLERenderer,
+ info.fANGLEDriver,
+ info.fANGLEDriverVersion) =
+ get_angle_gl_vendor_and_renderer(innerAngleRendererString.c_str(),
+ interface->fExtensions);
+ }
return info;
}
diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h
index 71d2a69acc..877779426b 100644
--- a/src/gpu/gl/GrGLUtil.h
+++ b/src/gpu/gl/GrGLUtil.h
@@ -135,7 +135,6 @@ enum class GrGLRenderer {
kMaliG,
/** T-6xx, T-7xx, or T-8xx */
kMaliT,
- kANGLE,
kAMDRadeonHD7xxx, // AMD Radeon HD 7000 Series
kAMDRadeonR9M3xx, // AMD Radeon R9 M300 Series
@@ -151,7 +150,6 @@ enum class GrGLDriver {
kChromium,
kNVIDIA,
kIntel,
- kANGLE,
kSwiftShader,
kQualcomm,
kAndroidEmulator,
@@ -165,20 +163,6 @@ enum class GrGLANGLEBackend {
kOpenGL
};
-enum class GrGLANGLEVendor {
- kUnknown,
- kIntel,
- kNVIDIA,
- kAMD
-};
-
-enum class GrGLANGLERenderer {
- kUnknown,
- kSandyBridge,
- kIvyBridge,
- kSkylake
-};
-
////////////////////////////////////////////////////////////////////////////////
/**
@@ -236,16 +220,19 @@ GrGLSLVersion GrGLGetVersion(const GrGLInterface*);
GrGLSLVersion GrGLGetVersionFromString(const char*);
struct GrGLDriverInfo {
- GrGLStandard fStandard = kNone_GrGLStandard;
- GrGLVersion fVersion = GR_GL_INVALID_VER;
- GrGLSLVersion fGLSLVersion = GR_GLSL_INVALID_VER;
- GrGLVendor fVendor = GrGLVendor::kOther;
- GrGLRenderer fRenderer = GrGLRenderer::kOther;
- GrGLDriver fDriver = GrGLDriver::kUnknown;
- GrGLDriverVersion fDriverVersion = GR_GL_DRIVER_UNKNOWN_VER;
- GrGLANGLEBackend fANGLEBackend = GrGLANGLEBackend::kUnknown;
- GrGLANGLEVendor fANGLEVendor = GrGLANGLEVendor::kUnknown;
- GrGLANGLERenderer fANGLERenderer = GrGLANGLERenderer::kUnknown;
+ GrGLStandard fStandard = kNone_GrGLStandard;
+ GrGLVersion fVersion = GR_GL_INVALID_VER;
+ GrGLSLVersion fGLSLVersion = GR_GLSL_INVALID_VER;
+ GrGLVendor fVendor = GrGLVendor::kOther;
+ GrGLRenderer fRenderer = GrGLRenderer::kOther;
+ GrGLDriver fDriver = GrGLDriver::kUnknown;
+ GrGLDriverVersion fDriverVersion = GR_GL_DRIVER_UNKNOWN_VER;
+
+ GrGLANGLEBackend fANGLEBackend = GrGLANGLEBackend::kUnknown;
+ GrGLVendor fANGLEVendor = GrGLVendor::kOther;
+ GrGLRenderer fANGLERenderer = GrGLRenderer::kOther;
+ GrGLDriver fANGLEDriver = GrGLDriver::kUnknown;
+ GrGLDriverVersion fANGLEDriverVersion = GR_GL_DRIVER_UNKNOWN_VER;
};
GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface*);
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 856d2b9836..210faaa234 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -389,8 +389,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
versionAndExtensionDecls.appendf("#extension %s : require\n", extensionString);
}
- SkString tessControlShader = geomProc.getTessControlShaderGLSL(
- fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler,
+ SkString tessControlShader = fGeometryProcessor->getTessControlShaderGLSL(
+ geomProc, versionAndExtensionDecls.c_str(), fUniformHandler,
*this->shaderCaps());
if (!this->compileAndAttachShaders(tessControlShader.c_str(), programID,
GR_GL_TESS_CONTROL_SHADER, &shadersToDelete,
@@ -399,8 +399,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
return nullptr;
}
- SkString tessEvaluationShader = geomProc.getTessEvaluationShaderGLSL(
- fGeometryProcessor.get(), versionAndExtensionDecls.c_str(), fUniformHandler,
+ SkString tessEvaluationShader = fGeometryProcessor->getTessEvaluationShaderGLSL(
+ geomProc, versionAndExtensionDecls.c_str(), fUniformHandler,
*this->shaderCaps());
if (!this->compileAndAttachShaders(tessEvaluationShader.c_str(), programID,
GR_GL_TESS_EVALUATION_SHADER, &shadersToDelete,
@@ -459,7 +459,7 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
if (!cached && !geomProc.willUseTessellationShaders() && !precompiledProgram) {
// FIXME: Remove the check for tessellation shaders in the above 'if' once the back door
// GLSL mechanism is removed.
- (void)&GrGeometryProcessor::getTessControlShaderGLSL;
+ (void)&GrGLSLGeometryProcessor::getTessControlShaderGLSL;
bool isSkSL = false;
if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
GrContextOptions::ShaderCacheStrategy::kSkSL) {
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.h b/src/gpu/glsl/GrGLSLGeometryProcessor.h
index a52406a8f1..bf1d62aed7 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.h
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.h
@@ -130,6 +130,21 @@ public:
const GrShaderCaps&,
const GrGeometryProcessor&) = 0;
+ // We use these methods as a temporary back door to inject OpenGL tessellation code. Once
+ // tessellation is supported by SkSL we can remove these.
+ virtual SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const {
+ SK_ABORT("Not implemented.");
+ }
+ virtual SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const {
+ SK_ABORT("Not implemented.");
+ }
+
protected:
void setupUniformColor(GrGLSLFPFragmentBuilder* fragBuilder,
GrGLSLUniformHandler* uniformHandler,
diff --git a/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp b/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp
index 6fe394dce3..0c28e5228b 100644
--- a/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp
@@ -16,20 +16,18 @@ void GrGLSLVertexGeoBuilder::emitNormalizedSkPosition(SkString* out, const char*
if (this->getProgramBuilder()->snapVerticesToPixelCenters()) {
if (kFloat3_GrSLType == devPosType) {
const char* p = devPos;
- out->appendf("{float2 _posTmp = float2(%s.x/%s.z, %s.y/%s.z);", p, p, p, p);
+ out->appendf("{float2 _posTmp = %s.xy / %s.z;", p, p);
} else {
SkASSERT(kFloat2_GrSLType == devPosType);
out->appendf("{float2 _posTmp = %s;", devPos);
}
- out->appendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
- "sk_Position = float4(_posTmp, 0, 1);}");
+ out->appendf("_posTmp = floor(_posTmp) + float2(0.5);"
+ "sk_Position = _posTmp.xy01;}");
} else if (kFloat3_GrSLType == devPosType) {
- out->appendf("sk_Position = float4(%s.x , %s.y, 0, %s.z);",
- devPos, devPos, devPos);
+ out->appendf("sk_Position = %s.xy0z;", devPos);
} else {
SkASSERT(kFloat2_GrSLType == devPosType);
- out->appendf("sk_Position = float4(%s.x , %s.y, 0, 1);",
- devPos, devPos);
+ out->appendf("sk_Position = %s.xy01;", devPos);
}
}
diff --git a/src/gpu/tessellate/GrStencilPathShader.cpp b/src/gpu/tessellate/GrStencilPathShader.cpp
index cf4e8bb004..85b1f42d73 100644
--- a/src/gpu/tessellate/GrStencilPathShader.cpp
+++ b/src/gpu/tessellate/GrStencilPathShader.cpp
@@ -109,185 +109,197 @@ GrGLSLGeometryProcessor* GrStencilPathShader::createGLSLInstance(const GrShaderC
return new Impl;
}
-SkString GrCubicTessellateShader::getTessControlShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const {
- SkString code(versionAndExtensionDecls);
- code.append(kWangsFormulaCubicFn);
- code.append(kSkSLTypeDefs);
- code.append(kUnpackRationalCubicFn);
- code.append(R"(
- layout(vertices = 1) out;
-
- in vec2 vsPt[];
- out vec4 X[];
- out vec4 Y[];
- out float w[];
-
- void main() {
- mat4x3 P = unpack_rational_cubic(vsPt[0], vsPt[1], vsPt[2], vsPt[3]);
-
- // Chop the curve at T=1/2. Here we take advantage of the fact that a uniform scalar has no
- // effect on homogeneous coordinates in order to eval quickly at .5:
- //
- // mix(p0, p1, .5) / mix(w0, w1, .5)
- // == ((p0 + p1) * .5) / ((w0 + w1) * .5)
- // == (p0 + p1) / (w0 + w1)
- //
- vec3 ab = P[0] + P[1];
- vec3 bc = P[1] + P[2];
- vec3 cd = P[2] + P[3];
- vec3 abc = ab + bc;
- vec3 bcd = bc + cd;
- vec3 abcd = abc + bcd;
-
- // Calculate how many triangles we need to linearize each half of the curve. We simply call
- // Wang's formula for integral cubics with the down-projected points. This appears to be an
- // upper bound on what the actual number of subdivisions would have been.
- float w0 = wangs_formula_cubic(P[0].xy, ab.xy/ab.z, abc.xy/abc.z, abcd.xy/abcd.z);
- float w1 = wangs_formula_cubic(abcd.xy/abcd.z, bcd.xy/bcd.z, cd.xy/cd.z, P[3].xy);
-
- gl_TessLevelOuter[0] = w1;
- gl_TessLevelOuter[1] = 1.0;
- gl_TessLevelOuter[2] = w0;
-
- // Changing the inner level to 1 when w0 == w1 == 1 collapses the entire patch to a single
- // triangle. Otherwise, we need an inner level of 2 so our curve triangles have an interior
- // point to originate from.
- gl_TessLevelInner[0] = min(max(w0, w1), 2.0);
-
- X[gl_InvocationID /*== 0*/] = vec4(P[0].x, P[1].x, P[2].x, P[3].x);
- Y[gl_InvocationID /*== 0*/] = vec4(P[0].y, P[1].y, P[2].y, P[3].y);
- w[gl_InvocationID /*== 0*/] = P[1].z;
- })");
-
- return code;
-}
-
-SkString GrCubicTessellateShader::getTessEvaluationShaderGLSL(
- const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const {
- SkString code(versionAndExtensionDecls);
- code.append(kSkSLTypeDefs);
- code.append(kEvalRationalCubicFn);
- code.append(R"(
- layout(triangles, equal_spacing, ccw) in;
-
- uniform vec4 sk_RTAdjust;
-
- in vec4 X[];
- in vec4 Y[];
- in float w[];
-
- void main() {
- // Locate our parametric point of interest. T ramps from [0..1/2] on the left edge of the
- // triangle, and [1/2..1] on the right. If we are the patch's interior vertex, then we want
- // T=1/2. Since the barycentric coords are (1/3, 1/3, 1/3) at the interior vertex, the below
- // fma() works in all 3 scenarios.
- float T = fma(.5, gl_TessCoord.y, gl_TessCoord.z);
-
- mat4x3 P = transpose(mat3x4(X[0], Y[0], 1,w[0],w[0],1));
- vec2 vertexpos = eval_rational_cubic(P, T);
- if (all(notEqual(gl_TessCoord.xz, vec2(0)))) {
- // We are the interior point of the patch; center it inside [C(0), C(.5), C(1)].
- vertexpos = (P[0].xy + vertexpos + P[3].xy) / 3.0;
+GrGLSLGeometryProcessor* GrCubicTessellateShader::createGLSLInstance(const GrShaderCaps&) const {
+ class CubicImpl : public GrStencilPathShader::Impl {
+ SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override {
+ SkString code(versionAndExtensionDecls);
+ code.append(kWangsFormulaCubicFn);
+ code.append(kSkSLTypeDefs);
+ code.append(kUnpackRationalCubicFn);
+ code.append(R"(
+ layout(vertices = 1) out;
+
+ in vec2 vsPt[];
+ out vec4 X[];
+ out vec4 Y[];
+ out float w[];
+
+ void main() {
+ mat4x3 P = unpack_rational_cubic(vsPt[0], vsPt[1], vsPt[2], vsPt[3]);
+
+ // Chop the curve at T=1/2. Here we take advantage of the fact that a uniform scalar
+ // has no effect on homogeneous coordinates in order to eval quickly at .5:
+ //
+ // mix(p0, p1, .5) / mix(w0, w1, .5)
+ // == ((p0 + p1) * .5) / ((w0 + w1) * .5)
+ // == (p0 + p1) / (w0 + w1)
+ //
+ vec3 ab = P[0] + P[1];
+ vec3 bc = P[1] + P[2];
+ vec3 cd = P[2] + P[3];
+ vec3 abc = ab + bc;
+ vec3 bcd = bc + cd;
+ vec3 abcd = abc + bcd;
+
+ // Calculate how many triangles we need to linearize each half of the curve. We
+ // simply call Wang's formula for integral cubics with the down-projected points.
+ // This appears to be an upper bound on what the actual number of subdivisions would
+ // have been.
+ float w0 = wangs_formula_cubic(P[0].xy, ab.xy/ab.z, abc.xy/abc.z, abcd.xy/abcd.z);
+ float w1 = wangs_formula_cubic(abcd.xy/abcd.z, bcd.xy/bcd.z, cd.xy/cd.z, P[3].xy);
+
+ gl_TessLevelOuter[0] = w1;
+ gl_TessLevelOuter[1] = 1.0;
+ gl_TessLevelOuter[2] = w0;
+
+ // Changing the inner level to 1 when w0 == w1 == 1 collapses the entire patch to a
+ // single triangle. Otherwise, we need an inner level of 2 so our curve triangles
+ // have an interior point to originate from.
+ gl_TessLevelInner[0] = min(max(w0, w1), 2.0);
+
+ X[gl_InvocationID /*== 0*/] = vec4(P[0].x, P[1].x, P[2].x, P[3].x);
+ Y[gl_InvocationID /*== 0*/] = vec4(P[0].y, P[1].y, P[2].y, P[3].y);
+ w[gl_InvocationID /*== 0*/] = P[1].z;
+ })");
+
+ return code;
}
- gl_Position = vec4(vertexpos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0);
- })");
-
- return code;
-}
+ SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override {
+ SkString code(versionAndExtensionDecls);
+ code.append(kSkSLTypeDefs);
+ code.append(kEvalRationalCubicFn);
+ code.append(R"(
+ layout(triangles, equal_spacing, ccw) in;
+
+ uniform vec4 sk_RTAdjust;
+
+ in vec4 X[];
+ in vec4 Y[];
+ in float w[];
+
+ void main() {
+ // Locate our parametric point of interest. T ramps from [0..1/2] on the left edge
+ // of the triangle, and [1/2..1] on the right. If we are the patch's interior
+ // vertex, then we want T=1/2. Since the barycentric coords are (1/3, 1/3, 1/3) at
+ // the interior vertex, the below fma() works in all 3 scenarios.
+ float T = fma(.5, gl_TessCoord.y, gl_TessCoord.z);
+
+ mat4x3 P = transpose(mat3x4(X[0], Y[0], 1,w[0],w[0],1));
+ vec2 vertexpos = eval_rational_cubic(P, T);
+ if (all(notEqual(gl_TessCoord.xz, vec2(0)))) {
+ // We are the interior point of the patch; center it inside [C(0), C(.5), C(1)].
+ vertexpos = (P[0].xy + vertexpos + P[3].xy) / 3.0;
+ }
+
+ gl_Position = vec4(vertexpos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0);
+ })");
+
+ return code;
+ }
+ };
-SkString GrWedgeTessellateShader::getTessControlShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const {
- SkString code(versionAndExtensionDecls);
- code.append(kWangsFormulaCubicFn);
- code.append(kSkSLTypeDefs);
- code.append(kUnpackRationalCubicFn);
- code.append(R"(
- layout(vertices = 1) out;
-
- in vec2 vsPt[];
- out vec4 X[];
- out vec4 Y[];
- out float w[];
- out vec2 fanpoint[];
-
- void main() {
- mat4x3 P = unpack_rational_cubic(vsPt[0], vsPt[1], vsPt[2], vsPt[3]);
-
- // Figure out how many segments to divide the curve into. To do this we simply call Wang's
- // formula for integral cubics with the down-projected points. This appears to be an upper
- // bound on what the actual number of subdivisions would have been.
- float num_segments = wangs_formula_cubic(P[0].xy, P[1].xy/P[1].z, P[2].xy/P[2].z, P[3].xy);
-
- // Tessellate the first side of the patch into num_segments triangles.
- gl_TessLevelOuter[0] = num_segments;
-
- // Leave the other two sides of the patch as single segments.
- gl_TessLevelOuter[1] = 1.0;
- gl_TessLevelOuter[2] = 1.0;
-
- // Changing the inner level to 1 when num_segments == 1 collapses the entire
- // patch to a single triangle. Otherwise, we need an inner level of 2 so our curve
- // triangles have an interior point to originate from.
- gl_TessLevelInner[0] = min(num_segments, 2.0);
-
- X[gl_InvocationID /*== 0*/] = vec4(P[0].x, P[1].x, P[2].x, P[3].x);
- Y[gl_InvocationID /*== 0*/] = vec4(P[0].y, P[1].y, P[2].y, P[3].y);
- w[gl_InvocationID /*== 0*/] = P[1].z;
- fanpoint[gl_InvocationID /*== 0*/] = vsPt[4];
- })");
-
- return code;
+ return new CubicImpl;
}
-SkString GrWedgeTessellateShader::getTessEvaluationShaderGLSL(
- const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const {
- SkString code(versionAndExtensionDecls);
- code.append(kSkSLTypeDefs);
- code.append(kEvalRationalCubicFn);
- code.append(R"(
- layout(triangles, equal_spacing, ccw) in;
-
- uniform vec4 sk_RTAdjust;
-
- in vec4 X[];
- in vec4 Y[];
- in float w[];
- in vec2 fanpoint[];
-
- void main() {
- // Locate our parametric point of interest. It is equal to the barycentric y-coordinate if
- // we are a vertex on the tessellated edge of the triangle patch, 0.5 if we are the patch's
- // interior vertex, or N/A if we are the fan point.
- // NOTE: We are on the tessellated edge when the barycentric x-coordinate == 0.
- float T = (gl_TessCoord.x == 0.0) ? gl_TessCoord.y : 0.5;
-
- mat4x3 P = transpose(mat3x4(X[0], Y[0], 1,w[0],w[0],1));
- vec2 vertexpos = eval_rational_cubic(P, T);
-
- if (gl_TessCoord.x == 1.0) {
- // We are the anchor point that fans from the center of the curve's contour.
- vertexpos = fanpoint[0];
- } else if (gl_TessCoord.x != 0.0) {
- // We are the interior point of the patch; center it inside [C(0), C(.5), C(1)].
- vertexpos = (P[0].xy + vertexpos + P[3].xy) / 3.0;
+GrGLSLGeometryProcessor* GrWedgeTessellateShader::createGLSLInstance(const GrShaderCaps&) const {
+ class WedgeImpl : public GrStencilPathShader::Impl {
+ SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override {
+ SkString code(versionAndExtensionDecls);
+ code.append(kWangsFormulaCubicFn);
+ code.append(kSkSLTypeDefs);
+ code.append(kUnpackRationalCubicFn);
+ code.append(R"(
+ layout(vertices = 1) out;
+
+ in vec2 vsPt[];
+ out vec4 X[];
+ out vec4 Y[];
+ out float w[];
+ out vec2 fanpoint[];
+
+ void main() {
+ mat4x3 P = unpack_rational_cubic(vsPt[0], vsPt[1], vsPt[2], vsPt[3]);
+
+ // Figure out how many segments to divide the curve into. To do this we simply call
+ // Wang's formula for integral cubics with the down-projected points. This appears
+ // to be an upper bound on what the actual number of subdivisions would have been.
+ float num_segments = wangs_formula_cubic(P[0].xy, P[1].xy/P[1].z, P[2].xy/P[2].z,
+ P[3].xy);
+
+ // Tessellate the first side of the patch into num_segments triangles.
+ gl_TessLevelOuter[0] = num_segments;
+
+ // Leave the other two sides of the patch as single segments.
+ gl_TessLevelOuter[1] = 1.0;
+ gl_TessLevelOuter[2] = 1.0;
+
+ // Changing the inner level to 1 when num_segments == 1 collapses the entire
+ // patch to a single triangle. Otherwise, we need an inner level of 2 so our curve
+ // triangles have an interior point to originate from.
+ gl_TessLevelInner[0] = min(num_segments, 2.0);
+
+ X[gl_InvocationID /*== 0*/] = vec4(P[0].x, P[1].x, P[2].x, P[3].x);
+ Y[gl_InvocationID /*== 0*/] = vec4(P[0].y, P[1].y, P[2].y, P[3].y);
+ w[gl_InvocationID /*== 0*/] = P[1].z;
+ fanpoint[gl_InvocationID /*== 0*/] = vsPt[4];
+ })");
+
+ return code;
}
- gl_Position = vec4(vertexpos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0);
- })");
+ SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override {
+ SkString code(versionAndExtensionDecls);
+ code.append(kSkSLTypeDefs);
+ code.append(kEvalRationalCubicFn);
+ code.append(R"(
+ layout(triangles, equal_spacing, ccw) in;
+
+ uniform vec4 sk_RTAdjust;
+
+ in vec4 X[];
+ in vec4 Y[];
+ in float w[];
+ in vec2 fanpoint[];
+
+ void main() {
+ // Locate our parametric point of interest. It is equal to the barycentric
+ // y-coordinate if we are a vertex on the tessellated edge of the triangle patch,
+ // 0.5 if we are the patch's interior vertex, or N/A if we are the fan point.
+ // NOTE: We are on the tessellated edge when the barycentric x-coordinate == 0.
+ float T = (gl_TessCoord.x == 0.0) ? gl_TessCoord.y : 0.5;
+
+ mat4x3 P = transpose(mat3x4(X[0], Y[0], 1,w[0],w[0],1));
+ vec2 vertexpos = eval_rational_cubic(P, T);
+
+ if (gl_TessCoord.x == 1.0) {
+ // We are the anchor point that fans from the center of the curve's contour.
+ vertexpos = fanpoint[0];
+ } else if (gl_TessCoord.x != 0.0) {
+ // We are the interior point of the patch; center it inside [C(0), C(.5), C(1)].
+ vertexpos = (P[0].xy + vertexpos + P[3].xy) / 3.0;
+ }
+
+ gl_Position = vec4(vertexpos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0);
+ })");
+
+ return code;
+ }
+ };
- return code;
+ return new WedgeImpl;
}
constexpr static int kMaxResolveLevel = GrTessellationPathRenderer::kMaxResolveLevel;
diff --git a/src/gpu/tessellate/GrStencilPathShader.h b/src/gpu/tessellate/GrStencilPathShader.h
index d5e7f7c04e..7236dea47b 100644
--- a/src/gpu/tessellate/GrStencilPathShader.h
+++ b/src/gpu/tessellate/GrStencilPathShader.h
@@ -114,14 +114,7 @@ public:
const char* name() const override { return "tessellate_GrCubicTessellateShader"; }
private:
- SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
- SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
+ GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override;
};
// Uses GPU tessellation shaders to linearize, triangulate, and render cubic "wedge" patches. A
@@ -137,14 +130,7 @@ public:
const char* name() const override { return "tessellate_GrWedgeTessellateShader"; }
private:
- SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
- SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
+ GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override;
};
// Uses indirect (instanced) draws to triangulate standalone closed cubics with a "middle-out"
diff --git a/src/gpu/tessellate/GrStrokeTessellateShader.cpp b/src/gpu/tessellate/GrStrokeTessellateShader.cpp
index 2ee59643a5..16b64ecf93 100644
--- a/src/gpu/tessellate/GrStrokeTessellateShader.cpp
+++ b/src/gpu/tessellate/GrStrokeTessellateShader.cpp
@@ -86,18 +86,6 @@ static void append_wangs_formula_fn(SkString* code, bool hasConics) {
}
class GrStrokeTessellateShader::TessellationImpl : public GrGLSLGeometryProcessor {
-public:
- const char* getTessArgsUniformName(const GrGLSLUniformHandler& uniformHandler) const {
- return uniformHandler.getUniformCStr(fTessArgsUniform);
- }
- const char* getTranslateUniformName(const GrGLSLUniformHandler& uniformHandler) const {
- return uniformHandler.getUniformCStr(fTranslateUniform);
- }
- const char* getAffineMatrixUniformName(const GrGLSLUniformHandler& uniformHandler) const {
- return uniformHandler.getUniformCStr(fAffineMatrixUniform);
- }
-
-private:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const auto& shader = args.fGeomProc.cast<GrStrokeTessellateShader>();
auto* uniHandler = args.fUniformHandler;
@@ -414,6 +402,16 @@ private:
args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
}
+ SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override;
+ SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
+ const char* versionAndExtensionDecls,
+ const GrGLSLUniformHandler&,
+ const GrShaderCaps&) const override;
+
+
void setData(const GrGLSLProgramDataManager& pdman,
const GrShaderCaps&,
const GrGeometryProcessor& geomProc) override {
@@ -461,13 +459,13 @@ private:
GrGLSLUniformHandler::UniformHandle fColorUniform;
};
-SkString GrStrokeTessellateShader::getTessControlShaderGLSL(
- const GrGLSLGeometryProcessor* glslGeomProc,
+SkString GrStrokeTessellateShader::TessellationImpl::getTessControlShaderGLSL(
+ const GrGeometryProcessor& geomProc,
const char* versionAndExtensionDecls,
const GrGLSLUniformHandler& uniformHandler,
const GrShaderCaps& shaderCaps) const {
- SkASSERT(fMode == Mode::kHardwareTessellation);
- auto impl = static_cast<const GrStrokeTessellateShader::TessellationImpl*>(glslGeomProc);
+ const auto& shader = geomProc.cast<GrStrokeTessellateShader>();
+ SkASSERT(shader.fMode == Mode::kHardwareTessellation);
SkString code(versionAndExtensionDecls);
// Run 3 invocations: 1 for each section that the vertex shader chopped the curve into.
@@ -483,8 +481,8 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL(
code.appendf("#define MAX_TESSELLATION_SEGMENTS %i.0\n", shaderCaps.maxTessellationSegments());
code.appendf("#define cross cross2d\n"); // GLSL already has a function named "cross".
- const char* tessArgsName = impl->getTessArgsUniformName(uniformHandler);
- if (!this->hasDynamicStroke()) {
+ const char* tessArgsName = uniformHandler.getUniformCStr(fTessArgsUniform);
+ if (!shader.hasDynamicStroke()) {
code.appendf("uniform vec4 %s;\n", tessArgsName);
code.appendf("#define PARAMETRIC_PRECISION %s.x\n", tessArgsName);
code.appendf("#define NUM_RADIAL_SEGMENTS_PER_RADIAN %s.y\n", tessArgsName);
@@ -495,7 +493,7 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL(
}
code.append(kLengthPow2Fn);
- append_wangs_formula_fn(&code, this->hasConics());
+ append_wangs_formula_fn(&code, shader.hasConics());
code.append(kAtan2Fn);
code.append(kCosineBetweenVectorsFn);
code.append(kMiterExtentFn);
@@ -514,11 +512,11 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL(
in vec4 vsPts89[];
in vec4 vsTans01[];
in vec4 vsTans23[];)");
- if (this->hasDynamicStroke()) {
+ if (shader.hasDynamicStroke()) {
code.append(R"(
in vec2 vsStrokeArgs[];)");
}
- if (this->hasDynamicColor()) {
+ if (shader.hasDynamicColor()) {
code.append(R"(
in mediump vec4 vsColor[];)");
}
@@ -531,11 +529,11 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL(
// prevJoinTangent.xy]
patch out vec4 tcsJoinArgs1; // [joinAngle0, radsPerJoinSegment, joinOutsetClamp.xy]
patch out vec4 tcsEndPtEndTan;)");
- if (this->hasDynamicStroke()) {
+ if (shader.hasDynamicStroke()) {
code.append(R"(
patch out float tcsStrokeRadius;)");
}
- if (this->hasDynamicColor()) {
+ if (shader.hasDynamicColor()) {
code.append(R"(
patch out mediump vec4 tcsColor;)");
}
@@ -545,11 +543,11 @@ SkString GrStrokeTessellateShader::getTessControlShaderGLSL(
// Forward join args to the evaluation stage.
tcsJoinArgs0 = vsJoinArgs0[0];
tcsJoinArgs1 = vsJoinArgs1[0];)");
- if (this->hasDynamicStroke()) {
+ if (shader.hasDynamicStroke()) {
code.append(R"(
tcsStrokeRadius = vsStrokeArgs[0].y;)");
}
- if (this->hasDynamicColor()) {
+ if (shader.hasDynamicColor()) {
code.append(R"(
tcsColor = vsColor[0];)");
}
@@ -821,13 +819,13 @@ static void append_eval_stroke_edge_fn(SkString* code, bool hasConics) {
})");
}
-SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL(
- const GrGLSLGeometryProcessor* glslGeomProc,
+SkString GrStrokeTessellateShader::TessellationImpl::getTessEvaluationShaderGLSL(
+ const GrGeometryProcessor& geomProc,
const char* versionAndExtensionDecls,
const GrGLSLUniformHandler& uniformHandler,
const GrShaderCaps& shaderCaps) const {
- SkASSERT(fMode == Mode::kHardwareTessellation);
- auto impl = static_cast<const GrStrokeTessellateShader::TessellationImpl*>(glslGeomProc);
+ const auto& shader = geomProc.cast<GrStrokeTessellateShader>();
+ SkASSERT(shader.fMode == Mode::kHardwareTessellation);
SkString code(versionAndExtensionDecls);
code.append("layout(quads, equal_spacing, ccw) in;\n");
@@ -843,22 +841,22 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL(
code.appendf("#define MAX_PARAMETRIC_SEGMENTS_LOG2 %i\n",
SkNextLog2(shaderCaps.maxTessellationSegments()));
- if (!this->hasDynamicStroke()) {
- const char* tessArgsName = impl->getTessArgsUniformName(uniformHandler);
+ if (!shader.hasDynamicStroke()) {
+ const char* tessArgsName = uniformHandler.getUniformCStr(fTessArgsUniform);
code.appendf("uniform vec4 %s;\n", tessArgsName);
code.appendf("#define STROKE_RADIUS %s.w\n", tessArgsName);
} else {
code.appendf("#define STROKE_RADIUS tcsStrokeRadius\n");
}
- if (!this->viewMatrix().isIdentity()) {
- const char* translateName = impl->getTranslateUniformName(uniformHandler);
+ if (!shader.viewMatrix().isIdentity()) {
+ const char* translateName = uniformHandler.getUniformCStr(fTranslateUniform);
code.appendf("uniform vec2 %s;\n", translateName);
code.appendf("#define TRANSLATE %s\n", translateName);
- if (!fStroke.isHairlineStyle()) {
+ if (!shader.fStroke.isHairlineStyle()) {
// In the normal case we need the affine matrix too. (In the hairline case we already
// applied the affine matrix in the vertex shader.)
- const char* affineMatrixName = impl->getAffineMatrixUniformName(uniformHandler);
+ const char* affineMatrixName = uniformHandler.getUniformCStr(fAffineMatrixUniform);
code.appendf("uniform vec4 %s;\n", affineMatrixName);
code.appendf("#define AFFINE_MATRIX mat2(%s)\n", affineMatrixName);
}
@@ -872,11 +870,11 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL(
// prevJoinTangent.xy]
patch in vec4 tcsJoinArgs1; // [joinAngle0, radsPerJoinSegment, joinOutsetClamp.xy]
patch in vec4 tcsEndPtEndTan;)");
- if (this->hasDynamicStroke()) {
+ if (shader.hasDynamicStroke()) {
code.append(R"(
patch in float tcsStrokeRadius;)");
}
- if (this->hasDynamicColor()) {
+ if (shader.hasDynamicColor()) {
code.appendf(R"(
patch in mediump vec4 tcsColor;
%s out mediump vec4 tesColor;)", shaderCaps.preferFlatInterpolation() ? "flat" : "");
@@ -886,7 +884,7 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL(
uniform vec4 sk_RTAdjust;)");
code.append(kUncheckedMixFn);
- append_eval_stroke_edge_fn(&code, this->hasConics());
+ append_eval_stroke_edge_fn(&code, shader.hasConics());
code.append(R"(
void main() {
@@ -937,7 +935,7 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL(
float w = -1.0; // w<0 means the curve is an integral cubic.)");
- if (this->hasConics()) {
+ if (shader.hasConics()) {
code.append(R"(
if (isinf(P[3].y)) {
w = P[3].x; // The curve is actually a conic.
@@ -971,8 +969,8 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL(
vec2 vertexPos = position + normalize(vec2(-tangent.y, tangent.x)) * outset;)");
- if (!this->viewMatrix().isIdentity()) {
- if (!fStroke.isHairlineStyle()) {
+ if (!shader.viewMatrix().isIdentity()) {
+ if (!shader.fStroke.isHairlineStyle()) {
// Normal case. Do the transform after tessellation.
code.append("vertexPos = AFFINE_MATRIX * vertexPos + TRANSLATE;");
} else {
@@ -984,7 +982,7 @@ SkString GrStrokeTessellateShader::getTessEvaluationShaderGLSL(
code.append(R"(
gl_Position = vec4(vertexPos * sk_RTAdjust.xz + sk_RTAdjust.yw, 0.0, 1.0);)");
- if (this->hasDynamicColor()) {
+ if (shader.hasDynamicColor()) {
code.append(R"(
tesColor = tcsColor;)");
}
diff --git a/src/gpu/tessellate/GrStrokeTessellateShader.h b/src/gpu/tessellate/GrStrokeTessellateShader.h
index 5b7118d3a4..9372a21e40 100644
--- a/src/gpu/tessellate/GrStrokeTessellateShader.h
+++ b/src/gpu/tessellate/GrStrokeTessellateShader.h
@@ -183,15 +183,6 @@ private:
void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override;
GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const final;
- SkString getTessControlShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
- SkString getTessEvaluationShaderGLSL(const GrGLSLGeometryProcessor*,
- const char* versionAndExtensionDecls,
- const GrGLSLUniformHandler&,
- const GrShaderCaps&) const override;
-
const Mode fMode;
const ShaderFlags fShaderFlags;
const SkStrokeRec fStroke;
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index 96d55cd065..4e25999745 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -409,7 +409,7 @@ std::tuple<bool, int> GlyphVector::regenerateAtlas(int begin, int end,
}
// Update atlas generation if there are no more glyphs to put in the atlas.
- if (success && begin + glyphsPlacedInAtlas == fGlyphs.count()) {
+ if (success && begin + glyphsPlacedInAtlas == SkCount(fGlyphs)) {
// Need to get the freshest value of the atlas' generation because
// updateTextureCoordinates may have changed it.
fAtlasGeneration = atlasManager->atlasGeneration(maskFormat);
@@ -418,7 +418,7 @@ std::tuple<bool, int> GlyphVector::regenerateAtlas(int begin, int end,
return {success, glyphsPlacedInAtlas};
} else {
// The atlas hasn't changed, so our texture coordinates are still valid.
- if (end == fGlyphs.count()) {
+ if (end == SkCount(fGlyphs)) {
// The atlas hasn't changed and the texture coordinates are all still valid. Update
// all the plots used to the new use token.
atlasManager->setUseTokenBulk(fBulkUseToken,
@@ -584,7 +584,7 @@ size_t DirectMaskSubRun::vertexStride(const SkMatrix&) const {
}
int DirectMaskSubRun::glyphCount() const {
- return fGlyphs.glyphs().count();
+ return SkCount(fGlyphs.glyphs());
}
namespace {
@@ -1059,7 +1059,7 @@ size_t TransformedMaskSubRun::vertexStride(const SkMatrix& drawMatrix) const {
}
int TransformedMaskSubRun::glyphCount() const {
- return fVertexData.count();
+ return SkCount(fVertexData);
}
SkRect TransformedMaskSubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
@@ -1327,7 +1327,7 @@ void SDFTSubRun::fillVertexData(
}
int SDFTSubRun::glyphCount() const {
- return fVertexData.count();
+ return SkCount(fVertexData);
}
SkRect SDFTSubRun::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
@@ -1743,7 +1743,7 @@ size_t DirectMaskSubRunNoCache::vertexStride(const SkMatrix&) const {
}
int DirectMaskSubRunNoCache::glyphCount() const {
- return fGlyphs.glyphs().count();
+ return SkCount(fGlyphs.glyphs());
}
std::tuple<const GrClip*, GrOp::Owner>
@@ -2076,7 +2076,7 @@ size_t TransformedMaskSubRunNoCache::vertexStride(const SkMatrix& drawMatrix) co
}
int TransformedMaskSubRunNoCache::glyphCount() const {
- return fVertexData.count();
+ return SkCount(fVertexData);
}
SkRect TransformedMaskSubRunNoCache::deviceRect(
@@ -2269,7 +2269,7 @@ void SDFTSubRunNoCache::fillVertexData(
}
int SDFTSubRunNoCache::glyphCount() const {
- return fVertexData.count();
+ return SkCount(fVertexData);
}
SkRect SDFTSubRunNoCache::deviceRect(const SkMatrix& drawMatrix, SkPoint drawOrigin) const {
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index b0db7efba6..cea30b033b 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -2037,7 +2037,7 @@ void GrVkGpu::prepareSurfacesForBackendAccessAndStateUpdates(
// only time we have multiple proxies is if we are flushing a yuv SkImage which won't have
// state updates anyways. Additionally if we have a newState than we must not have any
// BackendSurfaceAccess.
- SkASSERT(!newState || proxies.count() == 1);
+ SkASSERT(!newState || proxies.size() == 1);
SkASSERT(!newState || access == SkSurface::BackendSurfaceAccess::kNoAccess);
GrVkImage* image;
for (GrSurfaceProxy* proxy : proxies) {
diff --git a/src/ports/SkFontHost_FreeType_common.cpp b/src/ports/SkFontHost_FreeType_common.cpp
index 805eafaec7..120a29eb0e 100644
--- a/src/ports/SkFontHost_FreeType_common.cpp
+++ b/src/ports/SkFontHost_FreeType_common.cpp
@@ -491,6 +491,28 @@ inline SkPoint SkVectorProjection(SkPoint a, SkPoint b) {
void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette,
FT_COLR_Paint colrv1_paint, SkPaint* paint) {
+ auto fetch_color_stops = [&face, &palette](FT_ColorStopIterator& color_stop_iterator,
+ std::vector<SkScalar>& stops,
+ std::vector<SkColor>& colors) {
+ const FT_UInt num_color_stops = color_stop_iterator.num_color_stops;
+ stops.resize(num_color_stops);
+ colors.resize(num_color_stops);
+
+ FT_ColorStop color_stop;
+ while (FT_Get_Colorline_Stops(face, &color_stop, &color_stop_iterator)) {
+ FT_UInt index = color_stop_iterator.current_color_stop - 1;
+ stops[index] = color_stop.stop_offset / float(1 << 14);
+ FT_UInt16& palette_index = color_stop.color.palette_index;
+ // TODO(drott): Ensure palette_index is sanitized on the FreeType
+ // side and 0xFFFF foreground color will be handled correctly here.
+ colors[index] = SkColorSetARGB(
+ palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha),
+ palette[palette_index].red,
+ palette[palette_index].green,
+ palette[palette_index].blue);
+ }
+ };
+
switch (colrv1_paint.format) {
case FT_COLR_PAINTFORMAT_SOLID: {
SkColor color =
@@ -529,31 +551,12 @@ void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette,
perpendicular_to_p2_p0 = SkPoint::Make(perpendicular_to_p2_p0.y(), -perpendicular_to_p2_p0.x());
line_positions[1] = p0 + SkVectorProjection((p1 - p0), perpendicular_to_p2_p0);
- /* populate points */
- const FT_UInt num_color_stops =
- colrv1_paint.u.linear_gradient.colorline.color_stop_iterator.num_color_stops;
std::vector<SkScalar> stops;
std::vector<SkColor> colors;
- stops.resize(num_color_stops);
- colors.resize(num_color_stops);
-
- FT_ColorStop color_stop;
- while (FT_Get_Colorline_Stops(
- face, &color_stop,
- &colrv1_paint.u.linear_gradient.colorline.color_stop_iterator)) {
- FT_UInt index = colrv1_paint.u.linear_gradient.colorline.color_stop_iterator
- .current_color_stop -
- 1;
- stops[index] = color_stop.stop_offset / float(1 << 14);
- FT_UInt16& palette_index = color_stop.color.palette_index;
- colors[index] = SkColorSetARGB(
- palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha),
- palette[palette_index].red, palette[palette_index].green,
- palette[palette_index].blue);
- }
+ fetch_color_stops(colrv1_paint.u.linear_gradient.colorline.color_stop_iterator, stops, colors);
sk_sp<SkShader> shader(SkGradientShader::MakeLinear(
- line_positions, colors.data(), stops.data(), num_color_stops,
+ line_positions, colors.data(), stops.data(), stops.size(),
ToSkTileMode(colrv1_paint.u.linear_gradient.colorline.extend)));
SkASSERT(shader);
// An opaque color is needed to ensure the gradient's not modulated by alpha.
@@ -572,33 +575,16 @@ void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette,
-colrv1_paint.u.radial_gradient.c1.y);
SkScalar end_radius = colrv1_paint.u.radial_gradient.r1;
- const FT_UInt num_color_stops =
- colrv1_paint.u.radial_gradient.colorline.color_stop_iterator.num_color_stops;
+
std::vector<SkScalar> stops;
std::vector<SkColor> colors;
- stops.resize(num_color_stops);
- colors.resize(num_color_stops);
-
- FT_ColorStop color_stop;
- while (FT_Get_Colorline_Stops(
- face, &color_stop,
- &colrv1_paint.u.radial_gradient.colorline.color_stop_iterator)) {
- FT_UInt index = colrv1_paint.u.radial_gradient.colorline.color_stop_iterator
- .current_color_stop -
- 1;
- stops[index] = color_stop.stop_offset / float(1 << 14);
- FT_UInt16& palette_index = color_stop.color.palette_index;
- colors[index] = SkColorSetARGB(
- palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha),
- palette[palette_index].red, palette[palette_index].green,
- palette[palette_index].blue);
- }
+ fetch_color_stops(colrv1_paint.u.radial_gradient.colorline.color_stop_iterator, stops, colors);
// An opaque color is needed to ensure the gradient's not modulated by alpha.
paint->setColor(SK_ColorBLACK);
paint->setShader(SkGradientShader::MakeTwoPointConical(
- start, radius, end, end_radius, colors.data(), stops.data(), num_color_stops,
+ start, radius, end, end_radius, colors.data(), stops.data(), stops.size(),
ToSkTileMode(colrv1_paint.u.radial_gradient.colorline.extend)));
break;
}
@@ -608,27 +594,9 @@ void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette,
SkScalar startAngle = SkFixedToScalar(colrv1_paint.u.sweep_gradient.start_angle);
SkScalar endAngle = SkFixedToScalar(colrv1_paint.u.sweep_gradient.end_angle);
- const FT_UInt num_color_stops =
- colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator.num_color_stops;
std::vector<SkScalar> stops;
std::vector<SkColor> colors;
- stops.resize(num_color_stops);
- colors.resize(num_color_stops);
-
- FT_ColorStop color_stop;
- while (FT_Get_Colorline_Stops(
- face, &color_stop,
- &colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator)) {
- FT_UInt index = colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator
- .current_color_stop -
- 1;
- stops[index] = color_stop.stop_offset / float(1 << 14);
- FT_UInt16& palette_index = color_stop.color.palette_index;
- colors[index] = SkColorSetARGB(
- palette[palette_index].alpha * SkColrV1AlphaToFloat(color_stop.color.alpha),
- palette[palette_index].red, palette[palette_index].green,
- palette[palette_index].blue);
- }
+ fetch_color_stops(colrv1_paint.u.sweep_gradient.colorline.color_stop_iterator, stops, colors);
// An opaque color is needed to ensure the gradient's not modulated by alpha.
paint->setColor(SK_ColorBLACK);
@@ -655,7 +623,7 @@ void colrv1_configure_skpaint(FT_Face face, const FT_Color* palette,
angle_adjust.postScale(-1, 1, center.x(), center.y());
paint->setShader(SkGradientShader::MakeSweep(
- center.x(), center.y(), colors.data(), stops.data(), num_color_stops,
+ center.x(), center.y(), colors.data(), stops.data(), stops.size(),
SkTileMode::kDecal, startAngle, endAngle, 0, &angle_adjust));
break;
}
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 6f2d6fb352..78758238a7 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -41,7 +41,6 @@ namespace dsl {
}
class ExternalFunction;
-class ExternalValue;
class FunctionCall;
class StructDefinition;
struct ParsedModule;
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index ca4a0d7ef9..0df361928d 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -95,7 +95,6 @@ void Parser::InitLayoutMap() {
TOKEN(INPUT_ATTACHMENT_INDEX, "input_attachment_index");
TOKEN(ORIGIN_UPPER_LEFT, "origin_upper_left");
TOKEN(OVERRIDE_COVERAGE, "override_coverage");
- TOKEN(EARLY_FRAGMENT_TESTS, "early_fragment_tests");
TOKEN(BLEND_SUPPORT_ALL_EQUATIONS, "blend_support_all_equations");
TOKEN(PUSH_CONSTANT, "push_constant");
TOKEN(POINTS, "points");
@@ -920,9 +919,6 @@ Layout Parser::layout() {
case LayoutToken::OVERRIDE_COVERAGE:
setFlag(Layout::kOverrideCoverage_Flag);
break;
- case LayoutToken::EARLY_FRAGMENT_TESTS:
- setFlag(Layout::kEarlyFragmentTests_Flag);
- break;
case LayoutToken::PUSH_CONSTANT:
setFlag(Layout::kPushConstant_Flag);
break;
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index 6131940dbb..701e4a7220 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -38,7 +38,6 @@ public:
INPUT_ATTACHMENT_INDEX,
ORIGIN_UPPER_LEFT,
OVERRIDE_COVERAGE,
- EARLY_FRAGMENT_TESTS,
BLEND_SUPPORT_ALL_EQUATIONS,
PUSH_CONSTANT,
POINTS,
diff --git a/src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp b/src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp
index e545e622c0..f1646d09be 100644
--- a/src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLDSLCPPCodeGenerator.cpp
@@ -32,6 +32,8 @@ static const char* get_scalar_type_name(const Context& context, const Type& type
return "Float";
} else if (type.isSigned()) {
return "Int";
+ } else if (type.isUnsigned()) {
+ return "UInt";
} else if (type.isBoolean()) {
return "Bool";
}
diff --git a/src/sksl/dsl/DSLCore.cpp b/src/sksl/dsl/DSLCore.cpp
index d5e162d914..cfaaecf013 100644
--- a/src/sksl/dsl/DSLCore.cpp
+++ b/src/sksl/dsl/DSLCore.cpp
@@ -204,6 +204,18 @@ DSLStatement Continue() {
return DSLCore::Continue();
}
+// Logically, we'd want the variable's initial value to appear on here in Declare, since that
+// matches how we actually write code (and in fact that was what our first attempt looked like).
+// Unfortunately, C++ doesn't guarantee execution order between arguments, and Declare() can appear
+// as a function argument in constructs like Block(Declare(x, 0), foo(x)). If these are executed out
+// of order, we will evaluate the reference to x before we evaluate Declare(x, 0), and thus the
+// variable's initial value is unknown at the point of reference. There are probably some other
+// issues with this as well, but it is particularly dangerous when x is const, since SkSL will
+// expect its value to be known when it is referenced and will end up asserting, dereferencing a
+// null pointer, or possibly doing something else awful.
+//
+// So, we put the initial value onto the Var itself instead of the Declare to guarantee that it is
+// always executed in the correct order.
DSLStatement Declare(DSLVar& var, PositionInfo pos) {
return DSLCore::Declare(var, pos);
}
diff --git a/src/sksl/generated/sksl_fp.dehydrated.sksl b/src/sksl/generated/sksl_fp.dehydrated.sksl
index 1467aeac6b..e032778633 100644
--- a/src/sksl/generated/sksl_fp.dehydrated.sksl
+++ b/src/sksl/generated/sksl_fp.dehydrated.sksl
@@ -27,25 +27,25 @@ static uint8_t SKSL_INCLUDE_sksl_fp[] = {255,0,
22,2,0,17,0,
53,3,0,
37,
-36,0,32,0,0,255,255,255,255,255,15,0,255,255,255,255,30,0,0,2,31,0,
+36,0,16,0,0,255,255,255,255,255,15,0,255,255,255,255,30,0,0,2,31,0,
50,4,0,44,0,0,
0,5,0,
47,4,0,1,
53,6,0,
37,
-36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,51,0,
+36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,51,0,
47,5,0,0,
53,7,0,
37,
-36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,67,0,
+36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,67,0,
50,8,0,84,0,0,
53,9,0,
37,
-36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,90,0,
+36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,90,0,
47,8,0,0,
53,10,0,
37,
-36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,110,0,
+36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,30,0,0,0,110,0,
47,8,0,0,
53,11,0,
16,135,0,
diff --git a/src/sksl/generated/sksl_frag.dehydrated.sksl b/src/sksl/generated/sksl_frag.dehydrated.sksl
index 12bd60b1f9..5477418509 100644
--- a/src/sksl/generated/sksl_frag.dehydrated.sksl
+++ b/src/sksl/generated/sksl_frag.dehydrated.sksl
@@ -11,23 +11,23 @@ static uint8_t SKSL_INCLUDE_sksl_frag[] = {100,0,
49,5,0,
53,1,0,
37,
-36,0,32,0,0,255,255,255,255,255,15,0,255,255,255,255,2,0,0,2,3,0,
+36,0,16,0,0,255,255,255,255,255,15,0,255,255,255,255,2,0,0,2,3,0,
50,2,0,16,0,0,
53,3,0,
37,
-36,0,32,0,0,255,255,255,255,255,17,0,255,255,255,255,2,0,0,2,23,0,
+36,0,16,0,0,255,255,255,255,255,17,0,255,255,255,255,2,0,0,2,23,0,
50,4,0,36,0,0,
53,5,0,
37,
-36,0,32,0,0,255,255,255,255,255,15,39,255,255,255,255,2,0,0,4,41,0,
+36,0,16,0,0,255,255,255,255,255,15,39,255,255,255,255,2,0,0,4,41,0,
50,6,0,66,0,0,
53,7,0,
37,
-36,0,41,0,0,0,255,255,0,255,17,39,255,255,255,255,2,0,0,4,72,0,
+36,128,20,0,0,0,255,255,0,255,17,39,255,255,255,255,2,0,0,4,72,0,
47,6,0,0,
53,8,0,
37,
-36,0,32,0,0,255,255,255,255,255,24,39,255,255,255,255,2,0,0,0,85,0,
+36,0,16,0,0,255,255,255,255,255,24,39,255,255,255,255,2,0,0,0,85,0,
47,6,0,0,5,0,
2,0,
1,0,
diff --git a/src/sksl/generated/sksl_geom.dehydrated.sksl b/src/sksl/generated/sksl_geom.dehydrated.sksl
index 100fbc2da6..91b9f04613 100644
--- a/src/sksl/generated/sksl_geom.dehydrated.sksl
+++ b/src/sksl/generated/sksl_geom.dehydrated.sksl
@@ -16,26 +16,26 @@ static uint8_t SKSL_INCLUDE_sksl_geom[] = {134,0,
49,12,0,
44,1,0,2,0,2,
37,
-36,0,32,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0,
+36,0,16,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0,
50,2,0,28,0,
37,
-36,0,32,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0,
+36,0,16,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0,
50,3,0,48,0,
53,4,0,
37,
-36,0,32,0,0,255,255,255,255,255,18,39,255,255,255,255,15,0,0,2,54,0,
+36,0,16,0,0,255,255,255,255,255,18,39,255,255,255,255,15,0,0,2,54,0,
0,5,0,
47,1,0,255,0,
44,6,0,2,0,2,
37,
-36,0,32,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0,
+36,0,16,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0,
47,2,0,
37,
-36,0,32,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0,
+36,0,16,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0,
47,3,0,
53,7,0,
37,
-36,0,32,0,0,255,255,255,255,255,23,39,255,255,255,255,15,0,0,4,2,0,
+36,0,16,0,0,255,255,255,255,255,23,39,255,255,255,255,15,0,0,4,2,0,
47,6,0,0,
24,7,0,0,
24,7,0,1,
diff --git a/src/sksl/generated/sksl_rt_shader.dehydrated.sksl b/src/sksl/generated/sksl_rt_shader.dehydrated.sksl
index f0e0516dd5..d9392d90ff 100644
--- a/src/sksl/generated/sksl_rt_shader.dehydrated.sksl
+++ b/src/sksl/generated/sksl_rt_shader.dehydrated.sksl
@@ -14,7 +14,7 @@ static uint8_t SKSL_INCLUDE_sksl_rt_shader[] = {77,0,
49,8,0,
53,1,0,
37,
-36,0,32,0,0,255,255,255,255,255,15,0,255,255,255,255,2,0,0,0,3,0,
+36,0,16,0,0,255,255,255,255,255,15,0,255,255,255,255,2,0,0,0,3,0,
50,2,0,16,0,0,
53,3,0,
16,23,0,
diff --git a/src/sksl/generated/sksl_vert.dehydrated.sksl b/src/sksl/generated/sksl_vert.dehydrated.sksl
index 4d1d64caaf..4f950edc8b 100644
--- a/src/sksl/generated/sksl_vert.dehydrated.sksl
+++ b/src/sksl/generated/sksl_vert.dehydrated.sksl
@@ -11,10 +11,10 @@ static uint8_t SKSL_INCLUDE_sksl_vert[] = {82,0,
49,6,0,
44,1,0,2,0,2,
37,
-36,0,32,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0,
+36,0,16,0,0,255,255,255,255,255,0,0,255,255,255,255,15,0,0,0,16,0,
50,2,0,28,0,
37,
-36,0,32,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0,
+36,0,16,0,0,255,255,255,255,255,1,0,255,255,255,255,15,0,0,0,35,0,
50,3,0,48,0,
53,4,0,
37,
@@ -24,11 +24,11 @@ static uint8_t SKSL_INCLUDE_sksl_vert[] = {82,0,
24,4,0,1,
53,5,0,
37,
-36,0,32,0,0,255,255,255,255,255,42,0,255,255,255,255,15,0,0,2,54,0,
+36,0,16,0,0,255,255,255,255,255,42,0,255,255,255,255,15,0,0,2,54,0,
50,6,0,66,0,0,
53,7,0,
37,
-36,0,32,0,0,255,255,255,255,255,43,0,255,255,255,255,15,0,0,2,70,0,
+36,0,16,0,0,255,255,255,255,255,43,0,255,255,255,255,15,0,0,2,70,0,
47,6,0,0,4,0,
5,0,
3,0,
diff --git a/src/sksl/ir/SkSLFunctionCall.cpp b/src/sksl/ir/SkSLFunctionCall.cpp
index 1f6e774fae..63384ad735 100644
--- a/src/sksl/ir/SkSLFunctionCall.cpp
+++ b/src/sksl/ir/SkSLFunctionCall.cpp
@@ -81,44 +81,89 @@ static std::unique_ptr<Expression> optimize_comparison(const Context& context,
SkASSERT(arguments.size() == 2);
const Expression* left = ConstantFolder::GetConstantValueForVariable(*arguments[0]);
const Expression* right = ConstantFolder::GetConstantValueForVariable(*arguments[1]);
+ const Type& type = left->type().componentType();
- if (left->type().componentType().isFloat()) {
+ if (type.isFloat()) {
return optimize_comparison_of_type<FloatLiteral>(context, *left, *right, compare);
}
- if (left->type().componentType().isInteger()) {
+ if (type.isInteger()) {
return optimize_comparison_of_type<IntLiteral>(context, *left, *right, compare);
}
- SkDEBUGFAILF("unsupported type %s", left->type().description().c_str());
+ SkDEBUGFAILF("unsupported type %s", type.description().c_str());
return nullptr;
}
-using Float1Fn = float (*)(float);
-static std::unique_ptr<Expression> evaluate_intrinsic_float1(const Context& context,
- const ExpressionArray& arguments,
- const Float1Fn& evaluate) {
- SkASSERT(arguments.size() == 1);
- const Expression* arg = ConstantFolder::GetConstantValueForVariable(*arguments.front());
+template <typename LITERAL, typename FN>
+static std::unique_ptr<Expression> evaluate_intrinsic_1_of_type(const Context& context,
+ const Expression* arg,
+ const FN& evaluate) {
const Type& vecType = arg->type();
const Type& type = vecType.componentType();
+ SkASSERT(type.isScalar());
- if (type.isFloat()) {
- ExpressionArray result;
- result.reserve_back(vecType.columns());
-
- for (int index = 0; index < vecType.columns(); ++index) {
- const Expression* subexpr = arg->getConstantSubexpression(index);
- SkASSERT(subexpr);
- float value = evaluate(subexpr->as<FloatLiteral>().value());
- result.push_back(FloatLiteral::Make(subexpr->fOffset, value, &type));
- }
+ ExpressionArray result;
+ result.reserve_back(vecType.columns());
- return ConstructorCompound::Make(context, arg->fOffset, vecType, std::move(result));
+ for (int index = 0; index < vecType.columns(); ++index) {
+ const Expression* subexpr = arg->getConstantSubexpression(index);
+ SkASSERT(subexpr);
+ auto value = evaluate(subexpr->as<LITERAL>().value());
+ result.push_back(LITERAL::Make(subexpr->fOffset, value, &type));
}
+ return ConstructorCompound::Make(context, arg->fOffset, vecType, std::move(result));
+}
+
+template <typename FN,
+ bool kSupportsFloat = true,
+ bool kSupportsInt = true,
+ bool kSupportsBool = false>
+static std::unique_ptr<Expression> evaluate_intrinsic_generic1(const Context& context,
+ const ExpressionArray& arguments,
+ const FN& evaluate) {
+ SkASSERT(arguments.size() == 1);
+ const Expression* arg = ConstantFolder::GetConstantValueForVariable(*arguments.front());
+ const Type& type = arg->type().componentType();
+
+ if constexpr (kSupportsFloat) {
+ if (type.isFloat()) {
+ return evaluate_intrinsic_1_of_type<FloatLiteral>(context, arg, evaluate);
+ }
+ }
+ if constexpr (kSupportsInt) {
+ if (type.isInteger()) {
+ return evaluate_intrinsic_1_of_type<IntLiteral>(context, arg, evaluate);
+ }
+ }
+ if constexpr (kSupportsBool) {
+ if (type.isBoolean()) {
+ return evaluate_intrinsic_1_of_type<BoolLiteral>(context, arg, evaluate);
+ }
+ }
SkDEBUGFAILF("unsupported type %s", type.description().c_str());
return nullptr;
}
+template <typename FN>
+static std::unique_ptr<Expression> evaluate_intrinsic_float1(const Context& context,
+ const ExpressionArray& arguments,
+ const FN& evaluate) {
+ return evaluate_intrinsic_generic1<FN,
+ /*kSupportsFloat=*/true,
+ /*kSupportsInt=*/false,
+ /*kSupportsBool=*/false>(context, arguments, evaluate);
+}
+
+template <typename FN>
+static std::unique_ptr<Expression> evaluate_intrinsic_bool1(const Context& context,
+ const ExpressionArray& arguments,
+ const FN& evaluate) {
+ return evaluate_intrinsic_generic1<FN,
+ /*kSupportsFloat=*/false,
+ /*kSupportsInt=*/false,
+ /*kSupportsBool=*/true>(context, arguments, evaluate);
+}
+
static std::unique_ptr<Expression> optimize_intrinsic_call(const Context& context,
IntrinsicKind intrinsic,
const ExpressionArray& arguments) {
@@ -129,6 +174,9 @@ static std::unique_ptr<Expression> optimize_intrinsic_call(const Context& contex
case k_any_IntrinsicKind:
return coalesce_bool_vector(arguments, /*startingState=*/false,
[](bool a, bool b) { return a || b; });
+ case k_not_IntrinsicKind:
+ return evaluate_intrinsic_bool1(context, arguments, [](bool a) { return !a; });
+
case k_greaterThan_IntrinsicKind:
return optimize_comparison(context, arguments, [](auto a, auto b) { return a > b; });
@@ -147,6 +195,12 @@ static std::unique_ptr<Expression> optimize_intrinsic_call(const Context& contex
case k_notEqual_IntrinsicKind:
return optimize_comparison(context, arguments, [](auto a, auto b) { return a != b; });
+ case k_abs_IntrinsicKind:
+ return evaluate_intrinsic_generic1(context, arguments, [](auto a) { return abs(a); });
+
+ case k_sign_IntrinsicKind:
+ return evaluate_intrinsic_generic1(context, arguments,
+ [](auto a) { return (a > 0) - (a < 0); });
case k_sin_IntrinsicKind:
return evaluate_intrinsic_float1(context, arguments, [](float a) { return sin(a); });
diff --git a/tests/AnimatedImageTest.cpp b/tests/AnimatedImageTest.cpp
index 180573adde..91c6606f18 100644
--- a/tests/AnimatedImageTest.cpp
+++ b/tests/AnimatedImageTest.cpp
@@ -48,6 +48,41 @@ DEF_TEST(AnimatedImage_simple, r) {
REPORTER_ASSERT(r, animatedImage);
}
+DEF_TEST(AnimatedImage_rotation, r) {
+ if (GetResourcePath().isEmpty()) {
+ return;
+ }
+
+ // These images use different exif orientations to achieve the same final
+ // dimensions
+ const auto expectedBounds = SkRect::MakeIWH(100, 80);
+ for (int i = 1; i <=8; i++) {
+ for (const SkString& name : { SkStringPrintf("images/orientation/%d.webp", i),
+ SkStringPrintf("images/orientation/%d_444.jpg", i) }) {
+
+ const char* file = name.c_str();
+ auto data = GetResourceAsData(file);
+ if (!data) {
+ ERRORF(r, "Could not get %s", file);
+ return;
+ }
+
+ auto androidCodec = SkAndroidCodec::MakeFromData(std::move(data));
+ auto animatedImage = SkAnimatedImage::Make(std::move(androidCodec));
+ if (!animatedImage) {
+ ERRORF(r, "Failed to create animated image from %s", file);
+ return;
+ }
+
+ auto bounds = animatedImage->getBounds();
+ if (bounds != expectedBounds) {
+ ERRORF(r, "Mismatched bounds for %", file);
+ bounds.dump();
+ }
+ }
+ }
+}
+
DEF_TEST(AnimatedImage_invalidCrop, r) {
if (GetResourcePath().isEmpty()) {
return;
diff --git a/tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp b/tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp
index 0b7c5f3dd1..ad94d7e846 100644
--- a/tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp
+++ b/tests/sksl/dslfp/GrDSLFPTest_ForStatement.dsl.cpp
@@ -31,10 +31,13 @@ Var _color(kNo_Modifier, DSLType(kHalf4_Type), "color", _colorWhite);
Var _a(kNo_Modifier, DSLType(kHalf_Type), "a", 0.0f);
Var _r(kNo_Modifier, DSLType(kHalf_Type), "r", -5.0f);
Var _b(kNo_Modifier, DSLType(kHalf_Type), "b", 5.0f);
+Var _x(kNo_Modifier, DSLType(kUInt_Type), "x", 0u);
+Var _y(kNo_Modifier, DSLType(kUInt_Type), "y", 1u);
Declare(_color);
For(Declare(_a), _a <= 1.0f, ++_a, /*Body:*/ _color.w() = _a);
For(Declare(_r), _r < 5.0f, _r += 1.0f, /*Body:*/ Block(_color.x() = _r, If(_color.x() == 0.0f, /*Then:*/ Break())));
For(Declare(_b), _b >= 0.0f, _b -= 1.0f, /*Body:*/ Block(_color.z() = _b, If(_color.w() == 1.0f, /*Then:*/ Continue()), _color.y() = 0.0f));
+Block(Declare(_x), Declare(_y), For(Statement(), _x <= _y, ++_x, /*Body:*/ Block(_color.w() = Half(_x))));
Return(_color);
EndFragmentProcessor();
}
diff --git a/tests/sksl/errors/LayoutRepeatedQualifiers.glsl b/tests/sksl/errors/LayoutRepeatedQualifiers.glsl
index 917d9219e5..5ceeaed0d9 100644
--- a/tests/sksl/errors/LayoutRepeatedQualifiers.glsl
+++ b/tests/sksl/errors/LayoutRepeatedQualifiers.glsl
@@ -1,22 +1,21 @@
### Compilation failed:
-error: 22: layout qualifier 'origin_upper_left' appears more than once
-error: 23: layout qualifier 'override_coverage' appears more than once
-error: 24: layout qualifier 'early_fragment_tests' appears more than once
-error: 25: layout qualifier 'push_constant' appears more than once
-error: 26: layout qualifier 'blend_support_all_equations' appears more than once
-error: 27: layout qualifier 'tracked' appears more than once
-error: 28: layout qualifier 'srgb_unpremul' appears more than once
-error: 29: layout qualifier 'key' appears more than once
-error: 30: layout qualifier 'location' appears more than once
-error: 31: layout qualifier 'offset' appears more than once
-error: 32: layout qualifier 'binding' appears more than once
-error: 33: layout qualifier 'index' appears more than once
-error: 34: layout qualifier 'set' appears more than once
-error: 35: layout qualifier 'builtin' appears more than once
-error: 36: layout qualifier 'input_attachment_index' appears more than once
-error: 37: layout qualifier 'max_vertices' appears more than once
-error: 38: layout qualifier 'invocations' appears more than once
-error: 39: layout qualifier 'when' appears more than once
-error: 40: layout qualifier 'ctype' appears more than once
-19 errors
+error: 21: layout qualifier 'origin_upper_left' appears more than once
+error: 22: layout qualifier 'override_coverage' appears more than once
+error: 23: layout qualifier 'push_constant' appears more than once
+error: 24: layout qualifier 'blend_support_all_equations' appears more than once
+error: 25: layout qualifier 'tracked' appears more than once
+error: 26: layout qualifier 'srgb_unpremul' appears more than once
+error: 27: layout qualifier 'key' appears more than once
+error: 28: layout qualifier 'location' appears more than once
+error: 29: layout qualifier 'offset' appears more than once
+error: 30: layout qualifier 'binding' appears more than once
+error: 31: layout qualifier 'index' appears more than once
+error: 32: layout qualifier 'set' appears more than once
+error: 33: layout qualifier 'builtin' appears more than once
+error: 34: layout qualifier 'input_attachment_index' appears more than once
+error: 35: layout qualifier 'max_vertices' appears more than once
+error: 36: layout qualifier 'invocations' appears more than once
+error: 37: layout qualifier 'when' appears more than once
+error: 38: layout qualifier 'ctype' appears more than once
+18 errors
diff --git a/tests/sksl/folding/BoolFolding.glsl b/tests/sksl/folding/BoolFolding.glsl
index a598aecea2..6aea1a5053 100644
--- a/tests/sksl/folding/BoolFolding.glsl
+++ b/tests/sksl/folding/BoolFolding.glsl
@@ -17,5 +17,7 @@ vec4 main() {
bool _13_l = false;
bool _14_m = true;
bool _15_n = false;
- return ((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _12_k) && !_13_l) && _14_m) && !_15_n ? colorGreen : colorRed;
+ bool _16_o = true;
+ bool _17_p = false;
+ return ((((((((((((((_0_a && !_1_b) && _2_c) && !_3_d) && _4_e) && !_5_f) && _6_g) && !_7_h) && _8_i) && !_9_j) && _12_k) && !_13_l) && _14_m) && !_15_n) && _16_o) && !_17_p ? colorGreen : colorRed;
}
diff --git a/tests/sksl/inliner/StaticSwitch.glsl b/tests/sksl/inliner/StaticSwitch.glsl
index 89ac653966..8f8b42e91a 100644
--- a/tests/sksl/inliner/StaticSwitch.glsl
+++ b/tests/sksl/inliner/StaticSwitch.glsl
@@ -4,9 +4,9 @@ uniform vec4 colorGreen;
uniform vec4 colorRed;
float get_f() {
{
- return abs(2.0);
+ return 2.0;
}
- return abs(5.0);
+ return 5.0;
}
vec4 main() {
float result = get_f();
diff --git a/tests/sksl/intrinsics/AbsFloat.asm.frag b/tests/sksl/intrinsics/AbsFloat.asm.frag
index baf68482e5..98df218500 100644
--- a/tests/sksl/intrinsics/AbsFloat.asm.frag
+++ b/tests/sksl/intrinsics/AbsFloat.asm.frag
@@ -45,9 +45,18 @@ OpDecorate %63 RelaxedPrecision
OpDecorate %70 RelaxedPrecision
OpDecorate %72 RelaxedPrecision
OpDecorate %73 RelaxedPrecision
-OpDecorate %84 RelaxedPrecision
+OpDecorate %80 RelaxedPrecision
+OpDecorate %81 RelaxedPrecision
+OpDecorate %86 RelaxedPrecision
OpDecorate %87 RelaxedPrecision
OpDecorate %88 RelaxedPrecision
+OpDecorate %94 RelaxedPrecision
+OpDecorate %95 RelaxedPrecision
+OpDecorate %96 RelaxedPrecision
+OpDecorate %102 RelaxedPrecision
+OpDecorate %112 RelaxedPrecision
+OpDecorate %115 RelaxedPrecision
+OpDecorate %116 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -78,6 +87,8 @@ OpDecorate %88 RelaxedPrecision
%v3float = OpTypeVector %float 3
%v3bool = OpTypeVector %bool 3
%v4bool = OpTypeVector %bool 4
+%86 = OpConstantComposite %v2float %float_1_25 %float_0
+%94 = OpConstantComposite %v3float %float_1_25 %float_0 %float_0_75
%int_1 = OpConstant %int 1
%int_2 = OpConstant %int 2
%_entrypoint_v = OpFunction %void None %15
@@ -92,7 +103,7 @@ OpFunctionEnd
%24 = OpFunctionParameter %_ptr_Function_v2float
%25 = OpLabel
%expected = OpVariable %_ptr_Function_v4float Function
-%78 = OpVariable %_ptr_Function_v4float Function
+%106 = OpVariable %_ptr_Function_v4float Function
OpStore %expected %31
%34 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%38 = OpLoad %v4float %34
@@ -141,19 +152,57 @@ OpBranchConditional %67 %68 %69
OpBranch %69
%69 = OpLabel
%77 = OpPhi %bool %false %56 %76 %68
-OpSelectionMerge %81 None
-OpBranchConditional %77 %79 %80
+OpSelectionMerge %79 None
+OpBranchConditional %77 %78 %79
+%78 = OpLabel
+%80 = OpLoad %v4float %expected
+%81 = OpCompositeExtract %float %80 0
+%82 = OpFOrdEqual %bool %float_1_25 %81
+OpBranch %79
%79 = OpLabel
-%82 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
-%84 = OpLoad %v4float %82
-OpStore %78 %84
-OpBranch %81
-%80 = OpLabel
-%85 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
-%87 = OpLoad %v4float %85
-OpStore %78 %87
-OpBranch %81
-%81 = OpLabel
-%88 = OpLoad %v4float %78
-OpReturnValue %88
+%83 = OpPhi %bool %false %69 %82 %78
+OpSelectionMerge %85 None
+OpBranchConditional %83 %84 %85
+%84 = OpLabel
+%87 = OpLoad %v4float %expected
+%88 = OpVectorShuffle %v2float %87 %87 0 1
+%89 = OpFOrdEqual %v2bool %86 %88
+%90 = OpAll %bool %89
+OpBranch %85
+%85 = OpLabel
+%91 = OpPhi %bool %false %79 %90 %84
+OpSelectionMerge %93 None
+OpBranchConditional %91 %92 %93
+%92 = OpLabel
+%95 = OpLoad %v4float %expected
+%96 = OpVectorShuffle %v3float %95 %95 0 1 2
+%97 = OpFOrdEqual %v3bool %94 %96
+%98 = OpAll %bool %97
+OpBranch %93
+%93 = OpLabel
+%99 = OpPhi %bool %false %85 %98 %92
+OpSelectionMerge %101 None
+OpBranchConditional %99 %100 %101
+%100 = OpLabel
+%102 = OpLoad %v4float %expected
+%103 = OpFOrdEqual %v4bool %31 %102
+%104 = OpAll %bool %103
+OpBranch %101
+%101 = OpLabel
+%105 = OpPhi %bool %false %93 %104 %100
+OpSelectionMerge %109 None
+OpBranchConditional %105 %107 %108
+%107 = OpLabel
+%110 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%112 = OpLoad %v4float %110
+OpStore %106 %112
+OpBranch %109
+%108 = OpLabel
+%113 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%115 = OpLoad %v4float %113
+OpStore %106 %115
+OpBranch %109
+%109 = OpLabel
+%116 = OpLoad %v4float %106
+OpReturnValue %116
OpFunctionEnd
diff --git a/tests/sksl/intrinsics/AbsFloat.glsl b/tests/sksl/intrinsics/AbsFloat.glsl
index d8ebb3fa2d..46a3d6b11c 100644
--- a/tests/sksl/intrinsics/AbsFloat.glsl
+++ b/tests/sksl/intrinsics/AbsFloat.glsl
@@ -5,5 +5,5 @@ uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
vec4 expected = vec4(1.25, 0.0, 0.75, 2.25);
- return ((abs(testInputs.x) == expected.x && abs(testInputs.xy) == expected.xy) && abs(testInputs.xyz) == expected.xyz) && abs(testInputs) == expected ? colorGreen : colorRed;
+ return ((((((abs(testInputs.x) == expected.x && abs(testInputs.xy) == expected.xy) && abs(testInputs.xyz) == expected.xyz) && abs(testInputs) == expected) && 1.25 == expected.x) && vec2(1.25, 0.0) == expected.xy) && vec3(1.25, 0.0, 0.75) == expected.xyz) && vec4(1.25, 0.0, 0.75, 2.25) == expected ? colorGreen : colorRed;
}
diff --git a/tests/sksl/intrinsics/AbsFloat.metal b/tests/sksl/intrinsics/AbsFloat.metal
index 4b829a97ac..93020cac8c 100644
--- a/tests/sksl/intrinsics/AbsFloat.metal
+++ b/tests/sksl/intrinsics/AbsFloat.metal
@@ -16,6 +16,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
Outputs _out;
(void)_out;
float4 expected = float4(1.25, 0.0, 0.75, 2.25);
- _out.sk_FragColor = ((abs(_uniforms.testInputs.x) == expected.x && all(abs(_uniforms.testInputs.xy) == expected.xy)) && all(abs(_uniforms.testInputs.xyz) == expected.xyz)) && all(abs(_uniforms.testInputs) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
+ _out.sk_FragColor = ((((((abs(_uniforms.testInputs.x) == expected.x && all(abs(_uniforms.testInputs.xy) == expected.xy)) && all(abs(_uniforms.testInputs.xyz) == expected.xyz)) && all(abs(_uniforms.testInputs) == expected)) && 1.25 == expected.x) && all(float2(1.25, 0.0) == expected.xy)) && all(float3(1.25, 0.0, 0.75) == expected.xyz)) && all(float4(1.25, 0.0, 0.75, 2.25) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}
diff --git a/tests/sksl/intrinsics/AbsInt.asm.frag b/tests/sksl/intrinsics/AbsInt.asm.frag
index d31bc058b8..7db6b5d3ce 100644
--- a/tests/sksl/intrinsics/AbsInt.asm.frag
+++ b/tests/sksl/intrinsics/AbsInt.asm.frag
@@ -41,9 +41,9 @@ OpDecorate %88 RelaxedPrecision
OpDecorate %90 RelaxedPrecision
OpDecorate %92 RelaxedPrecision
OpDecorate %94 RelaxedPrecision
-OpDecorate %108 RelaxedPrecision
-OpDecorate %110 RelaxedPrecision
-OpDecorate %111 RelaxedPrecision
+OpDecorate %136 RelaxedPrecision
+OpDecorate %138 RelaxedPrecision
+OpDecorate %139 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -76,6 +76,8 @@ OpDecorate %111 RelaxedPrecision
%v3int = OpTypeVector %int 3
%v3bool = OpTypeVector %bool 3
%v4bool = OpTypeVector %bool 4
+%110 = OpConstantComposite %v2int %int_1 %int_0
+%118 = OpConstantComposite %v3int %int_1 %int_0 %int_0
%_ptr_Function_v4float = OpTypePointer Function %v4float
%_entrypoint_v = OpFunction %void None %15
%16 = OpLabel
@@ -89,7 +91,7 @@ OpFunctionEnd
%24 = OpFunctionParameter %_ptr_Function_v2float
%25 = OpLabel
%expected = OpVariable %_ptr_Function_v4int Function
-%102 = OpVariable %_ptr_Function_v4float Function
+%130 = OpVariable %_ptr_Function_v4float Function
OpStore %expected %33
%36 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%38 = OpLoad %v4float %36
@@ -160,19 +162,57 @@ OpBranchConditional %82 %83 %84
OpBranch %84
%84 = OpLabel
%101 = OpPhi %bool %false %63 %100 %83
-OpSelectionMerge %106 None
-OpBranchConditional %101 %104 %105
-%104 = OpLabel
-%107 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
-%108 = OpLoad %v4float %107
-OpStore %102 %108
-OpBranch %106
-%105 = OpLabel
-%109 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
-%110 = OpLoad %v4float %109
-OpStore %102 %110
-OpBranch %106
-%106 = OpLabel
-%111 = OpLoad %v4float %102
-OpReturnValue %111
+OpSelectionMerge %103 None
+OpBranchConditional %101 %102 %103
+%102 = OpLabel
+%104 = OpLoad %v4int %expected
+%105 = OpCompositeExtract %int %104 0
+%106 = OpIEqual %bool %int_1 %105
+OpBranch %103
+%103 = OpLabel
+%107 = OpPhi %bool %false %84 %106 %102
+OpSelectionMerge %109 None
+OpBranchConditional %107 %108 %109
+%108 = OpLabel
+%111 = OpLoad %v4int %expected
+%112 = OpVectorShuffle %v2int %111 %111 0 1
+%113 = OpIEqual %v2bool %110 %112
+%114 = OpAll %bool %113
+OpBranch %109
+%109 = OpLabel
+%115 = OpPhi %bool %false %103 %114 %108
+OpSelectionMerge %117 None
+OpBranchConditional %115 %116 %117
+%116 = OpLabel
+%119 = OpLoad %v4int %expected
+%120 = OpVectorShuffle %v3int %119 %119 0 1 2
+%121 = OpIEqual %v3bool %118 %120
+%122 = OpAll %bool %121
+OpBranch %117
+%117 = OpLabel
+%123 = OpPhi %bool %false %109 %122 %116
+OpSelectionMerge %125 None
+OpBranchConditional %123 %124 %125
+%124 = OpLabel
+%126 = OpLoad %v4int %expected
+%127 = OpIEqual %v4bool %33 %126
+%128 = OpAll %bool %127
+OpBranch %125
+%125 = OpLabel
+%129 = OpPhi %bool %false %117 %128 %124
+OpSelectionMerge %134 None
+OpBranchConditional %129 %132 %133
+%132 = OpLabel
+%135 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%136 = OpLoad %v4float %135
+OpStore %130 %136
+OpBranch %134
+%133 = OpLabel
+%137 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%138 = OpLoad %v4float %137
+OpStore %130 %138
+OpBranch %134
+%134 = OpLabel
+%139 = OpLoad %v4float %130
+OpReturnValue %139
OpFunctionEnd
diff --git a/tests/sksl/intrinsics/AbsInt.glsl b/tests/sksl/intrinsics/AbsInt.glsl
index b032933b41..f5da94f649 100644
--- a/tests/sksl/intrinsics/AbsInt.glsl
+++ b/tests/sksl/intrinsics/AbsInt.glsl
@@ -5,5 +5,5 @@ uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
ivec4 expected = ivec4(1, 0, 0, 2);
- return ((abs(int(testInputs.x)) == expected.x && abs(ivec2(testInputs.xy)) == expected.xy) && abs(ivec3(testInputs.xyz)) == expected.xyz) && abs(ivec4(testInputs)) == expected ? colorGreen : colorRed;
+ return ((((((abs(int(testInputs.x)) == expected.x && abs(ivec2(testInputs.xy)) == expected.xy) && abs(ivec3(testInputs.xyz)) == expected.xyz) && abs(ivec4(testInputs)) == expected) && 1 == expected.x) && ivec2(1, 0) == expected.xy) && ivec3(1, 0, 0) == expected.xyz) && ivec4(1, 0, 0, 2) == expected ? colorGreen : colorRed;
}
diff --git a/tests/sksl/intrinsics/AbsInt.metal b/tests/sksl/intrinsics/AbsInt.metal
index 21747e9221..4a97949234 100644
--- a/tests/sksl/intrinsics/AbsInt.metal
+++ b/tests/sksl/intrinsics/AbsInt.metal
@@ -16,6 +16,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
Outputs _out;
(void)_out;
int4 expected = int4(1, 0, 0, 2);
- _out.sk_FragColor = ((abs(int(_uniforms.testInputs.x)) == expected.x && all(abs(int2(_uniforms.testInputs.xy)) == expected.xy)) && all(abs(int3(_uniforms.testInputs.xyz)) == expected.xyz)) && all(abs(int4(_uniforms.testInputs)) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
+ _out.sk_FragColor = ((((((abs(int(_uniforms.testInputs.x)) == expected.x && all(abs(int2(_uniforms.testInputs.xy)) == expected.xy)) && all(abs(int3(_uniforms.testInputs.xyz)) == expected.xyz)) && all(abs(int4(_uniforms.testInputs)) == expected)) && 1 == expected.x) && all(int2(1, 0) == expected.xy)) && all(int3(1, 0, 0) == expected.xyz)) && all(int4(1, 0, 0, 2) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}
diff --git a/tests/sksl/intrinsics/All.asm.frag b/tests/sksl/intrinsics/All.asm.frag
index be5aaf7857..5b3112f7ab 100644
--- a/tests/sksl/intrinsics/All.asm.frag
+++ b/tests/sksl/intrinsics/All.asm.frag
@@ -1,18 +1,56 @@
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise
-OpExecutionMode %main OriginUpperLeft
+OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
+OpExecutionMode %_entrypoint_v OriginUpperLeft
OpName %sk_FragColor "sk_FragColor"
OpName %sk_Clockwise "sk_Clockwise"
-OpName %a "a"
+OpName %_UniformBuffer "_UniformBuffer"
+OpMemberName %_UniformBuffer 0 "inputH4"
+OpMemberName %_UniformBuffer 1 "expectedH4"
+OpMemberName %_UniformBuffer 2 "colorGreen"
+OpMemberName %_UniformBuffer 3 "colorRed"
+OpName %_entrypoint_v "_entrypoint_v"
OpName %main "main"
+OpName %input "input"
+OpName %expected "expected"
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
OpDecorate %sk_Clockwise BuiltIn FrontFacing
-OpDecorate %17 RelaxedPrecision
-OpDecorate %22 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 0 Offset 0
+OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 1 Offset 16
+OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 2 Offset 32
+OpMemberDecorate %_UniformBuffer 2 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 3 Offset 48
+OpMemberDecorate %_UniformBuffer 3 RelaxedPrecision
+OpDecorate %_UniformBuffer Block
+OpDecorate %10 Binding 0
+OpDecorate %10 DescriptorSet 0
+OpDecorate %33 RelaxedPrecision
+OpDecorate %34 RelaxedPrecision
+OpDecorate %36 RelaxedPrecision
+OpDecorate %38 RelaxedPrecision
+OpDecorate %40 RelaxedPrecision
+OpDecorate %46 RelaxedPrecision
+OpDecorate %47 RelaxedPrecision
+OpDecorate %49 RelaxedPrecision
+OpDecorate %51 RelaxedPrecision
+OpDecorate %53 RelaxedPrecision
+OpDecorate %58 RelaxedPrecision
+OpDecorate %61 RelaxedPrecision
+OpDecorate %67 RelaxedPrecision
+OpDecorate %70 RelaxedPrecision
+OpDecorate %77 RelaxedPrecision
+OpDecorate %78 RelaxedPrecision
+OpDecorate %84 RelaxedPrecision
+OpDecorate %89 RelaxedPrecision
+OpDecorate %95 RelaxedPrecision
+OpDecorate %106 RelaxedPrecision
+OpDecorate %109 RelaxedPrecision
+OpDecorate %110 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -20,22 +58,134 @@ OpDecorate %22 RelaxedPrecision
%bool = OpTypeBool
%_ptr_Input_bool = OpTypePointer Input %bool
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
-%v4bool = OpTypeVector %bool 4
-%_ptr_Private_v4bool = OpTypePointer Private %v4bool
-%a = OpVariable %_ptr_Private_v4bool Private
+%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float %v4float
+%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
+%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
%void = OpTypeVoid
-%14 = OpTypeFunction %void
+%15 = OpTypeFunction %void
+%v2float = OpTypeVector %float 2
+%float_0 = OpConstant %float 0
+%19 = OpConstantComposite %v2float %float_0 %float_0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%23 = OpTypeFunction %v4float %_ptr_Function_v2float
+%v4bool = OpTypeVector %bool 4
+%_ptr_Function_v4bool = OpTypePointer Function %v4bool
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
%int_0 = OpConstant %int 0
-%_ptr_Output_float = OpTypePointer Output %float
-%main = OpFunction %void None %14
-%15 = OpLabel
-%17 = OpLoad %v4bool %a
-%16 = OpAll %bool %17
-%18 = OpSelect %int %16 %int_1 %int_0
-%22 = OpConvertSToF %float %18
-%23 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0
-OpStore %23 %22
+%int_1 = OpConstant %int 1
+%false = OpConstantFalse %bool
+%v2bool = OpTypeVector %bool 2
+%v3bool = OpTypeVector %bool 3
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%_entrypoint_v = OpFunction %void None %15
+%16 = OpLabel
+%20 = OpVariable %_ptr_Function_v2float Function
+OpStore %20 %19
+%22 = OpFunctionCall %v4float %main %20
+OpStore %sk_FragColor %22
OpReturn
OpFunctionEnd
+%main = OpFunction %v4float None %23
+%24 = OpFunctionParameter %_ptr_Function_v2float
+%25 = OpLabel
+%input = OpVariable %_ptr_Function_v4bool Function
+%expected = OpVariable %_ptr_Function_v4bool Function
+%99 = OpVariable %_ptr_Function_v4float Function
+%29 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%33 = OpLoad %v4float %29
+%34 = OpCompositeExtract %float %33 0
+%35 = OpFUnordNotEqual %bool %34 %float_0
+%36 = OpCompositeExtract %float %33 1
+%37 = OpFUnordNotEqual %bool %36 %float_0
+%38 = OpCompositeExtract %float %33 2
+%39 = OpFUnordNotEqual %bool %38 %float_0
+%40 = OpCompositeExtract %float %33 3
+%41 = OpFUnordNotEqual %bool %40 %float_0
+%42 = OpCompositeConstruct %v4bool %35 %37 %39 %41
+OpStore %input %42
+%44 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%46 = OpLoad %v4float %44
+%47 = OpCompositeExtract %float %46 0
+%48 = OpFUnordNotEqual %bool %47 %float_0
+%49 = OpCompositeExtract %float %46 1
+%50 = OpFUnordNotEqual %bool %49 %float_0
+%51 = OpCompositeExtract %float %46 2
+%52 = OpFUnordNotEqual %bool %51 %float_0
+%53 = OpCompositeExtract %float %46 3
+%54 = OpFUnordNotEqual %bool %53 %float_0
+%55 = OpCompositeConstruct %v4bool %48 %50 %52 %54
+OpStore %expected %55
+%58 = OpLoad %v4bool %input
+%59 = OpVectorShuffle %v2bool %58 %58 0 1
+%57 = OpAll %bool %59
+%61 = OpLoad %v4bool %expected
+%62 = OpCompositeExtract %bool %61 0
+%63 = OpLogicalEqual %bool %57 %62
+OpSelectionMerge %65 None
+OpBranchConditional %63 %64 %65
+%64 = OpLabel
+%67 = OpLoad %v4bool %input
+%68 = OpVectorShuffle %v3bool %67 %67 0 1 2
+%66 = OpAll %bool %68
+%70 = OpLoad %v4bool %expected
+%71 = OpCompositeExtract %bool %70 1
+%72 = OpLogicalEqual %bool %66 %71
+OpBranch %65
+%65 = OpLabel
+%73 = OpPhi %bool %false %25 %72 %64
+OpSelectionMerge %75 None
+OpBranchConditional %73 %74 %75
+%74 = OpLabel
+%77 = OpLoad %v4bool %input
+%76 = OpAll %bool %77
+%78 = OpLoad %v4bool %expected
+%79 = OpCompositeExtract %bool %78 2
+%80 = OpLogicalEqual %bool %76 %79
+OpBranch %75
+%75 = OpLabel
+%81 = OpPhi %bool %false %65 %80 %74
+OpSelectionMerge %83 None
+OpBranchConditional %81 %82 %83
+%82 = OpLabel
+%84 = OpLoad %v4bool %expected
+%85 = OpCompositeExtract %bool %84 0
+OpBranch %83
+%83 = OpLabel
+%86 = OpPhi %bool %false %75 %85 %82
+OpSelectionMerge %88 None
+OpBranchConditional %86 %87 %88
+%87 = OpLabel
+%89 = OpLoad %v4bool %expected
+%90 = OpCompositeExtract %bool %89 1
+%91 = OpLogicalEqual %bool %false %90
+OpBranch %88
+%88 = OpLabel
+%92 = OpPhi %bool %false %83 %91 %87
+OpSelectionMerge %94 None
+OpBranchConditional %92 %93 %94
+%93 = OpLabel
+%95 = OpLoad %v4bool %expected
+%96 = OpCompositeExtract %bool %95 2
+%97 = OpLogicalEqual %bool %false %96
+OpBranch %94
+%94 = OpLabel
+%98 = OpPhi %bool %false %88 %97 %93
+OpSelectionMerge %103 None
+OpBranchConditional %98 %101 %102
+%101 = OpLabel
+%104 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%106 = OpLoad %v4float %104
+OpStore %99 %106
+OpBranch %103
+%102 = OpLabel
+%107 = OpAccessChain %_ptr_Uniform_v4float %10 %int_3
+%109 = OpLoad %v4float %107
+OpStore %99 %109
+OpBranch %103
+%103 = OpLabel
+%110 = OpLoad %v4float %99
+OpReturnValue %110
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/All.glsl b/tests/sksl/intrinsics/All.glsl
index e7db8f69f7..c524ee64e5 100644
--- a/tests/sksl/intrinsics/All.glsl
+++ b/tests/sksl/intrinsics/All.glsl
@@ -1,6 +1,11 @@
out vec4 sk_FragColor;
-bvec4 a;
-void main() {
- sk_FragColor.x = float(all(a) ? 1 : 0);
+uniform vec4 inputH4;
+uniform vec4 expectedH4;
+uniform vec4 colorGreen;
+uniform vec4 colorRed;
+vec4 main() {
+ bvec4 input = bvec4(inputH4);
+ bvec4 expected = bvec4(expectedH4);
+ return ((((all(input.xy) == expected.x && all(input.xyz) == expected.y) && all(input) == expected.z) && expected.x) && false == expected.y) && false == expected.z ? colorGreen : colorRed;
}
diff --git a/tests/sksl/intrinsics/All.metal b/tests/sksl/intrinsics/All.metal
index d521a14996..8412515a54 100644
--- a/tests/sksl/intrinsics/All.metal
+++ b/tests/sksl/intrinsics/All.metal
@@ -1,19 +1,23 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
+struct Uniforms {
+ float4 inputH4;
+ float4 expectedH4;
+ float4 colorGreen;
+ float4 colorRed;
+};
struct Inputs {
};
struct Outputs {
float4 sk_FragColor [[color(0)]];
};
-struct Globals {
- bool4 a;
-};
-fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
- Globals _globals{{}};
- (void)_globals;
+
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
Outputs _out;
(void)_out;
- _out.sk_FragColor.x = float(all(_globals.a) ? 1 : 0);
+ bool4 input = bool4(_uniforms.inputH4);
+ bool4 expected = bool4(_uniforms.expectedH4);
+ _out.sk_FragColor = ((((all(input.xy) == expected.x && all(input.xyz) == expected.y) && all(input) == expected.z) && expected.x) && false == expected.y) && false == expected.z ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}
diff --git a/tests/sksl/intrinsics/Any.asm.frag b/tests/sksl/intrinsics/Any.asm.frag
index d924998f5a..7424a93ee1 100644
--- a/tests/sksl/intrinsics/Any.asm.frag
+++ b/tests/sksl/intrinsics/Any.asm.frag
@@ -1,18 +1,56 @@
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise
-OpExecutionMode %main OriginUpperLeft
+OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
+OpExecutionMode %_entrypoint_v OriginUpperLeft
OpName %sk_FragColor "sk_FragColor"
OpName %sk_Clockwise "sk_Clockwise"
-OpName %a "a"
+OpName %_UniformBuffer "_UniformBuffer"
+OpMemberName %_UniformBuffer 0 "inputH4"
+OpMemberName %_UniformBuffer 1 "expectedH4"
+OpMemberName %_UniformBuffer 2 "colorGreen"
+OpMemberName %_UniformBuffer 3 "colorRed"
+OpName %_entrypoint_v "_entrypoint_v"
OpName %main "main"
+OpName %input "input"
+OpName %expected "expected"
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
OpDecorate %sk_Clockwise BuiltIn FrontFacing
-OpDecorate %17 RelaxedPrecision
-OpDecorate %22 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 0 Offset 0
+OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 1 Offset 16
+OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 2 Offset 32
+OpMemberDecorate %_UniformBuffer 2 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 3 Offset 48
+OpMemberDecorate %_UniformBuffer 3 RelaxedPrecision
+OpDecorate %_UniformBuffer Block
+OpDecorate %10 Binding 0
+OpDecorate %10 DescriptorSet 0
+OpDecorate %33 RelaxedPrecision
+OpDecorate %34 RelaxedPrecision
+OpDecorate %36 RelaxedPrecision
+OpDecorate %38 RelaxedPrecision
+OpDecorate %40 RelaxedPrecision
+OpDecorate %46 RelaxedPrecision
+OpDecorate %47 RelaxedPrecision
+OpDecorate %49 RelaxedPrecision
+OpDecorate %51 RelaxedPrecision
+OpDecorate %53 RelaxedPrecision
+OpDecorate %58 RelaxedPrecision
+OpDecorate %61 RelaxedPrecision
+OpDecorate %67 RelaxedPrecision
+OpDecorate %70 RelaxedPrecision
+OpDecorate %77 RelaxedPrecision
+OpDecorate %78 RelaxedPrecision
+OpDecorate %84 RelaxedPrecision
+OpDecorate %90 RelaxedPrecision
+OpDecorate %95 RelaxedPrecision
+OpDecorate %105 RelaxedPrecision
+OpDecorate %108 RelaxedPrecision
+OpDecorate %109 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -20,22 +58,133 @@ OpDecorate %22 RelaxedPrecision
%bool = OpTypeBool
%_ptr_Input_bool = OpTypePointer Input %bool
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
-%v4bool = OpTypeVector %bool 4
-%_ptr_Private_v4bool = OpTypePointer Private %v4bool
-%a = OpVariable %_ptr_Private_v4bool Private
+%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float %v4float
+%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
+%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
%void = OpTypeVoid
-%14 = OpTypeFunction %void
+%15 = OpTypeFunction %void
+%v2float = OpTypeVector %float 2
+%float_0 = OpConstant %float 0
+%19 = OpConstantComposite %v2float %float_0 %float_0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%23 = OpTypeFunction %v4float %_ptr_Function_v2float
+%v4bool = OpTypeVector %bool 4
+%_ptr_Function_v4bool = OpTypePointer Function %v4bool
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
%int_0 = OpConstant %int 0
-%_ptr_Output_float = OpTypePointer Output %float
-%main = OpFunction %void None %14
-%15 = OpLabel
-%17 = OpLoad %v4bool %a
-%16 = OpAny %bool %17
-%18 = OpSelect %int %16 %int_1 %int_0
-%22 = OpConvertSToF %float %18
-%23 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0
-OpStore %23 %22
+%int_1 = OpConstant %int 1
+%false = OpConstantFalse %bool
+%v2bool = OpTypeVector %bool 2
+%v3bool = OpTypeVector %bool 3
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%_entrypoint_v = OpFunction %void None %15
+%16 = OpLabel
+%20 = OpVariable %_ptr_Function_v2float Function
+OpStore %20 %19
+%22 = OpFunctionCall %v4float %main %20
+OpStore %sk_FragColor %22
OpReturn
OpFunctionEnd
+%main = OpFunction %v4float None %23
+%24 = OpFunctionParameter %_ptr_Function_v2float
+%25 = OpLabel
+%input = OpVariable %_ptr_Function_v4bool Function
+%expected = OpVariable %_ptr_Function_v4bool Function
+%98 = OpVariable %_ptr_Function_v4float Function
+%29 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%33 = OpLoad %v4float %29
+%34 = OpCompositeExtract %float %33 0
+%35 = OpFUnordNotEqual %bool %34 %float_0
+%36 = OpCompositeExtract %float %33 1
+%37 = OpFUnordNotEqual %bool %36 %float_0
+%38 = OpCompositeExtract %float %33 2
+%39 = OpFUnordNotEqual %bool %38 %float_0
+%40 = OpCompositeExtract %float %33 3
+%41 = OpFUnordNotEqual %bool %40 %float_0
+%42 = OpCompositeConstruct %v4bool %35 %37 %39 %41
+OpStore %input %42
+%44 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%46 = OpLoad %v4float %44
+%47 = OpCompositeExtract %float %46 0
+%48 = OpFUnordNotEqual %bool %47 %float_0
+%49 = OpCompositeExtract %float %46 1
+%50 = OpFUnordNotEqual %bool %49 %float_0
+%51 = OpCompositeExtract %float %46 2
+%52 = OpFUnordNotEqual %bool %51 %float_0
+%53 = OpCompositeExtract %float %46 3
+%54 = OpFUnordNotEqual %bool %53 %float_0
+%55 = OpCompositeConstruct %v4bool %48 %50 %52 %54
+OpStore %expected %55
+%58 = OpLoad %v4bool %input
+%59 = OpVectorShuffle %v2bool %58 %58 0 1
+%57 = OpAny %bool %59
+%61 = OpLoad %v4bool %expected
+%62 = OpCompositeExtract %bool %61 0
+%63 = OpLogicalEqual %bool %57 %62
+OpSelectionMerge %65 None
+OpBranchConditional %63 %64 %65
+%64 = OpLabel
+%67 = OpLoad %v4bool %input
+%68 = OpVectorShuffle %v3bool %67 %67 0 1 2
+%66 = OpAny %bool %68
+%70 = OpLoad %v4bool %expected
+%71 = OpCompositeExtract %bool %70 1
+%72 = OpLogicalEqual %bool %66 %71
+OpBranch %65
+%65 = OpLabel
+%73 = OpPhi %bool %false %25 %72 %64
+OpSelectionMerge %75 None
+OpBranchConditional %73 %74 %75
+%74 = OpLabel
+%77 = OpLoad %v4bool %input
+%76 = OpAny %bool %77
+%78 = OpLoad %v4bool %expected
+%79 = OpCompositeExtract %bool %78 2
+%80 = OpLogicalEqual %bool %76 %79
+OpBranch %75
+%75 = OpLabel
+%81 = OpPhi %bool %false %65 %80 %74
+OpSelectionMerge %83 None
+OpBranchConditional %81 %82 %83
+%82 = OpLabel
+%84 = OpLoad %v4bool %expected
+%85 = OpCompositeExtract %bool %84 0
+%86 = OpLogicalEqual %bool %false %85
+OpBranch %83
+%83 = OpLabel
+%87 = OpPhi %bool %false %75 %86 %82
+OpSelectionMerge %89 None
+OpBranchConditional %87 %88 %89
+%88 = OpLabel
+%90 = OpLoad %v4bool %expected
+%91 = OpCompositeExtract %bool %90 1
+OpBranch %89
+%89 = OpLabel
+%92 = OpPhi %bool %false %83 %91 %88
+OpSelectionMerge %94 None
+OpBranchConditional %92 %93 %94
+%93 = OpLabel
+%95 = OpLoad %v4bool %expected
+%96 = OpCompositeExtract %bool %95 2
+OpBranch %94
+%94 = OpLabel
+%97 = OpPhi %bool %false %89 %96 %93
+OpSelectionMerge %102 None
+OpBranchConditional %97 %100 %101
+%100 = OpLabel
+%103 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%105 = OpLoad %v4float %103
+OpStore %98 %105
+OpBranch %102
+%101 = OpLabel
+%106 = OpAccessChain %_ptr_Uniform_v4float %10 %int_3
+%108 = OpLoad %v4float %106
+OpStore %98 %108
+OpBranch %102
+%102 = OpLabel
+%109 = OpLoad %v4float %98
+OpReturnValue %109
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/Any.glsl b/tests/sksl/intrinsics/Any.glsl
index 41d3671e74..e78bcb128e 100644
--- a/tests/sksl/intrinsics/Any.glsl
+++ b/tests/sksl/intrinsics/Any.glsl
@@ -1,6 +1,11 @@
out vec4 sk_FragColor;
-bvec4 a;
-void main() {
- sk_FragColor.x = float(any(a) ? 1 : 0);
+uniform vec4 inputH4;
+uniform vec4 expectedH4;
+uniform vec4 colorGreen;
+uniform vec4 colorRed;
+vec4 main() {
+ bvec4 input = bvec4(inputH4);
+ bvec4 expected = bvec4(expectedH4);
+ return ((((any(input.xy) == expected.x && any(input.xyz) == expected.y) && any(input) == expected.z) && false == expected.x) && expected.y) && expected.z ? colorGreen : colorRed;
}
diff --git a/tests/sksl/intrinsics/Any.metal b/tests/sksl/intrinsics/Any.metal
index 402e25b8bb..b21eb7f5da 100644
--- a/tests/sksl/intrinsics/Any.metal
+++ b/tests/sksl/intrinsics/Any.metal
@@ -1,19 +1,23 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
+struct Uniforms {
+ float4 inputH4;
+ float4 expectedH4;
+ float4 colorGreen;
+ float4 colorRed;
+};
struct Inputs {
};
struct Outputs {
float4 sk_FragColor [[color(0)]];
};
-struct Globals {
- bool4 a;
-};
-fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
- Globals _globals{{}};
- (void)_globals;
+
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
Outputs _out;
(void)_out;
- _out.sk_FragColor.x = float(any(_globals.a) ? 1 : 0);
+ bool4 input = bool4(_uniforms.inputH4);
+ bool4 expected = bool4(_uniforms.expectedH4);
+ _out.sk_FragColor = ((((any(input.xy) == expected.x && any(input.xyz) == expected.y) && any(input) == expected.z) && false == expected.x) && expected.y) && expected.z ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}
diff --git a/tests/sksl/intrinsics/Not.asm.frag b/tests/sksl/intrinsics/Not.asm.frag
index 5cb4270384..d217a18722 100644
--- a/tests/sksl/intrinsics/Not.asm.frag
+++ b/tests/sksl/intrinsics/Not.asm.frag
@@ -1,18 +1,56 @@
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise
-OpExecutionMode %main OriginUpperLeft
+OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
+OpExecutionMode %_entrypoint_v OriginUpperLeft
OpName %sk_FragColor "sk_FragColor"
OpName %sk_Clockwise "sk_Clockwise"
-OpName %a "a"
+OpName %_UniformBuffer "_UniformBuffer"
+OpMemberName %_UniformBuffer 0 "inputH4"
+OpMemberName %_UniformBuffer 1 "expectedH4"
+OpMemberName %_UniformBuffer 2 "colorGreen"
+OpMemberName %_UniformBuffer 3 "colorRed"
+OpName %_entrypoint_v "_entrypoint_v"
OpName %main "main"
+OpName %input "input"
+OpName %expected "expected"
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
OpDecorate %sk_Clockwise BuiltIn FrontFacing
-OpDecorate %17 RelaxedPrecision
-OpDecorate %23 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 0 Offset 0
+OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 1 Offset 16
+OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 2 Offset 32
+OpMemberDecorate %_UniformBuffer 2 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 3 Offset 48
+OpMemberDecorate %_UniformBuffer 3 RelaxedPrecision
+OpDecorate %_UniformBuffer Block
+OpDecorate %10 Binding 0
+OpDecorate %10 DescriptorSet 0
+OpDecorate %33 RelaxedPrecision
+OpDecorate %34 RelaxedPrecision
+OpDecorate %36 RelaxedPrecision
+OpDecorate %38 RelaxedPrecision
+OpDecorate %40 RelaxedPrecision
+OpDecorate %46 RelaxedPrecision
+OpDecorate %47 RelaxedPrecision
+OpDecorate %49 RelaxedPrecision
+OpDecorate %51 RelaxedPrecision
+OpDecorate %53 RelaxedPrecision
+OpDecorate %58 RelaxedPrecision
+OpDecorate %61 RelaxedPrecision
+OpDecorate %68 RelaxedPrecision
+OpDecorate %71 RelaxedPrecision
+OpDecorate %79 RelaxedPrecision
+OpDecorate %80 RelaxedPrecision
+OpDecorate %88 RelaxedPrecision
+OpDecorate %96 RelaxedPrecision
+OpDecorate %104 RelaxedPrecision
+OpDecorate %115 RelaxedPrecision
+OpDecorate %118 RelaxedPrecision
+OpDecorate %119 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -20,23 +58,143 @@ OpDecorate %23 RelaxedPrecision
%bool = OpTypeBool
%_ptr_Input_bool = OpTypePointer Input %bool
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
-%v4bool = OpTypeVector %bool 4
-%_ptr_Private_v4bool = OpTypePointer Private %v4bool
-%a = OpVariable %_ptr_Private_v4bool Private
+%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float %v4float
+%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
+%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
%void = OpTypeVoid
-%14 = OpTypeFunction %void
+%15 = OpTypeFunction %void
+%v2float = OpTypeVector %float 2
+%float_0 = OpConstant %float 0
+%19 = OpConstantComposite %v2float %float_0 %float_0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%23 = OpTypeFunction %v4float %_ptr_Function_v2float
+%v4bool = OpTypeVector %bool 4
+%_ptr_Function_v4bool = OpTypePointer Function %v4bool
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%int = OpTypeInt 32 1
-%int_1 = OpConstant %int 1
%int_0 = OpConstant %int 0
-%_ptr_Output_float = OpTypePointer Output %float
-%main = OpFunction %void None %14
-%15 = OpLabel
-%17 = OpLoad %v4bool %a
-%16 = OpLogicalNot %v4bool %17
-%18 = OpCompositeExtract %bool %16 0
-%19 = OpSelect %int %18 %int_1 %int_0
-%23 = OpConvertSToF %float %19
-%24 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0
-OpStore %24 %23
+%int_1 = OpConstant %int 1
+%false = OpConstantFalse %bool
+%v2bool = OpTypeVector %bool 2
+%v3bool = OpTypeVector %bool 3
+%true = OpConstantTrue %bool
+%87 = OpConstantComposite %v2bool %false %true
+%95 = OpConstantComposite %v3bool %false %true %false
+%103 = OpConstantComposite %v4bool %false %true %false %true
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%int_2 = OpConstant %int 2
+%int_3 = OpConstant %int 3
+%_entrypoint_v = OpFunction %void None %15
+%16 = OpLabel
+%20 = OpVariable %_ptr_Function_v2float Function
+OpStore %20 %19
+%22 = OpFunctionCall %v4float %main %20
+OpStore %sk_FragColor %22
OpReturn
OpFunctionEnd
+%main = OpFunction %v4float None %23
+%24 = OpFunctionParameter %_ptr_Function_v2float
+%25 = OpLabel
+%input = OpVariable %_ptr_Function_v4bool Function
+%expected = OpVariable %_ptr_Function_v4bool Function
+%108 = OpVariable %_ptr_Function_v4float Function
+%29 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%33 = OpLoad %v4float %29
+%34 = OpCompositeExtract %float %33 0
+%35 = OpFUnordNotEqual %bool %34 %float_0
+%36 = OpCompositeExtract %float %33 1
+%37 = OpFUnordNotEqual %bool %36 %float_0
+%38 = OpCompositeExtract %float %33 2
+%39 = OpFUnordNotEqual %bool %38 %float_0
+%40 = OpCompositeExtract %float %33 3
+%41 = OpFUnordNotEqual %bool %40 %float_0
+%42 = OpCompositeConstruct %v4bool %35 %37 %39 %41
+OpStore %input %42
+%44 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%46 = OpLoad %v4float %44
+%47 = OpCompositeExtract %float %46 0
+%48 = OpFUnordNotEqual %bool %47 %float_0
+%49 = OpCompositeExtract %float %46 1
+%50 = OpFUnordNotEqual %bool %49 %float_0
+%51 = OpCompositeExtract %float %46 2
+%52 = OpFUnordNotEqual %bool %51 %float_0
+%53 = OpCompositeExtract %float %46 3
+%54 = OpFUnordNotEqual %bool %53 %float_0
+%55 = OpCompositeConstruct %v4bool %48 %50 %52 %54
+OpStore %expected %55
+%58 = OpLoad %v4bool %input
+%59 = OpVectorShuffle %v2bool %58 %58 0 1
+%57 = OpLogicalNot %v2bool %59
+%61 = OpLoad %v4bool %expected
+%62 = OpVectorShuffle %v2bool %61 %61 0 1
+%63 = OpLogicalEqual %v2bool %57 %62
+%64 = OpAll %bool %63
+OpSelectionMerge %66 None
+OpBranchConditional %64 %65 %66
+%65 = OpLabel
+%68 = OpLoad %v4bool %input
+%69 = OpVectorShuffle %v3bool %68 %68 0 1 2
+%67 = OpLogicalNot %v3bool %69
+%71 = OpLoad %v4bool %expected
+%72 = OpVectorShuffle %v3bool %71 %71 0 1 2
+%73 = OpLogicalEqual %v3bool %67 %72
+%74 = OpAll %bool %73
+OpBranch %66
+%66 = OpLabel
+%75 = OpPhi %bool %false %25 %74 %65
+OpSelectionMerge %77 None
+OpBranchConditional %75 %76 %77
+%76 = OpLabel
+%79 = OpLoad %v4bool %input
+%78 = OpLogicalNot %v4bool %79
+%80 = OpLoad %v4bool %expected
+%81 = OpLogicalEqual %v4bool %78 %80
+%82 = OpAll %bool %81
+OpBranch %77
+%77 = OpLabel
+%83 = OpPhi %bool %false %66 %82 %76
+OpSelectionMerge %85 None
+OpBranchConditional %83 %84 %85
+%84 = OpLabel
+%88 = OpLoad %v4bool %expected
+%89 = OpVectorShuffle %v2bool %88 %88 0 1
+%90 = OpLogicalEqual %v2bool %87 %89
+%91 = OpAll %bool %90
+OpBranch %85
+%85 = OpLabel
+%92 = OpPhi %bool %false %77 %91 %84
+OpSelectionMerge %94 None
+OpBranchConditional %92 %93 %94
+%93 = OpLabel
+%96 = OpLoad %v4bool %expected
+%97 = OpVectorShuffle %v3bool %96 %96 0 1 2
+%98 = OpLogicalEqual %v3bool %95 %97
+%99 = OpAll %bool %98
+OpBranch %94
+%94 = OpLabel
+%100 = OpPhi %bool %false %85 %99 %93
+OpSelectionMerge %102 None
+OpBranchConditional %100 %101 %102
+%101 = OpLabel
+%104 = OpLoad %v4bool %expected
+%105 = OpLogicalEqual %v4bool %103 %104
+%106 = OpAll %bool %105
+OpBranch %102
+%102 = OpLabel
+%107 = OpPhi %bool %false %94 %106 %101
+OpSelectionMerge %112 None
+OpBranchConditional %107 %110 %111
+%110 = OpLabel
+%113 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%115 = OpLoad %v4float %113
+OpStore %108 %115
+OpBranch %112
+%111 = OpLabel
+%116 = OpAccessChain %_ptr_Uniform_v4float %10 %int_3
+%118 = OpLoad %v4float %116
+OpStore %108 %118
+OpBranch %112
+%112 = OpLabel
+%119 = OpLoad %v4float %108
+OpReturnValue %119
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/Not.glsl b/tests/sksl/intrinsics/Not.glsl
index da4df6183c..b6b8d3dfd3 100644
--- a/tests/sksl/intrinsics/Not.glsl
+++ b/tests/sksl/intrinsics/Not.glsl
@@ -1,6 +1,11 @@
out vec4 sk_FragColor;
-bvec4 a;
-void main() {
- sk_FragColor.x = float(not(a).x ? 1 : 0);
+uniform vec4 inputH4;
+uniform vec4 expectedH4;
+uniform vec4 colorGreen;
+uniform vec4 colorRed;
+vec4 main() {
+ bvec4 input = bvec4(inputH4);
+ bvec4 expected = bvec4(expectedH4);
+ return ((((not(input.xy) == expected.xy && not(input.xyz) == expected.xyz) && not(input) == expected) && bvec2(false, true) == expected.xy) && bvec3(false, true, false) == expected.xyz) && bvec4(false, true, false, true) == expected ? colorGreen : colorRed;
}
diff --git a/tests/sksl/intrinsics/Not.metal b/tests/sksl/intrinsics/Not.metal
index 5535bfd0d6..bb17fc6d8f 100644
--- a/tests/sksl/intrinsics/Not.metal
+++ b/tests/sksl/intrinsics/Not.metal
@@ -1,19 +1,23 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
+struct Uniforms {
+ float4 inputH4;
+ float4 expectedH4;
+ float4 colorGreen;
+ float4 colorRed;
+};
struct Inputs {
};
struct Outputs {
float4 sk_FragColor [[color(0)]];
};
-struct Globals {
- bool4 a;
-};
-fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
- Globals _globals{{}};
- (void)_globals;
+
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
Outputs _out;
(void)_out;
- _out.sk_FragColor.x = float(not(_globals.a).x ? 1 : 0);
+ bool4 input = bool4(_uniforms.inputH4);
+ bool4 expected = bool4(_uniforms.expectedH4);
+ _out.sk_FragColor = ((((all(not(input.xy) == expected.xy) && all(not(input.xyz) == expected.xyz)) && all(not(input) == expected)) && all(bool2(false, true) == expected.xy)) && all(bool3(false, true, false) == expected.xyz)) && all(bool4(false, true, false, true) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}
diff --git a/tests/sksl/intrinsics/SignFloat.asm.frag b/tests/sksl/intrinsics/SignFloat.asm.frag
index daebc2b205..b2a0a46c63 100644
--- a/tests/sksl/intrinsics/SignFloat.asm.frag
+++ b/tests/sksl/intrinsics/SignFloat.asm.frag
@@ -45,9 +45,18 @@ OpDecorate %62 RelaxedPrecision
OpDecorate %69 RelaxedPrecision
OpDecorate %71 RelaxedPrecision
OpDecorate %72 RelaxedPrecision
-OpDecorate %83 RelaxedPrecision
+OpDecorate %79 RelaxedPrecision
+OpDecorate %80 RelaxedPrecision
+OpDecorate %85 RelaxedPrecision
OpDecorate %86 RelaxedPrecision
OpDecorate %87 RelaxedPrecision
+OpDecorate %93 RelaxedPrecision
+OpDecorate %94 RelaxedPrecision
+OpDecorate %95 RelaxedPrecision
+OpDecorate %101 RelaxedPrecision
+OpDecorate %111 RelaxedPrecision
+OpDecorate %114 RelaxedPrecision
+OpDecorate %115 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -77,6 +86,8 @@ OpDecorate %87 RelaxedPrecision
%v3float = OpTypeVector %float 3
%v3bool = OpTypeVector %bool 3
%v4bool = OpTypeVector %bool 4
+%85 = OpConstantComposite %v2float %float_n1 %float_0
+%93 = OpConstantComposite %v3float %float_n1 %float_0 %float_1
%int_1 = OpConstant %int 1
%int_2 = OpConstant %int 2
%_entrypoint_v = OpFunction %void None %15
@@ -91,7 +102,7 @@ OpFunctionEnd
%24 = OpFunctionParameter %_ptr_Function_v2float
%25 = OpLabel
%expected = OpVariable %_ptr_Function_v4float Function
-%77 = OpVariable %_ptr_Function_v4float Function
+%105 = OpVariable %_ptr_Function_v4float Function
OpStore %expected %30
%33 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%37 = OpLoad %v4float %33
@@ -140,19 +151,57 @@ OpBranchConditional %66 %67 %68
OpBranch %68
%68 = OpLabel
%76 = OpPhi %bool %false %55 %75 %67
-OpSelectionMerge %80 None
-OpBranchConditional %76 %78 %79
+OpSelectionMerge %78 None
+OpBranchConditional %76 %77 %78
+%77 = OpLabel
+%79 = OpLoad %v4float %expected
+%80 = OpCompositeExtract %float %79 0
+%81 = OpFOrdEqual %bool %float_n1 %80
+OpBranch %78
%78 = OpLabel
-%81 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
-%83 = OpLoad %v4float %81
-OpStore %77 %83
-OpBranch %80
-%79 = OpLabel
-%84 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
-%86 = OpLoad %v4float %84
-OpStore %77 %86
-OpBranch %80
-%80 = OpLabel
-%87 = OpLoad %v4float %77
-OpReturnValue %87
+%82 = OpPhi %bool %false %68 %81 %77
+OpSelectionMerge %84 None
+OpBranchConditional %82 %83 %84
+%83 = OpLabel
+%86 = OpLoad %v4float %expected
+%87 = OpVectorShuffle %v2float %86 %86 0 1
+%88 = OpFOrdEqual %v2bool %85 %87
+%89 = OpAll %bool %88
+OpBranch %84
+%84 = OpLabel
+%90 = OpPhi %bool %false %78 %89 %83
+OpSelectionMerge %92 None
+OpBranchConditional %90 %91 %92
+%91 = OpLabel
+%94 = OpLoad %v4float %expected
+%95 = OpVectorShuffle %v3float %94 %94 0 1 2
+%96 = OpFOrdEqual %v3bool %93 %95
+%97 = OpAll %bool %96
+OpBranch %92
+%92 = OpLabel
+%98 = OpPhi %bool %false %84 %97 %91
+OpSelectionMerge %100 None
+OpBranchConditional %98 %99 %100
+%99 = OpLabel
+%101 = OpLoad %v4float %expected
+%102 = OpFOrdEqual %v4bool %30 %101
+%103 = OpAll %bool %102
+OpBranch %100
+%100 = OpLabel
+%104 = OpPhi %bool %false %92 %103 %99
+OpSelectionMerge %108 None
+OpBranchConditional %104 %106 %107
+%106 = OpLabel
+%109 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%111 = OpLoad %v4float %109
+OpStore %105 %111
+OpBranch %108
+%107 = OpLabel
+%112 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%114 = OpLoad %v4float %112
+OpStore %105 %114
+OpBranch %108
+%108 = OpLabel
+%115 = OpLoad %v4float %105
+OpReturnValue %115
OpFunctionEnd
diff --git a/tests/sksl/intrinsics/SignFloat.glsl b/tests/sksl/intrinsics/SignFloat.glsl
index c7b71cf442..f0e5510850 100644
--- a/tests/sksl/intrinsics/SignFloat.glsl
+++ b/tests/sksl/intrinsics/SignFloat.glsl
@@ -5,5 +5,5 @@ uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
vec4 expected = vec4(-1.0, 0.0, 1.0, 1.0);
- return ((sign(testInputs.x) == expected.x && sign(testInputs.xy) == expected.xy) && sign(testInputs.xyz) == expected.xyz) && sign(testInputs) == expected ? colorGreen : colorRed;
+ return ((((((sign(testInputs.x) == expected.x && sign(testInputs.xy) == expected.xy) && sign(testInputs.xyz) == expected.xyz) && sign(testInputs) == expected) && -1.0 == expected.x) && vec2(-1.0, 0.0) == expected.xy) && vec3(-1.0, 0.0, 1.0) == expected.xyz) && vec4(-1.0, 0.0, 1.0, 1.0) == expected ? colorGreen : colorRed;
}
diff --git a/tests/sksl/intrinsics/SignFloat.metal b/tests/sksl/intrinsics/SignFloat.metal
index 15e5c7ec8c..db1ed725ef 100644
--- a/tests/sksl/intrinsics/SignFloat.metal
+++ b/tests/sksl/intrinsics/SignFloat.metal
@@ -16,6 +16,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
Outputs _out;
(void)_out;
float4 expected = float4(-1.0, 0.0, 1.0, 1.0);
- _out.sk_FragColor = ((sign(_uniforms.testInputs.x) == expected.x && all(sign(_uniforms.testInputs.xy) == expected.xy)) && all(sign(_uniforms.testInputs.xyz) == expected.xyz)) && all(sign(_uniforms.testInputs) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
+ _out.sk_FragColor = ((((((sign(_uniforms.testInputs.x) == expected.x && all(sign(_uniforms.testInputs.xy) == expected.xy)) && all(sign(_uniforms.testInputs.xyz) == expected.xyz)) && all(sign(_uniforms.testInputs) == expected)) && -1.0 == expected.x) && all(float2(-1.0, 0.0) == expected.xy)) && all(float3(-1.0, 0.0, 1.0) == expected.xyz)) && all(float4(-1.0, 0.0, 1.0, 1.0) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}
diff --git a/tests/sksl/intrinsics/SignInt.asm.frag b/tests/sksl/intrinsics/SignInt.asm.frag
index 82285401d4..97a563d95f 100644
--- a/tests/sksl/intrinsics/SignInt.asm.frag
+++ b/tests/sksl/intrinsics/SignInt.asm.frag
@@ -1,4 +1,219 @@
-### Compilation failed:
-
-error: 6: unknown identifier 'testInputs'
-1 error
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
+OpExecutionMode %_entrypoint_v OriginUpperLeft
+OpName %sk_FragColor "sk_FragColor"
+OpName %sk_Clockwise "sk_Clockwise"
+OpName %_UniformBuffer "_UniformBuffer"
+OpMemberName %_UniformBuffer 0 "testInputs"
+OpMemberName %_UniformBuffer 1 "colorGreen"
+OpMemberName %_UniformBuffer 2 "colorRed"
+OpName %_entrypoint_v "_entrypoint_v"
+OpName %main "main"
+OpName %expected "expected"
+OpDecorate %sk_FragColor RelaxedPrecision
+OpDecorate %sk_FragColor Location 0
+OpDecorate %sk_FragColor Index 0
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+OpMemberDecorate %_UniformBuffer 0 Offset 0
+OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 1 Offset 16
+OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
+OpMemberDecorate %_UniformBuffer 2 Offset 32
+OpMemberDecorate %_UniformBuffer 2 RelaxedPrecision
+OpDecorate %_UniformBuffer Block
+OpDecorate %10 Binding 0
+OpDecorate %10 DescriptorSet 0
+OpDecorate %38 RelaxedPrecision
+OpDecorate %39 RelaxedPrecision
+OpDecorate %48 RelaxedPrecision
+OpDecorate %49 RelaxedPrecision
+OpDecorate %50 RelaxedPrecision
+OpDecorate %52 RelaxedPrecision
+OpDecorate %66 RelaxedPrecision
+OpDecorate %67 RelaxedPrecision
+OpDecorate %69 RelaxedPrecision
+OpDecorate %71 RelaxedPrecision
+OpDecorate %73 RelaxedPrecision
+OpDecorate %87 RelaxedPrecision
+OpDecorate %88 RelaxedPrecision
+OpDecorate %90 RelaxedPrecision
+OpDecorate %92 RelaxedPrecision
+OpDecorate %94 RelaxedPrecision
+OpDecorate %136 RelaxedPrecision
+OpDecorate %139 RelaxedPrecision
+OpDecorate %140 RelaxedPrecision
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%sk_FragColor = OpVariable %_ptr_Output_v4float Output
+%bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%sk_Clockwise = OpVariable %_ptr_Input_bool Input
+%_UniformBuffer = OpTypeStruct %v4float %v4float %v4float
+%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
+%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
+%void = OpTypeVoid
+%15 = OpTypeFunction %void
+%v2float = OpTypeVector %float 2
+%float_0 = OpConstant %float 0
+%19 = OpConstantComposite %v2float %float_0 %float_0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%23 = OpTypeFunction %v4float %_ptr_Function_v2float
+%int = OpTypeInt 32 1
+%v4int = OpTypeVector %int 4
+%_ptr_Function_v4int = OpTypePointer Function %v4int
+%int_n1 = OpConstant %int -1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%33 = OpConstantComposite %v4int %int_n1 %int_0 %int_0 %int_1
+%false = OpConstantFalse %bool
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%v2int = OpTypeVector %int 2
+%v2bool = OpTypeVector %bool 2
+%v3float = OpTypeVector %float 3
+%v3int = OpTypeVector %int 3
+%v3bool = OpTypeVector %bool 3
+%v4bool = OpTypeVector %bool 4
+%110 = OpConstantComposite %v2int %int_n1 %int_0
+%118 = OpConstantComposite %v3int %int_n1 %int_0 %int_0
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%int_2 = OpConstant %int 2
+%_entrypoint_v = OpFunction %void None %15
+%16 = OpLabel
+%20 = OpVariable %_ptr_Function_v2float Function
+OpStore %20 %19
+%22 = OpFunctionCall %v4float %main %20
+OpStore %sk_FragColor %22
+OpReturn
+OpFunctionEnd
+%main = OpFunction %v4float None %23
+%24 = OpFunctionParameter %_ptr_Function_v2float
+%25 = OpLabel
+%expected = OpVariable %_ptr_Function_v4int Function
+%130 = OpVariable %_ptr_Function_v4float Function
+OpStore %expected %33
+%36 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%38 = OpLoad %v4float %36
+%39 = OpCompositeExtract %float %38 0
+%40 = OpConvertFToS %int %39
+%35 = OpExtInst %int %1 SSign %40
+%41 = OpLoad %v4int %expected
+%42 = OpCompositeExtract %int %41 0
+%43 = OpIEqual %bool %35 %42
+OpSelectionMerge %45 None
+OpBranchConditional %43 %44 %45
+%44 = OpLabel
+%47 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%48 = OpLoad %v4float %47
+%49 = OpVectorShuffle %v2float %48 %48 0 1
+%50 = OpCompositeExtract %float %49 0
+%51 = OpConvertFToS %int %50
+%52 = OpCompositeExtract %float %49 1
+%53 = OpConvertFToS %int %52
+%54 = OpCompositeConstruct %v2int %51 %53
+%46 = OpExtInst %v2int %1 SSign %54
+%56 = OpLoad %v4int %expected
+%57 = OpVectorShuffle %v2int %56 %56 0 1
+%58 = OpIEqual %v2bool %46 %57
+%60 = OpAll %bool %58
+OpBranch %45
+%45 = OpLabel
+%61 = OpPhi %bool %false %25 %60 %44
+OpSelectionMerge %63 None
+OpBranchConditional %61 %62 %63
+%62 = OpLabel
+%65 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%66 = OpLoad %v4float %65
+%67 = OpVectorShuffle %v3float %66 %66 0 1 2
+%69 = OpCompositeExtract %float %67 0
+%70 = OpConvertFToS %int %69
+%71 = OpCompositeExtract %float %67 1
+%72 = OpConvertFToS %int %71
+%73 = OpCompositeExtract %float %67 2
+%74 = OpConvertFToS %int %73
+%75 = OpCompositeConstruct %v3int %70 %72 %74
+%64 = OpExtInst %v3int %1 SSign %75
+%77 = OpLoad %v4int %expected
+%78 = OpVectorShuffle %v3int %77 %77 0 1 2
+%79 = OpIEqual %v3bool %64 %78
+%81 = OpAll %bool %79
+OpBranch %63
+%63 = OpLabel
+%82 = OpPhi %bool %false %45 %81 %62
+OpSelectionMerge %84 None
+OpBranchConditional %82 %83 %84
+%83 = OpLabel
+%86 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%87 = OpLoad %v4float %86
+%88 = OpCompositeExtract %float %87 0
+%89 = OpConvertFToS %int %88
+%90 = OpCompositeExtract %float %87 1
+%91 = OpConvertFToS %int %90
+%92 = OpCompositeExtract %float %87 2
+%93 = OpConvertFToS %int %92
+%94 = OpCompositeExtract %float %87 3
+%95 = OpConvertFToS %int %94
+%96 = OpCompositeConstruct %v4int %89 %91 %93 %95
+%85 = OpExtInst %v4int %1 SSign %96
+%97 = OpLoad %v4int %expected
+%98 = OpIEqual %v4bool %85 %97
+%100 = OpAll %bool %98
+OpBranch %84
+%84 = OpLabel
+%101 = OpPhi %bool %false %63 %100 %83
+OpSelectionMerge %103 None
+OpBranchConditional %101 %102 %103
+%102 = OpLabel
+%104 = OpLoad %v4int %expected
+%105 = OpCompositeExtract %int %104 0
+%106 = OpIEqual %bool %int_n1 %105
+OpBranch %103
+%103 = OpLabel
+%107 = OpPhi %bool %false %84 %106 %102
+OpSelectionMerge %109 None
+OpBranchConditional %107 %108 %109
+%108 = OpLabel
+%111 = OpLoad %v4int %expected
+%112 = OpVectorShuffle %v2int %111 %111 0 1
+%113 = OpIEqual %v2bool %110 %112
+%114 = OpAll %bool %113
+OpBranch %109
+%109 = OpLabel
+%115 = OpPhi %bool %false %103 %114 %108
+OpSelectionMerge %117 None
+OpBranchConditional %115 %116 %117
+%116 = OpLabel
+%119 = OpLoad %v4int %expected
+%120 = OpVectorShuffle %v3int %119 %119 0 1 2
+%121 = OpIEqual %v3bool %118 %120
+%122 = OpAll %bool %121
+OpBranch %117
+%117 = OpLabel
+%123 = OpPhi %bool %false %109 %122 %116
+OpSelectionMerge %125 None
+OpBranchConditional %123 %124 %125
+%124 = OpLabel
+%126 = OpLoad %v4int %expected
+%127 = OpIEqual %v4bool %33 %126
+%128 = OpAll %bool %127
+OpBranch %125
+%125 = OpLabel
+%129 = OpPhi %bool %false %117 %128 %124
+OpSelectionMerge %134 None
+OpBranchConditional %129 %132 %133
+%132 = OpLabel
+%135 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%136 = OpLoad %v4float %135
+OpStore %130 %136
+OpBranch %134
+%133 = OpLabel
+%137 = OpAccessChain %_ptr_Uniform_v4float %10 %int_2
+%139 = OpLoad %v4float %137
+OpStore %130 %139
+OpBranch %134
+%134 = OpLabel
+%140 = OpLoad %v4float %130
+OpReturnValue %140
+OpFunctionEnd
diff --git a/tests/sksl/intrinsics/SignInt.glsl b/tests/sksl/intrinsics/SignInt.glsl
index 82285401d4..a1dab10cc0 100644
--- a/tests/sksl/intrinsics/SignInt.glsl
+++ b/tests/sksl/intrinsics/SignInt.glsl
@@ -1,4 +1,9 @@
-### Compilation failed:
-error: 6: unknown identifier 'testInputs'
-1 error
+out vec4 sk_FragColor;
+uniform vec4 testInputs;
+uniform vec4 colorGreen;
+uniform vec4 colorRed;
+vec4 main() {
+ ivec4 expected = ivec4(-1, 0, 0, 1);
+ return ((((((sign(int(testInputs.x)) == expected.x && sign(ivec2(testInputs.xy)) == expected.xy) && sign(ivec3(testInputs.xyz)) == expected.xyz) && sign(ivec4(testInputs)) == expected) && -1 == expected.x) && ivec2(-1, 0) == expected.xy) && ivec3(-1, 0, 0) == expected.xyz) && ivec4(-1, 0, 0, 1) == expected ? colorGreen : colorRed;
+}
diff --git a/tests/sksl/intrinsics/SignInt.metal b/tests/sksl/intrinsics/SignInt.metal
index 82285401d4..ac5260f8c8 100644
--- a/tests/sksl/intrinsics/SignInt.metal
+++ b/tests/sksl/intrinsics/SignInt.metal
@@ -1,4 +1,21 @@
-### Compilation failed:
+#include <metal_stdlib>
+#include <simd/simd.h>
+using namespace metal;
+struct Uniforms {
+ float4 testInputs;
+ float4 colorGreen;
+ float4 colorRed;
+};
+struct Inputs {
+};
+struct Outputs {
+ float4 sk_FragColor [[color(0)]];
+};
-error: 6: unknown identifier 'testInputs'
-1 error
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
+ Outputs _out;
+ (void)_out;
+ int4 expected = int4(-1, 0, 0, 1);
+ _out.sk_FragColor = ((((((sign(int(_uniforms.testInputs.x)) == expected.x && all(sign(int2(_uniforms.testInputs.xy)) == expected.xy)) && all(sign(int3(_uniforms.testInputs.xyz)) == expected.xyz)) && all(sign(int4(_uniforms.testInputs)) == expected)) && -1 == expected.x) && all(int2(-1, 0) == expected.xy)) && all(int3(-1, 0, 0) == expected.xyz)) && all(int4(-1, 0, 0, 1) == expected) ? _uniforms.colorGreen : _uniforms.colorRed;
+ return _out;
+}
diff --git a/tests/sksl/runtime_errors/IllegalIndexing.skvm b/tests/sksl/runtime_errors/IllegalIndexing.skvm
index cf4620b014..aaf54774d1 100644
--- a/tests/sksl/runtime_errors/IllegalIndexing.skvm
+++ b/tests/sksl/runtime_errors/IllegalIndexing.skvm
@@ -2,5 +2,4 @@
error: 25: index expression must be constant
error: 26: index expression must be constant
-error: 29: index expression must be constant
-3 errors
+2 errors
diff --git a/tests/sksl/shared/ConstVariableComparison.asm.frag b/tests/sksl/shared/ConstVariableComparison.asm.frag
index 6daa0e4514..0cd10e55a5 100644
--- a/tests/sksl/shared/ConstVariableComparison.asm.frag
+++ b/tests/sksl/shared/ConstVariableComparison.asm.frag
@@ -23,8 +23,8 @@ OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
OpDecorate %_UniformBuffer Block
OpDecorate %10 Binding 0
OpDecorate %10 DescriptorSet 0
-OpDecorate %45 RelaxedPrecision
-OpDecorate %48 RelaxedPrecision
+OpDecorate %43 RelaxedPrecision
+OpDecorate %46 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -64,23 +64,21 @@ OpFunctionEnd
%b = OpVariable %_ptr_Function_v4float Function
%c = OpVariable %_ptr_Function_v4float Function
OpStore %b %29
-%32 = OpLoad %v4float %b
-%31 = OpExtInst %v4float %1 FAbs %32
-OpStore %c %31
-%33 = OpLoad %v4float %b
-%34 = OpLoad %v4float %c
-%35 = OpFOrdNotEqual %v4bool %33 %34
-%37 = OpAny %bool %35
-OpSelectionMerge %40 None
-OpBranchConditional %37 %38 %39
+OpStore %c %29
+%31 = OpLoad %v4float %b
+%32 = OpLoad %v4float %c
+%33 = OpFOrdNotEqual %v4bool %31 %32
+%35 = OpAny %bool %33
+OpSelectionMerge %38 None
+OpBranchConditional %35 %36 %37
+%36 = OpLabel
+%39 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%43 = OpLoad %v4float %39
+OpReturnValue %43
+%37 = OpLabel
+%44 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%46 = OpLoad %v4float %44
+OpReturnValue %46
%38 = OpLabel
-%41 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
-%45 = OpLoad %v4float %41
-OpReturnValue %45
-%39 = OpLabel
-%46 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
-%48 = OpLoad %v4float %46
-OpReturnValue %48
-%40 = OpLabel
OpUnreachable
OpFunctionEnd
diff --git a/tests/sksl/shared/ConstVariableComparison.glsl b/tests/sksl/shared/ConstVariableComparison.glsl
index 6ee8a9605e..98599b0ece 100644
--- a/tests/sksl/shared/ConstVariableComparison.glsl
+++ b/tests/sksl/shared/ConstVariableComparison.glsl
@@ -4,7 +4,7 @@ uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
const vec4 b = vec4(1.0);
- vec4 c = abs(b);
+ vec4 c = vec4(1.0, 1.0, 1.0, 1.0);
if (b != c) {
return colorRed;
} else {
diff --git a/tests/sksl/shared/ConstVariableComparison.metal b/tests/sksl/shared/ConstVariableComparison.metal
index d679750de0..e50d400521 100644
--- a/tests/sksl/shared/ConstVariableComparison.metal
+++ b/tests/sksl/shared/ConstVariableComparison.metal
@@ -15,7 +15,7 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
Outputs _out;
(void)_out;
const float4 b = float4(1.0);
- float4 c = abs(b);
+ float4 c = float4(1.0, 1.0, 1.0, 1.0);
if (any(b != c)) {
_out.sk_FragColor = _uniforms.colorRed;
return _out;
diff --git a/tests/sksl/shared/StaticSwitchWithContinue.asm.frag b/tests/sksl/shared/StaticSwitchWithContinue.asm.frag
index 3ccb6ebffa..bac74a4160 100644
--- a/tests/sksl/shared/StaticSwitchWithContinue.asm.frag
+++ b/tests/sksl/shared/StaticSwitchWithContinue.asm.frag
@@ -23,9 +23,9 @@ OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
OpDecorate %_UniformBuffer Block
OpDecorate %10 Binding 0
OpDecorate %10 DescriptorSet 0
-OpDecorate %53 RelaxedPrecision
+OpDecorate %52 RelaxedPrecision
+OpDecorate %54 RelaxedPrecision
OpDecorate %55 RelaxedPrecision
-OpDecorate %56 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -64,7 +64,7 @@ OpFunctionEnd
%25 = OpLabel
%result = OpVariable %_ptr_Function_float Function
%x = OpVariable %_ptr_Function_int Function
-%46 = OpVariable %_ptr_Function_v4float Function
+%45 = OpVariable %_ptr_Function_v4float Function
OpStore %result %float_0
OpStore %x %int_0
OpBranch %32
@@ -76,30 +76,29 @@ OpBranch %33
%39 = OpSLessThanEqual %bool %37 %int_1
OpBranchConditional %39 %34 %36
%34 = OpLabel
-%40 = OpExtInst %float %1 FAbs %float_2
-OpStore %result %40
+OpStore %result %float_2
OpBranch %35
%35 = OpLabel
-%42 = OpLoad %int %x
-%43 = OpIAdd %int %42 %int_1
-OpStore %x %43
+%41 = OpLoad %int %x
+%42 = OpIAdd %int %41 %int_1
+OpStore %x %42
OpBranch %32
%36 = OpLabel
-%44 = OpLoad %float %result
-%45 = OpFOrdEqual %bool %44 %float_2
-OpSelectionMerge %50 None
-OpBranchConditional %45 %48 %49
+%43 = OpLoad %float %result
+%44 = OpFOrdEqual %bool %43 %float_2
+OpSelectionMerge %49 None
+OpBranchConditional %44 %47 %48
+%47 = OpLabel
+%50 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
+%52 = OpLoad %v4float %50
+OpStore %45 %52
+OpBranch %49
%48 = OpLabel
-%51 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
-%53 = OpLoad %v4float %51
-OpStore %46 %53
-OpBranch %50
+%53 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
+%54 = OpLoad %v4float %53
+OpStore %45 %54
+OpBranch %49
%49 = OpLabel
-%54 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
-%55 = OpLoad %v4float %54
-OpStore %46 %55
-OpBranch %50
-%50 = OpLabel
-%56 = OpLoad %v4float %46
-OpReturnValue %56
+%55 = OpLoad %v4float %45
+OpReturnValue %55
OpFunctionEnd
diff --git a/tests/sksl/shared/StaticSwitchWithContinue.glsl b/tests/sksl/shared/StaticSwitchWithContinue.glsl
index be465dbfd1..c15d3fc7c2 100644
--- a/tests/sksl/shared/StaticSwitchWithContinue.glsl
+++ b/tests/sksl/shared/StaticSwitchWithContinue.glsl
@@ -6,7 +6,7 @@ vec4 main() {
float result = 0.0;
for (int x = 0;x <= 1; x++) {
{
- result = abs(2.0);
+ result = 2.0;
continue;
}
}
diff --git a/tests/sksl/shared/StaticSwitchWithContinue.metal b/tests/sksl/shared/StaticSwitchWithContinue.metal
index cc1cf51f05..f422829288 100644
--- a/tests/sksl/shared/StaticSwitchWithContinue.metal
+++ b/tests/sksl/shared/StaticSwitchWithContinue.metal
@@ -17,7 +17,7 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
float result = 0.0;
for (int x = 0;x <= 1; x++) {
{
- result = abs(2.0);
+ result = 2.0;
continue;
}
}
diff --git a/tests/sksl/spirv/ConstantVectorFromVector.asm.frag b/tests/sksl/spirv/ConstantVectorFromVector.asm.frag
index 027c270889..678fa60ea0 100644
--- a/tests/sksl/spirv/ConstantVectorFromVector.asm.frag
+++ b/tests/sksl/spirv/ConstantVectorFromVector.asm.frag
@@ -10,7 +10,6 @@ OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
OpDecorate %sk_Clockwise BuiltIn FrontFacing
-OpDecorate %19 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@@ -20,17 +19,13 @@ OpDecorate %19 RelaxedPrecision
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
%void = OpTypeVoid
%11 = OpTypeFunction %void
+%float_0 = OpConstant %float 0
+%_ptr_Output_float = OpTypePointer Output %float
%int = OpTypeInt 32 1
-%v2int = OpTypeVector %int 2
%int_0 = OpConstant %int 0
-%17 = OpConstantComposite %v2int %int_0 %int_0
-%_ptr_Output_float = OpTypePointer Output %float
%main = OpFunction %void None %11
%12 = OpLabel
-%13 = OpExtInst %v2int %1 SAbs %17
-%18 = OpCompositeExtract %int %13 0
-%19 = OpConvertSToF %float %18
-%20 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0
-OpStore %20 %19
+%14 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0
+OpStore %14 %float_0
OpReturn
OpFunctionEnd
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index b5efcad471..c4159c824a 100644
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -189,7 +189,7 @@ ContextInfo GrContextFactory::getContextInfoInternal(ContextType type, ContextOv
// using this backend.
if (glCtx) {
GrGLDriverInfo info = GrGLGetDriverInfo(glCtx->gl());
- if (info.fANGLEVendor == GrGLANGLEVendor::kNVIDIA) {
+ if (info.fANGLEVendor == GrGLVendor::kNVIDIA) {
delete glCtx;
return ContextInfo();
}